1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "abc2program_compiler.h"
17 #include "abc_class_processor.h"
18 #include "file_format_version.h"
19
20 namespace panda::abc2program {
21
~Abc2ProgramCompiler()22 Abc2ProgramCompiler::~Abc2ProgramCompiler()
23 {
24 if (prog_ != nullptr) {
25 delete prog_;
26 prog_ = nullptr;
27 }
28 }
29
OpenAbcFile(const std::string & file_path)30 bool Abc2ProgramCompiler::OpenAbcFile(const std::string &file_path)
31 {
32 file_ = panda_file::File::Open(file_path);
33 if (file_ == nullptr) {
34 return false;
35 }
36 debug_info_extractor_ = std::make_unique<panda_file::DebugInfoExtractor>(file_.get());
37 return true;
38 }
39
IsVersionLessEqual(const std::array<uint8_t,panda_file::File::VERSION_SIZE> & version_1,const std::array<uint8_t,panda_file::File::VERSION_SIZE> & version_2) const40 bool Abc2ProgramCompiler::IsVersionLessEqual(
41 const std::array<uint8_t, panda_file::File::VERSION_SIZE> &version_1,
42 const std::array<uint8_t, panda_file::File::VERSION_SIZE> &version_2) const
43 {
44 for (size_t i = 0; i < panda_file::File::VERSION_SIZE; ++i) {
45 if (version_1[i] != version_2[i]) {
46 return version_1[i] < version_2[i];
47 }
48 }
49 return true;
50 }
51
CheckFileVersionIsSupported(std::array<uint8_t,panda_file::File::VERSION_SIZE> min_version,uint8_t target_api_version,std::string target_api_sub_version) const52 bool Abc2ProgramCompiler::CheckFileVersionIsSupported(std::array<uint8_t, panda_file::File::VERSION_SIZE> min_version,
53 uint8_t target_api_version,
54 std::string target_api_sub_version) const
55 {
56 auto target_version = panda_file::GetVersionByApi(target_api_version, target_api_sub_version);
57 if (!target_version.has_value()) {
58 return false;
59 }
60 const auto &file_version = file_->GetHeader()->version;
61 return IsVersionLessEqual(min_version, file_version) &&
62 IsVersionLessEqual(file_version, target_version.value());
63 }
64
GetAbcFile() const65 const panda_file::File &Abc2ProgramCompiler::GetAbcFile() const
66 {
67 return *file_;
68 }
69
GetDebugInfoExtractor() const70 const panda_file::DebugInfoExtractor &Abc2ProgramCompiler::GetDebugInfoExtractor() const
71 {
72 return *debug_info_extractor_;
73 }
74
CompileAbcFile()75 pandasm::Program *Abc2ProgramCompiler::CompileAbcFile()
76 {
77 prog_ = new pandasm::Program();
78 prog_->lang = LANG_ECMA;
79 auto classes = file_->GetClasses();
80 for (size_t i = 0; i < classes.size(); i++) {
81 panda_file::File::EntityId record_id(classes[i]);
82 if (file_->IsExternal(record_id)) {
83 UNREACHABLE();
84 }
85 CompileAbcClass(record_id, *prog_);
86 }
87 return prog_;
88 }
89
CompileAbcClass(const panda_file::File::EntityId & record_id,pandasm::Program & program)90 void Abc2ProgramCompiler::CompileAbcClass(const panda_file::File::EntityId &record_id,
91 pandasm::Program &program)
92 {
93 ASSERT(!file_->IsExternal(record_id));
94 Abc2ProgramEntityContainer entity_container(*file_, program, *debug_info_extractor_, record_id.GetOffset());
95 AbcClassProcessor class_processor(record_id, entity_container);
96 class_processor.FillProgramData();
97 }
98
CheckClassId(uint32_t class_id,size_t offset) const99 bool Abc2ProgramCompiler::CheckClassId(uint32_t class_id, size_t offset) const
100 {
101 auto *header = file_->GetHeader();
102 auto class_off = header->class_idx_off + sizeof(uint32_t) * offset;
103 if (class_id > header->file_size) {
104 LOG(FATAL, ABC2PROGRAM) << "> error encountered in record at " << class_off << " (0x" << std::hex
105 << class_off << "). binary file corrupted. record offset (0x" << class_id
106 << ") out of bounds (0x" << header->file_size << ")!";
107 }
108 return !file_->IsExternal(panda_file::File::EntityId(class_id));
109 }
110
111 } // namespace panda::abc2program
112