• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 
15  */
16 
17 #include "libabckit/src/metadata_inspect_impl.h"
18 #include "libabckit/src/adapter_dynamic/helpers_dynamic.h"
19 #include "libabckit/src/logger.h"
20 #include "libabckit/src/statuses_impl.h"
21 #include "assembler/assembly-program.h"
22 #include "assembler/assembly-record.h"
23 
24 #if defined(_WIN32)
25 #include <cwchar>
26 #include <codecvt>
27 #include <locale>
28 #endif
29 #include <cstdint>
30 #include <memory>
31 
32 // CC-OFFNXT(WordsTool.95) sensitive word conflict
33 // NOLINTNEXTLINE(google-build-using-namespace)
34 using namespace panda;
35 // CC-OFFNXT(WordsTool.95) sensitive word conflict
36 // NOLINTNEXTLINE(google-build-using-namespace)
37 using namespace libabckit;
38 
39 namespace {
40 
41 // CC-OFFNXT(G.NAM.03) project code style
UpdateLitArrSectionPostAction(ModuleIterateData * data,std::pair<size_t,size_t> res)42 bool UpdateLitArrSectionPostAction(ModuleIterateData *data, std::pair<size_t, size_t> res)
43 {
44     bool *isChangeField {nullptr};
45     size_t *offset {nullptr};
46     if (data->isRegularImport.first) {
47         if (data->isRegularImport.second) {
48             ASSERT(data->payload->regularImportsOffset == res.second);
49             isChangeField = &(data->updateData.isRegularImportsChange);
50             offset = &(data->payload->regularImportsOffset);
51         } else {
52             offset = &(data->payload->namespaceImportsOffset);
53         }
54     } else {
55         switch (data->kind) {
56             case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT: {
57                 isChangeField = &(data->updateData.isLocalExportsChange);
58                 offset = &(data->payload->localExportsOffset);
59                 break;
60             }
61             case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT: {
62                 offset = &(data->payload->indirectExportsOffset);
63                 break;
64             }
65             case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT: {
66                 offset = &(data->payload->starExportsOffset);
67                 break;
68             }
69         }
70     }
71 
72     auto prevNum = std::get<uint32_t>(data->moduleLitArr->literals_[*offset - 1].value_);
73     auto newNum = std::get<uint32_t>((data->updateData.newLiterals)[res.second - 1].value_);
74     if (prevNum != newNum && (isChangeField != nullptr)) {
75         *isChangeField = true;
76     }
77     return true;
78 }
79 
UpdateLitArrSection(ModuleIterateData * data,size_t idx,size_t fieldNum)80 std::pair<size_t, size_t> UpdateLitArrSection(ModuleIterateData *data, size_t idx, size_t fieldNum)
81 {
82     auto &newLiterals = data->updateData.newLiterals;
83     auto *idxMap =
84         data->isRegularImport.first ? &data->updateData.regularImportsIdxMap : &data->updateData.localExportsIdxMap;
85 
86     auto num = std::get<uint32_t>(data->moduleLitArr->literals_[idx].value_);
87     newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
88     auto newOffset = newLiterals.size();
89     auto prevOffset = idx;
90     uint32_t oldIdx = 0;
91     uint32_t actualNumber = 0;
92     while (idx < prevOffset + num * fieldNum) {
93         if (data->moduleLitArr->literals_[idx].tag_ == panda_file::LiteralTag::NULLVALUE) {
94             for (size_t i = 0; i < fieldNum; i++) {
95                 idx++;
96             }
97             oldIdx++;
98             continue;
99         }
100         idxMap->emplace(oldIdx, actualNumber);
101         actualNumber++;
102         oldIdx++;
103         for (size_t i = 0; i < fieldNum; i++) {
104             newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
105         }
106     }
107     if (actualNumber != num) {
108         newLiterals[newOffset - 1].value_ = actualNumber;
109     }
110     return {idx, newOffset};
111 }
112 
IterateRequestIdxSectionBeforeUpdate(ModuleIterateData * data)113 size_t IterateRequestIdxSectionBeforeUpdate(ModuleIterateData *data)
114 {
115     auto &newLiterals = data->updateData.newLiterals;
116     size_t idx = 0;
117     while (idx < (data->payload->regularImportsOffset - 1)) {
118         newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
119     }
120     return idx;
121 }
122 
CheckRegularImport(ModuleUpdateData * updateData,panda::pandasm::InsPtr & inst)123 bool CheckRegularImport(ModuleUpdateData *updateData, panda::pandasm::InsPtr &inst)
124 {
125     if (updateData->isRegularImportsChange) {
126         if (inst->opcode == pandasm::Opcode::LDEXTERNALMODULEVAR ||
127             inst->opcode == pandasm::Opcode::WIDE_LDEXTERNALMODULEVAR) {
128             auto imm = static_cast<uint32_t>(std::get<int64_t>(inst->GetImm(0)));
129             auto foundIdx = updateData->regularImportsIdxMap.find(imm);
130             if (foundIdx == updateData->regularImportsIdxMap.end()) {
131                 LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << inst->ToString()
132                                      << "' with an unknown regular import index '" << std::hex << imm << "'\n";
133                 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
134                 return false;
135             }
136             auto idx = (int64_t)foundIdx->second;
137             inst->SetImm(0, idx);
138         }
139     }
140     return true;
141 }
142 
CheckLocalExports(ModuleUpdateData * updateData,panda::pandasm::InsPtr & inst)143 bool CheckLocalExports(ModuleUpdateData *updateData, panda::pandasm::InsPtr &inst)
144 {
145     if (updateData->isLocalExportsChange) {
146         auto op = inst->opcode;
147         if (op == pandasm::Opcode::LDLOCALMODULEVAR || op == pandasm::Opcode::WIDE_LDLOCALMODULEVAR ||
148             op == pandasm::Opcode::STMODULEVAR || op == pandasm::Opcode::WIDE_STMODULEVAR) {
149             auto imm = static_cast<uint32_t>(std::get<int64_t>(inst->GetImm(0)));
150             auto foundIdx = updateData->localExportsIdxMap.find(imm);
151             if (foundIdx == updateData->localExportsIdxMap.end()) {
152                 LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << inst->ToString()
153                                      << "' with an unknown local export index '" << std::hex << imm << "'\n";
154                 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
155                 return false;
156             }
157             auto idx = (int64_t)foundIdx->second;
158             inst->SetImm(0, idx);
159         }
160     }
161     return true;
162 }
163 
UpdateInsImms(pandasm::Program * program,ModuleUpdateData * updateData,const std::string & mainRecordName)164 bool UpdateInsImms(pandasm::Program *program, ModuleUpdateData *updateData, const std::string &mainRecordName)
165 {
166     for (auto &[name, func] : program->function_table) {
167         if (pandasm::GetOwnerName(name) != mainRecordName) {
168             continue;
169         }
170         for (auto &inst : func.ins) {
171             if (!CheckRegularImport(updateData, inst)) {
172                 return false;
173             }
174 
175             if (!CheckLocalExports(updateData, inst)) {
176                 return false;
177             }
178         }
179     }
180     return true;
181 }
182 
GetModulePayload(AbckitCoreModule * module)183 AbckitModulePayloadDyn *GetModulePayload(AbckitCoreModule *module)
184 {
185     switch (module->target) {
186         case ABCKIT_TARGET_JS:
187             return &(module->GetJsImpl()->impl);
188             break;
189         case ABCKIT_TARGET_ARK_TS_V1:
190             return &(module->GetArkTSImpl()->impl.GetDynModule());
191         default:
192             LIBABCKIT_UNREACHABLE;
193     }
194 }
195 
UpdateModuleLiteralArray(AbckitFile * file,const std::string & recName)196 bool UpdateModuleLiteralArray(AbckitFile *file, const std::string &recName)
197 {
198     auto program = file->GetDynamicProgram();
199     auto module = file->localModules.find(recName);
200     if (module == file->localModules.end()) {
201         LIBABCKIT_LOG(DEBUG) << "Can not find module with name '" << recName << "'\n";
202         statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
203         return false;
204     }
205     AbckitModulePayloadDyn *mPayload = GetModulePayload(module->second.get());
206     auto moduleLitArr = mPayload->moduleLiteralArray->GetDynamicImpl();
207     if (mPayload->absPaths) {
208         size_t idx = 1;
209         auto moduleBasePath = fs::path("./" + recName).remove_filename();
210         while (idx < (mPayload->regularImportsOffset - 1)) {
211             auto moduleAbsPath = std::get<std::string>(moduleLitArr->literals_[idx].value_);
212             if (moduleAbsPath[0] == '@') {
213                 moduleLitArr->literals_[idx++].value_ = moduleAbsPath;
214             } else {
215                 auto relativePath = Relative(moduleAbsPath, moduleBasePath).string();
216                 moduleLitArr->literals_[idx++].value_ = fs::path("./").append(relativePath).string();
217             }
218         }
219         mPayload->absPaths = false;
220     }
221 
222     bool modified = std::any_of(
223         moduleLitArr->literals_.cbegin(), moduleLitArr->literals_.cend(),
224         [](const pandasm::LiteralArray::Literal &lit) { return lit.tag_ == panda_file::LiteralTag::NULLVALUE; });
225     if (!modified) {
226         return true;
227     }
228 
229     ModuleIterateData iterData;
230     iterData.m = module->second.get();
231     iterData.payload = mPayload;
232     iterData.moduleLitArr = moduleLitArr;
233 
234     if (!IterateModuleSections(iterData, IterateRequestIdxSectionBeforeUpdate, UpdateLitArrSection,
235                                UpdateLitArrSectionPostAction)) {
236         return false;
237     }
238 
239     if (iterData.updateData.isRegularImportsChange || iterData.updateData.isLocalExportsChange) {
240         if (!UpdateInsImms(program, &iterData.updateData, recName)) {
241             return false;
242         }
243     }
244 
245     moduleLitArr->literals_ = std::move(iterData.updateData.newLiterals);
246 
247     LIBABCKIT_LOG_DUMP(DumpModuleArray(moduleLitArr, iterData.m->moduleName->impl), DEBUG);
248     return true;
249 }
250 
251 }  // namespace
252 
253 namespace libabckit {
254 
255 // CC-OFFNXT(G.FUN.01-CPP) helper function
EmitDynamicProgram(AbckitFile * file,pandasm::Program * program,pandasm::AsmEmitter::PandaFileToPandaAsmMaps * mapsp,bool getFile,std::string_view path)256 const panda_file::File *EmitDynamicProgram(AbckitFile *file, pandasm::Program *program,
257                                            pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp, bool getFile,
258                                            std::string_view path)
259 {
260     for (auto &[recName, rec] : program->record_table) {
261         if (!IsModuleDescriptorRecord(rec) || IsExternalRecord(rec)) {
262             continue;
263         }
264         if (!UpdateModuleLiteralArray(file, recName)) {
265             return nullptr;
266         }
267     }
268 
269     const panda_file::File *pf = [&]() {
270         const panda_file::File *res {nullptr};
271         if (!getFile) {
272             std::map<std::string, size_t> *statp = nullptr;
273             if (!pandasm::AsmEmitter::Emit(std::string(path), *program, statp, mapsp)) {
274                 LIBABCKIT_LOG_NO_FUNC(DEBUG)
275                     << "[EmitDynamicProgram] FAILURE: " << pandasm::AsmEmitter::GetLastError() << '\n';
276                 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
277             }
278             return res;
279         }
280         return pandasm::AsmEmitter::Emit(*program, mapsp, 1U).release();
281     }();
282     if (getFile && pf == nullptr) {
283         LIBABCKIT_LOG(DEBUG) << "FAILURE: " << pandasm::AsmEmitter::GetLastError() << '\n';
284         statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
285         return nullptr;
286     }
287 
288     return pf;
289 }
290 
Relative(const fs::path & src,const fs::path & base)291 fs::path Relative(const fs::path &src, const fs::path &base)
292 {
293 #ifdef STD_FILESYSTEM_EXPERIMENTAL
294     fs::path tmpPath = src;
295     fs::path relPath;
296     while (fs::abcolute(tmpPath) != fs::absolute(base)) {
297         relPath = relPath.empty() ? tmpPath.filename() : tmpPath.filename() / relPath;
298         if (tmpPath == tmpPath.parent_path()) {
299             return "";
300         }
301         tmpPath = tmpPath.parent_path();
302     }
303     return relPath;
304 #else
305     return fs::relative(src, base);
306 #endif
307 }
308 
IterateModuleSections(ModuleIterateData & data,const std::function<size_t (ModuleIterateData *)> & requestIdxSectionModifier,const std::function<std::pair<size_t,size_t> (ModuleIterateData *,size_t,size_t)> & sectionModifier,const std::function<bool (ModuleIterateData *,std::pair<size_t,size_t>)> & postAction)309 bool IterateModuleSections(
310     ModuleIterateData &data, const std::function<size_t(ModuleIterateData *)> &requestIdxSectionModifier,
311     const std::function<std::pair<size_t, size_t>(ModuleIterateData *, size_t, size_t)> &sectionModifier,
312     const std::function<bool(ModuleIterateData *, std::pair<size_t, size_t>)> &postAction)
313 {
314     auto idx = requestIdxSectionModifier(&data);
315 
316     data.isRegularImport = {true, true};
317     auto r = sectionModifier(&data, idx, 3U);
318     if (!postAction(&data, r)) {
319         return false;
320     }
321     idx = r.first;
322     data.payload->regularImportsOffset = r.second;
323 
324     data.isRegularImport = {true, false};
325     r = sectionModifier(&data, idx, 2U);
326     if (!postAction(&data, r)) {
327         return false;
328     }
329     idx = r.first;
330     data.payload->namespaceImportsOffset = r.second;
331 
332     data.isRegularImport = {false, false};
333     data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
334     r = sectionModifier(&data, idx, 2U);
335     if (!postAction(&data, r)) {
336         return false;
337     }
338     idx = r.first;
339     data.payload->localExportsOffset = r.second;
340 
341     data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT;
342     r = sectionModifier(&data, idx, 3U);
343     if (!postAction(&data, r)) {
344         return false;
345     }
346     idx = r.first;
347     data.payload->indirectExportsOffset = r.second;
348 
349     data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT;
350     r = sectionModifier(&data, idx, 1);
351     if (!postAction(&data, r)) {
352         return false;
353     }
354     data.payload->starExportsOffset = r.second;
355 
356     return true;
357 }
358 
DumpModuleRequests(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)359 void DumpModuleRequests(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
360 {
361     auto numModuleRequests = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
362     auto moduleRequestsOffset = idx;
363     ss << "\n    numModuleRequests " << numModuleRequests << " | offset " << idx << std::endl;
364     while (idx < moduleRequestsOffset + numModuleRequests) {
365         ss << "        [\n";
366         ss << "            module_request: " << std::get<std::string>(moduleLitArr->literals_[idx].value_) << std::endl;
367         idx++;
368         ss << "        ]\n";
369     }
370 }
371 
DumpRegularImports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)372 void DumpRegularImports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
373 {
374     auto numRegularImports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
375     auto regularImportsOffset = idx;
376     ss << "    numRegularImports " << numRegularImports << " | offset " << idx << std::endl;
377     while (idx < regularImportsOffset + numRegularImports * 3U) {
378         ss << "        [\n";
379         ss << "            localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
380            << std::endl;
381         idx++;
382         ss << "            importNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
383            << std::endl;
384         idx++;
385         ss << "            moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
386         idx++;
387         ss << "        ]\n";
388     }
389 }
390 
DumpNamespaceImports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)391 void DumpNamespaceImports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
392 {
393     auto numNamespaceImports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
394     auto namespaceImportsOffset = idx;
395     ss << "    numNamespaceImports " << numNamespaceImports << " | offset " << idx << std::endl;
396     while (idx < namespaceImportsOffset + numNamespaceImports * 2U) {
397         ss << "        [\n";
398         ss << "            localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
399            << std::endl;
400         idx++;
401         ss << "            moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
402         idx++;
403         ss << "        ]\n";
404     }
405 }
406 
DumpLocalExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)407 void DumpLocalExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
408 {
409     auto numLocalExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
410     auto localExportsOffset = idx;
411     ss << "    numLocalExports " << numLocalExports << " | offset " << idx << std::endl;
412     while (idx < localExportsOffset + numLocalExports * 2U) {
413         ss << "        [\n";
414         ss << "            localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
415            << std::endl;
416         idx++;
417         ss << "            exportNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
418            << std::endl;
419         idx++;
420         ss << "        ]\n";
421     }
422 }
423 
DumpIndirectExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)424 void DumpIndirectExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
425 {
426     auto numIndirectExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
427     auto indirectExportsOffset = idx;
428     ss << "    numIndirectExports " << numIndirectExports << " | offset " << idx << std::endl;
429     while (idx < indirectExportsOffset + numIndirectExports * 3U) {
430         ss << "        [\n";
431         ss << "            exportNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
432            << std::endl;
433         idx++;
434         ss << "            importNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
435            << std::endl;
436         idx++;
437         ss << "            moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
438         idx++;
439         ss << "        ]\n";
440     }
441 }
442 
DumpStarExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)443 void DumpStarExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
444 {
445     auto numStarExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
446     auto starExportsOffset = idx;
447     ss << "    numStarExports " << numStarExports << " | offset " << idx << std::endl;
448     while (idx < starExportsOffset + numStarExports) {
449         ss << "        [\n";
450         ss << "          moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
451         idx++;
452         ss << "        ]\n";
453     }
454     ss << "]\n";
455 }
456 
DumpModuleArray(const pandasm::LiteralArray * moduleLitArr,std::string_view name)457 void DumpModuleArray(const pandasm::LiteralArray *moduleLitArr, std::string_view name)
458 {
459     std::stringstream ss;
460     ss << "ModuleLiteralArray " << name << " \n[";
461     size_t idx = 0;
462 
463     DumpModuleRequests(moduleLitArr, idx, ss);
464     DumpRegularImports(moduleLitArr, idx, ss);
465     DumpNamespaceImports(moduleLitArr, idx, ss);
466     DumpLocalExports(moduleLitArr, idx, ss);
467     DumpIndirectExports(moduleLitArr, idx, ss);
468     DumpStarExports(moduleLitArr, idx, ss);
469     LIBABCKIT_LOG(DEBUG) << ss.str();
470 }
471 
IsServiceRecord(const std::string & name)472 bool IsServiceRecord(const std::string &name)
473 {
474     constexpr const std::string_view TSTYPE_ANNO_RECORD_NAME = "_TestAnnotation";
475     return name == TSTYPE_ANNO_RECORD_NAME || name == "_ESConcurrentModuleRequestsAnnotation" ||
476            name == "L_ESSlotNumberAnnotation" || name == "_ESSlotNumberAnnotation" ||
477            name == "_ESExpectedPropertyCountAnnotation";
478 }
479 
IsModuleDescriptorRecord(const pandasm::Record & rec)480 bool IsModuleDescriptorRecord(const pandasm::Record &rec)
481 {
482     constexpr std::array<std::string_view, 2> REQUIRED_FIELDS = {
483         "moduleRecordIdx",
484         "scopeNames",
485     };
486 
487     for (const auto &fieldName : REQUIRED_FIELDS) {
488         auto it = std::find_if(rec.field_list.begin(), rec.field_list.end(),
489                                [&fieldName](const auto &field) { return fieldName == field.name; });
490         if (it == rec.field_list.end()) {
491             return false;
492         }
493     }
494 
495     return true;
496 }
497 
IsAnnotationInterfaceRecord(const pandasm::Record & rec)498 bool IsAnnotationInterfaceRecord(const pandasm::Record &rec)
499 {
500     return (rec.metadata->GetAccessFlags() & ACC_ANNOTATION) != 0;
501 }
502 
IsExternalRecord(const pandasm::Record & rec)503 bool IsExternalRecord(const pandasm::Record &rec)
504 {
505     return rec.metadata->IsForeign();
506 }
507 
IsMain(const std::string & funcName)508 bool IsMain(const std::string &funcName)
509 {
510     size_t dotPos = funcName.rfind('.');
511     ASSERT(dotPos != std::string::npos);
512     return funcName.substr(dotPos + 1) == "func_main_0";
513 }
514 
IsFunction(const std::string & fullFuncName)515 bool IsFunction(const std::string &fullFuncName)
516 {
517     if (IsMain(fullFuncName)) {
518         return true;
519     }
520     size_t dotPos = fullFuncName.rfind('.');
521     ASSERT(dotPos != std::string::npos);
522     std::string funcName = fullFuncName.substr(dotPos);
523     for (auto &sub : {"<#", ">#", "=#", "*#"}) {
524         if (funcName.find(sub) != std::string::npos) {
525             return true;
526         }
527     }
528     return false;
529 }
530 
IsCtor(const std::string & funcName)531 bool IsCtor(const std::string &funcName)
532 {
533     return funcName.find("=#") != std::string::npos;
534 }
535 
IsStatic(const std::string & funcName)536 bool IsStatic(const std::string &funcName)
537 {
538     if (IsMain(funcName)) {
539         return true;
540     }
541     if (funcName.find("<#") != std::string::npos) {
542         return true;
543     }
544     return funcName.find("*#") != std::string::npos;
545 }
546 
IsAnonymousName(const std::string & funcName)547 bool IsAnonymousName(const std::string &funcName)
548 {
549     if (IsMain(funcName)) {
550         return false;
551     }
552     size_t pos = funcName.rfind('#');
553     ASSERT(pos != std::string::npos);
554     std::string name = funcName.substr(pos + 1);
555     return name.empty() || name.find('^') == 0;
556 }
557 
DemangleScopeName(const std::string & mangled,const AbckitLiteralArray * scopeNames)558 static std::string DemangleScopeName(const std::string &mangled, const AbckitLiteralArray *scopeNames)
559 {
560     const int base = 16;
561     size_t scopeIdx = stoi(mangled, nullptr, base);
562     auto *litArr = scopeNames->GetDynamicImpl();
563     ASSERT(litArr->literals_.size() % 2U == 0);
564     ASSERT(scopeIdx < litArr->literals_.size());
565     auto &lit = litArr->literals_[scopeIdx * 2 + 1];
566     ASSERT(lit.tag_ == panda_file::LiteralTag::STRING);
567     return std::get<std::string>(lit.value_);
568 }
569 
GetDynFunction(AbckitCoreFunction * function)570 panda::pandasm::Function *GetDynFunction(AbckitCoreFunction *function)
571 {
572     switch (function->owningModule->target) {
573         case ABCKIT_TARGET_JS:
574             return function->GetJsImpl()->impl;
575         case ABCKIT_TARGET_ARK_TS_V1:
576             return function->GetArkTSImpl()->GetDynamicImpl();
577         default:
578             LIBABCKIT_UNREACHABLE;
579     }
580 }
581 
GetDynFunction(AbckitCoreClass * klass)582 panda::pandasm::Function *GetDynFunction(AbckitCoreClass *klass)
583 {
584     switch (klass->owningModule->target) {
585         case ABCKIT_TARGET_JS:
586             return klass->GetJsImpl()->impl;
587         case ABCKIT_TARGET_ARK_TS_V1:
588             return klass->GetArkTSImpl()->impl.GetDynamicClass();
589         default:
590             LIBABCKIT_UNREACHABLE;
591     }
592 }
593 
GetDynModulePayload(AbckitCoreModule * mod)594 AbckitModulePayloadDyn *GetDynModulePayload(AbckitCoreModule *mod)
595 {
596     switch (mod->target) {
597         case ABCKIT_TARGET_JS:
598             return &mod->GetJsImpl()->impl;
599         case ABCKIT_TARGET_ARK_TS_V1:
600             return &mod->GetArkTSImpl()->impl.GetDynModule();
601         default:
602             LIBABCKIT_UNREACHABLE;
603     }
604 }
605 
GetDynImportDescriptorPayload(AbckitCoreImportDescriptor * id)606 AbckitDynamicImportDescriptorPayload *GetDynImportDescriptorPayload(AbckitCoreImportDescriptor *id)
607 {
608     switch (id->importingModule->target) {
609         case ABCKIT_TARGET_JS:
610             return &id->GetJsImpl()->payload.GetDynId();
611         case ABCKIT_TARGET_ARK_TS_V1:
612             return &id->GetArkTSImpl()->payload.GetDynId();
613         default:
614             LIBABCKIT_UNREACHABLE;
615     }
616 }
617 
GetDynExportDescriptorPayload(AbckitCoreExportDescriptor * ed)618 AbckitDynamicExportDescriptorPayload *GetDynExportDescriptorPayload(AbckitCoreExportDescriptor *ed)
619 {
620     AbckitDynamicExportDescriptorPayload *edPayload = nullptr;
621     switch (ed->exportingModule->target) {
622         case ABCKIT_TARGET_JS:
623             edPayload = &ed->GetJsImpl()->payload.GetDynamicPayload();
624             break;
625         case ABCKIT_TARGET_ARK_TS_V1:
626             edPayload = &ed->GetArkTSImpl()->payload.GetDynamicPayload();
627             break;
628         default:
629             LIBABCKIT_UNREACHABLE;
630     }
631     return edPayload;
632 }
633 
GetClassNameFromCtor(const std::string & ctorName,const AbckitLiteralArray * scopeNames)634 std::string GetClassNameFromCtor(const std::string &ctorName, const AbckitLiteralArray *scopeNames)
635 {
636     ASSERT(IsCtor(ctorName));
637     auto className = ctorName.substr(ctorName.find('~') + 1);
638     className = className.substr(0, className.find("=#"));
639     if (className[0] != '@') {
640         return className;
641     }
642     return DemangleScopeName(className.substr(1), scopeNames);
643 }
644 
645 template <class T>
FindOrCreateLiteral(AbckitFile * file,std::unordered_map<T,std::unique_ptr<AbckitLiteral>> & cache,T value,panda_file::LiteralTag tagImpl)646 static AbckitLiteral *FindOrCreateLiteral(AbckitFile *file,
647                                           std::unordered_map<T, std::unique_ptr<AbckitLiteral>> &cache, T value,
648                                           panda_file::LiteralTag tagImpl)
649 {
650     if (cache.count(value) == 1) {
651         return cache[value].get();
652     }
653 
654     auto literalDeleter = [](pandasm_Literal *p) -> void {
655         delete reinterpret_cast<pandasm::LiteralArray::Literal *>(p);
656     };
657 
658     auto *literal = new pandasm::LiteralArray::Literal();
659     literal->tag_ = tagImpl;
660     literal->value_ = value;
661     auto abcLit = std::make_unique<AbckitLiteral>(
662         file, AbckitLiteralImplT(reinterpret_cast<pandasm_Literal *>(literal), literalDeleter));
663     cache.insert({value, std::move(abcLit)});
664     return cache[value].get();
665 }
666 
FindOrCreateLiteralBoolDynamicImpl(AbckitFile * file,bool value)667 AbckitLiteral *FindOrCreateLiteralBoolDynamicImpl(AbckitFile *file, bool value)
668 {
669     return FindOrCreateLiteral(file, file->literals.boolLits, value, panda_file::LiteralTag::BOOL);
670 }
671 
FindOrCreateLiteralU8DynamicImpl(AbckitFile * file,uint8_t value)672 AbckitLiteral *FindOrCreateLiteralU8DynamicImpl(AbckitFile *file, uint8_t value)
673 {
674     return FindOrCreateLiteral(file, file->literals.u8Lits, value, panda_file::LiteralTag::ARRAY_U8);
675 }
676 
FindOrCreateLiteralU16DynamicImpl(AbckitFile * file,uint16_t value)677 AbckitLiteral *FindOrCreateLiteralU16DynamicImpl(AbckitFile *file, uint16_t value)
678 {
679     return FindOrCreateLiteral(file, file->literals.u16Lits, value, panda_file::LiteralTag::ARRAY_U16);
680 }
681 
FindOrCreateLiteralMethodAffiliateDynamicImpl(AbckitFile * file,uint16_t value)682 AbckitLiteral *FindOrCreateLiteralMethodAffiliateDynamicImpl(AbckitFile *file, uint16_t value)
683 {
684     return FindOrCreateLiteral(file, file->literals.methodAffilateLits, value, panda_file::LiteralTag::METHODAFFILIATE);
685 }
686 
FindOrCreateLiteralU32DynamicImpl(AbckitFile * file,uint32_t value)687 AbckitLiteral *FindOrCreateLiteralU32DynamicImpl(AbckitFile *file, uint32_t value)
688 {
689     return FindOrCreateLiteral(file, file->literals.u32Lits, value, panda_file::LiteralTag::INTEGER);
690 }
691 
FindOrCreateLiteralU64DynamicImpl(AbckitFile * file,uint64_t value)692 AbckitLiteral *FindOrCreateLiteralU64DynamicImpl(AbckitFile *file, uint64_t value)
693 {
694     return FindOrCreateLiteral(file, file->literals.u64Lits, value, panda_file::LiteralTag::ARRAY_U64);
695 }
696 
FindOrCreateLiteralFloatDynamicImpl(AbckitFile * file,float value)697 AbckitLiteral *FindOrCreateLiteralFloatDynamicImpl(AbckitFile *file, float value)
698 {
699     return FindOrCreateLiteral(file, file->literals.floatLits, value, panda_file::LiteralTag::FLOAT);
700 }
701 
FindOrCreateLiteralDoubleDynamicImpl(AbckitFile * file,double value)702 AbckitLiteral *FindOrCreateLiteralDoubleDynamicImpl(AbckitFile *file, double value)
703 {
704     return FindOrCreateLiteral(file, file->literals.doubleLits, value, panda_file::LiteralTag::DOUBLE);
705 }
706 
FindOrCreateLiteralLiteralArrayDynamicImpl(AbckitFile * file,const std::string & value)707 AbckitLiteral *FindOrCreateLiteralLiteralArrayDynamicImpl(AbckitFile *file, const std::string &value)
708 {
709     return FindOrCreateLiteral(file, file->literals.litArrLits, value, panda_file::LiteralTag::LITERALARRAY);
710 }
711 
FindOrCreateLiteralStringDynamicImpl(AbckitFile * file,const std::string & value)712 AbckitLiteral *FindOrCreateLiteralStringDynamicImpl(AbckitFile *file, const std::string &value)
713 {
714     return FindOrCreateLiteral(file, file->literals.stringLits, value, panda_file::LiteralTag::STRING);
715 }
716 
FindOrCreateLiteralMethodDynamicImpl(AbckitFile * file,const std::string & value)717 AbckitLiteral *FindOrCreateLiteralMethodDynamicImpl(AbckitFile *file, const std::string &value)
718 {
719     return FindOrCreateLiteral(file, file->literals.methodLits, value, panda_file::LiteralTag::METHOD);
720 }
721 
FindOrCreateLiteralDynamic(AbckitFile * file,const pandasm::LiteralArray::Literal & value)722 AbckitLiteral *FindOrCreateLiteralDynamic(AbckitFile *file, const pandasm::LiteralArray::Literal &value)
723 {
724     switch (value.tag_) {
725         case panda_file::LiteralTag::ARRAY_U1:
726         case panda_file::LiteralTag::BOOL:
727             return FindOrCreateLiteralBoolDynamicImpl(file, std::get<bool>(value.value_));
728         case panda_file::LiteralTag::ARRAY_U8:
729         case panda_file::LiteralTag::ARRAY_I8:
730             return FindOrCreateLiteralU8DynamicImpl(file, std::get<uint8_t>(value.value_));
731         case panda_file::LiteralTag::ARRAY_U16:
732         case panda_file::LiteralTag::ARRAY_I16:
733             return FindOrCreateLiteralU16DynamicImpl(file, std::get<uint16_t>(value.value_));
734         case panda_file::LiteralTag::ARRAY_U32:
735         case panda_file::LiteralTag::ARRAY_I32:
736         case panda_file::LiteralTag::INTEGER:
737             return FindOrCreateLiteralU32DynamicImpl(file, std::get<uint32_t>(value.value_));
738         case panda_file::LiteralTag::ARRAY_U64:
739         case panda_file::LiteralTag::ARRAY_I64:
740             return FindOrCreateLiteralU64DynamicImpl(file, std::get<uint64_t>(value.value_));
741         case panda_file::LiteralTag::ARRAY_F32:
742         case panda_file::LiteralTag::FLOAT:
743             return FindOrCreateLiteralFloatDynamicImpl(file, std::get<float>(value.value_));
744         case panda_file::LiteralTag::ARRAY_F64:
745         case panda_file::LiteralTag::DOUBLE:
746             return FindOrCreateLiteralDoubleDynamicImpl(file, std::get<double>(value.value_));
747         case panda_file::LiteralTag::ARRAY_STRING:
748         case panda_file::LiteralTag::STRING:
749             return FindOrCreateLiteralStringDynamicImpl(file, std::get<std::string>(value.value_));
750         case panda_file::LiteralTag::METHOD:
751         case panda_file::LiteralTag::GETTER:
752         case panda_file::LiteralTag::SETTER:
753         case panda_file::LiteralTag::GENERATORMETHOD:
754         case panda_file::LiteralTag::ASYNCGENERATORMETHOD:
755             return FindOrCreateLiteralMethodDynamicImpl(file, std::get<std::string>(value.value_));
756         case panda_file::LiteralTag::METHODAFFILIATE:
757             return FindOrCreateLiteralMethodAffiliateDynamicImpl(file, std::get<uint16_t>(value.value_));
758         case panda_file::LiteralTag::LITERALARRAY:
759             return FindOrCreateLiteralLiteralArrayDynamicImpl(file, std::get<std::string>(value.value_));
760         default:
761             LIBABCKIT_UNREACHABLE;
762     }
763 }
764 
765 template <class T, pandasm::Value::Type PANDASM_VALUE_TYPE>
FindOrCreateScalarValue(AbckitFile * file,std::unordered_map<T,std::unique_ptr<AbckitValue>> & cache,T value)766 static AbckitValue *FindOrCreateScalarValue(AbckitFile *file,
767                                             std::unordered_map<T, std::unique_ptr<AbckitValue>> &cache, T value)
768 {
769     if (cache.count(value) == 1) {
770         return cache[value].get();
771     }
772 
773     auto valueDeleter = [](pandasm_Value *val) -> void { delete reinterpret_cast<panda::pandasm::ScalarValue *>(val); };
774 
775     auto *pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create<PANDASM_VALUE_TYPE>(value));
776     auto abcVal =
777         std::make_unique<AbckitValue>(file, AbckitValueImplT(reinterpret_cast<pandasm_Value *>(pval), valueDeleter));
778     cache.insert({value, std::move(abcVal)});
779     return cache[value].get();
780 }
781 
FindOrCreateValueU1DynamicImpl(AbckitFile * file,bool value)782 AbckitValue *FindOrCreateValueU1DynamicImpl(AbckitFile *file, bool value)
783 {
784     return FindOrCreateScalarValue<bool, panda::pandasm::Value::Type::U1>(file, file->values.boolVals, value);
785 }
786 
FindOrCreateValueDoubleDynamicImpl(AbckitFile * file,double value)787 AbckitValue *FindOrCreateValueDoubleDynamicImpl(AbckitFile *file, double value)
788 {
789     return FindOrCreateScalarValue<double, panda::pandasm::Value::Type::F64>(file, file->values.doubleVals, value);
790 }
791 
FindOrCreateValueStringDynamicImpl(AbckitFile * file,const std::string & value)792 AbckitValue *FindOrCreateValueStringDynamicImpl(AbckitFile *file, const std::string &value)
793 {
794     return FindOrCreateScalarValue<std::string, panda::pandasm::Value::Type::STRING>(file, file->values.stringVals,
795                                                                                      value);
796 }
797 
FindOrCreateLiteralArrayValueDynamicImpl(AbckitFile * file,const std::string & value)798 AbckitValue *FindOrCreateLiteralArrayValueDynamicImpl(AbckitFile *file, const std::string &value)
799 {
800     return FindOrCreateScalarValue<std::string, panda::pandasm::Value::Type::LITERALARRAY>(
801         file, file->values.litarrVals, value);
802 }
803 
FindOrCreateValueDynamic(AbckitFile * file,const pandasm::Value & value)804 AbckitValue *FindOrCreateValueDynamic(AbckitFile *file, const pandasm::Value &value)
805 {
806     switch (value.GetType()) {
807         case pandasm::Value::Type::U1:
808             return FindOrCreateValueU1DynamicImpl(file, value.GetAsScalar()->GetValue<bool>());
809         case pandasm::Value::Type::F64:
810             return FindOrCreateValueDoubleDynamicImpl(file, value.GetAsScalar()->GetValue<double>());
811         case pandasm::Value::Type::STRING:
812             return FindOrCreateValueStringDynamicImpl(file, value.GetAsScalar()->GetValue<std::string>());
813         case pandasm::Value::Type::LITERALARRAY:
814             return FindOrCreateLiteralArrayValueDynamicImpl(file, value.GetAsScalar()->GetValue<std::string>());
815         case pandasm::Value::Type::I8:
816         case pandasm::Value::Type::U8:
817         case pandasm::Value::Type::I16:
818         case pandasm::Value::Type::U16:
819         case pandasm::Value::Type::I32:
820         case pandasm::Value::Type::U32:
821         case pandasm::Value::Type::I64:
822         case pandasm::Value::Type::U64:
823         case pandasm::Value::Type::F32:
824         case pandasm::Value::Type::STRING_NULLPTR:
825         case pandasm::Value::Type::RECORD:
826         case pandasm::Value::Type::METHOD:
827         case pandasm::Value::Type::ENUM:
828         case pandasm::Value::Type::ANNOTATION:
829         case pandasm::Value::Type::ARRAY:
830         case pandasm::Value::Type::VOID:
831         case pandasm::Value::Type::METHOD_HANDLE:
832         case pandasm::Value::Type::UNKNOWN:
833         default:
834             LIBABCKIT_UNREACHABLE;
835     }
836 }
837 
838 }  // namespace libabckit
839