• 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 #include "node.h"
17 
18 #include "utils/logger.h"
19 
20 #include "configs/guard_context.h"
21 #include "graph_analyzer.h"
22 #include "program.h"
23 #include "util/assert_util.h"
24 #include "util/string_util.h"
25 
26 namespace {
27 using OpcodeList = std::vector<panda::pandasm::Opcode>;
28 
29 constexpr std::string_view TAG = "[Node]";
30 constexpr std::string_view ENTRY_FUNC_NAME = ".func_main_0";
31 constexpr std::string_view NORMALIZED_OHM_DELIMITER = "&";
32 constexpr std::string_view PATH_DELIMITER = "/";
33 constexpr std::string_view PACKAGE_MODULES_PREFIX = "pkg_modules";
34 constexpr std::string_view PKG_NAME_PREFIX = "pkgName@";
35 constexpr std::string_view SCOPE_NAMES_FIELD = "scopeNames";
36 constexpr std::string_view JSON_FILE_FIELD = "jsonFileContent";
37 
38 const OpcodeList METHOD_NAME_DIRECT_LIST = {
39     panda::pandasm::Opcode::STOWNBYNAME,
40     panda::pandasm::Opcode::STOWNBYNAMEWITHNAMESET,
41 };
42 
43 const OpcodeList METHOD_NAME_INDIRECT_LIST = {
44     panda::pandasm::Opcode::DEFINEGETTERSETTERBYVALUE,
45     panda::pandasm::Opcode::STOWNBYVALUE,
46     panda::pandasm::Opcode::STOWNBYVALUEWITHNAMESET,
47 };
48 
InOpcodeList(const panda::guard::InstructionInfo & info,const OpcodeList & list)49 bool InOpcodeList(const panda::guard::InstructionInfo &info, const OpcodeList &list)
50 {
51     return std::any_of(list.begin(), list.end(), [&](const auto &elem) { return elem == info.ins_->opcode; });
52 }
53 
UpdateScopeNamesLiteralArray(panda::pandasm::LiteralArray & literalArray)54 void UpdateScopeNamesLiteralArray(panda::pandasm::LiteralArray &literalArray)
55 {
56     for (auto &literal : literalArray.literals_) {
57         if (!literal.IsStringValue()) {
58             continue;
59         }
60 
61         const auto &value = std::get<std::string>(literal.value_);
62         literal.value_ = panda::guard::GuardContext::GetInstance()->GetNameMapping()->GetName(value);
63     }
64 }
65 
66 }  // namespace
67 
Build()68 void panda::guard::Node::Build()
69 {
70     LOG(INFO, PANDAGUARD) << TAG << "node create for " << this->name_ << " start";
71 
72     this->sourceName_ = GuardContext::GetInstance()->GetGuardOptions()->GetSourceName(this->name_);
73     this->obfSourceName_ = this->sourceName_;
74     LOG(INFO, PANDAGUARD) << TAG << "node sourceName_ " << this->sourceName_;
75 
76     this->isNormalizedOhmUrl_ = GuardContext::GetInstance()->GetGuardOptions()->IsUseNormalizedOhmUrl();
77     CreateFilePath();
78     this->filepath_.obfName = this->filepath_.name;
79     LOG(INFO, PANDAGUARD) << TAG << "pre part: " << this->filepath_.prePart;
80     LOG(INFO, PANDAGUARD) << TAG << "file path: " << this->filepath_.name;
81     LOG(INFO, PANDAGUARD) << TAG << "post part: " << this->filepath_.postPart;
82 
83     moduleRecord_.Create();
84     if (!Node::IsJsonFile(this->program_->prog_->record_table.at(this->name_))) {
85         Function entryFunc(this->program_, this->name_ + ENTRY_FUNC_NAME.data(), false);
86         entryFunc.Init();
87         entryFunc.Create();
88 
89         const auto &function = entryFunc.GetOriginFunction();
90         this->sourceFile_ = function.source_file;
91         this->obfSourceFile_ = function.source_file;
92 
93         this->functionTable_.emplace(entryFunc.idx_, entryFunc);
94 
95         entryFunc.ForEachIns([&](const InstructionInfo &info) -> void { ForEachIns(info, TOP_LEVEL); });
96     } else {
97         LOG(INFO, PANDAGUARD) << "json file record:" << this->name_;
98     }
99 
100     this->ExtractNames();
101 
102     LOG(INFO, PANDAGUARD) << TAG << "node create for " << this->name_ << " end";
103 }
104 
ForEachIns(const panda::guard::InstructionInfo & info,panda::guard::Scope scope)105 void panda::guard::Node::ForEachIns(const panda::guard::InstructionInfo &info, panda::guard::Scope scope)
106 {
107     CreateFunction(info, scope);
108     CreateClass(info, scope);
109     CreateOuterMethod(info);
110     CreateObject(info, scope);
111     CreateObjectOuterProperty(info);
112     CreateOuterProperty(info);
113     FindStLexVarName(info);
114 }
115 
CreateFunction(const InstructionInfo & info,const Scope scope)116 void panda::guard::Node::CreateFunction(const InstructionInfo &info, const Scope scope)
117 {
118     if (info.ins_->opcode != pandasm::Opcode::DEFINEFUNC) {
119         return;
120     }
121 
122     const std::string idx = info.ins_->ids[0];
123     if (this->functionTable_.find(idx) != this->functionTable_.end()) {
124         this->functionTable_.at(idx).defineInsList_.push_back(info);
125         return;
126     }
127 
128     Function function(this->program_, idx);
129     function.scope_ = scope;
130     function.defineInsList_.push_back(info);
131 
132     function.Init();
133 
134     function.export_ = this->moduleRecord_.IsExportVar(function.name_);
135     function.Create();
136 
137     function.ForEachIns([&](const InstructionInfo &insInfo) -> void { ForEachIns(insInfo, FUNCTION); });
138 
139     this->functionTable_.emplace(function.idx_, function);
140 }
141 
CreateClass(const InstructionInfo & info,const Scope scope)142 void panda::guard::Node::CreateClass(const InstructionInfo &info, const Scope scope)
143 {
144     if ((info.ins_->opcode != pandasm::Opcode::DEFINECLASSWITHBUFFER) &&
145         (info.ins_->opcode != pandasm::Opcode::CALLRUNTIME_DEFINESENDABLECLASS)) {
146         return;
147     }
148 
149     const std::string idx = info.ins_->ids[1];
150     if (this->classTable_.find(idx) != this->classTable_.end()) {
151         this->classTable_.at(idx).defineInsList_.push_back(info);
152         return;
153     }
154 
155     Class clazz(this->program_, info.ins_->ids[0]);
156     clazz.moduleRecord_ = &this->moduleRecord_;
157     clazz.literalArrayIdx_ = idx;
158     clazz.defineInsList_.push_back(info);
159     clazz.component = GraphAnalyzer::IsComponentClass(info);
160     clazz.scope_ = scope;
161     if (info.ins_->opcode == pandasm::Opcode::CALLRUNTIME_DEFINESENDABLECLASS) {
162         clazz.callRunTimeInst_ = true;
163     }
164     clazz.Create();
165 
166     clazz.ForEachMethodIns([&](const InstructionInfo &insInfo) -> void { ForEachIns(insInfo, FUNCTION); });
167 
168     this->classTable_.emplace(clazz.literalArrayIdx_, clazz);
169 }
170 
CreateOuterMethod(const InstructionInfo & info)171 void panda::guard::Node::CreateOuterMethod(const InstructionInfo &info)
172 {
173     if (info.ins_->opcode != pandasm::Opcode::DEFINEMETHOD) {
174         return;
175     }
176 
177     InstructionInfo defineInsInfo;
178     InstructionInfo nameInsInfo;
179     GraphAnalyzer::HandleDefineMethod(info, defineInsInfo, nameInsInfo);
180 
181     const std::string methodIdx = info.ins_->ids[0];
182     std::string literalArrayIdx;
183     if ((defineInsInfo.ins_->opcode == pandasm::Opcode::DEFINECLASSWITHBUFFER) ||
184         (defineInsInfo.ins_->opcode == pandasm::Opcode::CALLRUNTIME_DEFINESENDABLECLASS)) {
185         literalArrayIdx = defineInsInfo.ins_->ids[1];
186     } else {  // createobjectwithbuffer
187         literalArrayIdx = defineInsInfo.ins_->ids[0];
188     }
189 
190     OuterMethod outerMethod(this->program_, methodIdx);
191     outerMethod.defineInsList_.push_back(info);
192     GetMethodNameInfo(nameInsInfo, outerMethod.nameInfo_);
193     outerMethod.Init();
194 
195     if (this->classTable_.find(literalArrayIdx) != this->classTable_.end()) {
196         auto &clazz = this->classTable_.at(literalArrayIdx);
197         outerMethod.className_ = clazz.name_;
198         outerMethod.export_ = clazz.export_;
199         outerMethod.scope_ = clazz.scope_;
200 
201         outerMethod.Create();
202 
203         LOG(INFO, PANDAGUARD) << TAG << "found method:" << methodIdx << " for class:" << clazz.constructor_.name_;
204         clazz.outerMethods_.push_back(outerMethod);
205     } else if (this->objectTable_.find(literalArrayIdx) != this->objectTable_.end()) {
206         auto &obj = this->objectTable_.at(literalArrayIdx);
207         outerMethod.export_ = obj.export_;
208         outerMethod.scope_ = obj.scope_;
209 
210         outerMethod.Create();
211 
212         LOG(INFO, PANDAGUARD) << TAG << "found method:" << methodIdx << " for obj:" << obj.literalArrayIdx_;
213         obj.outerMethods_.push_back(outerMethod);
214     } else {
215         PANDA_GUARD_ABORT_PRINT(TAG, ErrorCode::GENERIC_ERROR, "unexpect outer method for:" << literalArrayIdx);
216     }
217 
218     outerMethod.ForEachIns([&](const InstructionInfo &insInfo) -> void { ForEachIns(insInfo, FUNCTION); });
219 }
220 
CreateObject(const InstructionInfo & info,const Scope scope)221 void panda::guard::Node::CreateObject(const InstructionInfo &info, const Scope scope)
222 {
223     if (info.ins_->opcode != pandasm::Opcode::CREATEOBJECTWITHBUFFER) {
224         return;
225     }
226 
227     const std::string idx = info.ins_->ids[0];
228     if (this->objectTable_.find(idx) != this->objectTable_.end()) {
229         this->objectTable_.at(idx).defineInsList_.push_back(info);
230         return;
231     }
232 
233     Object object(this->program_, idx);
234     LOG(INFO, PANDAGUARD) << TAG << "found record object:" << object.literalArrayIdx_;
235     object.defineInsList_.push_back(info);
236     object.scope_ = scope;
237     object.moduleRecord = &this->moduleRecord_;
238     object.Create();
239 
240     object.ForEachMethod([&](Function &function) -> void {
241         function.ForEachIns([&](const InstructionInfo &insInfo) -> void { ForEachIns(insInfo, FUNCTION); });
242     });
243 
244     this->objectTable_.emplace(object.literalArrayIdx_, object);
245 }
246 
CreateObjectOuterProperty(const panda::guard::InstructionInfo & info)247 void panda::guard::Node::CreateObjectOuterProperty(const panda::guard::InstructionInfo &info)
248 {
249     if (info.ins_->opcode != pandasm::Opcode::DEFINEPROPERTYBYNAME) {
250         return;
251     }
252 
253     InstructionInfo defineIns;
254     GraphAnalyzer::HandleDefineProperty(info, defineIns);
255     if (!defineIns.IsValid()) {
256         return;
257     }
258 
259     PANDA_GUARD_ASSERT_PRINT(defineIns.ins_->opcode != pandasm::Opcode::CREATEOBJECTWITHBUFFER, TAG,
260                              ErrorCode::GENERIC_ERROR, "unexpect related define ins");
261 
262     const std::string literalArrayIdx = defineIns.ins_->ids[0];
263     PANDA_GUARD_ASSERT_PRINT(this->objectTable_.find(literalArrayIdx) == this->objectTable_.end(), TAG,
264                              ErrorCode::GENERIC_ERROR, "no record object for literalArrayIdx:" << literalArrayIdx);
265 
266     auto &object = this->objectTable_.at(literalArrayIdx);
267     Property property(this->program_, info.ins_->ids[0]);
268     property.defineInsList_.push_back(info);
269     property.nameInfo_ = info;
270     property.export_ = object.export_;
271     property.scope_ = object.scope_;
272 
273     property.Create();
274 
275     object.outerProperties_.push_back(property);
276     LOG(INFO, PANDAGUARD) << TAG << "found object outer property:" << property.name_;
277 }
278 
CreateOuterProperty(const InstructionInfo & info)279 void panda::guard::Node::CreateOuterProperty(const InstructionInfo &info)
280 {
281     if ((info.ins_->opcode != pandasm::Opcode::STOBJBYNAME) && (info.ins_->opcode != pandasm::Opcode::STOBJBYVALUE)) {
282         return;
283     }
284 
285     InstructionInfo nameInfo;
286     Property::GetPropertyNameInfo(info, nameInfo);
287     if (!nameInfo.IsValid()) {
288         LOG(INFO, PANDAGUARD) << TAG << "invalid nameInfo:" << info.index_ << " " << info.ins_->ToString();
289         return;
290     }
291 
292     Property property(this->program_, nameInfo.ins_->ids[0]);
293     property.defineInsList_.push_back(info);
294     property.nameInfo_ = nameInfo;
295 
296     property.Create();
297 
298     this->outerProperties_.push_back(property);
299     LOG(INFO, PANDAGUARD) << TAG << "found outer property:" << property.name_;
300 }
301 
FindStLexVarName(const panda::guard::InstructionInfo & info)302 void panda::guard::Node::FindStLexVarName(const panda::guard::InstructionInfo &info)
303 {
304     if (info.ins_->opcode != pandasm::Opcode::STLEXVAR) {
305         return;
306     }
307 
308     InstructionInfo outInfo;
309     GraphAnalyzer::GetLdaStr(info, outInfo);
310     if (!outInfo.IsValid()) {
311         return;
312     }
313 
314     LOG(INFO, PANDAGUARD) << TAG << "found stlexvar name:" << outInfo.ins_->ids[0];
315     GuardContext::GetInstance()->GetNameMapping()->AddNameMapping(outInfo.ins_->ids[0]);
316 }
317 
CreateFilePath()318 void panda::guard::Node::CreateFilePath()
319 {
320     if (!GuardContext::GetInstance()->GetGuardOptions()->IsFileNameObfEnabled()) {
321         this->filepath_.name = this->name_;
322         return;
323     }
324 
325     if (this->isNormalizedOhmUrl_) {
326         CreateFilePathForNormalizedMode();
327     } else {
328         CreateFilePathForDefaultMode();
329     }
330 }
331 
CreateFilePathForDefaultMode()332 void panda::guard::Node::CreateFilePathForDefaultMode()
333 {
334     bool isRemoteHar = StringUtil::IsPrefixMatched(name_, PACKAGE_MODULES_PREFIX.data());
335     if (isRemoteHar) {
336         std::string prefix = pkgName_ + PATH_DELIMITER.data();
337         PANDA_GUARD_ASSERT_PRINT(!StringUtil::IsPrefixMatched(name_, prefix), TAG, ErrorCode::GENERIC_ERROR,
338                                  "invalid remote har prefix");
339         filepath_.prePart = std::move(prefix);
340 
341         filepath_.name = name_.substr(filepath_.prePart.size(), name_.size() - filepath_.prePart.size());
342         return;
343     }
344 
345     // format: bundleName/hapPkgName@pkgName/filepath
346     size_t startPos = name_.find_first_of(PATH_DELIMITER.data(), 0);
347     if (startPos == std::string::npos) {
348         filepath_.name = name_;
349         return;
350     }
351 
352     std::string toFound = pkgName_ + PATH_DELIMITER.data();
353     size_t foundPos = name_.find(toFound, startPos);
354     if (foundPos == std::string::npos) {
355         filepath_.name = name_;
356         return;
357     }
358 
359     foundPos += toFound.size();
360     filepath_.prePart = name_.substr(0, foundPos);
361     filepath_.name = name_.substr(foundPos, name_.size() - foundPos);
362 }
363 
CreateFilePathForNormalizedMode()364 void panda::guard::Node::CreateFilePathForNormalizedMode()
365 {
366     // [<bundle name>?]&<package name>/<file path>&[<version>?]
367     size_t startPos = name_.find_first_of(NORMALIZED_OHM_DELIMITER.data(), 0);
368     std::string prefix = NORMALIZED_OHM_DELIMITER.data() + pkgName_ + PATH_DELIMITER.data();
369     PANDA_GUARD_ASSERT_PRINT(!StringUtil::IsPrefixMatched(name_, prefix, startPos), TAG, ErrorCode::GENERIC_ERROR,
370                              "invalid normalizedOhmUrl prefix");
371     size_t prefixEnd = startPos + prefix.size();
372     filepath_.prePart = name_.substr(0, prefixEnd);
373 
374     size_t filePathEnd = name_.find_first_of(NORMALIZED_OHM_DELIMITER.data(), prefixEnd);
375     PANDA_GUARD_ASSERT_PRINT(filePathEnd == std::string::npos, TAG, ErrorCode::GENERIC_ERROR,
376                              "invalid normalizedOhmUrl format");
377     filepath_.name = name_.substr(prefixEnd, filePathEnd - prefixEnd);
378 
379     filepath_.postPart = name_.substr(filePathEnd, name_.size() - filePathEnd);
380 }
381 
ExtractNames()382 void panda::guard::Node::ExtractNames()
383 {
384     moduleRecord_.ExtractNames(this->strings_);
385 
386     for (const auto &[_, function] : this->functionTable_) {
387         function.ExtractNames(this->strings_);
388     }
389 
390     for (const auto &[_, clazz] : this->classTable_) {
391         clazz.ExtractNames(this->strings_);
392     }
393 
394     for (const auto &[_, object] : this->objectTable_) {
395         object.ExtractNames(this->strings_);
396     }
397 
398     auto parts = StringUtil::Split(filepath_.name, PATH_DELIMITER.data());
399     for (const auto &part : parts) {
400         this->strings_.emplace(part);
401     }
402 
403     GuardContext::GetInstance()->GetNameMapping()->AddReservedNames(this->strings_);
404 
405     LOG(INFO, PANDAGUARD) << TAG << "strings:";
406     for (const auto &str : this->strings_) {
407         LOG(INFO, PANDAGUARD) << TAG << str;
408     }
409 }
410 
RefreshNeedUpdate()411 void panda::guard::Node::RefreshNeedUpdate()
412 {
413     this->fileNameNeedUpdate_ = GuardContext::GetInstance()->GetGuardOptions()->IsFileNameObfEnabled();
414 
415     if (GuardContext::GetInstance()->GetGuardOptions()->IsKeepPath(this->name_)) {
416         LOG(INFO, PANDAGUARD) << TAG << "found keep rule for:" << this->name_;
417         this->contentNeedUpdate_ = false;
418         GuardContext::GetInstance()->GetNameMapping()->AddNameMapping(this->strings_);
419     }
420 
421     for (auto &[_, object] : this->objectTable_) {
422         object.SetContentNeedUpdate(this->contentNeedUpdate_);
423     }
424 
425     this->needUpdate = this->fileNameNeedUpdate_ || this->contentNeedUpdate_;
426 }
427 
ForEachFunction(const std::function<FunctionTraver> & callback)428 void panda::guard::Node::ForEachFunction(const std::function<FunctionTraver> &callback)
429 {
430     for (auto &[_, function] : this->functionTable_) {
431         callback(function);
432     }
433 
434     for (auto &[_, clazz] : this->classTable_) {
435         clazz.ForEachFunction(callback);
436     }
437 
438     for (auto &[_, object] : this->objectTable_) {
439         object.ForEachMethod(callback);
440     }
441 }
442 
Update()443 void panda::guard::Node::Update()
444 {
445     LOG(INFO, PANDAGUARD) << TAG << "node update for " << this->name_ << " start";
446 
447     if (this->fileNameNeedUpdate_) {
448         UpdateFileNameDefine();
449     }
450 
451     // fileNameNeedUpdate_ || contentNeedUpdate_
452     for (auto &[_, function] : this->functionTable_) {
453         function.Obfuscate();
454         function.WriteNameCache(this->sourceName_);
455     }
456 
457     for (auto &[_, clazz] : this->classTable_) {
458         clazz.Obfuscate();
459         clazz.WriteNameCache(this->sourceName_);
460     }
461 
462     for (auto &[_, object] : this->objectTable_) {
463         object.Obfuscate();
464         object.WriteNameCache(this->sourceName_);
465     }
466 
467     for (auto &property : this->outerProperties_) {
468         property.Obfuscate();
469         property.WriteNameCache(this->sourceName_);
470     }
471 
472     if (this->contentNeedUpdate_) {
473         moduleRecord_.Obfuscate();
474         moduleRecord_.WriteNameCache(this->sourceName_);
475     }
476 
477     this->WriteFileCache(this->sourceName_);
478 
479     LOG(INFO, PANDAGUARD) << TAG << "node update for " << this->name_ << " end";
480 }
481 
WriteFileCache(const std::string & filePath)482 void panda::guard::Node::WriteFileCache(const std::string &filePath)
483 {
484     GuardContext::GetInstance()->GetNameCache()->AddObfName(filePath, this->obfSourceName_);
485     GuardContext::GetInstance()->GetNameCache()->AddSourceFile(filePath, this->sourceFile_, this->obfSourceFile_);
486 }
487 
UpdateRecordTable()488 void panda::guard::Node::UpdateRecordTable()
489 {
490     auto entry = this->program_->prog_->record_table.extract(this->name_);
491     entry.key() = this->obfName_;
492     entry.mapped().name = this->obfName_;
493     if (!entry.mapped().source_file.empty()) {
494         this->UpdateSourceFile(entry.mapped().source_file);
495         entry.mapped().source_file = this->obfSourceFile_;
496     }
497     this->program_->prog_->record_table.insert(std::move(entry));
498 }
499 
UpdateFileNameDefine()500 void panda::guard::Node::UpdateFileNameDefine()
501 {
502     filepath_.obfName = GuardContext::GetInstance()->GetNameMapping()->GetFilePath(filepath_.name);
503     obfName_ = filepath_.prePart + filepath_.obfName + filepath_.postPart;
504     UpdateRecordTable();
505 
506     /* e.g.
507      *  sourceName_: entry/src/main/ets/entryability/EntryAbility.ets
508      *  filepath_.name: src/main/ets/entryability/EntryAbility
509      *  sourceNamePrePart: entry/
510      *  sourceNamePostPart: .ets
511      */
512     const auto &[sourceNamePrePart, sourceNamePostPart] = StringUtil::RSplitOnce(this->sourceName_, filepath_.name);
513     if (sourceNamePrePart.empty() && sourceNamePostPart.empty()) {
514         this->obfSourceName_ = obfName_;
515     } else {
516         this->obfSourceName_ = sourceNamePrePart + filepath_.obfName + sourceNamePostPart;
517     }
518 }
519 
UpdateFileNameReferences()520 void panda::guard::Node::UpdateFileNameReferences()
521 {
522     moduleRecord_.UpdateFileNameReferences();
523 }
524 
UpdateSourceFile(const std::string & file)525 void panda::guard::Node::UpdateSourceFile(const std::string &file)
526 {
527     PANDA_GUARD_ASSERT_PRINT(file != this->sourceFile_, TAG, ErrorCode::GENERIC_ERROR, "duplicate source file" << file);
528     if (this->sourceFileUpdated_) {
529         return;
530     }
531 
532     this->sourceFile_ = file;
533 
534     /* e.g.
535      *  file: entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ets
536      *  filepath_.name: src/main/ets/entryability/EntryAbility
537      *  prefix: entry|entry|1.0.0|
538      *  suffix: .ets
539      */
540     const auto &[prefix, suffix] = StringUtil::RSplitOnce(file, filepath_.name);
541     PANDA_GUARD_ASSERT_PRINT(file != filepath_.name && prefix.empty() && suffix.empty(), TAG, ErrorCode::GENERIC_ERROR,
542                              "invalid source file" << file << ",record: " << this->name_);
543     this->obfSourceFile_ = prefix + filepath_.obfName + suffix;
544     this->sourceFileUpdated_ = true;
545 
546     LOG(INFO, PANDAGUARD) << TAG << "source_file: " << this->sourceFile_;
547 }
548 
UpdateScopeNames()549 void panda::guard::Node::UpdateScopeNames()
550 {
551     LOG(INFO, PANDAGUARD) << TAG << "update scopeNames for:" << this->name_;
552     auto &record = this->program_->prog_->record_table.at(this->obfName_);
553     for (auto &it : record.field_list) {
554         if (it.name == SCOPE_NAMES_FIELD) {
555             const auto &literalArrayIdx = it.metadata->GetValue()->GetValue<std::string>();
556             LOG(INFO, PANDAGUARD) << TAG << "scopeNames literalArrayIdx:" << literalArrayIdx;
557             auto &literalArray = this->program_->prog_->literalarray_table.at(literalArrayIdx);
558             UpdateScopeNamesLiteralArray(literalArray);
559             break;
560         }
561     }
562 }
563 
FindPkgName(const panda::pandasm::Record & record,std::string & pkgName)564 bool panda::guard::Node::FindPkgName(const panda::pandasm::Record &record, std::string &pkgName)
565 {
566     return std::any_of(
567         record.field_list.begin(), record.field_list.end(), [&](const panda::pandasm::Field &field) -> bool {
568             bool found = field.name.rfind(PKG_NAME_PREFIX, 0) == 0;
569             if (found) {
570                 pkgName = field.name.substr(PKG_NAME_PREFIX.size(), field.name.size() - PKG_NAME_PREFIX.size());
571             }
572             return found;
573         });
574 }
575 
IsJsonFile(const pandasm::Record & record)576 bool panda::guard::Node::IsJsonFile(const pandasm::Record &record)
577 {
578     return std::any_of(record.field_list.begin(), record.field_list.end(),
579                        [](const auto &field) { return field.name == JSON_FILE_FIELD; });
580 }
581 
GetMethodNameInfo(const panda::guard::InstructionInfo & info,panda::guard::InstructionInfo & nameInfo)582 void panda::guard::Node::GetMethodNameInfo(const panda::guard::InstructionInfo &info,
583                                            panda::guard::InstructionInfo &nameInfo)
584 {
585     if (!info.IsValid()) {
586         return;
587     }
588 
589     if (InOpcodeList(info, METHOD_NAME_DIRECT_LIST)) {
590         nameInfo = info;
591     } else if (InOpcodeList(info, METHOD_NAME_INDIRECT_LIST)) {
592         GraphAnalyzer::GetLdaStr(info, nameInfo);
593     }
594 }
595