• 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 "program_dump.h"
17 #include "mangling.h"
18 #include "method_data_accessor-inl.h"
19 #include "abc2program_log.h"
20 #include "abc_file_utils.h"
21 #include "source_language.h"
22 
23 namespace ark::abc2program {
24 
Dump(std::ostream & os,const pandasm::Program & program) const25 void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program) const
26 {
27     os << std::flush;
28     DumpAbcFilePath(os);
29     DumpProgramLanguage(os, program);
30     DumpLiteralArrayTable(os, program);
31     DumpRecordTable(os, program);
32     DumpFunctionTable(os, program);
33 }
34 
HasNoAbcInput() const35 bool PandasmProgramDumper::HasNoAbcInput() const
36 {
37     return ((file_ == nullptr) || (stringTable_ == nullptr));
38 }
39 
DumpAbcFilePath(std::ostream & os) const40 void PandasmProgramDumper::DumpAbcFilePath(std::ostream &os) const
41 {
42     if (HasNoAbcInput()) {
43         return;
44     }
45     os << DUMP_TITLE_SOURCE_BINARY << file_->GetFilename() << DUMP_CONTENT_DOUBLE_ENDL;
46 }
47 
DumpProgramLanguage(std::ostream & os,const pandasm::Program & program) const48 void PandasmProgramDumper::DumpProgramLanguage(std::ostream &os, const pandasm::Program &program) const
49 {
50     os << DUMP_TITLE_LANGUAGE;
51     os << ark::panda_file::LanguageToString(program.lang);
52     os << DUMP_CONTENT_DOUBLE_ENDL;
53 }
54 
DumpLiteralArrayTable(std::ostream & os,const pandasm::Program & program) const55 void PandasmProgramDumper::DumpLiteralArrayTable(std::ostream &os, const pandasm::Program &program) const
56 {
57     if (HasNoAbcInput()) {
58         DumpLiteralArrayTableWithoutKey(os, program);
59     } else {
60         DumpLiteralArrayTableWithKey(os, program);
61     }
62 }
63 
DumpLiteralArrayTableWithKey(std::ostream & os,const pandasm::Program & program) const64 void PandasmProgramDumper::DumpLiteralArrayTableWithKey(std::ostream &os, const pandasm::Program &program) const
65 {
66     os << DUMP_TITLE_SEPARATOR;
67     os << DUMP_TITLE_LITERALS << DUMP_CONTENT_SINGLE_ENDL;
68     for (auto &[key, litArray] : program.literalarrayTable) {
69         DumpLiteralArrayWithKey(os, key, litArray, program);
70     }
71     os << DUMP_CONTENT_DOUBLE_ENDL;
72 }
73 
DumpLiteralArrayWithKey(std::ostream & os,const std::string & key,const pandasm::LiteralArray & litArray,const pandasm::Program & program) const74 void PandasmProgramDumper::DumpLiteralArrayWithKey(std::ostream &os, const std::string &key,
75                                                    const pandasm::LiteralArray &litArray,
76                                                    const pandasm::Program &program) const
77 {
78     os << DUMP_TITLE_LITERAL_ARRAY;
79     os << DUMP_LITERAL_ARRAY_PREFIX;
80     os << key << " ";
81     DumpLiteralArray(os, litArray, program);
82     os << DUMP_CONTENT_SINGLE_ENDL;
83 }
84 
DumpLiteralArrayTableWithoutKey(std::ostream & os,const pandasm::Program & program) const85 void PandasmProgramDumper::DumpLiteralArrayTableWithoutKey(std::ostream &os, const pandasm::Program &program) const
86 {
87     for (auto &[unused, litArray] : program.literalarrayTable) {
88         (void)unused;
89         DumpLiteralArray(os, litArray, program);
90         os << DUMP_CONTENT_SINGLE_ENDL;
91     }
92     os << DUMP_CONTENT_DOUBLE_ENDL;
93 }
94 
DumpRecordTable(std::ostream & os,const pandasm::Program & program) const95 void PandasmProgramDumper::DumpRecordTable(std::ostream &os, const pandasm::Program &program) const
96 {
97     os << DUMP_TITLE_SEPARATOR;
98     os << DUMP_TITLE_RECORDS;
99     os << DUMP_CONTENT_DOUBLE_ENDL;
100     for (const auto &it : program.recordTable) {
101         DumpRecord(os, it.second);
102     }
103     os << DUMP_CONTENT_SINGLE_ENDL;
104 }
105 
DumpRecord(std::ostream & os,const pandasm::Record & record) const106 void PandasmProgramDumper::DumpRecord(std::ostream &os, const pandasm::Record &record) const
107 {
108     if (AbcFileUtils::IsSystemTypeName(record.name)) {
109         return;
110     }
111     os << DUMP_TITLE_RECORD << record.name;
112     if (DumpMetaData(os, *record.metadata)) {
113         DumpFieldList(os, record);
114     }
115     DumpRecordSourceFile(os, record);
116 }
117 
DumpFieldList(std::ostream & os,const pandasm::Record & record) const118 void PandasmProgramDumper::DumpFieldList(std::ostream &os, const pandasm::Record &record) const
119 {
120     if (record.metadata->IsForeign() && record.fieldList.empty()) {
121         os << DUMP_CONTENT_DOUBLE_ENDL;
122         return;
123     }
124     os << " {" << DUMP_CONTENT_SINGLE_ENDL;
125     for (const auto &it : record.fieldList) {
126         DumpField(os, it);
127         os << DUMP_CONTENT_SINGLE_ENDL;
128     }
129     os << DUMP_CONTENT_SINGLE_ENDL << "}" << DUMP_CONTENT_SINGLE_ENDL;
130 }
131 
DumpField(std::ostream & os,const pandasm::Field & field) const132 void PandasmProgramDumper::DumpField(std::ostream &os, const pandasm::Field &field) const
133 {
134     os << "\t" << field.type.GetPandasmName() << " " << field.name;
135     DumpMetaData(os, *field.metadata);
136 }
137 
DumpMetaData(std::ostream & os,const pandasm::ItemMetadata & meta) const138 bool PandasmProgramDumper::DumpMetaData(std::ostream &os, const pandasm::ItemMetadata &meta) const
139 {
140     auto boolAttributes = meta.GetBoolAttributes();
141     auto attributes = meta.GetAttributes();
142     if (boolAttributes.empty() && attributes.empty()) {
143         return true;
144     }
145 
146     os << " <";
147 
148     size_t size = boolAttributes.size();
149     size_t idx = 0;
150     for (const auto &attr : boolAttributes) {
151         os << attr;
152         ++idx;
153 
154         if (!attributes.empty() || idx < size) {
155             os << ", ";
156         }
157     }
158 
159     size = attributes.size();
160     idx = 0;
161     for (const auto &[key, values] : attributes) {
162         for (size_t i = 0; i < values.size(); i++) {
163             os << key << "=" << values[i];
164 
165             if (i < values.size() - 1) {
166                 os << ", ";
167             }
168         }
169 
170         ++idx;
171 
172         if (idx < size) {
173             os << ", ";
174         }
175     }
176 
177     os << ">";
178     return true;
179 }
180 
DumpRecordSourceFile(std::ostream & os,const pandasm::Record & record) const181 void PandasmProgramDumper::DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const
182 {
183     os << DUMP_TITLE_RECORD_SOURCE_FILE << record.sourceFile << DUMP_CONTENT_DOUBLE_ENDL;
184 }
185 
DumpFunctionTable(std::ostream & os,const pandasm::Program & program) const186 void PandasmProgramDumper::DumpFunctionTable(std::ostream &os, const pandasm::Program &program) const
187 {
188     os << DUMP_TITLE_SEPARATOR;
189     os << DUMP_TITLE_METHODS;
190     os << DUMP_CONTENT_DOUBLE_ENDL;
191     for (const auto &it : program.functionTable) {
192         DumpFunction(os, it.second);
193     }
194 }
195 
DumpFunction(std::ostream & os,const pandasm::Function & function) const196 void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function) const
197 {
198     os << DUMP_TITLE_FUNCTION;
199     os << function.returnType.GetPandasmName() << " " << function.name << "(";
200     if (!function.params.empty()) {
201         os << function.params[0].type.GetPandasmName() << " a0";
202 
203         for (size_t i = 1; i < function.params.size(); i++) {
204             os << ", " << function.params[i].type.GetPandasmName() << " a" << (size_t)i;
205         }
206     }
207     os << ")";
208 
209     const std::string signature = pandasm::GetFunctionSignatureFromName(function.name, function.params);
210 
211     DumpMetaData(os, *function.metadata);
212 
213     if (!function.HasImplementation()) {
214         os << DUMP_CONTENT_DOUBLE_ENDL;
215         return;
216     }
217 
218     os << " {";
219 
220     os << DUMP_CONTENT_SINGLE_ENDL;
221 
222     DumpInstructions(os, function);
223 
224     os << "}" << DUMP_CONTENT_DOUBLE_ENDL;
225 }
226 
DumpInstructions(std::ostream & os,const pandasm::Function & function) const227 void PandasmProgramDumper::DumpInstructions(std::ostream &os, const pandasm::Function &function) const
228 {
229     for (const auto &instr : function.ins) {
230         std::string ins = instr.ToString("", function.GetParamsNum() != 0, function.regsNum);
231         if (instr.setLabel) {
232             std::string delim = ": ";
233             size_t pos = ins.find(delim);
234             std::string label = ins.substr(0, pos);
235             ins.erase(0, pos + delim.length());
236 
237             os << label << ":";
238             os << DUMP_CONTENT_SINGLE_ENDL;
239         }
240 
241         os << "\t";
242         os << ins;
243         os << DUMP_CONTENT_SINGLE_ENDL;
244     }
245 }
246 
DumpStrings(std::ostream & os,const pandasm::Program & program) const247 void PandasmProgramDumper::DumpStrings(std::ostream &os, const pandasm::Program &program) const
248 {
249     if (HasNoAbcInput()) {
250         DumpStringsByProgram(os, program);
251     } else {
252         DumpStringsByStringTable(os, *stringTable_);
253     }
254 }
255 
DumpStringsByStringTable(std::ostream & os,const AbcStringTable & stringTable) const256 void PandasmProgramDumper::DumpStringsByStringTable(std::ostream &os, const AbcStringTable &stringTable) const
257 {
258     os << DUMP_TITLE_SEPARATOR;
259     os << DUMP_TITLE_STRING;
260     stringTable.Dump(os);
261     os << DUMP_CONTENT_SINGLE_ENDL;
262 }
263 
DumpStringsByProgram(std::ostream & os,const pandasm::Program & program) const264 void PandasmProgramDumper::DumpStringsByProgram(std::ostream &os, const pandasm::Program &program) const
265 {
266     os << DUMP_TITLE_SEPARATOR;
267     os << DUMP_TITLE_STRING;
268     os << DUMP_CONTENT_SINGLE_ENDL;
269     for (const std::string &str : program.strings) {
270         os << str << DUMP_CONTENT_SINGLE_ENDL;
271     }
272     os << DUMP_CONTENT_SINGLE_ENDL;
273 }
274 
DumpLiteralArray(std::ostream & os,const pandasm::LiteralArray & litArray,const pandasm::Program & program) const275 void PandasmProgramDumper::DumpLiteralArray(std::ostream &os, const pandasm::LiteralArray &litArray,
276                                             const pandasm::Program &program) const
277 {
278     if (litArray.literals.empty()) {
279         return;
280     }
281 
282     bool isConst = litArray.literals[0].IsArray();
283 
284     std::stringstream specifiers {};
285     if (isConst) {
286         specifiers << LiteralTagToString(litArray.literals[0].tag, program) << " " << litArray.literals.size() << " ";
287     }
288     os << specifiers.str() << "{";
289 
290     DumpValues(litArray, isConst, os, program);
291 
292     os << "}" << DUMP_CONTENT_SINGLE_ENDL;
293 }
294 
295 template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)296 std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit)
297 {
298     std::stringstream res {};
299     T value = std::get<T>(lit.value);
300     if (lit.IsSigned()) {
301         res << +static_cast<typename std::make_signed<T>::type>(value);
302     } else {
303         res << +value;
304     }
305     return res.str();
306 }
307 
LiteralValueToString(const pandasm::LiteralArray::Literal & lit) const308 std::string PandasmProgramDumper::LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const
309 {
310     if (lit.IsBoolValue()) {
311         std::stringstream res {};
312         res << (std::get<bool>(lit.value));
313         return res.str();
314     }
315 
316     if (lit.IsByteValue()) {
317         return LiteralIntegralValueToString<uint8_t>(lit);
318     }
319 
320     if (lit.IsShortValue()) {
321         return LiteralIntegralValueToString<uint16_t>(lit);
322     }
323 
324     if (lit.IsIntegerValue()) {
325         return LiteralIntegralValueToString<uint32_t>(lit);
326     }
327 
328     if (lit.IsLongValue()) {
329         return LiteralIntegralValueToString<uint64_t>(lit);
330     }
331 
332     if (lit.IsDoubleValue()) {
333         std::stringstream res {};
334         res << std::get<double>(lit.value);
335         return res.str();
336     }
337 
338     if (lit.IsFloatValue()) {
339         std::stringstream res {};
340         res << std::get<float>(lit.value);
341         return res.str();
342     }
343 
344     if (lit.IsStringValue()) {
345         std::stringstream res {};
346         res << "\"" << std::get<std::string>(lit.value) << "\"";
347         return res.str();
348     }
349 
350     UNREACHABLE();
351 }
352 
DumpValues(const pandasm::LiteralArray & litArray,const bool isConst,std::ostream & os,const pandasm::Program & program) const353 void PandasmProgramDumper::DumpValues(const pandasm::LiteralArray &litArray, const bool isConst, std::ostream &os,
354                                       const pandasm::Program &program) const
355 {
356     std::string separator = (isConst) ? (" ") : ("\n");
357 
358     os << separator;
359 
360     if (isConst) {
361         for (const auto &l : litArray.literals) {
362             os << LiteralValueToString(l) << separator;
363         }
364     } else {
365         for (const auto &l : litArray.literals) {
366             os << "\t" << LiteralTagToString(l.tag, program) << " " << LiteralValueToString(l) << separator;
367         }
368     }
369 }
370 
LiteralTagToString(const panda_file::LiteralTag & tag,const pandasm::Program & program) const371 std::string PandasmProgramDumper::LiteralTagToString(const panda_file::LiteralTag &tag,
372                                                      const pandasm::Program &program) const
373 {
374     switch (tag) {
375         case panda_file::LiteralTag::BOOL:
376         case panda_file::LiteralTag::ARRAY_U1:
377             return "u1";
378         case panda_file::LiteralTag::ARRAY_U8:
379             return "u8";
380         case panda_file::LiteralTag::ARRAY_I8:
381             return "i8";
382         case panda_file::LiteralTag::ARRAY_U16:
383             return "u16";
384         case panda_file::LiteralTag::ARRAY_I16:
385             return "i16";
386         case panda_file::LiteralTag::ARRAY_U32:
387             return "u32";
388         case panda_file::LiteralTag::INTEGER:
389         case panda_file::LiteralTag::ARRAY_I32:
390             return "i32";
391         case panda_file::LiteralTag::ARRAY_U64:
392             return "u64";
393         case panda_file::LiteralTag::BIGINT:
394         case panda_file::LiteralTag::ARRAY_I64:
395             return "i64";
396         case panda_file::LiteralTag::FLOAT:
397         case panda_file::LiteralTag::ARRAY_F32:
398             return "f32";
399         case panda_file::LiteralTag::DOUBLE:
400         case panda_file::LiteralTag::ARRAY_F64:
401             return "f64";
402         case panda_file::LiteralTag::STRING:
403         case panda_file::LiteralTag::ARRAY_STRING:
404             return pandasm::Type::FromDescriptor(panda_file::GetStringClassDescriptor(program.lang)).GetPandasmName();
405         case panda_file::LiteralTag::ACCESSOR:
406             return "accessor";
407         case panda_file::LiteralTag::NULLVALUE:
408             return "nullvalue";
409         case panda_file::LiteralTag::METHODAFFILIATE:
410             return "method_affiliate";
411         case panda_file::LiteralTag::METHOD:
412             return "method";
413         case panda_file::LiteralTag::GENERATORMETHOD:
414             return "generator_method";
415         default:
416             LOG(ERROR, ABC2PROGRAM) << "Unsupported literal with tag 0x" << std::hex << static_cast<uint32_t>(tag);
417             UNREACHABLE();
418     }
419 }
420 
421 }  // namespace ark::abc2program
422