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