• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "abc_file_processor.h"
17 #include <iostream>
18 #include "abc_class_processor.h"
19 #include "abc2program_log.h"
20 #include "abc_file_utils.h"
21 
22 #include "abc_literal_array_processor.h"
23 #include "abc_method_processor.h"
24 #include "get_language_specific_metadata.inc"
25 #include "mangling.h"
26 
27 namespace ark::abc2program {
28 
AbcFileProcessor(Abc2ProgramKeyData & keyData)29 AbcFileProcessor::AbcFileProcessor(Abc2ProgramKeyData &keyData) : keyData_(keyData)
30 {
31     file_ = &(keyData_.GetAbcFile());
32     stringTable_ = &(keyData_.GetAbcStringTable());
33     program_ = &(keyData_.GetProgram());
34 }
35 
ProcessFile()36 bool AbcFileProcessor::ProcessFile()
37 {
38     ProcessClasses();
39     FillLiteralArrays();
40     FillProgramStrings();
41     FillExternalFieldsToRecords();
42     GetLanguageSpecificMetadata();
43     program_->lang = keyData_.GetFileLanguage();
44     return true;
45 }
46 
FillLiteralArrays()47 void AbcFileProcessor::FillLiteralArrays()
48 {
49     AbcLiteralArrayProcessor litArrayProcessor(file_->GetLiteralArraysId(), keyData_);
50 }
51 
ProcessClasses()52 void AbcFileProcessor::ProcessClasses()
53 {
54     const auto classes = file_->GetClasses();
55     for (size_t i = 0; i < classes.size(); i++) {
56         uint32_t classIdx = classes[i];
57         auto classOff = file_->GetHeader()->classIdxOff + sizeof(uint32_t) * i;
58         if (classIdx > file_->GetHeader()->fileSize) {
59             LOG(FATAL, ABC2PROGRAM) << "> error encountered in record at " << classOff << " (0x" << std::hex << classOff
60                                     << "). binary file corrupted. record offset (0x" << classIdx
61                                     << ") out of bounds (0x" << file_->GetHeader()->fileSize << ")!";
62             break;
63         }
64         panda_file::File::EntityId recordId(classIdx);
65         auto language = GetRecordLanguage(recordId);
66         if (language != keyData_.GetFileLanguage()) {
67             if (keyData_.GetFileLanguage() == panda_file::SourceLang::PANDA_ASSEMBLY) {
68                 keyData_.SetFileLanguage(language);
69             } else if (language != panda_file::SourceLang::PANDA_ASSEMBLY) {
70                 LOG(ERROR, ABC2PROGRAM) << "> possible error encountered in record at" << classOff << " (0x" << std::hex
71                                         << classOff << "). record's language  ("
72                                         << panda_file::LanguageToString(language) << ")  differs from file's language ("
73                                         << panda_file::LanguageToString(keyData_.GetFileLanguage()) << ")!";
74             }
75         }
76         AbcClassProcessor classProcessor(recordId, keyData_);
77     }
78 }
79 
FillProgramStrings()80 void AbcFileProcessor::FillProgramStrings()
81 {
82     program_->strings = stringTable_->GetStringSet();
83 }
84 
FillExternalFieldsToRecords()85 void AbcFileProcessor::FillExternalFieldsToRecords()
86 {
87     for (auto &[recordName, record] : program_->recordTable) {
88         auto it = keyData_.GetExternalFieldTable().find(recordName);
89         if (it == keyData_.GetExternalFieldTable().end()) {
90             continue;
91         }
92         auto &[unused, fieldList] = *it;
93         (void)unused;
94         if (fieldList.empty()) {
95             continue;
96         }
97         for (auto &fieldIter : fieldList) {
98             if (!fieldIter.name.empty()) {
99                 record.fieldList.push_back(std::move(fieldIter));
100             }
101         }
102         keyData_.GetExternalFieldTable().erase(recordName);
103     }
104 }
105 
AnnotationTagToString(const char tag) const106 std::string AbcFileProcessor::AnnotationTagToString(const char tag) const
107 {
108     static const std::unordered_map<char, std::string> TAG_TO_STRING = {{'1', "u1"},
109                                                                         {'2', "i8"},
110                                                                         {'3', "u8"},
111                                                                         {'4', "i16"},
112                                                                         {'5', "u16"},
113                                                                         {'6', "i32"},
114                                                                         {'7', "u32"},
115                                                                         {'8', "i64"},
116                                                                         {'9', "u64"},
117                                                                         {'A', "f32"},
118                                                                         {'B', "f64"},
119                                                                         {'C', "string"},
120                                                                         {'D', "record"},
121                                                                         {'E', "method"},
122                                                                         {'F', "enum"},
123                                                                         {'G', "annotation"},
124                                                                         {'J', "method_handle"},
125                                                                         {'H', "array"},
126                                                                         {'K', "u1[]"},
127                                                                         {'L', "i8[]"},
128                                                                         {'M', "u8[]"},
129                                                                         {'N', "i16[]"},
130                                                                         {'O', "u16[]"},
131                                                                         {'P', "i32[]"},
132                                                                         {'Q', "u32[]"},
133                                                                         {'R', "i64[]"},
134                                                                         {'S', "u64[]"},
135                                                                         {'T', "f32[]"},
136                                                                         {'U', "f64[]"},
137                                                                         {'V', "string[]"},
138                                                                         {'W', "record[]"},
139                                                                         {'X', "method[]"},
140                                                                         {'Y', "enum[]"},
141                                                                         {'Z', "annotation[]"},
142                                                                         {'@', "method_handle[]"},
143                                                                         {'*', "nullptr_string"}};
144 
145     return TAG_TO_STRING.at(tag);
146 }
147 
ScalarValueToString(const panda_file::ScalarValue & value,const std::string & type)148 std::string AbcFileProcessor::ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type)
149 {
150     std::stringstream ss;
151 
152     if (type == "i8") {
153         auto res = value.Get<int8_t>();
154         ss << static_cast<int>(res);
155     } else if (type == "u1" || type == "u8") {
156         auto res = value.Get<uint8_t>();
157         ss << static_cast<unsigned int>(res);
158     } else if (type == "i16") {
159         ss << value.Get<int16_t>();
160     } else if (type == "u16") {
161         ss << value.Get<uint16_t>();
162     } else if (type == "i32") {
163         ss << value.Get<int32_t>();
164     } else if (type == "u32") {
165         ss << value.Get<uint32_t>();
166     } else if (type == "i64") {
167         ss << value.Get<int64_t>();
168     } else if (type == "u64") {
169         ss << value.Get<uint64_t>();
170     } else if (type == "f32") {
171         ss << value.Get<float>();
172     } else if (type == "f64") {
173         ss << value.Get<double>();
174     } else if (type == "string") {
175         const auto id = value.Get<panda_file::File::EntityId>();
176         ss << "\"" << stringTable_->GetStringById(id) << "\"";
177     } else if (type == "record") {
178         const auto id = value.Get<panda_file::File::EntityId>();
179         ss << keyData_.GetFullRecordNameById(id);
180     } else if (type == "method") {
181         const auto id = value.Get<panda_file::File::EntityId>();
182         AbcMethodProcessor methodProcessor(id, keyData_);
183         ss << methodProcessor.GetMethodSignature();
184     } else if (type == "enum") {
185         const auto id = value.Get<panda_file::File::EntityId>();
186         panda_file::FieldDataAccessor fieldAccessor(*file_, id);
187         ss << keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()) << "."
188            << stringTable_->GetStringById(fieldAccessor.GetNameId());
189     } else if (type == "annotation") {
190         const auto id = value.Get<panda_file::File::EntityId>();
191         ss << "id_" << id;
192     } else if (type == "void") {
193         return std::string();
194     } else if (type == "method_handle") {
195     } else if (type == "nullptr_string") {
196         ss << static_cast<uint32_t>(0);
197     }
198 
199     return ss.str();
200 }
201 
ArrayValueToString(const panda_file::ArrayValue & value,const std::string & type,const size_t idx)202 std::string AbcFileProcessor::ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type,
203                                                  const size_t idx)
204 {
205     std::stringstream ss;
206 
207     if (type == "i8") {
208         auto res = value.Get<int8_t>(idx);
209         ss << (static_cast<int>(res));
210     } else if (type == "u1" || type == "u8") {
211         auto res = value.Get<uint8_t>(idx);
212         ss << (static_cast<unsigned int>(res));
213     } else if (type == "i16") {
214         ss << (value.Get<int16_t>(idx));
215     } else if (type == "u16") {
216         ss << (value.Get<uint16_t>(idx));
217     } else if (type == "i32") {
218         ss << (value.Get<int32_t>(idx));
219     } else if (type == "u32") {
220         ss << (value.Get<uint32_t>(idx));
221     } else if (type == "i64") {
222         ss << (value.Get<int64_t>(idx));
223     } else if (type == "u64") {
224         ss << (value.Get<uint64_t>(idx));
225     } else if (type == "f32") {
226         ss << (value.Get<float>(idx));
227     } else if (type == "f64") {
228         ss << (value.Get<double>(idx));
229     } else if (type == "string") {
230         const auto id = value.Get<panda_file::File::EntityId>(idx);
231         ss << ('\"') << (stringTable_->GetStringById(id)) << ('\"');
232     } else if (type == "record") {
233         const auto id = value.Get<panda_file::File::EntityId>(idx);
234         ss << (keyData_.GetFullRecordNameById(id));
235     } else if (type == "method") {
236         const auto id = value.Get<panda_file::File::EntityId>(idx);
237         AbcMethodProcessor methodProcessor(id, keyData_);
238         ss << (methodProcessor.GetMethodSignature());
239     } else if (type == "enum") {
240         const auto id = value.Get<panda_file::File::EntityId>(idx);
241         panda_file::FieldDataAccessor fieldAccessor(*file_, id);
242         ss << keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()) << "."
243            << stringTable_->GetStringById(fieldAccessor.GetNameId());
244     } else if (type == "annotation") {
245         const auto id = value.Get<panda_file::File::EntityId>(idx);
246         ss << ("id_") << (id);
247     } else if (type == "method_handle") {
248     } else if (type == "nullptr_string") {
249     }
250 
251     return ss.str();
252 }
253 
GetRecordLanguage(panda_file::File::EntityId classId) const254 ark::panda_file::SourceLang AbcFileProcessor::GetRecordLanguage(panda_file::File::EntityId classId) const
255 {
256     if (file_->IsExternal(classId)) {
257         return ark::panda_file::SourceLang::PANDA_ASSEMBLY;
258     }
259 
260     panda_file::ClassDataAccessor cda(*file_, classId);
261     return cda.GetSourceLang().value_or(panda_file::SourceLang::PANDA_ASSEMBLY);
262 }
263 
264 }  // namespace ark::abc2program
265