• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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.functionStaticTable) {
192         DumpFunction(os, it.second);
193     }
194     for (const auto &it : program.functionInstanceTable) {
195         DumpFunction(os, it.second);
196     }
197 }
198 
DumpFunction(std::ostream & os,const pandasm::Function & function) const199 void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function) const
200 {
201     os << DUMP_TITLE_FUNCTION;
202     os << function.returnType.GetPandasmName() << " " << function.name << "(";
203     if (!function.params.empty()) {
204         os << function.params[0].type.GetPandasmName() << " a0";
205 
206         for (size_t i = 1; i < function.params.size(); i++) {
207             os << ", " << function.params[i].type.GetPandasmName() << " a" << (size_t)i;
208         }
209     }
210     os << ")";
211 
212     const std::string signature = pandasm::GetFunctionSignatureFromName(function.name, function.params);
213 
214     DumpMetaData(os, *function.metadata);
215 
216     if (!function.HasImplementation()) {
217         os << DUMP_CONTENT_DOUBLE_ENDL;
218         return;
219     }
220 
221     os << " {";
222 
223     os << DUMP_CONTENT_SINGLE_ENDL;
224 
225     DumpInstructions(os, function);
226 
227     os << "}" << DUMP_CONTENT_DOUBLE_ENDL;
228 }
229 
DumpInstructions(std::ostream & os,const pandasm::Function & function) const230 void PandasmProgramDumper::DumpInstructions(std::ostream &os, const pandasm::Function &function) const
231 {
232     for (const auto &instr : function.ins) {
233         std::string ins = instr.ToString("", function.GetParamsNum() != 0, function.regsNum);
234         if (instr.setLabel) {
235             std::string delim = ": ";
236             size_t pos = ins.find(delim);
237             std::string label = ins.substr(0, pos);
238             ins.erase(0, pos + delim.length());
239 
240             os << label << ":";
241             os << DUMP_CONTENT_SINGLE_ENDL;
242         }
243 
244         os << "\t";
245         os << ins;
246         os << DUMP_CONTENT_SINGLE_ENDL;
247     }
248 }
249 
DumpStrings(std::ostream & os,const pandasm::Program & program) const250 void PandasmProgramDumper::DumpStrings(std::ostream &os, const pandasm::Program &program) const
251 {
252     if (HasNoAbcInput()) {
253         DumpStringsByProgram(os, program);
254     } else {
255         DumpStringsByStringTable(os, *stringTable_);
256     }
257 }
258 
DumpStringsByStringTable(std::ostream & os,const AbcStringTable & stringTable) const259 void PandasmProgramDumper::DumpStringsByStringTable(std::ostream &os, const AbcStringTable &stringTable) const
260 {
261     os << DUMP_TITLE_SEPARATOR;
262     os << DUMP_TITLE_STRING;
263     stringTable.Dump(os);
264     os << DUMP_CONTENT_SINGLE_ENDL;
265 }
266 
DumpStringsByProgram(std::ostream & os,const pandasm::Program & program) const267 void PandasmProgramDumper::DumpStringsByProgram(std::ostream &os, const pandasm::Program &program) const
268 {
269     os << DUMP_TITLE_SEPARATOR;
270     os << DUMP_TITLE_STRING;
271     os << DUMP_CONTENT_SINGLE_ENDL;
272     for (const std::string &str : program.strings) {
273         os << str << DUMP_CONTENT_SINGLE_ENDL;
274     }
275     os << DUMP_CONTENT_SINGLE_ENDL;
276 }
277 
DumpLiteralArray(std::ostream & os,const pandasm::LiteralArray & litArray,const pandasm::Program & program) const278 void PandasmProgramDumper::DumpLiteralArray(std::ostream &os, const pandasm::LiteralArray &litArray,
279                                             const pandasm::Program &program) const
280 {
281     if (litArray.literals.empty()) {
282         return;
283     }
284 
285     bool isConst = litArray.literals[0].IsArray();
286 
287     std::stringstream specifiers {};
288     if (isConst) {
289         specifiers << LiteralTagToString(litArray.literals[0].tag, program) << " " << litArray.literals.size() << " ";
290     }
291     os << specifiers.str() << "{";
292 
293     DumpValues(litArray, isConst, os, program);
294 
295     os << "}" << DUMP_CONTENT_SINGLE_ENDL;
296 }
297 
298 template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)299 std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit)
300 {
301     std::stringstream res {};
302     T value = std::get<T>(lit.value);
303     if (lit.IsSigned()) {
304         res << +static_cast<typename std::make_signed<T>::type>(value);
305     } else {
306         res << +value;
307     }
308     return res.str();
309 }
310 
LiteralValueToString(const pandasm::LiteralArray::Literal & lit) const311 std::string PandasmProgramDumper::LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const
312 {
313     if (lit.IsBoolValue()) {
314         std::stringstream res {};
315         res << (std::get<bool>(lit.value));
316         return res.str();
317     }
318 
319     if (lit.IsByteValue()) {
320         return LiteralIntegralValueToString<uint8_t>(lit);
321     }
322 
323     if (lit.IsShortValue()) {
324         return LiteralIntegralValueToString<uint16_t>(lit);
325     }
326 
327     if (lit.IsIntegerValue()) {
328         return LiteralIntegralValueToString<uint32_t>(lit);
329     }
330 
331     if (lit.IsLongValue()) {
332         return LiteralIntegralValueToString<uint64_t>(lit);
333     }
334 
335     if (lit.IsDoubleValue()) {
336         std::stringstream res {};
337         res << std::get<double>(lit.value);
338         return res.str();
339     }
340 
341     if (lit.IsFloatValue()) {
342         std::stringstream res {};
343         res << std::get<float>(lit.value);
344         return res.str();
345     }
346 
347     if (lit.IsStringValue()) {
348         std::stringstream res {};
349         res << "\"" << std::get<std::string>(lit.value) << "\"";
350         return res.str();
351     }
352 
353     UNREACHABLE();
354 }
355 
DumpValues(const pandasm::LiteralArray & litArray,const bool isConst,std::ostream & os,const pandasm::Program & program) const356 void PandasmProgramDumper::DumpValues(const pandasm::LiteralArray &litArray, const bool isConst, std::ostream &os,
357                                       const pandasm::Program &program) const
358 {
359     std::string separator = (isConst) ? (" ") : ("\n");
360 
361     os << separator;
362 
363     if (isConst) {
364         for (const auto &l : litArray.literals) {
365             os << LiteralValueToString(l) << separator;
366         }
367     } else {
368         for (const auto &l : litArray.literals) {
369             os << "\t" << LiteralTagToString(l.tag, program) << " " << LiteralValueToString(l) << separator;
370         }
371     }
372 }
373 
LiteralTagToString(const panda_file::LiteralTag & tag,const pandasm::Program & program) const374 std::string PandasmProgramDumper::LiteralTagToString(const panda_file::LiteralTag &tag,
375                                                      const pandasm::Program &program) const
376 {
377     switch (tag) {
378         case panda_file::LiteralTag::BOOL:
379         case panda_file::LiteralTag::ARRAY_U1:
380             return "u1";
381         case panda_file::LiteralTag::ARRAY_U8:
382             return "u8";
383         case panda_file::LiteralTag::ARRAY_I8:
384             return "i8";
385         case panda_file::LiteralTag::ARRAY_U16:
386             return "u16";
387         case panda_file::LiteralTag::ARRAY_I16:
388             return "i16";
389         case panda_file::LiteralTag::ARRAY_U32:
390             return "u32";
391         case panda_file::LiteralTag::INTEGER:
392         case panda_file::LiteralTag::ARRAY_I32:
393             return "i32";
394         case panda_file::LiteralTag::ARRAY_U64:
395             return "u64";
396         case panda_file::LiteralTag::BIGINT:
397         case panda_file::LiteralTag::ARRAY_I64:
398             return "i64";
399         case panda_file::LiteralTag::FLOAT:
400         case panda_file::LiteralTag::ARRAY_F32:
401             return "f32";
402         case panda_file::LiteralTag::DOUBLE:
403         case panda_file::LiteralTag::ARRAY_F64:
404             return "f64";
405         case panda_file::LiteralTag::STRING:
406         case panda_file::LiteralTag::ARRAY_STRING:
407             return pandasm::Type::FromDescriptor(panda_file::GetStringClassDescriptor(program.lang)).GetPandasmName();
408         case panda_file::LiteralTag::ACCESSOR:
409             return "accessor";
410         case panda_file::LiteralTag::NULLVALUE:
411             return "nullvalue";
412         case panda_file::LiteralTag::METHODAFFILIATE:
413             return "method_affiliate";
414         case panda_file::LiteralTag::METHOD:
415             return "method";
416         case panda_file::LiteralTag::GENERATORMETHOD:
417             return "generator_method";
418         default:
419             LOG(ERROR, ABC2PROGRAM) << "Unsupported literal with tag 0x" << std::hex << static_cast<uint32_t>(tag);
420             UNREACHABLE();
421     }
422 }
423 
424 }  // namespace ark::abc2program
425