• 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/runtime_adapter.h"
26 #include "callee_info.h"
27 #include "class.h"
28 #include "function.h"
29 #include "module_record.h"
30 
31 namespace panda::defect_scan_aux {
32 using EntityId = panda_file::File::EntityId;
33 using StringData = panda_file::StringData;
34 using LiteralTag = panda_file::LiteralTag;
35 using ModuleDataAccessor = panda_file::ModuleDataAccessor;
36 using ModuleTag = panda_file::ModuleTag;
37 
AbcFile(std::string_view filename,std::unique_ptr<const panda_file::File> && panda_file)38 AbcFile::AbcFile(std::string_view filename, std::unique_ptr<const panda_file::File> &&panda_file)
39     : filename_(filename), panda_file_(std::forward<std::unique_ptr<const panda_file::File>>(panda_file))
40 {
41     PoolManager::Initialize(PoolType::MALLOC);
42     allocator_ = std::make_unique<ArenaAllocator>(SpaceType::SPACE_TYPE_COMPILER);
43     local_allocator_ = std::make_unique<ArenaAllocator>(SpaceType::SPACE_TYPE_COMPILER, nullptr, true);
44 }
45 
~AbcFile()46 AbcFile::~AbcFile()
47 {
48     PoolManager::Finalize();
49 }
50 
Open(std::string_view abc_filename)51 std::unique_ptr<const AbcFile> AbcFile::Open(std::string_view abc_filename)
52 {
53     auto panda_file = panda_file::OpenPandaFile(abc_filename);
54     if (panda_file == nullptr) {
55         LOG(ERROR, DEFECT_SCAN_AUX) << "Can not open binary file '" << abc_filename << "'";
56         return nullptr;
57     }
58 
59     std::unique_ptr<AbcFile> abc_file(new (std::nothrow) AbcFile(abc_filename, std::move(panda_file)));
60     if (abc_file == nullptr) {
61         LOG(ERROR, DEFECT_SCAN_AUX) << "Can not create AbcFile instance for '" << abc_filename << "'";
62         return nullptr;
63     }
64 
65     abc_file->ExtractDebugInfo();
66     abc_file->ExtractModuleInfo();
67     abc_file->InitializeAllDefinedFunction();
68     abc_file->ExtractDefinedClassAndFunctionInfo();
69     abc_file->ExtractClassAndFunctionExportList();
70     return abc_file;
71 }
72 
IsModule() const73 bool AbcFile::IsModule() const
74 {
75     return module_record_ != nullptr;
76 }
77 
GetAbcFileName() const78 const std::string &AbcFile::GetAbcFileName() const
79 {
80     return filename_;
81 }
82 
GetDefinedFunctionCount() const83 size_t AbcFile::GetDefinedFunctionCount() const
84 {
85     return def_func_list_.size();
86 }
87 
GetDefinedClassCount() const88 size_t AbcFile::GetDefinedClassCount() const
89 {
90     return def_class_list_.size();
91 }
92 
GetDefinedFunctionByIndex(size_t index) const93 const Function *AbcFile::GetDefinedFunctionByIndex(size_t index) const
94 {
95     ASSERT(index < def_func_list_.size());
96     return def_func_list_[index].get();
97 }
98 
GetFunctionByName(std::string_view func_name) const99 const Function *AbcFile::GetFunctionByName(std::string_view func_name) const
100 {
101     return GetFunctionByNameImpl(func_name);
102 }
103 
GetExportFunctionByExportName(std::string_view export_func_name) const104 const Function *AbcFile::GetExportFunctionByExportName(std::string_view export_func_name) const
105 {
106     if (!IsModule()) {
107         return nullptr;
108     }
109 
110     std::string inter_func_name = GetInternalNameByExportName(export_func_name);
111     for (auto export_func : export_func_list_) {
112         const std::string &ex_func_name = export_func->GetFunctionName();
113         std::string_view no_hashtag_name = GetNameWithoutHashtag(ex_func_name);
114         if (no_hashtag_name == inter_func_name) {
115             return export_func;
116         }
117     }
118     return nullptr;
119 }
120 
GetDefinedClassByIndex(size_t index) const121 const Class *AbcFile::GetDefinedClassByIndex(size_t index) const
122 {
123     ASSERT(index < def_class_list_.size());
124     return def_class_list_[index].get();
125 }
126 
GetClassByName(std::string_view class_name) const127 const Class *AbcFile::GetClassByName(std::string_view class_name) const
128 {
129     return GetClassByNameImpl(class_name);
130 }
131 
GetExportClassByExportName(std::string_view export_class_name) const132 const Class *AbcFile::GetExportClassByExportName(std::string_view export_class_name) const
133 {
134     if (!IsModule()) {
135         return nullptr;
136     }
137 
138     std::string inter_class_name = GetInternalNameByExportName(export_class_name);
139     for (auto export_class : export_class_list_) {
140         const std::string &ex_class_name = export_class->GetClassName();
141         std::string_view no_hashtag_name = GetNameWithoutHashtag(ex_class_name);
142         if (no_hashtag_name == inter_class_name) {
143             return export_class;
144         }
145     }
146     return nullptr;
147 }
148 
GetLineNumberByInst(const Function * func,const Inst & inst) const149 ssize_t AbcFile::GetLineNumberByInst(const Function *func, const Inst &inst) const
150 {
151     auto &line_number_table = debug_info_->GetLineNumberTable(func->GetMethodId());
152     if (!line_number_table.empty()) {
153         uint32_t inst_pc = inst.GetPc();
154         // line_number_table is in ascending order, find the element that satisfies e1.pc <= inst_pc < e2.pc
155         auto comp = [](size_t value, const panda_file::LineTableEntry &entry) { return value >= entry.offset; };
156         auto iter = std::upper_bound(line_number_table.rbegin(), line_number_table.rend(), inst_pc, comp);
157         if (iter != line_number_table.rend()) {
158             // line number written in a .abc file starts from 0
159             return iter->line + 1;
160         }
161     }
162     return -1;
163 }
164 
GetInternalNameByExportName(std::string_view export_name) const165 std::string AbcFile::GetInternalNameByExportName(std::string_view export_name) const
166 {
167     if (!IsModule()) {
168         return EMPTY_STR;
169     }
170     return module_record_->GetInternalNameByExportName(export_name);
171 }
172 
GetImportNameByExportName(std::string_view export_name) const173 std::string AbcFile::GetImportNameByExportName(std::string_view export_name) const
174 {
175     if (!IsModule()) {
176         return EMPTY_STR;
177     }
178     return module_record_->GetImportNameByExportName(export_name);
179 }
180 
GetModuleNameByExportName(std::string_view export_name) const181 std::string AbcFile::GetModuleNameByExportName(std::string_view export_name) const
182 {
183     if (!IsModule()) {
184         return EMPTY_STR;
185     }
186     return module_record_->GetModuleNameByExportName(export_name);
187 }
188 
GetModuleNameByInternalName(std::string_view local_name) const189 std::string AbcFile::GetModuleNameByInternalName(std::string_view local_name) const
190 {
191     if (!IsModule()) {
192         return EMPTY_STR;
193     }
194     return module_record_->GetModuleNameByInternalName(local_name);
195 }
196 
GetImportNameByInternalName(std::string_view local_name) const197 std::string AbcFile::GetImportNameByInternalName(std::string_view local_name) const
198 {
199     if (!IsModule()) {
200         return EMPTY_STR;
201     }
202     return module_record_->GetImportNameByInternalName(local_name);
203 }
204 
GetNameWithoutHashtag(std::string_view name) const205 std::string_view AbcFile::GetNameWithoutHashtag(std::string_view name) const
206 {
207     if (name[0] == '#') {
208         size_t sec_hashtag_idx = name.find_first_of('#', 1);
209         if (sec_hashtag_idx != std::string::npos && (sec_hashtag_idx + 1) <= name.size()) {
210             return name.substr(sec_hashtag_idx + 1);
211         }
212     }
213     return name;
214 }
215 
GetStringByInst(const Inst & inst) const216 std::string AbcFile::GetStringByInst(const Inst &inst) const
217 {
218     auto type = inst.GetType();
219     switch (type) {
220         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
221         case InstType::DEFINEFUNC_IMM16_ID16_IMM8:
222         case InstType::DEFINEMETHOD_IMM8_ID16_IMM8:
223         case InstType::DEFINEMETHOD_IMM16_ID16_IMM8:
224         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
225         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
226             uint32_t method_id = inst.GetImms()[1];
227             return GetStringByMethodId(EntityId(method_id));
228         }
229         case InstType::TRYLDGLOBALBYNAME_IMM8_ID16:
230         case InstType::TRYSTGLOBALBYNAME_IMM8_ID16:
231         case InstType::TRYLDGLOBALBYNAME_IMM16_ID16:
232         case InstType::TRYSTGLOBALBYNAME_IMM16_ID16:
233         case InstType::STCONSTTOGLOBALRECORD_IMM16_ID16:
234         case InstType::STTOGLOBALRECORD_IMM16_ID16:
235         case InstType::LDGLOBALVAR_IMM16_ID16:
236         case InstType::STGLOBALVAR_IMM16_ID16:
237         case InstType::LDOBJBYNAME_IMM8_ID16:
238         case InstType::LDOBJBYNAME_IMM16_ID16:
239         case InstType::STOBJBYNAME_IMM8_ID16_V8:
240         case InstType::STOBJBYNAME_IMM16_ID16_V8:
241         case InstType::LDSUPERBYNAME_IMM8_ID16:
242         case InstType::LDSUPERBYNAME_IMM16_ID16:
243         case InstType::STSUPERBYNAME_IMM8_ID16_V8:
244         case InstType::STSUPERBYNAME_IMM16_ID16_V8:
245         case InstType::LDTHISBYNAME_IMM8_ID16:
246         case InstType::LDTHISBYNAME_IMM16_ID16:
247         case InstType::STTHISBYNAME_IMM8_ID16:
248         case InstType::STTHISBYNAME_IMM16_ID16:
249         case InstType::STOWNBYNAME_IMM8_ID16_V8:
250         case InstType::STOWNBYNAME_IMM16_ID16_V8:
251         case InstType::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
252         case InstType::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8: {
253             uint32_t string_id = inst.GetImms()[1];
254             return GetStringByStringId(EntityId(string_id));
255         }
256         default:
257             return EMPTY_STR;
258     }
259 }
260 
261 // TODO(wangyantian): may match multiple stlex inst when considering control flow
GetStLexInstByLdLexInst(FuncInstPair func_inst_pair) const262 std::optional<FuncInstPair> AbcFile::GetStLexInstByLdLexInst(FuncInstPair func_inst_pair) const
263 {
264     const Function *func = func_inst_pair.first;
265     const Inst &ld_lex_inst = func_inst_pair.second;
266     if (func == nullptr || !ld_lex_inst.IsInstLdLexVar()) {
267         return std::nullopt;
268     }
269 
270     auto ld_imms = ld_lex_inst.GetImms();
271     uint32_t ld_level = ld_imms[0];
272     uint32_t ld_slot_id = ld_imms[1];
273     const Function *cur_func = func;
274     uint32_t i = 0;
275     while (true) {
276         bool has_new_lexenv = false;
277         const auto &graph = cur_func->GetGraph();
278         graph.VisitAllInstructions([&has_new_lexenv](const Inst &inst) {
279             if (inst.GetType() == InstType::NEWLEXENV_IMM8 || inst.GetType() == InstType::WIDE_NEWLEXENV_PREF_IMM16) {
280                 has_new_lexenv = true;
281             }
282         });
283         if (has_new_lexenv) {
284             i++;
285         }
286         if (i == ld_level + 1) {
287             break;
288         }
289         cur_func = cur_func->GetParentFunction();
290         if (cur_func == nullptr) {
291             return std::nullopt;
292         }
293     }
294     auto &graph = cur_func->GetGraph();
295     Inst st_lex_inst = ld_lex_inst;
296     graph.VisitAllInstructions([ld_slot_id, &st_lex_inst](const Inst &inst) {
297         if (inst.IsInstStLexVar()) {
298             auto st_imms = inst.GetImms();
299             uint32_t st_level = st_imms[0];
300             uint32_t st_slot_id = st_imms[1];
301             if (st_level == 0 && st_slot_id == ld_slot_id) {
302                 st_lex_inst = inst;
303             }
304         }
305     });
306     if (st_lex_inst != ld_lex_inst) {
307         return FuncInstPair(cur_func, st_lex_inst);
308     }
309 
310     return std::nullopt;
311 }
312 
GetStGlobalInstByLdGlobalInst(FuncInstPair func_inst_pair) const313 std::optional<FuncInstPair> AbcFile::GetStGlobalInstByLdGlobalInst(FuncInstPair func_inst_pair) const
314 {
315     const Function *func = func_inst_pair.first;
316     const Inst &ld_global_inst = func_inst_pair.second;
317     if (func == nullptr || !ld_global_inst.IsInstLdGlobal()) {
318         return std::nullopt;
319     }
320 
321     uint32_t ld_str_id = ld_global_inst.GetImms()[0];
322     // TODO(wangyantian): only consider that func_main_0 has StGlobal inst for now, what about other cases?
323     const Function *func_main = def_func_list_[0].get();
324     auto &graph = func_main->GetGraph();
325     Inst st_global_inst = ld_global_inst;
326     graph.VisitAllInstructions([ld_str_id, &st_global_inst](const Inst &inst) {
327         if (inst.IsInstStGlobal()) {
328             uint32_t st_str_id = inst.GetImms()[0];
329             if (st_str_id == ld_str_id) {
330                 st_global_inst = inst;
331             }
332         }
333     });
334     if (st_global_inst != ld_global_inst) {
335         return FuncInstPair(func_main, st_global_inst);
336     }
337 
338     return std::nullopt;
339 }
340 
ExtractDebugInfo()341 void AbcFile::ExtractDebugInfo()
342 {
343     debug_info_ = std::make_unique<const panda_file::DebugInfoExtractor>(panda_file_.get());
344     if (debug_info_ == nullptr) {
345         LOG(FATAL, DEFECT_SCAN_AUX) << "Failed to extract debug info";
346     }
347 }
348 
ExtractModuleInfo()349 void AbcFile::ExtractModuleInfo()
350 {
351     int module_offset = -1;
352     for (uint32_t id : panda_file_->GetClasses()) {
353         EntityId class_id(id);
354         if (panda_file_->IsExternal(class_id)) {
355             continue;
356         }
357         panda_file::ClassDataAccessor cda(*panda_file_, class_id);
358         const char *desc = utf::Mutf8AsCString(cda.GetDescriptor());
359         if (std::strcmp(MODULE_CLASS, desc) == 0) {
360             cda.EnumerateFields([&](panda_file::FieldDataAccessor &field_accessor) -> void {
361                 EntityId field_name_id = field_accessor.GetNameId();
362                 StringData sd = panda_file_->GetStringData(field_name_id);
363                 if (std::strcmp(utf::Mutf8AsCString(sd.data), filename_.data())) {
364                     module_offset = field_accessor.GetValue<int32_t>().value();
365                     return;
366                 }
367             });
368             break;
369         }
370     }
371     if (module_offset == -1) {
372         return;
373     }
374 
375     std::unique_ptr<ModuleRecord> module_record = std::make_unique<ModuleRecord>(filename_);
376     if (module_record == nullptr) {
377         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not create ModuleRecord instance for '" << filename_ << "'";
378     }
379     ExtractModuleRecord(EntityId(module_offset), module_record);
380     module_record_ = std::move(module_record);
381 }
382 
ExtractModuleRecord(EntityId module_id,std::unique_ptr<ModuleRecord> & module_record)383 void AbcFile::ExtractModuleRecord(EntityId module_id, std::unique_ptr<ModuleRecord> &module_record)
384 {
385     ModuleDataAccessor mda(*panda_file_, module_id);
386     const std::vector<uint32_t> &request_modules_idx = mda.getRequestModules();
387     std::vector<std::string> request_modules;
388     for (size_t idx = 0; idx < request_modules_idx.size(); ++idx) {
389         request_modules.push_back(GetStringByStringId(EntityId(request_modules_idx[idx])));
390     }
391     module_record->SetRequestModules(request_modules);
392 
393     size_t regular_import_num = 0;
394     size_t local_export_num = 0;
395     mda.EnumerateModuleRecord([&](const ModuleTag &tag, uint32_t export_name_offset, uint32_t module_request_idx,
396                                   uint32_t import_name_offset, uint32_t local_name_offset) {
397         size_t request_num = request_modules.size();
398         ASSERT(request_num == 0 || module_request_idx < request_num);
399         std::string module_request = EMPTY_STR;
400         if (request_num != 0) {
401             module_request = request_modules[module_request_idx];
402         }
403         switch (tag) {
404             case ModuleTag::REGULAR_IMPORT: {
405                 ++regular_import_num;
406                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
407                 std::string import_name = GetStringByStringId(EntityId(import_name_offset));
408                 module_record->AddImportEntry({module_request, import_name, local_name});
409                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds a regular import: [" << module_request << ", "
410                                             << import_name << ", " << local_name << "]";
411                 break;
412             }
413             case ModuleTag::NAMESPACE_IMPORT: {
414                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
415                 module_record->AddImportEntry({module_request, "*", local_name});
416                 LOG(DEBUG, DEFECT_SCAN_AUX)
417                     << "ModuleRecord adds a namespace import: [" << module_request << ", *, " << local_name << "]";
418                 break;
419             }
420             case ModuleTag::LOCAL_EXPORT: {
421                 ++local_export_num;
422                 std::string local_name = GetStringByStringId(EntityId(local_name_offset));
423                 std::string export_name = GetStringByStringId(EntityId(export_name_offset));
424                 module_record->AddExportEntry({export_name, EMPTY_STR, EMPTY_STR, local_name});
425                 LOG(DEBUG, DEFECT_SCAN_AUX)
426                     << "ModuleRecord adds a local export: [" << export_name << ", null, null, " << local_name << "]";
427                 break;
428             }
429             case ModuleTag::INDIRECT_EXPORT: {
430                 std::string export_name = GetStringByStringId(EntityId(export_name_offset));
431                 std::string import_name = GetStringByStringId(EntityId(import_name_offset));
432                 module_record->AddExportEntry({export_name, module_request, import_name, EMPTY_STR});
433                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds an indirect export: [" << export_name << ", "
434                                             << module_request << ", " << import_name << ", null]";
435                 break;
436             }
437             case ModuleTag::STAR_EXPORT: {
438                 module_record->AddExportEntry({EMPTY_STR, module_request, "*", EMPTY_STR});
439                 LOG(DEBUG, DEFECT_SCAN_AUX) << "ModuleRecord adds a start export: ["
440                                             << "null, " << module_request << "*, null]";
441                 break;
442             }
443             default: {
444                 UNREACHABLE();
445                 break;
446             }
447         }
448     });
449     module_record->SetRegularImportNum(regular_import_num);
450     module_record->SetLocalExportNum(local_export_num);
451 }
452 
InitializeAllDefinedFunction()453 void AbcFile::InitializeAllDefinedFunction()
454 {
455     for (uint32_t id : panda_file_->GetClasses()) {
456         EntityId class_id {id};
457         if (panda_file_->IsExternal(class_id)) {
458             continue;
459         }
460 
461         panda_file::ClassDataAccessor cda {*panda_file_, class_id};
462         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
463             if (!mda.IsExternal()) {
464                 std::string func_name = GetStringByStringId(mda.GetNameId());
465                 EntityId m_id = mda.GetMethodId();
466                 panda_file::CodeDataAccessor cda {*panda_file_, mda.GetCodeId().value()};
467                 uint32_t arg_count = cda.GetNumArgs();
468                 compiler::Graph *graph = GenerateFunctionGraph(mda, func_name);
469                 if (graph == nullptr) {
470                     return;
471                 }
472                 std::unique_ptr<Function> func =
473                     std::make_unique<Function>(func_name, m_id, arg_count, Graph(graph), this);
474                 if (func == nullptr) {
475                     LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
476                 }
477                 LOG(DEBUG, DEFECT_SCAN_AUX) << "Create a new function: " << func_name;
478                 AddDefinedFunction(std::move(func));
479             }
480         });
481     }
482 }
483 
ExtractDefinedClassAndFunctionInfo()484 void AbcFile::ExtractDefinedClassAndFunctionInfo()
485 {
486     for (auto &func : def_func_list_) {
487         ExtractClassAndFunctionInfo(func.get());
488     }
489 
490     std::unordered_set<const Function *> processed_func;
491     for (auto &def_class : def_class_list_) {
492         const Function *def_func = def_class->GetDefineFunction();
493         if (def_func != nullptr && processed_func.count(def_func) == 0) {
494             ExtractClassInheritInfo(def_func);
495             processed_func.insert(def_func);
496         }
497     }
498 
499     for (auto &func : def_func_list_) {
500         ExtractFunctionCalleeInfo(func.get());
501     }
502 }
503 
ExtractClassAndFunctionInfo(Function * func)504 void AbcFile::ExtractClassAndFunctionInfo(Function *func)
505 {
506     auto &graph = func->GetGraph();
507     graph.VisitAllInstructions([&](const Inst &inst) {
508         auto type = inst.GetType();
509         switch (type) {
510             case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
511             case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
512                 auto def_class = ResolveDefineClassWithBufferInst(func, inst);
513                 AddDefinedClass(std::move(def_class));
514                 break;
515             }
516             case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
517             case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
518                 Function *def_func = ResolveDefineFuncInstCommon(func, inst);
519                 BuildFunctionDefineChain(func, def_func);
520                 break;
521             }
522             case InstType::DEFINEMETHOD_IMM8_ID16_IMM8:
523             case InstType::DEFINEMETHOD_IMM16_ID16_IMM8: {
524                 auto member_func = ResolveDefineFuncInstCommon(func, inst);
525                 BuildFunctionDefineChain(func, member_func);
526                 // resolve the class where it's defined
527                 Inst def_method_input0 = inst.GetInputInsts()[0];
528                 Inst ld_obj_input0 = def_method_input0.GetInputInsts()[0];
529                 if ((def_method_input0.GetType() == InstType::LDOBJBYNAME_IMM8_ID16 ||
530                      def_method_input0.GetType() == InstType::LDOBJBYNAME_IMM16_ID16) &&
531                     GetStringByInst(def_method_input0) == PROTOTYPE &&
532                     (ld_obj_input0.GetType() == InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8 ||
533                      ld_obj_input0.GetType() == InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8)) {
534                     auto clazz = GetClassByNameImpl(GetStringByInst(ld_obj_input0));
535                     if (clazz != nullptr) {
536                         BuildClassAndMemberFuncRelation(clazz, member_func);
537                     }
538                 }
539                 break;
540             }
541             default:
542                 break;
543         }
544     });
545 }
546 
ExtractClassInheritInfo(const Function * func) const547 void AbcFile::ExtractClassInheritInfo(const Function *func) const
548 {
549     auto &graph = func->GetGraph();
550     graph.VisitAllInstructions([&](const Inst &inst) {
551         if (inst.GetType() != InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8 &&
552             inst.GetType() != InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8) {
553             return;
554         }
555 
556         Class *cur_class = GetClassByNameImpl(GetStringByInst(inst));
557         ASSERT(cur_class != nullptr);
558         Inst def_class_input1 = inst.GetInputInsts()[0];
559         auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(func, def_class_input1);
560         if (ret_ptr != nullptr && ret_type == ResolveType::CLASS_OBJECT) {
561             auto par_class = reinterpret_cast<const Class *>(ret_ptr);
562             cur_class->SetParentClass(par_class);
563             return;
564         }
565         size_t first_delim_idx = ret_sym.find_first_of(DELIM);
566         size_t last_delim_idx = ret_sym.find_last_of(DELIM);
567         std::string par_class_name = ret_sym;
568         std::string var_name = EMPTY_STR;
569         if (last_delim_idx != std::string::npos) {
570             par_class_name = ret_sym.substr(last_delim_idx + 1);
571             var_name = ret_sym.substr(0, first_delim_idx);
572             cur_class->SetParentClassName(par_class_name);
573         }
574         if (ret_type == ResolveType::UNRESOLVED_MODULE) {
575             std::string imp_par_class_name = GetImportNameByInternalName(par_class_name);
576             if (!imp_par_class_name.empty()) {
577                 cur_class->SetParentClassName(imp_par_class_name);
578             }
579             std::string inter_name = var_name.empty() ? par_class_name : var_name;
580             std::string module_name = GetModuleNameByInternalName(inter_name);
581             if (!module_name.empty()) {
582                 cur_class->SetParClassExternalModuleName(module_name);
583             }
584         }
585         if (ret_type == ResolveType::UNRESOLVED_GLOBAL_VAR) {
586             cur_class->SetParentClassName(par_class_name);
587             var_name = var_name.empty() ? var_name : ret_sym.substr(0, last_delim_idx);
588             cur_class->SetParClassGlobalVarName(var_name);
589         }
590     });
591 }
592 
ExtractFunctionCalleeInfo(Function * func)593 void AbcFile::ExtractFunctionCalleeInfo(Function *func)
594 {
595     auto &graph = func->GetGraph();
596     graph.VisitAllInstructions([&](const Inst &inst) {
597         std::unique_ptr<CalleeInfo> callee_info {nullptr};
598         switch (inst.GetType()) {
599             case InstType::CALLARG0_IMM8: {
600                 callee_info = ResolveCallInstCommon(func, inst);
601                 callee_info->SetCalleeArgCount(0);
602                 break;
603             }
604             case InstType::CALLARG1_IMM8_V8: {
605                 callee_info = ResolveCallInstCommon(func, inst, 1);
606                 callee_info->SetCalleeArgCount(1);
607                 break;
608             }
609             case InstType::CALLARGS2_IMM8_V8_V8: {
610                 constexpr int ARG_COUNT = 2;
611                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT);
612                 callee_info->SetCalleeArgCount(ARG_COUNT);
613                 break;
614             }
615             case InstType::CALLARGS3_IMM8_V8_V8_V8: {
616                 constexpr int ARG_COUNT = 3;
617                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT);
618                 callee_info->SetCalleeArgCount(ARG_COUNT);
619                 break;
620             }
621             case InstType::CALLRANGE_IMM8_IMM8_V8: {
622                 uint32_t arg_count = inst.GetImms()[1];
623                 callee_info = ResolveCallInstCommon(func, inst, arg_count);
624                 callee_info->SetCalleeArgCount(arg_count);
625                 break;
626             }
627             case InstType::WIDE_CALLRANGE_PREF_IMM16_V8: {
628                 uint32_t arg_count = inst.GetImms()[0];
629                 callee_info = ResolveCallInstCommon(func, inst, arg_count);
630                 callee_info->SetCalleeArgCount(arg_count);
631                 break;
632             }
633             case InstType::SUPERCALLSPREAD_IMM8_V8: {
634                 callee_info = ResolveCallInstCommon(func, inst, 1);
635                 break;
636             }
637             case InstType::APPLY_IMM8_V8_V8: {
638                 constexpr uint32_t FUNC_OBJ_INDEX = 2;
639                 callee_info = ResolveCallInstCommon(func, inst, FUNC_OBJ_INDEX);
640                 break;
641             }
642             case InstType::CALLTHIS0_IMM8_V8: {
643                 callee_info = ResolveCallInstCommon(func, inst, 1);
644                 callee_info->SetCalleeArgCount(0);
645                 break;
646             }
647             case InstType::CALLTHIS1_IMM8_V8_V8: {
648                 constexpr int ARG_COUNT = 1;
649                 // 1 represents the this pointer
650                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
651                 callee_info->SetCalleeArgCount(ARG_COUNT);
652                 break;
653             }
654             case InstType::CALLTHIS2_IMM8_V8_V8_V8: {
655                 constexpr int ARG_COUNT = 2;
656                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
657                 callee_info->SetCalleeArgCount(ARG_COUNT);
658                 break;
659             }
660             case InstType::CALLTHIS3_IMM8_V8_V8_V8_V8: {
661                 constexpr int ARG_COUNT = 3;
662                 callee_info = ResolveCallInstCommon(func, inst, ARG_COUNT + 1);
663                 callee_info->SetCalleeArgCount(ARG_COUNT);
664                 break;
665             }
666             case InstType::CALLTHISRANGE_IMM8_IMM8_V8: {
667                 uint32_t arg_count = inst.GetImms()[1];
668                 callee_info = ResolveCallInstCommon(func, inst, arg_count + 1);
669                 callee_info->SetCalleeArgCount(arg_count);
670                 break;
671             }
672             case InstType::WIDE_CALLTHISRANGE_PREF_IMM16_V8: {
673                 uint32_t arg_count = inst.GetImms()[0];
674                 callee_info = ResolveCallInstCommon(func, inst, arg_count + 1);
675                 callee_info->SetCalleeArgCount(arg_count);
676                 break;
677             }
678             case InstType::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
679             case InstType::SUPERCALLARROWRANGE_IMM8_IMM8_V8: {
680                 uint32_t arg_count = inst.GetImms()[1];
681                 callee_info = ResolveSuperCallInst(func, inst);
682                 callee_info->SetCalleeArgCount(arg_count);
683                 break;
684             }
685             case InstType::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
686             case InstType::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8: {
687                 uint32_t arg_count = inst.GetImms()[0];
688                 callee_info = ResolveSuperCallInst(func, inst);
689                 callee_info->SetCalleeArgCount(arg_count);
690                 break;
691             }
692             default:
693                 break;
694         }
695         if (callee_info != nullptr) {
696             AddCalleeInfo(std::move(callee_info));
697         }
698     });
699 }
700 
BuildFunctionDefineChain(Function * parent_func,Function * child_func) const701 void AbcFile::BuildFunctionDefineChain(Function *parent_func, Function *child_func) const
702 {
703     if (parent_func == nullptr || child_func == nullptr || child_func->GetParentFunction() == parent_func) {
704         return;
705     }
706     child_func->SetParentFunction(parent_func);
707     parent_func->AddDefinedFunction(child_func);
708 }
709 
BuildClassAndMemberFuncRelation(Class * clazz,Function * member_func) const710 void AbcFile::BuildClassAndMemberFuncRelation(Class *clazz, Function *member_func) const
711 {
712     if (clazz == nullptr || member_func == nullptr || member_func->GetClass() == clazz) {
713         return;
714     }
715     clazz->AddMemberFunction(member_func);
716     member_func->SetClass(clazz);
717 }
718 
ExtractClassAndFunctionExportList()719 void AbcFile::ExtractClassAndFunctionExportList()
720 {
721     if (!IsModule() || def_func_list_.empty()) {
722         return;
723     }
724     const Function *func_main = def_func_list_[0].get();
725     ASSERT(func_main->GetFunctionName() == ENTRY_FUNCTION_NAME);
726     auto &graph = func_main->GetGraph();
727     graph.VisitAllInstructions([&](const Inst &inst) {
728         auto type = inst.GetType();
729         if (type == InstType::STMODULEVAR_IMM8 || type == InstType::WIDE_STMODULEVAR_PREF_IMM16) {
730             Inst st_module_input0 = inst.GetInputInsts()[0];
731             switch (st_module_input0.GetType()) {
732                 case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
733                 case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
734                     auto export_func = ResolveDefineFuncInstCommon(func_main, st_module_input0);
735                     ASSERT(export_func != nullptr);
736                     export_func_list_.push_back(export_func);
737                     break;
738                 }
739                 case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
740                 case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
741                     Class *export_clazz = GetClassByNameImpl(GetStringByInst(st_module_input0));
742                     ASSERT(export_clazz != nullptr);
743                     export_class_list_.push_back(export_clazz);
744                     break;
745                 }
746                 default:
747                     break;
748             }
749         }
750     });
751 }
752 
GenerateFunctionGraph(const panda_file::MethodDataAccessor & mda,std::string_view func_name)753 compiler::Graph *AbcFile::GenerateFunctionGraph(const panda_file::MethodDataAccessor &mda, std::string_view func_name)
754 {
755     panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
756     auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(mda.GetMethodId().GetOffset());
757     compiler::Graph *graph = allocator_->New<compiler::Graph>(allocator_.get(), local_allocator_.get(), Arch::NONE,
758                                                               method_ptr, &adapter, false, nullptr, true, true);
759     if ((graph == nullptr) || !graph->RunPass<compiler::IrBuilder>()) {
760         LOG(FATAL, DEFECT_SCAN_AUX) << "Cannot generate graph for function '" << func_name << "'";
761     }
762     return graph;
763 }
764 
ResolveInstCommon(const Function * func,Inst inst) const765 ResolveResult AbcFile::ResolveInstCommon(const Function *func, Inst inst) const
766 {
767     auto type = inst.GetType();
768     switch (type) {
769         case InstType::DEFINEFUNC_IMM8_ID16_IMM8:
770         case InstType::DEFINEFUNC_IMM16_ID16_IMM8: {
771             std::string func_name = GetStringByInst(inst);
772             const Function *func = GetFunctionByName(func_name);
773             ASSERT(func != nullptr);
774             return std::make_tuple(func, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
775         }
776         case InstType::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
777         case InstType::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
778             std::string class_name = GetStringByInst(inst);
779             const Class *clazz = GetClassByName(class_name);
780             ASSERT(clazz != nullptr);
781             return std::make_tuple(clazz, EMPTY_STR, ResolveType::CLASS_OBJECT);
782         }
783         case InstType::NEWOBJAPPLY_IMM8_V8:
784         case InstType::NEWOBJAPPLY_IMM16_V8:
785         case InstType::NEWOBJRANGE_IMM8_IMM8_V8:
786         case InstType::NEWOBJRANGE_IMM16_IMM8_V8:
787         case InstType::WIDE_NEWOBJRANGE_PREF_IMM16_V8: {
788             Inst newobj_input0 = inst.GetInputInsts()[0];
789             auto resolve_res = ResolveInstCommon(func, newobj_input0);
790             return HandleNewObjInstResolveResultCommon(resolve_res);
791         }
792         case InstType::LDOBJBYNAME_IMM8_ID16:
793         case InstType::LDOBJBYNAME_IMM16_ID16: {
794             Inst ld_obj_input0 = inst.GetInputInsts()[0];
795             auto resolve_res = ResolveInstCommon(func, ld_obj_input0);
796             return HandleLdObjByNameInstResolveResult(inst, resolve_res);
797         }
798         case InstType::LDLEXVAR_IMM4_IMM4:
799         case InstType::LDLEXVAR_IMM8_IMM8:
800         case InstType::WIDE_LDLEXVAR_PREF_IMM16_IMM16: {
801             auto p = GetStLexInstByLdLexInst({func, inst});
802             if (p == std::nullopt) {
803                 return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
804             }
805             return ResolveInstCommon(p.value().first, p.value().second);
806         }
807         case InstType::STLEXVAR_IMM4_IMM4:
808         case InstType::STLEXVAR_IMM8_IMM8:
809         case InstType::WIDE_STLEXVAR_PREF_IMM16_IMM16: {
810             Inst stlex_input0 = inst.GetInputInsts()[0];
811             return ResolveInstCommon(func, stlex_input0);
812         }
813         case InstType::LDLOCALMODULEVAR_IMM8:
814         case InstType::WIDE_LDLOCALMODULEVAR_PREF_IMM16: {
815             size_t index = inst.GetImms()[0];
816             const std::string &export_name = module_record_->GetExportNameByIndex(index);
817             const Function *func = GetExportFunctionByExportName(export_name);
818             if (func != nullptr) {
819                 return std::make_tuple(func, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
820             }
821             const Class *clazz = GetExportClassByExportName(export_name);
822             if (clazz != nullptr) {
823                 return std::make_tuple(clazz, EMPTY_STR, ResolveType::CLASS_OBJECT);
824             }
825             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
826         }
827         case InstType::LDEXTERNALMODULEVAR_IMM8:
828         case InstType::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: {
829             size_t index = inst.GetImms()[0];
830             const std::string &inter_name = module_record_->GetImportInternalNameByIndex(index);
831             return std::make_tuple(nullptr, inter_name, ResolveType::UNRESOLVED_MODULE);
832         }
833         case InstType::GETMODULENAMESPACE_IMM8:
834         case InstType::WIDE_GETMODULENAMESPACE_PREF_IMM16: {
835             size_t index = inst.GetImms()[0];
836             const std::string &str = module_record_->GetImportNamespaceNameByIndex(index);
837             return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_MODULE);
838         }
839         case InstType::LDGLOBAL: {
840             // TODO(wangyantian): load a specific global variable, namely 'globalThis'
841             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
842         }
843         case InstType::LDGLOBALVAR_IMM16_ID16:
844         case InstType::TRYLDGLOBALBYNAME_IMM8_ID16:
845         case InstType::TRYLDGLOBALBYNAME_IMM16_ID16: {
846             std::string str = GetStringByInst(inst);
847             auto p = GetStGlobalInstByLdGlobalInst({func, inst});
848             if (p == std::nullopt) {
849                 return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_GLOBAL_VAR);
850             }
851             auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(p.value().first, p.value().second);
852             if (ret_ptr != nullptr) {
853                 return std::make_tuple(ret_ptr, str, ret_type);
854             }
855             return std::make_tuple(nullptr, str, ResolveType::UNRESOLVED_GLOBAL_VAR);
856         }
857         case InstType::TRYSTGLOBALBYNAME_IMM8_ID16:
858         case InstType::TRYSTGLOBALBYNAME_IMM16_ID16:
859         case InstType::STGLOBALVAR_IMM16_ID16:
860         case InstType::STCONSTTOGLOBALRECORD_IMM16_ID16:
861         case InstType::STTOGLOBALRECORD_IMM16_ID16: {
862             Inst stglobal_input0 = inst.GetInputInsts()[0];
863             return ResolveInstCommon(func, stglobal_input0);
864         }
865         case InstType::OPCODE_PHI: {
866             // TODO(wangyantian): only the first path is considered for now, what about other paths?
867             Inst phi_input0 = inst.GetInputInsts()[0];
868             return ResolveInstCommon(func, phi_input0);
869         }
870         // don't deal with the situation that func obj comes from parameter or the output of another call inst
871         default: {
872             return std::make_tuple(nullptr, EMPTY_STR, ResolveType::UNRESOLVED_OTHER);
873         }
874     }
875 }
876 
HandleLdObjByNameInstResolveResult(const Inst & ldobjbyname_inst,const ResolveResult & resolve_res) const877 ResolveResult AbcFile::HandleLdObjByNameInstResolveResult(const Inst &ldobjbyname_inst,
878                                                           const ResolveResult &resolve_res) const
879 {
880     auto &[ret_ptr, ret_sym, ret_type] = resolve_res;
881     std::string name = GetStringByInst(ldobjbyname_inst);
882     switch (ret_type) {
883         case ResolveType::UNRESOLVED_MODULE:
884         case ResolveType::UNRESOLVED_GLOBAL_VAR: {
885             return std::make_tuple(nullptr, ret_sym + "." + name, ret_type);
886         }
887         case ResolveType::FUNCTION_OBJECT: {
888             ASSERT(ret_ptr != nullptr);
889             if (name == CALL || name == APPLY) {
890                 return std::make_tuple(ret_ptr, EMPTY_STR, ResolveType::FUNCTION_OBJECT);
891             }
892             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
893         }
894         case ResolveType::CLASS_OBJECT:
895         case ResolveType::CLASS_INSTANCE: {
896             ASSERT(ret_ptr != nullptr);
897             // TODO(wangyantian): distinguish static func from member func in a class
898             const void *member_func = reinterpret_cast<const Class *>(ret_ptr)->GetMemberFunctionByName(name);
899             if (member_func != nullptr) {
900                 return std::make_tuple(member_func, name, ResolveType::FUNCTION_OBJECT);
901             }
902             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
903         }
904         default: {
905             return std::make_tuple(nullptr, ret_sym + "." + name, ResolveType::UNRESOLVED_OTHER);
906         }
907     }
908 }
909 
HandleNewObjInstResolveResultCommon(const ResolveResult & resolve_res) const910 ResolveResult AbcFile::HandleNewObjInstResolveResultCommon(const ResolveResult &resolve_res) const
911 {
912     auto &[ret_ptr, ret_sym, ret_type] = resolve_res;
913     switch (ret_type) {
914         case ResolveType::CLASS_OBJECT: {
915             ASSERT(ret_ptr != nullptr);
916             return std::make_tuple(ret_ptr, EMPTY_STR, ResolveType::CLASS_INSTANCE);
917         }
918         case ResolveType::UNRESOLVED_GLOBAL_VAR:
919         case ResolveType::UNRESOLVED_MODULE: {
920             return std::make_tuple(nullptr, ret_sym, ret_type);
921         }
922         default: {
923             return std::make_tuple(nullptr, ret_sym, ResolveType::UNRESOLVED_OTHER);
924         }
925     }
926 }
927 
ResolveDefineFuncInstCommon(const Function * func,const Inst & def_func_inst) const928 Function *AbcFile::ResolveDefineFuncInstCommon(const Function *func, const Inst &def_func_inst) const
929 {
930     std::string def_func_name = GetStringByInst(def_func_inst);
931     Function *def_func = GetFunctionByNameImpl(def_func_name);
932     ASSERT(def_func != nullptr);
933     return def_func;
934 }
935 
ResolveDefineClassWithBufferInst(Function * func,const Inst & define_class_inst) const936 std::unique_ptr<Class> AbcFile::ResolveDefineClassWithBufferInst(Function *func, const Inst &define_class_inst) const
937 {
938     auto imms = define_class_inst.GetImms();
939     auto m_id = EntityId(imms[1]);
940     std::string class_name = GetStringByMethodId(m_id);
941     std::unique_ptr<Class> def_class = std::make_unique<Class>(class_name, this, func);
942     if (def_class == nullptr) {
943         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
944     }
945     LOG(DEBUG, DEFECT_SCAN_AUX) << "Create a new class: " << class_name;
946     func->AddDefinedClass(def_class.get());
947 
948     // handle ctor of the class
949     std::string ctor_name = GetStringByInst(define_class_inst);
950     HandleMemberFunctionFromClassBuf(ctor_name, func, def_class.get());
951 
952     auto literal_array_id = EntityId(imms[2]);
953     panda_file::LiteralDataAccessor lit_array_accessor(*panda_file_, panda_file_->GetLiteralArraysId());
954     lit_array_accessor.EnumerateLiteralVals(
955         literal_array_id, [&](const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
956             if (tag == LiteralTag::METHOD || tag == LiteralTag::GENERATORMETHOD ||
957                 tag == LiteralTag::ASYNCGENERATORMETHOD) {
958                 auto method_id = EntityId(std::get<uint32_t>(value));
959                 std::string member_func_name = GetStringByMethodId(method_id);
960                 HandleMemberFunctionFromClassBuf(member_func_name, func, def_class.get());
961             }
962         });
963 
964     return def_class;
965 }
966 
ResolveCallInstCommon(Function * func,const Inst & call_inst,uint32_t func_obj_idx) const967 std::unique_ptr<CalleeInfo> AbcFile::ResolveCallInstCommon(Function *func, const Inst &call_inst,
968                                                            uint32_t func_obj_idx) const
969 {
970     std::unique_ptr<CalleeInfo> callee_info = std::make_unique<CalleeInfo>(call_inst, func);
971     if (callee_info == nullptr) {
972         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
973     }
974 
975     Inst call_input0 = call_inst.GetInputInsts()[func_obj_idx];
976     auto [ret_ptr, ret_sym, ret_type] = ResolveInstCommon(func, call_input0);
977     if (ret_ptr != nullptr && ret_type == ResolveType::FUNCTION_OBJECT) {
978         auto callee = reinterpret_cast<const Function *>(ret_ptr);
979         callee_info->SetCallee(callee);
980     } else {
981         size_t first_delim_idx = ret_sym.find_first_of(DELIM);
982         size_t last_delim_idx = ret_sym.find_last_of(DELIM);
983         std::string callee_name = ret_sym;
984         std::string var_name = EMPTY_STR;
985         if (first_delim_idx != std::string::npos) {
986             callee_name = ret_sym.substr(last_delim_idx + 1);
987             var_name = ret_sym.substr(0, first_delim_idx);
988             callee_info->SetFunctionName(callee_name);
989         }
990         if (ret_type == ResolveType::UNRESOLVED_MODULE) {
991             std::string imp_callee_name = GetImportNameByInternalName(callee_name);
992             if (!imp_callee_name.empty()) {
993                 callee_info->SetFunctionName(imp_callee_name);
994             }
995             std::string inter_name = var_name.empty() ? callee_name : var_name;
996             std::string module_name = GetModuleNameByInternalName(inter_name);
997             if (!module_name.empty()) {
998                 callee_info->SetExternalModuleName(module_name);
999             }
1000         } else if (ret_type == ResolveType::UNRESOLVED_GLOBAL_VAR) {
1001             callee_info->SetFunctionName(callee_name);
1002             var_name = var_name.empty() ? var_name : ret_sym.substr(0, last_delim_idx);
1003             callee_info->SetGlobalVarName(var_name);
1004         }
1005     }
1006     func->AddCalleeInfo(callee_info.get());
1007     return callee_info;
1008 }
1009 
ResolveSuperCallInst(Function * func,const Inst & call_inst) const1010 std::unique_ptr<CalleeInfo> AbcFile::ResolveSuperCallInst(Function *func, const Inst &call_inst) const
1011 {
1012     std::unique_ptr<CalleeInfo> callee_info = std::make_unique<CalleeInfo>(call_inst, func);
1013     if (callee_info == nullptr) {
1014         LOG(FATAL, DEFECT_SCAN_AUX) << "Can not allocate memory when processing '" << filename_ << "'";
1015     }
1016     const Class *clazz = func->GetClass();
1017     if (clazz != nullptr && clazz->GetParentClass() != nullptr) {
1018         const std::string &parent_ctor_name = clazz->GetParentClass()->GetClassName();
1019         const Function *parent_ctor = GetFunctionByName(parent_ctor_name);
1020         ASSERT(parent_ctor != nullptr);
1021         callee_info->SetCallee(parent_ctor);
1022     }
1023     // TODO(wangyantian): deal with situations when above if doesn't hold
1024     func->AddCalleeInfo(callee_info.get());
1025     return callee_info;
1026 }
1027 
HandleMemberFunctionFromClassBuf(const std::string & func_name,Function * def_func,Class * def_class) const1028 void AbcFile::HandleMemberFunctionFromClassBuf(const std::string &func_name, Function *def_func, Class *def_class) const
1029 {
1030     Function *member_func = GetFunctionByNameImpl(func_name);
1031     ASSERT(member_func != nullptr);
1032     BuildFunctionDefineChain(def_func, member_func);
1033     BuildClassAndMemberFuncRelation(def_class, member_func);
1034 }
1035 
AddDefinedClass(std::unique_ptr<Class> && def_class)1036 void AbcFile::AddDefinedClass(std::unique_ptr<Class> &&def_class)
1037 {
1038     auto &class_name = def_class->GetClassName();
1039     ASSERT(def_class_map_.find(class_name) == def_class_map_.end());
1040     def_class_map_[class_name] = def_class.get();
1041     def_class_list_.emplace_back(std::move(def_class));
1042 }
1043 
AddDefinedFunction(std::unique_ptr<Function> && def_func)1044 void AbcFile::AddDefinedFunction(std::unique_ptr<Function> &&def_func)
1045 {
1046     const std::string &func_name = def_func->GetFunctionName();
1047     ASSERT(def_func_map_.find(func_name) == def_func_map_.end());
1048     def_func_map_[func_name] = def_func.get();
1049     if (func_name != ENTRY_FUNCTION_NAME) {
1050         def_func_list_.emplace_back(std::move(def_func));
1051     } else {
1052         // make def_func_list_[0] the 'func_main_0'
1053         def_func_list_.insert(def_func_list_.begin(), std::move(def_func));
1054     }
1055 }
1056 
AddCalleeInfo(std::unique_ptr<CalleeInfo> && callee_info)1057 void AbcFile::AddCalleeInfo(std::unique_ptr<CalleeInfo> &&callee_info)
1058 {
1059     callee_info_list_.emplace_back(std::move(callee_info));
1060 }
1061 
GetFunctionByNameImpl(std::string_view func_name) const1062 Function *AbcFile::GetFunctionByNameImpl(std::string_view func_name) const
1063 {
1064     auto iter = def_func_map_.find(std::string(func_name));
1065     if (iter != def_func_map_.end()) {
1066         return iter->second;
1067     }
1068     return nullptr;
1069 }
1070 
GetClassByNameImpl(std::string_view class_name) const1071 Class *AbcFile::GetClassByNameImpl(std::string_view class_name) const
1072 {
1073     auto iter = def_class_map_.find(std::string(class_name));
1074     if (iter != def_class_map_.end()) {
1075         return iter->second;
1076     }
1077     return nullptr;
1078 }
1079 
GetStringByMethodId(EntityId method_id) const1080 std::string AbcFile::GetStringByMethodId(EntityId method_id) const
1081 {
1082     panda_file::MethodDataAccessor mda {*panda_file_, method_id};
1083     return GetStringByStringId(mda.GetNameId());
1084 }
1085 
GetStringByStringId(EntityId string_id) const1086 std::string AbcFile::GetStringByStringId(EntityId string_id) const
1087 {
1088     StringData sd = panda_file_->GetStringData(string_id);
1089     // TODO(wangyantian): what if sd.is_ascii equals false?
1090     return std::string(utf::Mutf8AsCString(sd.data));
1091 }
1092 }  // namespace panda::defect_scan_aux