• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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.h"
17 #include "libpandabase/mem/pool_manager.h"
18 #include "libpandafile/class_data_accessor-inl.h"
19 #include "libpandafile/code_data_accessor-inl.h"
20 #include "libpandafile/method_data_accessor-inl.h"
21 #include "libpandafile/literal_data_accessor-inl.h"
22 #include "libpandafile/field_data_accessor-inl.h"
23 #include "libpandafile/module_data_accessor-inl.h"
24 #include "compiler/optimizer/ir_builder/ir_builder.h"
25 #include "bytecode_optimizer/common.h"
26 #include "bytecode_optimizer/runtime_adapter.h"
27 #include "callee_info.h"
28 #include "class.h"
29 #include "function.h"
30 #include "module_record.h"
31 
32 namespace panda::defect_scan_aux {
33 using EntityId = panda_file::File::EntityId;
34 using StringData = panda_file::StringData;
35 using LiteralTag = panda_file::LiteralTag;
36 using ModuleDataAccessor = panda_file::ModuleDataAccessor;
37 using ModuleTag = panda_file::ModuleTag;
38 
AbcFile(std::string_view filename,std::unique_ptr<const panda_file::File> && panda_file)39 AbcFile::AbcFile(std::string_view filename, std::unique_ptr<const panda_file::File> &&panda_file)
40     : filename_(filename), panda_file_(std::forward<std::unique_ptr<const panda_file::File>>(panda_file))
41 {
42     PoolManager::Initialize(PoolType::MALLOC);
43     allocator_ = std::make_unique<ArenaAllocator>(SpaceType::SPACE_TYPE_COMPILER);
44     local_allocator_ = std::make_unique<ArenaAllocator>(SpaceType::SPACE_TYPE_COMPILER, nullptr, true);
45 }
46 
~AbcFile()47 AbcFile::~AbcFile()
48 {
49     PoolManager::Finalize();
50 }
51 
Open(std::string_view abc_filename)52 std::unique_ptr<const AbcFile> AbcFile::Open(std::string_view abc_filename)
53 {
54     auto panda_file = panda_file::OpenPandaFile(abc_filename);
55     if (panda_file == nullptr) {
56         LOG(ERROR, DEFECT_SCAN_AUX) << "Can not open binary file '" << abc_filename << "'";
57         return nullptr;
58     }
59 
60     std::unique_ptr<AbcFile> abc_file(new (std::nothrow) AbcFile(abc_filename, std::move(panda_file)));
61     if (abc_file == nullptr) {
62         LOG(ERROR, DEFECT_SCAN_AUX) << "Can not create AbcFile instance for '" << abc_filename << "'";
63         return nullptr;
64     }
65 
66     abc_file->ExtractDebugInfo();
67     abc_file->ExtractModuleInfo();
68     abc_file->InitializeAllDefinedFunction();
69     abc_file->ExtractDefinedClassAndFunctionInfo();
70     abc_file->ExtractClassAndFunctionExportList();
71     return abc_file;
72 }
73 
IsModule(std::string_view record_name) const74 bool AbcFile::IsModule(std::string_view record_name) const
75 {
76     if (IsMergeAbc() && record_name == "") {
77         LOG(FATAL, DEFECT_SCAN_AUX) <<
78             "For merge abc, need to specify record name to check if it has module info";
79     }
80     return GetModuleRecordByName(std::string(record_name)) != nullptr;
81 }
82 
IsMergeAbc() const83 bool AbcFile::IsMergeAbc() const
84 {
85     return is_merge_abc_;
86 }
87 
GetAbcFileName() const88 const std::string &AbcFile::GetAbcFileName() const
89 {
90     return filename_;
91 }
92 
GetDefinedFunctionCount() const93 size_t AbcFile::GetDefinedFunctionCount() const
94 {
95     if (IsMergeAbc()) {
96         return merged_def_func_list_.size();
97     }
98     return def_func_list_.size();
99 }
100 
GetDefinedClassCount() const101 size_t AbcFile::GetDefinedClassCount() const
102 {
103     if (IsMergeAbc()) {
104         return merged_def_class_list_.size();
105     }
106     return def_class_list_.size();
107 }
108 
GetClassList() const109 const std::vector<std::shared_ptr<Class>> &AbcFile::GetClassList() const
110 {
111     if (IsMergeAbc()) {
112         return merged_def_class_list_;
113     }
114     return def_class_list_;
115 }
116 
GetDefinedFunctionByIndex(size_t index) const117 const Function *AbcFile::GetDefinedFunctionByIndex(size_t index) const
118 {
119     if (IsMergeAbc()) {
120         ASSERT(index < merged_def_func_list_.size());
121         return merged_def_func_list_[index].get();
122     }
123     ASSERT(index < def_func_list_.size());
124     return def_func_list_[index].get();
125 }
126 
GetFunctionByName(std::string_view func_name) const127 const Function *AbcFile::GetFunctionByName(std::string_view func_name) const
128 {
129     return GetFunctionByNameImpl(func_name);
130 }
131 
GetExportFunctionByExportName(std::string_view export_func_name,std::string_view record_name) const132 const Function *AbcFile::GetExportFunctionByExportName(std::string_view export_func_name,
133                                                        std::string_view record_name) const
134 {
135     if (!IsModule(record_name)) {
136         return nullptr;
137     }
138 
139     if (IsMergeAbc() && record_name == "") {
140         LOG(FATAL, DEFECT_SCAN_AUX) <<
141             "Failed to GetExportFunctionByExportName from merge abc, need to specify record name";
142     }
143     std::string inter_func_name = GetLocalNameByExportName(export_func_name, record_name);
144     auto export_func_list = export_func_list_;
145     if (IsMergeAbc()) {
146         const std::string record_name_str = std::string(record_name);
147         auto it = merge_export_func_map_.find(record_name_str);
148         if (it == merge_export_func_map_.end()) {
149             return nullptr;
150         }
151         export_func_list = it->second;
152     }
153     for (auto &export_func : export_func_list) {
154         const std::string &ex_func_name = export_func->GetFunctionName();
155         std::string_view no_hashtag_name = GetNameWithoutHashtag(ex_func_name, record_name);
156         if (no_hashtag_name == inter_func_name) {
157             return export_func;
158         }
159     }
160     return nullptr;
161 }
162 
GetDefinedClassByIndex(size_t index) const163 const Class *AbcFile::GetDefinedClassByIndex(size_t index) const
164 {
165     if (IsMergeAbc()) {
166         ASSERT(index < merged_def_class_list_.size());
167         return merged_def_class_list_[index].get();
168     }
169     ASSERT(index < def_class_list_.size());
170     return def_class_list_[index].get();
171 }
172 
GetClassByName(std::string_view class_name) const173 const Class *AbcFile::GetClassByName(std::string_view class_name) const
174 {
175     return GetClassByNameImpl(class_name);
176 }
177 
GetExportClassByExportName(std::string_view export_class_name,std::string_view record_name) const178 const Class *AbcFile::GetExportClassByExportName(std::string_view export_class_name,
179                                                  std::string_view record_name) const
180 {
181     if (!IsModule(record_name)) {
182         return nullptr;
183     }
184 
185     if (IsMergeAbc() && record_name == "") {
186         LOG(FATAL, DEFECT_SCAN_AUX) <<
187             "Failed to GetExportClassByExportName from merge abc, need to specify record name";
188     }
189     if (!IsMergeAbc()) {
190         record_name = std::string(MODULE_CLASS);
191     }
192     std::string inter_class_name = GetLocalNameByExportName(export_class_name, record_name);
193     auto export_class_list = export_class_list_;
194     if (IsMergeAbc()) {
195         const std::string record_name_str = std::string(record_name);
196         auto it = merge_export_class_map_.find(record_name_str);
197         if (it == merge_export_class_map_.end()) {
198             return nullptr;
199         }
200         export_class_list = it->second;
201     }
202     for (auto export_class : export_class_list) {
203         const std::string &ex_class_name = export_class->GetClassName();
204         std::string_view no_hashtag_name = GetNameWithoutHashtag(ex_class_name, record_name);
205         if (no_hashtag_name == inter_class_name) {
206             return export_class;
207         }
208     }
209     return nullptr;
210 }
211 
GetLineNumberByInst(const Function * func,const Inst & inst) const212 ssize_t AbcFile::GetLineNumberByInst(const Function *func, const Inst &inst) const
213 {
214     auto &line_number_table = debug_info_->GetLineNumberTable(func->GetMethodId());
215     if (!line_number_table.empty()) {
216         uint32_t inst_pc = inst.GetPc();
217         // line_number_table is in ascending order, find the element that satisfies e1.pc <= inst_pc < e2.pc
218         auto comp = [](size_t value, const panda_file::LineTableEntry &entry) { return value >= entry.offset; };
219         auto iter = std::upper_bound(line_number_table.rbegin(), line_number_table.rend(), inst_pc, comp);
220         if (iter != line_number_table.rend()) {
221             // line number written in a .abc file starts from 0
222             return iter->line + 1;
223         }
224     }
225     return -1;
226 }
227 
GetFileRecordList() const228 const std::set<std::string> AbcFile::GetFileRecordList() const
229 {
230     return record_name_set_;
231 }
232 
GetFileRecordCount() const233 size_t AbcFile::GetFileRecordCount() const
234 {
235     return record_name_set_.size();
236 }
237 
GetLocalNameByExportName(std::string_view export_name,std::string_view record_name) const238 std::string AbcFile::GetLocalNameByExportName(std::string_view export_name, std::string_view record_name) const
239 {
240     if (!IsModule(record_name)) {
241         return EMPTY_STR;
242     }
243     if (IsMergeAbc() && record_name == "") {
244         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, need to specify record name";
245     }
246     if (!IsMergeAbc()) {
247         record_name = std::string(MODULE_CLASS);
248     }
249     auto module_record = GetModuleRecordByName(std::string(record_name));
250     if (module_record == nullptr) {
251         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, can't get module_record";
252     }
253     return module_record->GetLocalNameByExportName(export_name);
254 }
255 
GetImportNameByExportName(std::string_view export_name,std::string_view record_name) const256 std::string AbcFile::GetImportNameByExportName(std::string_view export_name, std::string_view record_name) const
257 {
258     if (!IsModule(record_name)) {
259         return EMPTY_STR;
260     }
261     if (IsMergeAbc() && record_name == "") {
262         LOG(FATAL, DEFECT_SCAN_AUX)
263             << "Failed to GetImportNameByExportName from merge abc, need to specify record name";
264     }
265     if (!IsMergeAbc()) {
266         record_name = std::string(MODULE_CLASS);
267     }
268     auto module_record = GetModuleRecordByName(std::string(record_name));
269     if (module_record == nullptr) {
270         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, can't get module_record";
271     }
272     return  module_record->GetImportNameByExportName(export_name);
273 }
274 
GetModuleNameByExportName(std::string_view export_name,std::string_view record_name) const275 std::string AbcFile::GetModuleNameByExportName(std::string_view export_name, std::string_view record_name) const
276 {
277     if (!IsModule(record_name)) {
278         return EMPTY_STR;
279     }
280     if (IsMergeAbc() && record_name == "") {
281         LOG(FATAL, DEFECT_SCAN_AUX)
282             << "Failed to GetModuleNameByExportName from merge abc, need to specify record name";
283     }
284     if (!IsMergeAbc()) {
285         record_name = std::string(MODULE_CLASS);
286     }
287     auto module_record = GetModuleRecordByName(std::string(record_name));
288     if (module_record == nullptr) {
289         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, can't get module_record";
290     }
291     return module_record->GetModuleNameByExportName(export_name);
292 }
293 
GetModuleNameByLocalName(std::string_view local_name,std::string_view record_name) const294 std::string AbcFile::GetModuleNameByLocalName(std::string_view local_name, std::string_view record_name) const
295 {
296     if (!IsModule(record_name)) {
297         return EMPTY_STR;
298     }
299     if (IsMergeAbc() && record_name == "") {
300         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetModuleNameByLocalName from merge abc, need to specify record name";
301     }
302     if (!IsMergeAbc()) {
303         record_name = std::string(MODULE_CLASS);
304     }
305     auto module_record = GetModuleRecordByName(std::string(record_name));
306     if (module_record == nullptr) {
307         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, can't get module_record";
308     }
309     return module_record->GetModuleNameByLocalName(local_name);
310 }
311 
GetImportNameByLocalName(std::string_view local_name,std::string_view record_name) const312 std::string AbcFile::GetImportNameByLocalName(std::string_view local_name, std::string_view record_name) const
313 {
314     if (!IsModule(record_name)) {
315         return EMPTY_STR;
316     }
317     if (IsMergeAbc() && record_name == "") {
318         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetImportNameByLocalName from merge abc, need to specify record name";
319     }
320     if (!IsMergeAbc()) {
321         record_name = std::string(MODULE_CLASS);
322     }
323     auto module_record = GetModuleRecordByName(std::string(record_name));
324     if (module_record == nullptr) {
325         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to GetLocalNameByExportName from merge abc, can't get module_record";
326     }
327     return module_record->GetImportNameByLocalName(local_name);
328 }
329 
GetNameWithoutHashtag(std::string_view full_name,std::string_view record_name) const330 std::string_view AbcFile::GetNameWithoutHashtag(std::string_view full_name, std::string_view record_name) const
331 {
332     size_t pos = full_name.find(record_name);
333     std::string_view name = pos == std::string::npos ? full_name : full_name.substr(pos + record_name.length());
334     if (name[0] == '#') {
335         size_t sec_hashtag_idx = name.find_first_of('#', 1);
336         if (sec_hashtag_idx != std::string::npos && (sec_hashtag_idx + 1) <= name.size()) {
337             return name.substr(sec_hashtag_idx + 1);
338         }
339     }
340     return name;
341 }
342 
GetStringByInst(const Inst & inst) const343 std::string AbcFile::GetStringByInst(const Inst &inst) const
344 {
345     auto type = inst.GetType();
346     switch (type) {
347         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
348         case InstType::DEFINEFUNC_IMM16_ID16_IMM8:
349         case InstType::DEFINEMETHOD_IMM8_ID16_IMM8:
350         case InstType::DEFINEMETHOD_IMM16_ID16_IMM8:
351         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
352         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
353         case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
354             uint32_t method_id = inst.GetImms()[1];
355             return GetStringByMethodId(EntityId(method_id));
356         }
357         case InstType::TRYLDGLOBALBYNAME_IMM8_ID16:
358         case InstType::TRYSTGLOBALBYNAME_IMM8_ID16:
359         case InstType::TRYLDGLOBALBYNAME_IMM16_ID16:
360         case InstType::TRYSTGLOBALBYNAME_IMM16_ID16:
361         case InstType::STCONSTTOGLOBALRECORD_IMM16_ID16:
362         case InstType::STTOGLOBALRECORD_IMM16_ID16:
363         case InstType::LDGLOBALVAR_IMM16_ID16:
364         case InstType::STGLOBALVAR_IMM16_ID16:
365         case InstType::LDOBJBYNAME_IMM8_ID16:
366         case InstType::LDOBJBYNAME_IMM16_ID16:
367         case InstType::STOBJBYNAME_IMM8_ID16_V8:
368         case InstType::STOBJBYNAME_IMM16_ID16_V8:
369         case InstType::LDSUPERBYNAME_IMM8_ID16:
370         case InstType::LDSUPERBYNAME_IMM16_ID16:
371         case InstType::STSUPERBYNAME_IMM8_ID16_V8:
372         case InstType::STSUPERBYNAME_IMM16_ID16_V8:
373         case InstType::LDTHISBYNAME_IMM8_ID16:
374         case InstType::LDTHISBYNAME_IMM16_ID16:
375         case InstType::STTHISBYNAME_IMM8_ID16:
376         case InstType::STTHISBYNAME_IMM16_ID16:
377         case InstType::STOWNBYNAME_IMM8_ID16_V8:
378         case InstType::STOWNBYNAME_IMM16_ID16_V8:
379         case InstType::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
380         case InstType::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8: {
381             uint32_t string_id = inst.GetImms()[1];
382             return GetStringByStringId(EntityId(string_id));
383         }
384         default:
385             return EMPTY_STR;
386     }
387 }
388 
389 // TODO(wangyantian): may match multiple stlex inst when considering control flow
GetStLexInstByLdLexInst(FuncInstPair func_inst_pair) const390 std::optional<FuncInstPair> AbcFile::GetStLexInstByLdLexInst(FuncInstPair func_inst_pair) const
391 {
392     Function *func = func_inst_pair.first;
393     const Inst &ld_lex_inst = func_inst_pair.second;
394     if (func == nullptr || !ld_lex_inst.IsInstLdLexVar()) {
395         return std::nullopt;
396     }
397 
398     auto ld_imms = ld_lex_inst.GetImms();
399     uint32_t ld_level = ld_imms[0];
400     uint32_t ld_slot_id = ld_imms[1];
401     Function *cur_func = func;
402     uint32_t i = 0;
403     while (true) {
404         bool has_new_lexenv = false;
405         const auto &graph = cur_func->GetGraph();
406         // TODO: Multiple newlexenv instructions and poplexenv instruction are not correctly supported in
407         //  the following code. Future fixes are required.
408         graph.VisitAllInstructions([&has_new_lexenv](const Inst &inst) {
409             if (inst.GetType() == InstType::NEWLEXENV_IMM8 || inst.GetType() == InstType::WIDE_NEWLEXENV_PREF_IMM16) {
410                 has_new_lexenv = true;
411             }
412         });
413         if (has_new_lexenv) {
414             i++;
415         }
416         if (i == ld_level + 1) {
417             break;
418         }
419         cur_func = cur_func->GetParentFunction();
420         if (cur_func == nullptr) {
421             return std::nullopt;
422         }
423     }
424     auto &graph = cur_func->GetGraph();
425     Inst st_lex_inst = ld_lex_inst;
426     bool is_same_func = (cur_func == func_inst_pair.first);
427     graph.VisitAllInstructions([is_same_func, ld_lex_inst, ld_slot_id, &st_lex_inst](const Inst &inst) {
428         if (inst.IsInstStLexVar()) {
429             auto st_imms = inst.GetImms();
430             uint32_t st_level = st_imms[0];
431             uint32_t st_slot_id = st_imms[1];
432             if (st_level == 0 && st_slot_id == ld_slot_id) {
433                 // Best effort to avoid the case where ld_lex_inst is some input of st_lex_inst
434                 // Current heuristics for choosing a valid st_lex_inst (or relationship between conditions):
435                 // 1. If no valid st_lex_inst is found (which is necessary to make the search process more sound).
436                 // 2. If they are not in the same function.
437                 // 3. If they are in the same function, but current st_lex_inst appears before ld_lex_inst (by PC).
438                 // More advanced heuristics (e.g. preforming dfs on all inputs of st_lex_inst) should be considered.
439                 if (st_lex_inst == ld_lex_inst || !is_same_func || inst.GetPc() < ld_lex_inst.GetPc()) {
440                     st_lex_inst = inst;
441                 }
442             }
443         }
444     });
445     if (st_lex_inst != ld_lex_inst) {
446         return FuncInstPair(cur_func, st_lex_inst);
447     }
448 
449     return std::nullopt;
450 }
451 
GetStGlobalInstByLdGlobalInst(FuncInstPair func_inst_pair) const452 std::optional<FuncInstPair> AbcFile::GetStGlobalInstByLdGlobalInst(FuncInstPair func_inst_pair) const
453 {
454     const Function *func = func_inst_pair.first;
455     const Inst &ld_global_inst = func_inst_pair.second;
456     if (func == nullptr || !ld_global_inst.IsInstLdGlobal()) {
457         return std::nullopt;
458     }
459 
460     uint32_t ld_str_id = ld_global_inst.GetImms()[0];
461     std::string record_name = func->GetRecordName();
462     Function *func_main;
463     // TODO(wangyantian): only consider that func_main_0 has StGlobal inst for now, what about other cases?
464     if (IsMergeAbc()) {
465         ASSERT(merge_def_func_map_.find(record_name) != merge_def_func_map_.end());
466         func_main = merge_def_func_map_.find(record_name)->second[0].get();
467     } else {
468         func_main = def_func_list_[0].get();
469     }
470     auto &graph = func_main->GetGraph();
471     Inst st_global_inst = ld_global_inst;
472     graph.VisitAllInstructions([ld_str_id, &st_global_inst](const Inst &inst) {
473         if (inst.IsInstStGlobal()) {
474             uint32_t st_str_id = inst.GetImms()[0];
475             if (st_str_id == ld_str_id) {
476                 st_global_inst = inst;
477             }
478         }
479     });
480     if (st_global_inst != ld_global_inst) {
481         return FuncInstPair(func_main, st_global_inst);
482     }
483 
484     return std::nullopt;
485 }
486 
ExtractDebugInfo()487 void AbcFile::ExtractDebugInfo()
488 {
489     debug_info_ = std::make_unique<const panda_file::DebugInfoExtractor>(panda_file_.get());
490     if (debug_info_ == nullptr) {
491         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to extract debug info";
492     }
493 }
494 
ExtractModuleInfo()495 void AbcFile::ExtractModuleInfo()
496 {
497     int module_offset = -1;
498     is_merge_abc_ = true;
499     for (uint32_t id : panda_file_->GetClasses()) {
500         EntityId class_id(id);
501         if (panda_file_->IsExternal(class_id)) {
502             continue;
503         }
504         panda_file::ClassDataAccessor cda(*panda_file_, class_id);
505         const char *desc = utf::Mutf8AsCString(cda.GetDescriptor());
506         if (std::strcmp(MODULE_CLASS, desc) == 0) {
507             is_merge_abc_ = false;
508             cda.EnumerateFields([&](panda_file::FieldDataAccessor &field_accessor) -> void {
509                 EntityId field_name_id = field_accessor.GetNameId();
510                 StringData sd = panda_file_->GetStringData(field_name_id);
511                 if (std::strcmp(utf::Mutf8AsCString(sd.data), filename_.data())) {
512                     module_offset = field_accessor.GetValue<int32_t>().value();
513                     return;
514                 }
515             });
516             break;
517         }
518     }
519     if (is_merge_abc_) {
520         ExtractMergeAbcModuleInfo();
521         return;
522     } else if (module_offset == -1) {
523         return;
524     }
525 
526     std::unique_ptr<ModuleRecord> module_record = std::make_unique<ModuleRecord>(filename_);
527     if (module_record == nullptr) {
528         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not create ModuleRecord instance for '" << filename_ << "'";
529     }
530     ExtractModuleRecord(EntityId(module_offset), module_record);
531     AddModuleRecord(MODULE_CLASS, std::move(module_record));
532 }
533 
ExtractMergeAbcModuleInfo()534 void AbcFile::ExtractMergeAbcModuleInfo()
535 {
536     for (uint32_t id : panda_file_->GetClasses()) {
537         EntityId class_id(id);
538         if (panda_file_->IsExternal(class_id)) {
539             continue;
540         }
541         panda_file::ClassDataAccessor cda(*panda_file_, class_id);
542         const char *desc = utf::Mutf8AsCString(cda.GetDescriptor());
543         cda.EnumerateFields([&](panda_file::FieldDataAccessor &field_accessor) -> void {
544             EntityId field_name_id = field_accessor.GetNameId();
545             StringData sd = panda_file_->GetStringData(field_name_id);
546             if (std::strcmp(utf::Mutf8AsCString(sd.data), MODULE_IDX_FIELD_NAME) != 0) {
547                 return;
548             }
549             auto module_offset = field_accessor.GetValue<int32_t>().value();
550             std::unique_ptr<ModuleRecord> module_record = std::make_unique<ModuleRecord>(desc);
551             ASSERT(module_record != nullptr);
552             ExtractModuleRecord(EntityId(module_offset), module_record);
553             AddModuleRecord(std::string(desc), std::move(module_record));
554         });
555     }
556 }
557 
ExtractModuleRecord(EntityId module_id,std::unique_ptr<ModuleRecord> & module_record)558 void AbcFile::ExtractModuleRecord(EntityId module_id, std::unique_ptr<ModuleRecord> &module_record)
559 {
560     ModuleDataAccessor mda(*panda_file_, module_id);
561     const std::vector<uint32_t> &request_modules_idx = mda.getRequestModules();
562     std::vector<std::string> request_modules;
563     for (size_t idx = 0; idx < request_modules_idx.size(); ++idx) {
564         request_modules.push_back(GetStringByStringId(EntityId(request_modules_idx[idx])));
565     }
566     module_record->SetRequestModules(request_modules);
567 
568     size_t regular_import_num = 0;
569     size_t local_export_num = 0;
570     mda.EnumerateModuleRecord([&](const ModuleTag &tag, uint32_t export_name_offset, uint32_t module_request_idx,
571                                   uint32_t import_name_offset, uint32_t local_name_offset) {
572         size_t request_num = request_modules.size();
573         ASSERT(request_num == 0 || module_request_idx < request_num);
574         std::string module_request = EMPTY_STR;
575         if (request_num != 0) {
576             module_request = request_modules[module_request_idx];
577         }
578         switch (tag) {
579             case ModuleTag::REGULAR_IMPORT: {
580                 ++regular_import_num;
581                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
582                 std::string import_name = GetStringByStringId(EntityId(import_name_offset));
583                 module_record->AddImportEntry({module_request, import_name, local_name});
584                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds a regular import: [" << module_request << ", "
585                                             << import_name << ", " << local_name << "]";
586                 break;
587             }
588             case ModuleTag::NAMESPACE_IMPORT: {
589                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
590                 module_record->AddImportEntry({module_request, "*", local_name});
591                 LOG(DEBUG, DEFECT_SCAN_AUX)
592                     << "ModuleRecord adds a namespace import: [" << module_request << ", *, " << local_name << "]";
593                 break;
594             }
595             case ModuleTag::LOCAL_EXPORT: {
596                 ++local_export_num;
597                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
598                 std::string export_name = GetStringByStringId(EntityId(export_name_offset));
599                 module_record->AddExportEntry({export_name, EMPTY_STR, EMPTY_STR, local_name});
600                 LOG(DEBUG, DEFECT_SCAN_AUX)
601                     << "ModuleRecord adds a local export: [" << export_name << ", null, null, " << local_name << "]";
602                 break;
603             }
604             case ModuleTag::INDIRECT_EXPORT: {
605                 std::string export_name = GetStringByStringId(EntityId(export_name_offset));
606                 std::string import_name = GetStringByStringId(EntityId(import_name_offset));
607                 module_record->AddExportEntry({export_name, module_request, import_name, EMPTY_STR});
608                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds an indirect export: [" << export_name << ", "
609                                             << module_request << ", " << import_name << ", null]";
610                 break;
611             }
612             case ModuleTag::STAR_EXPORT: {
613                 module_record->AddExportEntry({EMPTY_STR, module_request, "*", EMPTY_STR});
614                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds a start export: ["
615                                             << "null, " << module_request << "*, null]";
616                 break;
617             }
618             default: {
619                 UNREACHABLE();
620                 break;
621             }
622         }
623     });
624     module_record->SetRegularImportNum(regular_import_num);
625     module_record->SetLocalExportNum(local_export_num);
626 }
627 
AddModuleRecord(std::string record_name,std::unique_ptr<ModuleRecord> && module_record)628 void AbcFile::AddModuleRecord(std::string record_name, std::unique_ptr<ModuleRecord> &&module_record)
629 {
630     ASSERT(module_record_map_.find(record_name) == module_record_map_.end());
631     module_record_map_[record_name] = module_record.get();
632     module_record_list_.emplace_back(std::move(module_record));
633 }
634 
InitializeAllDefinedFunction()635 void AbcFile::InitializeAllDefinedFunction()
636 {
637     for (uint32_t id : panda_file_->GetClasses()) {
638         EntityId class_id {id};
639         if (panda_file_->IsExternal(class_id)) {
640             continue;
641         }
642 
643         panda_file::ClassDataAccessor cda {*panda_file_, class_id};
644         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
645             if (!mda.IsExternal()) {
646                 std::string func_name = GetStringByStringId(mda.GetNameId());
647                 std::string record_name = "";
648                 std::string name = func_name;
649                 if (IsMergeAbc()) {
650                     record_name = std::string(utf::Mutf8AsCString(cda.GetName().data));
651                     record_name_set_.insert(record_name);
652                     func_name = record_name + func_name;
653                 }
654                 EntityId m_id = mda.GetMethodId();
655                 panda_file::CodeDataAccessor cda {*panda_file_, mda.GetCodeId().value()};
656                 uint32_t arg_count = cda.GetNumArgs();
657                 compiler::Graph *graph = GenerateFunctionGraph(mda, func_name);
658                 if (graph == nullptr) {
659                     return;
660                 }
661                 std::unique_ptr<Function> func =
662                     std::make_unique<Function>(record_name, func_name, m_id, arg_count, Graph(graph), this);
663                 if (func == nullptr) {
664                     LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
665                 }
666                 LOG(DEBUG, DEFECT_SCAN_AUX) << "Create a new function: " << func_name;
667                 if (IsMergeAbc()) {
668                     AddMergedDefinedFunction(std::move(func));
669                 } else {
670                     AddDefinedFunction(std::move(func));
671                 }
672             }
673         });
674     }
675 }
676 
ExtractDefinedClassAndFunctionInfo()677 void AbcFile::ExtractDefinedClassAndFunctionInfo()
678 {
679     if (IsMergeAbc()) {
680         ExtractMergedDefinedClassAndFunctionInfo();
681     } else {
682         ExtractSingleDefinedClassAndFunctionInfo();
683     }
684 }
685 
ExtractMergedDefinedClassAndFunctionInfo()686 void AbcFile::ExtractMergedDefinedClassAndFunctionInfo()
687 {
688     for (auto &merge_def_func_pair : merge_def_func_map_) {
689         for (auto &func : merge_def_func_pair.second) {
690             ExtractMergedClassAndFunctionInfo(func.get());
691         }
692     }
693     std::unordered_set<const Function *> processed_func;
694     for (auto &merge_def_class_pair : merge_def_class_map_) {
695         for (auto &def_class : merge_def_class_pair.second) {
696             Function *def_func = def_class->GetDefiningFunction();
697             if (def_func != nullptr && processed_func.count(def_func) == 0) {
698                 ExtractClassInheritInfo(def_func);
699                 processed_func.insert(def_func);
700             }
701         }
702     }
703     for (auto &merge_def_func_pair : merge_def_func_map_) {
704         for (auto &func : merge_def_func_pair.second) {
705             ExtractFunctionCalleeInfo(func.get());
706         }
707     }
708 }
709 
ExtractSingleDefinedClassAndFunctionInfo()710 void AbcFile::ExtractSingleDefinedClassAndFunctionInfo()
711 {
712     for (auto &func : def_func_list_) {
713         ExtractClassAndFunctionInfo(func.get());
714     }
715 
716     std::unordered_set<const Function *> processed_func;
717     for (auto &def_class : def_class_list_) {
718         Function *def_func = def_class->GetDefiningFunction();
719         if (def_func != nullptr && processed_func.count(def_func) == 0) {
720             ExtractClassInheritInfo(def_func);
721             processed_func.insert(def_func);
722         }
723     }
724 
725     for (auto &func : def_func_list_) {
726         ExtractFunctionCalleeInfo(func.get());
727     }
728 }
729 
ExtractClassAndFunctionInfo(Function * func)730 void AbcFile::ExtractClassAndFunctionInfo(Function *func)
731 {
732     auto &graph = func->GetGraph();
733     graph.VisitAllInstructions([&](const Inst &inst) {
734         auto type = inst.GetType();
735         switch (type) {
736             case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
737             case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
738             case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
739                 auto def_class = ResolveDefineClassWithBufferInst(func, inst);
740                 AddDefinedClass(std::move(def_class));
741                 break;
742             }
743             case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
744             case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
745                 Function *def_func = ResolveDefineFuncInstCommon(func, inst);
746                 BuildFunctionDefineChain(func, def_func);
747                 break;
748             }
749             case InstType::DEFINEMETHOD_IMM8_ID16_IMM8:
750             case InstType::DEFINEMETHOD_IMM16_ID16_IMM8: {
751                 auto member_func = ResolveDefineFuncInstCommon(func, inst);
752                 BuildFunctionDefineChain(func, member_func);
753                 // resolve the class where it's defined
754                 ResolveDefineMethodInst(member_func, inst);
755                 break;
756             }
757             case InstType::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: {
758                 ResolveDefineMethodWithBufferInst(func, inst);
759                 break;
760             }
761             default:
762                 break;
763         }
764     });
765 }
766 
ExtractMergedClassAndFunctionInfo(Function * func)767 void AbcFile::ExtractMergedClassAndFunctionInfo(Function *func)
768 {
769     auto &graph = func->GetGraph();
770     std::string record_name = func->GetRecordName();
771     graph.VisitAllInstructions([&](const Inst &inst) {
772         auto type = inst.GetType();
773         switch (type) {
774             case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
775             case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
776             case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
777                 auto def_class = ResolveDefineClassWithBufferInst(func, inst);
778                 AddMergedDefinedClass(std::move(def_class), record_name);
779                 break;
780             }
781             case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
782             case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
783                 Function *def_func = ResolveDefineFuncInstCommon(func, inst);
784                 BuildFunctionDefineChain(func, def_func);
785                 break;
786             }
787             case InstType::DEFINEMETHOD_IMM8_ID16_IMM8:
788             case InstType::DEFINEMETHOD_IMM16_ID16_IMM8: {
789                 auto member_func = ResolveDefineFuncInstCommon(func, inst);
790                 BuildFunctionDefineChain(func, member_func);
791                 // resolve the class where it's defined
792                 ResolveDefineMethodInst(member_func, inst);
793                 break;
794             }
795             case InstType::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: {
796                 ResolveDefineMethodWithBufferInst(func, inst);
797                 break;
798             }
799             default:
800                 break;
801         }
802     });
803 }
804 
ExtractClassInheritInfo(Function * func) const805 void AbcFile::ExtractClassInheritInfo(Function *func) const
806 {
807     auto &graph = func->GetGraph();
808     std::string record_name = func->GetRecordName();
809     graph.VisitAllInstructions([&](const Inst &inst) {
810         if (inst.GetType() != InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8 &&
811             inst.GetType() != InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8 &&
812             inst.GetType() != InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8) {
813             return;
814         }
815 
816         Class *cur_class = GetClassByNameImpl(record_name + GetStringByInst(inst));
817         ASSERT(cur_class != nullptr);
818         Inst def_class_input1 = inst.GetInputInsts()[0];
819         auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(func, def_class_input1);
820         if (ret_ptr != nullptr && ret_type == ResolveType::CLASS_OBJECT) {
821             auto par_class = reinterpret_cast<const Class *>(ret_ptr);
822             cur_class->SetParentClass(par_class);
823             return;
824         }
825         size_t first_delim_idx = ret_sym.find_first_of(DELIM);
826         size_t last_delim_idx = ret_sym.find_last_of(DELIM);
827         std::string par_class_name = ret_sym;
828         std::string var_name = EMPTY_STR;
829         if (last_delim_idx != std::string::npos) {
830             par_class_name = ret_sym.substr(last_delim_idx + 1);
831             var_name = ret_sym.substr(0, first_delim_idx);
832             cur_class->SetParentClassName(record_name + par_class_name);
833         }
834         std::string record_name = func->GetRecordName();
835         if (ret_type == ResolveType::UNRESOLVED_MODULE) {
836             std::string imp_par_class_name = GetImportNameByLocalName(par_class_name, record_name);
837             if (!imp_par_class_name.empty()) {
838                 cur_class->SetParentClassName(record_name + imp_par_class_name);
839             }
840             std::string inter_name = var_name.empty() ? par_class_name : var_name;
841             std::string module_name = GetModuleNameByLocalName(inter_name, record_name);
842             if (!module_name.empty()) {
843                 cur_class->SetParClassExternalModuleName(module_name);
844             }
845         }
846         if (ret_type == ResolveType::UNRESOLVED_GLOBAL_VAR) {
847             cur_class->SetParentClassName(record_name + par_class_name);
848             var_name = var_name.empty() ? var_name : ret_sym.substr(0, last_delim_idx);
849             cur_class->SetParClassGlobalVarName(var_name);
850         }
851     });
852 }
853 
ExtractFunctionCalleeInfo(Function * func)854 void AbcFile::ExtractFunctionCalleeInfo(Function *func)
855 {
856     auto &graph = func->GetGraph();
857     graph.VisitAllInstructions([&](const Inst &inst) {
858         std::unique_ptr<CalleeInfo> callee_info {nullptr};
859         switch (inst.GetType()) {
860             case InstType::CALLARG0_IMM8: {
861                 callee_info = ResolveCallInstCommon(func, inst);
862                 callee_info->SetCalleeArgCount(0);
863                 break;
864             }
865             case InstType::CALLARG1_IMM8_V8: {
866                 callee_info = ResolveCallInstCommon(func, inst, 1);
867                 callee_info->SetCalleeArgCount(1);
868                 break;
869             }
870             case InstType::CALLARGS2_IMM8_V8_V8: {
871                 constexpr int ARG_COUNT = 2;
872                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT);
873                 callee_info->SetCalleeArgCount(ARG_COUNT);
874                 break;
875             }
876             case InstType::CALLARGS3_IMM8_V8_V8_V8: {
877                 constexpr int ARG_COUNT = 3;
878                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT);
879                 callee_info->SetCalleeArgCount(ARG_COUNT);
880                 break;
881             }
882             case InstType::CALLRANGE_IMM8_IMM8_V8: {
883                 uint32_t arg_count = inst.GetImms()[1];
884                 callee_info = ResolveCallInstCommon(func, inst, arg_count);
885                 callee_info->SetCalleeArgCount(arg_count);
886                 break;
887             }
888             case InstType::WIDE_CALLRANGE_PREF_IMM16_V8: {
889                 uint32_t arg_count = inst.GetImms()[0];
890                 callee_info = ResolveCallInstCommon(func, inst, arg_count);
891                 callee_info->SetCalleeArgCount(arg_count);
892                 break;
893             }
894             case InstType::SUPERCALLSPREAD_IMM8_V8: {
895                 callee_info = ResolveCallInstCommon(func, inst, 1);
896                 break;
897             }
898             case InstType::APPLY_IMM8_V8_V8: {
899                 constexpr uint32_t FUNC_OBJ_INDEX = 2;
900                 callee_info = ResolveCallInstCommon(func, inst, FUNC_OBJ_INDEX);
901                 break;
902             }
903             case InstType::CALLTHIS0_IMM8_V8: {
904                 callee_info = ResolveCallInstCommon(func, inst, 1);
905                 callee_info->SetCalleeArgCount(0);
906                 break;
907             }
908             case InstType::CALLTHIS1_IMM8_V8_V8: {
909                 constexpr int ARG_COUNT = 1;
910                 // 1 represents the this pointer
911                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
912                 callee_info->SetCalleeArgCount(ARG_COUNT);
913                 break;
914             }
915             case InstType::CALLTHIS2_IMM8_V8_V8_V8: {
916                 constexpr int ARG_COUNT = 2;
917                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
918                 callee_info->SetCalleeArgCount(ARG_COUNT);
919                 break;
920             }
921             case InstType::CALLTHIS3_IMM8_V8_V8_V8_V8: {
922                 constexpr int ARG_COUNT = 3;
923                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
924                 callee_info->SetCalleeArgCount(ARG_COUNT);
925                 break;
926             }
927             case InstType::CALLTHISRANGE_IMM8_IMM8_V8: {
928                 uint32_t arg_count = inst.GetImms()[1];
929                 callee_info = ResolveCallInstCommon(func, inst, arg_count + 1);
930                 callee_info->SetCalleeArgCount(arg_count);
931                 break;
932             }
933             case InstType::WIDE_CALLTHISRANGE_PREF_IMM16_V8: {
934                 uint32_t arg_count = inst.GetImms()[0];
935                 callee_info = ResolveCallInstCommon(func, inst, arg_count + 1);
936                 callee_info->SetCalleeArgCount(arg_count);
937                 break;
938             }
939             case InstType::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
940             case InstType::SUPERCALLARROWRANGE_IMM8_IMM8_V8: {
941                 uint32_t arg_count = inst.GetImms()[1];
942                 callee_info = ResolveSuperCallInst(func, inst);
943                 callee_info->SetCalleeArgCount(arg_count);
944                 break;
945             }
946             case InstType::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
947             case InstType::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8: {
948                 uint32_t arg_count = inst.GetImms()[0];
949                 callee_info = ResolveSuperCallInst(func, inst);
950                 callee_info->SetCalleeArgCount(arg_count);
951                 break;
952             }
953             default:
954                 break;
955         }
956         if (callee_info != nullptr) {
957             AddCalleeInfo(std::move(callee_info));
958         }
959     });
960 }
961 
BuildFunctionDefineChain(Function * parent_func,Function * child_func) const962 void AbcFile::BuildFunctionDefineChain(Function *parent_func, Function *child_func) const
963 {
964     if (parent_func == nullptr || child_func == nullptr || child_func->GetParentFunction() == parent_func) {
965         return;
966     }
967     child_func->SetParentFunction(parent_func);
968     parent_func->AddDefinedFunction(child_func);
969 }
970 
BuildClassAndMemberFuncRelation(Class * clazz,Function * member_func) const971 void AbcFile::BuildClassAndMemberFuncRelation(Class *clazz, Function *member_func) const
972 {
973     if (clazz == nullptr || member_func == nullptr || member_func->GetClass() == clazz) {
974         return;
975     }
976     clazz->AddMemberFunction(member_func);
977     member_func->SetClass(clazz);
978 }
979 
ExtractClassAndFunctionExportList()980 void AbcFile::ExtractClassAndFunctionExportList()
981 {
982     if (IsMergeAbc()) {
983         ExtractMergedClassAndFunctionExportList();
984     } else {
985         ExtractSingleClassAndFunctionExportList();
986     }
987 }
988 
ExtractMergedClassAndFunctionExportList()989 void AbcFile::ExtractMergedClassAndFunctionExportList()
990 {
991     if (merge_def_func_map_.empty()) {
992         return;
993     }
994 
995     for (auto &merge_def_func_pair : merge_def_func_map_) {
996         if (merge_def_func_pair.second.empty()) {
997             continue;
998         }
999         const Function *func_main = merge_def_func_pair.second[0].get();
1000         auto &graph = func_main->GetGraph();
1001         graph.VisitAllInstructions([&](const Inst &inst) {
1002             auto type = inst.GetType();
1003             if (type == InstType::STMODULEVAR_IMM8 || type == InstType::WIDE_STMODULEVAR_PREF_IMM16) {
1004                 AddExportListForMerge(func_main, inst);
1005             }
1006         });
1007     }
1008 }
1009 
AddExportListForMerge(const Function * func_main,const Inst & inst)1010 void AbcFile::AddExportListForMerge(const Function *func_main, const Inst &inst)
1011 {
1012     [[maybe_unused]] auto type = inst.GetType();
1013     ASSERT(type == InstType::STMODULEVAR_IMM8 || type == InstType::WIDE_STMODULEVAR_PREF_IMM16);
1014 
1015     std::string record_name = func_main->GetRecordName();
1016     Inst st_module_input0 = inst.GetInputInsts()[0];
1017     switch (st_module_input0.GetType()) {
1018         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
1019         case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
1020             auto export_func = ResolveDefineFuncInstCommon(func_main, st_module_input0);
1021             ASSERT(export_func != nullptr);
1022             if (merge_export_func_map_.find(record_name) == merge_export_func_map_.end()) {
1023                 merge_export_func_map_.emplace(record_name, std::vector<const Function *>());
1024             }
1025             merge_export_func_map_[record_name].push_back(export_func);
1026             break;
1027         }
1028         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
1029         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
1030         case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
1031             Class *export_clazz = GetClassByNameImpl(record_name + GetStringByInst(st_module_input0));
1032             ASSERT(export_clazz != nullptr);
1033             if (merge_export_class_map_.find(record_name) == merge_export_class_map_.end()) {
1034                 merge_export_class_map_.emplace(record_name, std::vector<const Class *>());
1035             }
1036             merge_export_class_map_[record_name].push_back(export_clazz);
1037             break;
1038         }
1039         default:
1040             break;
1041     }
1042 }
1043 
ExtractSingleClassAndFunctionExportList()1044 void AbcFile::ExtractSingleClassAndFunctionExportList()
1045 {
1046     if (!IsModule() || def_func_list_.empty()) {
1047         return;
1048     }
1049     const Function *func_main = def_func_list_[0].get();
1050     ASSERT(func_main->GetFunctionName() == ENTRY_FUNCTION_NAME);
1051     auto &graph = func_main->GetGraph();
1052     std::string record_name = func_main->GetRecordName();
1053     graph.VisitAllInstructions([&](const Inst &inst) {
1054         auto type = inst.GetType();
1055         if (type == InstType::STMODULEVAR_IMM8 || type == InstType::WIDE_STMODULEVAR_PREF_IMM16) {
1056             AddExportListForSingle(func_main, inst);
1057         }
1058     });
1059 }
1060 
AddExportListForSingle(const Function * func_main,const Inst & inst)1061 void AbcFile::AddExportListForSingle(const Function *func_main, const Inst &inst)
1062 {
1063     [[maybe_unused]] auto type = inst.GetType();
1064     ASSERT(type == InstType::STMODULEVAR_IMM8 || type == InstType::WIDE_STMODULEVAR_PREF_IMM16);
1065     Inst st_module_input0 = inst.GetInputInsts()[0];
1066     switch (st_module_input0.GetType()) {
1067         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
1068         case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
1069             auto export_func = ResolveDefineFuncInstCommon(func_main, st_module_input0);
1070             ASSERT(export_func != nullptr);
1071             export_func_list_.push_back(export_func);
1072             break;
1073         }
1074         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
1075         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
1076         case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
1077             Class *export_clazz = GetClassByNameImpl(GetStringByInst(st_module_input0));
1078             ASSERT(export_clazz != nullptr);
1079             export_class_list_.push_back(export_clazz);
1080             break;
1081         }
1082         default:
1083             break;
1084     }
1085 }
1086 
GenerateFunctionGraph(const panda_file::MethodDataAccessor & mda,std::string_view func_name)1087 compiler::Graph *AbcFile::GenerateFunctionGraph(const panda_file::MethodDataAccessor &mda, std::string_view func_name)
1088 {
1089     panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
1090     auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(mda.GetMethodId().GetOffset());
1091     compiler::options.SetCompilerUseSafepoint(false);
1092     compiler::options.SetCompilerMaxBytecodeSize(bytecodeopt::MAX_BYTECODE_SIZE);
1093     compiler::Graph *graph = allocator_->New<compiler::Graph>(allocator_.get(), local_allocator_.get(), Arch::NONE,
1094                                                               method_ptr, &adapter, false, nullptr, true, true);
1095     if ((graph == nullptr) || !graph->RunPass<compiler::IrBuilder>()) {
1096         LOG(FATAL, DEFECT_SCAN_AUX) << "Cannot generate graph for function '" << func_name << "'";
1097     }
1098     return graph;
1099 }
1100 
ResolveInstCommon(Function * func,Inst inst) const1101 ResolveResult AbcFile::ResolveInstCommon(Function *func, Inst inst) const
1102 {
1103     auto type = inst.GetType();
1104     std::string record_name = func->GetRecordName();
1105     switch (type) {
1106         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
1107         case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
1108             std::string func_name = record_name + GetStringByInst(inst);
1109             const Function *func = GetFunctionByName(func_name);
1110             ASSERT(func != nullptr);
1111             return std::make_tuple(func, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
1112         }
1113         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
1114         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
1115         case InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
1116             std::string class_name = record_name + GetStringByInst(inst);
1117             const Class *clazz = GetClassByName(class_name);
1118             ASSERT(clazz != nullptr);
1119             return std::make_tuple(clazz, EMPTY_STR, ResolveType::CLASS_OBJECT);
1120         }
1121         case InstType::NEWOBJAPPLY_IMM8_V8:
1122         case InstType::NEWOBJAPPLY_IMM16_V8:
1123         case InstType::NEWOBJRANGE_IMM8_IMM8_V8:
1124         case InstType::NEWOBJRANGE_IMM16_IMM8_V8:
1125         case InstType::WIDE_NEWOBJRANGE_PREF_IMM16_V8: {
1126             Inst newobj_input0 = inst.GetInputInsts()[0];
1127             auto resolve_res = ResolveInstCommon(func, newobj_input0);
1128             return HandleNewObjInstResolveResultCommon(resolve_res);
1129         }
1130         case InstType::LDOBJBYNAME_IMM8_ID16:
1131         case InstType::LDOBJBYNAME_IMM16_ID16: {
1132             Inst ld_obj_input0 = inst.GetInputInsts()[0];
1133             auto resolve_res = ResolveInstCommon(func, ld_obj_input0);
1134             return HandleLdObjByNameInstResolveResult(inst, resolve_res, record_name);
1135         }
1136         case InstType::LDLEXVAR_IMM4_IMM4:
1137         case InstType::LDLEXVAR_IMM8_IMM8:
1138         case InstType::WIDE_LDLEXVAR_PREF_IMM16_IMM16: {
1139             auto p = GetStLexInstByLdLexInst({func, inst});
1140             if (p == std::nullopt) {
1141                 return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
1142             }
1143             return ResolveInstCommon(p.value().first, p.value().second);
1144         }
1145         case InstType::STLEXVAR_IMM4_IMM4:
1146         case InstType::STLEXVAR_IMM8_IMM8:
1147         case InstType::WIDE_STLEXVAR_PREF_IMM16_IMM16: {
1148             Inst stlex_input0 = inst.GetInputInsts()[0];
1149             return ResolveInstCommon(func, stlex_input0);
1150         }
1151         case InstType::LDLOCALMODULEVAR_IMM8:
1152         case InstType::WIDE_LDLOCALMODULEVAR_PREF_IMM16: {
1153             size_t index = inst.GetImms()[0];
1154             auto module_record = GetModuleRecordByName(record_name);
1155             const std::string &export_name = module_record->GetExportNameByIndex(index);
1156             const Function *func = GetExportFunctionByExportName(export_name, record_name);
1157             if (func != nullptr) {
1158                 return std::make_tuple(func, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
1159             }
1160             const Class *clazz = GetExportClassByExportName(export_name, record_name);
1161             if (clazz != nullptr) {
1162                 return std::make_tuple(clazz, EMPTY_STR, ResolveType::CLASS_OBJECT);
1163             }
1164             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
1165         }
1166         case InstType::LDEXTERNALMODULEVAR_IMM8:
1167         case InstType::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: {
1168             size_t index = inst.GetImms()[0];
1169             auto module_record = GetModuleRecordByName(func->GetRecordName());
1170             const std::string &inter_name = module_record->GetImportLocalNameByIndex(index);
1171             return std::make_tuple(nullptr, inter_name, ResolveType::UNRESOLVED_MODULE);
1172         }
1173         case InstType::GETMODULENAMESPACE_IMM8:
1174         case InstType::WIDE_GETMODULENAMESPACE_PREF_IMM16: {
1175             size_t index = inst.GetImms()[0];
1176             auto module_record = GetModuleRecordByName(func->GetRecordName());
1177             const std::string &str = module_record->GetImportNamespaceNameByIndex(index);
1178             return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_MODULE);
1179         }
1180         case InstType::LDGLOBAL: {
1181             // TODO(wangyantian): load a specific global variable, namely 'globalThis'
1182             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
1183         }
1184         case InstType::LDGLOBALVAR_IMM16_ID16:
1185         case InstType::TRYLDGLOBALBYNAME_IMM8_ID16:
1186         case InstType::TRYLDGLOBALBYNAME_IMM16_ID16: {
1187             std::string str = GetStringByInst(inst);
1188             auto p = GetStGlobalInstByLdGlobalInst({func, inst});
1189             if (p == std::nullopt) {
1190                 return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_GLOBAL_VAR);
1191             }
1192             auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(p.value().first, p.value().second);
1193             if (ret_ptr != nullptr) {
1194                 return std::make_tuple(ret_ptr, str, ret_type);
1195             }
1196             return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_GLOBAL_VAR);
1197         }
1198         case InstType::TRYSTGLOBALBYNAME_IMM8_ID16:
1199         case InstType::TRYSTGLOBALBYNAME_IMM16_ID16:
1200         case InstType::STGLOBALVAR_IMM16_ID16:
1201         case InstType::STCONSTTOGLOBALRECORD_IMM16_ID16:
1202         case InstType::STTOGLOBALRECORD_IMM16_ID16: {
1203             Inst stglobal_input0 = inst.GetInputInsts()[0];
1204             return ResolveInstCommon(func, stglobal_input0);
1205         }
1206         case InstType::OPCODE_PHI: {
1207             // TODO: only the next unvisited path is considered for now, what about other paths?
1208             // TODO: when all inputs of the phi instruction contain a path to the phi instruction itself,
1209             //  the current solution still causes infinite recursion and stack overflow. However, this case
1210             //  should not occur in real-world applications. However, the following part needs to be redesigned
1211             //  when encountering such scenarios.
1212             auto phi_input_idx = func->GetAndUpdateToVisitInputForInst(inst);
1213             return ResolveInstCommon(func, inst.GetInputInsts()[phi_input_idx]);
1214         }
1215         // don't deal with the situation that func obj comes from parameter or the output of another call inst
1216         default: {
1217             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
1218         }
1219     }
1220 }
1221 
HandleLdObjByNameInstResolveResult(const Inst & ldobjbyname_inst,const ResolveResult & resolve_res,const std::string record_name) const1222 ResolveResult AbcFile::HandleLdObjByNameInstResolveResult(const Inst &ldobjbyname_inst,
1223                                                           const ResolveResult &resolve_res,
1224                                                           const std::string record_name) const
1225 {
1226     auto &[ret_ptr, ret_sym, ret_type] = resolve_res;
1227     std::string name = GetStringByInst(ldobjbyname_inst);
1228     switch (ret_type) {
1229         case ResolveType::UNRESOLVED_MODULE:
1230         case ResolveType::UNRESOLVED_GLOBAL_VAR: {
1231             return std::make_tuple(nullptr, ret_sym + "." + name, ret_type);
1232         }
1233         case ResolveType::FUNCTION_OBJECT: {
1234             ASSERT(ret_ptr != nullptr);
1235             if (name == CALL || name == APPLY) {
1236                 return std::make_tuple(ret_ptr, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
1237             }
1238             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
1239         }
1240         case ResolveType::CLASS_OBJECT:
1241         case ResolveType::CLASS_INSTANCE: {
1242             ASSERT(ret_ptr != nullptr);
1243             // TODO(wangyantian): distinguish static func from member func in a class
1244             const void *member_func =
1245                 reinterpret_cast<const Class *>(ret_ptr)->GetMemberFunctionByName(record_name + name);
1246             if (member_func != nullptr) {
1247                 return std::make_tuple(member_func, name, ResolveType::FUNCTION_OBJECT);
1248             }
1249             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
1250         }
1251         default: {
1252             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
1253         }
1254     }
1255 }
1256 
HandleNewObjInstResolveResultCommon(const ResolveResult & resolve_res) const1257 ResolveResult AbcFile::HandleNewObjInstResolveResultCommon(const ResolveResult &resolve_res) const
1258 {
1259     auto &[ret_ptr, ret_sym, ret_type] = resolve_res;
1260     switch (ret_type) {
1261         case ResolveType::CLASS_OBJECT: {
1262             ASSERT(ret_ptr != nullptr);
1263             return std::make_tuple(ret_ptr, EMPTY_STR, ResolveType::CLASS_INSTANCE);
1264         }
1265         case ResolveType::UNRESOLVED_GLOBAL_VAR:
1266         case ResolveType::UNRESOLVED_MODULE: {
1267             return std::make_tuple(nullptr, ret_sym, ret_type);
1268         }
1269         default: {
1270             return std::make_tuple(nullptr, ret_sym, ResolveType::UNRESOLVED_OTHER);
1271         }
1272     }
1273 }
1274 
ResolveDefineFuncInstCommon(const Function * func,const Inst & def_func_inst) const1275 Function *AbcFile::ResolveDefineFuncInstCommon(const Function *func, const Inst &def_func_inst) const
1276 {
1277     std::string record_name = func->GetRecordName();
1278     std::string def_func_name = record_name + GetStringByInst(def_func_inst);
1279     Function *def_func = GetFunctionByNameImpl(def_func_name);
1280     ASSERT(def_func != nullptr);
1281     return def_func;
1282 }
1283 
ResolveDefineClassWithBufferInst(Function * func,const Inst & define_class_inst) const1284 std::unique_ptr<Class> AbcFile::ResolveDefineClassWithBufferInst(Function *func, const Inst &define_class_inst) const
1285 {
1286     auto imms = define_class_inst.GetImms();
1287     auto m_id = EntityId(imms[1]);
1288     std::string record_name = func->GetRecordName();
1289     std::string class_name = record_name + GetStringByMethodId(m_id);
1290     std::unique_ptr<Class> def_class = std::make_unique<Class>(class_name, record_name, this, func);
1291     if (def_class == nullptr) {
1292         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
1293     }
1294     LOG(DEBUG, DEFECT_SCAN_AUX) << "Create a new class: " << class_name;
1295     func->AddDefinedClass(def_class.get());
1296 
1297     // handle ctor of the class
1298     std::string ctor_name = record_name + GetStringByInst(define_class_inst);
1299     HandleMemberFunctionFromClassBuf(ctor_name, func, def_class.get());
1300 
1301     auto literal_array_id = EntityId(imms[2]);
1302     panda_file::LiteralDataAccessor lit_array_accessor(*panda_file_, panda_file_->GetLiteralArraysId());
1303     lit_array_accessor.EnumerateLiteralVals(
1304         literal_array_id, [&](const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
1305             if (tag == LiteralTag::METHOD || tag == panda_file::LiteralTag::GETTER ||
1306                 tag == panda_file::LiteralTag::SETTER || tag == LiteralTag::GENERATORMETHOD ||
1307                 tag == LiteralTag::ASYNCGENERATORMETHOD) {
1308                 auto method_id = EntityId(std::get<uint32_t>(value));
1309                 std::string member_func_name = record_name + GetStringByMethodId(method_id);
1310                 HandleMemberFunctionFromClassBuf(member_func_name, func, def_class.get());
1311             }
1312         });
1313 
1314     return def_class;
1315 }
1316 
ResolveDefineMethodWithBufferInst(Function * func,const Inst & define_class_inst) const1317 void AbcFile::ResolveDefineMethodWithBufferInst(Function *func, const Inst &define_class_inst) const
1318 {
1319     auto imms = define_class_inst.GetImms();
1320     auto literal_array_id = EntityId(imms[1]);
1321     std::string record_name = func->GetRecordName();
1322 
1323     panda_file::LiteralDataAccessor lit_array_accessor(*panda_file_, panda_file_->GetLiteralArraysId());
1324     lit_array_accessor.EnumerateLiteralVals(
1325         literal_array_id, [&](const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
1326             if (tag == LiteralTag::METHOD || tag == panda_file::LiteralTag::GETTER ||
1327                 tag == panda_file::LiteralTag::SETTER || tag == LiteralTag::GENERATORMETHOD ||
1328                 tag == LiteralTag::ASYNCGENERATORMETHOD) {
1329                 auto method_id = EntityId(std::get<uint32_t>(value));
1330                 std::string member_func_name = record_name + GetStringByMethodId(method_id);
1331                 Class *def_class = GetClassFromMemberFunctionName(member_func_name);
1332                 if (def_class == nullptr) {
1333                     LOG(ERROR, DEFECT_SCAN_AUX) << "Unable to find class for private property '" <<
1334                                                    member_func_name << "'";
1335                     return;
1336                 }
1337                 HandleMemberFunctionFromClassBuf(member_func_name, func, def_class);
1338             }
1339         });
1340 }
1341 
GetClassFromMemberFunctionName(const std::string & member_func_name) const1342 Class *AbcFile::GetClassFromMemberFunctionName(const std::string &member_func_name) const
1343 {
1344     // The character > indicates the instance function scope of a class
1345     // The character < indicates the static function scope of a class
1346     size_t pos = member_func_name.find_first_of("><");
1347     if (pos == std::string::npos) {
1348         return nullptr;
1349     }
1350     std::string processed_name = member_func_name.substr(0, pos);
1351     // Concatenate constructor prefixes
1352     // The character = represents the constructor scope of a class
1353     processed_name += '=';
1354 
1355     std::vector<std::shared_ptr<Class>> class_list = GetClassList();
1356     for (const auto &cls : class_list) {
1357         const std::string &class_name = cls->GetClassName();
1358         if (class_name.find(processed_name) == 0) {
1359             return cls.get();
1360         }
1361     }
1362 
1363     return nullptr;
1364 }
1365 
ResolveCallInstCommon(Function * func,const Inst & call_inst,uint32_t func_obj_idx) const1366 std::unique_ptr<CalleeInfo> AbcFile::ResolveCallInstCommon(Function *func, const Inst &call_inst,
1367                                                            uint32_t func_obj_idx) const
1368 {
1369     std::unique_ptr<CalleeInfo> callee_info = std::make_unique<CalleeInfo>(call_inst, func);
1370     if (callee_info == nullptr) {
1371         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
1372     }
1373 
1374     Inst call_input0 = call_inst.GetInputInsts()[func_obj_idx];
1375     auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(func, call_input0);
1376     std::string record_name = func->GetRecordName();
1377     if (ret_ptr != nullptr && ret_type == ResolveType::FUNCTION_OBJECT) {
1378         auto callee = reinterpret_cast<const Function *>(ret_ptr);
1379         callee_info->SetCallee(callee);
1380     } else {
1381         size_t first_delim_idx = ret_sym.find_first_of(DELIM);
1382         size_t last_delim_idx = ret_sym.find_last_of(DELIM);
1383         std::string callee_name = ret_sym;
1384         std::string var_name = EMPTY_STR;
1385         if (first_delim_idx != std::string::npos) {
1386             callee_name = ret_sym.substr(last_delim_idx + 1);
1387             var_name = ret_sym.substr(0, first_delim_idx);
1388             callee_info->SetFunctionName(record_name + callee_name);
1389         }
1390         if (ret_type == ResolveType::UNRESOLVED_MODULE) {
1391             std::string imp_callee_name = GetImportNameByLocalName(callee_name, record_name);
1392             if (!imp_callee_name.empty()) {
1393                 callee_info->SetFunctionName(record_name + imp_callee_name);
1394             }
1395             std::string inter_name = var_name.empty() ? callee_name : var_name;
1396             std::string module_name = GetModuleNameByLocalName(inter_name, record_name);
1397             if (!module_name.empty()) {
1398                 callee_info->SetExternalModuleName(module_name);
1399             }
1400         } else if (ret_type == ResolveType::UNRESOLVED_GLOBAL_VAR) {
1401             callee_info->SetFunctionName(record_name + callee_name);
1402             var_name = var_name.empty() ? var_name : ret_sym.substr(0, last_delim_idx);
1403             callee_info->SetGlobalVarName(var_name);
1404         }
1405     }
1406     func->AddCalleeInfo(callee_info.get());
1407     return callee_info;
1408 }
1409 
ResolveSuperCallInst(Function * func,const Inst & call_inst) const1410 std::unique_ptr<CalleeInfo> AbcFile::ResolveSuperCallInst(Function *func, const Inst &call_inst) const
1411 {
1412     std::unique_ptr<CalleeInfo> callee_info = std::make_unique<CalleeInfo>(call_inst, func);
1413     if (callee_info == nullptr) {
1414         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
1415     }
1416     const Class *clazz = func->GetClass();
1417     if (clazz != nullptr && clazz->GetParentClass() != nullptr) {
1418         const std::string &parent_ctor_name = clazz->GetParentClass()->GetClassName();
1419         const Function *parent_ctor = GetFunctionByName(parent_ctor_name);
1420         ASSERT(parent_ctor != nullptr);
1421         callee_info->SetCallee(parent_ctor);
1422     }
1423     // TODO(wangyantian): deal with situations when above if doesn't hold
1424     func->AddCalleeInfo(callee_info.get());
1425     return callee_info;
1426 }
1427 
ResolveDefineMethodInst(Function * member_func,const Inst & define_method_inst)1428 void AbcFile::ResolveDefineMethodInst(Function *member_func, const Inst &define_method_inst)
1429 {
1430     std::string record_name = member_func->GetRecordName();
1431     Inst def_method_input0 = define_method_inst.GetInputInsts()[0];
1432     if ((def_method_input0.GetType() == InstType::LDOBJBYNAME_IMM8_ID16 ||
1433          def_method_input0.GetType() == InstType::LDOBJBYNAME_IMM16_ID16) &&
1434         GetStringByInst(def_method_input0) == PROTOTYPE) {
1435         Inst ld_obj_input0 = def_method_input0.GetInputInsts()[0];
1436         if (ld_obj_input0.GetType() == InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8 ||
1437             ld_obj_input0.GetType() == InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8 ||
1438             ld_obj_input0.GetType() == InstType::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8) {
1439             auto clazz = GetClassByNameImpl(record_name + GetStringByInst(ld_obj_input0));
1440             if (clazz != nullptr) {
1441                 BuildClassAndMemberFuncRelation(clazz, member_func);
1442             }
1443         }
1444     }
1445 }
1446 
HandleMemberFunctionFromClassBuf(const std::string & func_name,Function * def_func,Class * def_class) const1447 void AbcFile::HandleMemberFunctionFromClassBuf(const std::string &func_name, Function *def_func, Class *def_class) const
1448 {
1449     Function *member_func = GetFunctionByNameImpl(func_name);
1450     ASSERT(member_func != nullptr);
1451     BuildFunctionDefineChain(def_func, member_func);
1452     BuildClassAndMemberFuncRelation(def_class, member_func);
1453 }
1454 
AddDefinedClass(std::shared_ptr<Class> && def_class)1455 void AbcFile::AddDefinedClass(std::shared_ptr<Class> &&def_class)
1456 {
1457     auto &class_name = def_class->GetClassName();
1458     ASSERT(def_class_map_.find(class_name) == def_class_map_.end());
1459     def_class_map_[class_name] = def_class.get();
1460     def_class_list_.emplace_back(std::move(def_class));
1461 }
1462 
AddMergedDefinedClass(std::shared_ptr<Class> && def_class,std::string record_name)1463 void AbcFile::AddMergedDefinedClass(std::shared_ptr<Class> &&def_class, std::string record_name)
1464 {
1465     auto &class_name = def_class->GetClassName();
1466     ASSERT(def_class_map_.find(class_name) == def_class_map_.end());
1467     def_class_map_[class_name] = def_class.get();
1468     if (merge_def_class_map_.find(record_name) == merge_def_class_map_.end()) {
1469         merge_def_class_map_.emplace(record_name, std::vector<std::shared_ptr<Class>>());
1470     }
1471     merge_def_class_map_[record_name].push_back(def_class);
1472     merged_def_class_list_.push_back(def_class);
1473 }
1474 
AddDefinedFunction(std::shared_ptr<Function> && def_func)1475 void AbcFile::AddDefinedFunction(std::shared_ptr<Function> &&def_func)
1476 {
1477     const std::string &func_name = def_func->GetFunctionName();
1478     ASSERT(def_func_map_.find(func_name) == def_func_map_.end());
1479     def_func_map_[func_name] = def_func.get();
1480     if (func_name != ENTRY_FUNCTION_NAME) {
1481         def_func_list_.emplace_back(std::move(def_func));
1482     } else {
1483         def_func_list_.insert(def_func_list_.begin(), std::move(def_func));
1484     }
1485 }
1486 
AddMergedDefinedFunction(std::shared_ptr<Function> && def_func)1487 void AbcFile::AddMergedDefinedFunction(std::shared_ptr<Function> &&def_func)
1488 {
1489     const std::string &record_name = def_func->GetRecordName();
1490     const std::string &func_name = def_func->GetFunctionName();
1491     ASSERT(def_func_map_.find(func_name) == def_func_map_.end());
1492     def_func_map_[func_name] = def_func.get();
1493     merged_def_func_list_.push_back(def_func);
1494     if (merge_def_func_map_.find(record_name) == merge_def_func_map_.end()) {
1495         merge_def_func_map_.emplace(record_name, std::vector<std::shared_ptr<Function>>());
1496     }
1497 
1498     if (func_name.find(ENTRY_FUNCTION_NAME) == std::string::npos) {
1499         merge_def_func_map_[record_name].push_back(def_func);
1500     } else {
1501         merge_def_func_map_[record_name].insert(merge_def_func_map_[record_name].begin(), def_func);
1502     }
1503 }
1504 
AddCalleeInfo(std::unique_ptr<CalleeInfo> && callee_info)1505 void AbcFile::AddCalleeInfo(std::unique_ptr<CalleeInfo> &&callee_info)
1506 {
1507     callee_info_list_.emplace_back(std::move(callee_info));
1508 }
1509 
GetFunctionByNameImpl(std::string_view func_name) const1510 Function *AbcFile::GetFunctionByNameImpl(std::string_view func_name) const
1511 {
1512     auto iter = def_func_map_.find(std::string(func_name));
1513     if (iter != def_func_map_.end()) {
1514         return iter->second;
1515     }
1516     return nullptr;
1517 }
1518 
GetModuleRecordByName(std::string record_name) const1519 const ModuleRecord *AbcFile::GetModuleRecordByName(std::string record_name) const
1520 {
1521     if (!IsMergeAbc()) {
1522         record_name = std::string(MODULE_CLASS);
1523     }
1524 
1525     auto iter = module_record_map_.find(record_name);
1526     if (iter != module_record_map_.end()) {
1527         return iter->second;
1528     }
1529     return nullptr;
1530 }
1531 
GetClassByNameImpl(std::string_view class_name) const1532 Class *AbcFile::GetClassByNameImpl(std::string_view class_name) const
1533 {
1534     auto iter = def_class_map_.find(std::string(class_name));
1535     if (iter != def_class_map_.end()) {
1536         return iter->second;
1537     }
1538     return nullptr;
1539 }
1540 
GetStringByMethodId(EntityId method_id) const1541 std::string AbcFile::GetStringByMethodId(EntityId method_id) const
1542 {
1543     panda_file::MethodDataAccessor mda {*panda_file_, method_id};
1544     return GetStringByStringId(mda.GetNameId());
1545 }
1546 
GetStringByStringId(EntityId string_id) const1547 std::string AbcFile::GetStringByStringId(EntityId string_id) const
1548 {
1549     StringData sd = panda_file_->GetStringData(string_id);
1550     // TODO(wangyantian): what if sd.is_ascii equals false?
1551     return std::string(utf::Mutf8AsCString(sd.data));
1552 }
1553 }  // namespace panda::defect_scan_aux
1554