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)> §ionModifier,
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