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 "subclasses_scanner.h"
17 #include <string>
18
Run()19 void SubclassesScanner::Run()
20 {
21 visitor_.EnumerateModules([&](AbckitCoreModule *mod) {
22 std::vector<std::pair<AbckitCoreImportDescriptor *, size_t>> impDescriptors;
23 GetImportDescriptors(mod, impDescriptors);
24 if (impDescriptors.empty()) {
25 return;
26 }
27 visitor_.EnumerateModuleFunctions(
28 mod, [&](AbckitCoreFunction *method) { CollectSubClasses(method, impDescriptors); });
29 });
30 }
31
CollectSubClasses(AbckitCoreFunction * method,const std::vector<std::pair<AbckitCoreImportDescriptor *,size_t>> & impDescrs)32 void SubclassesScanner::CollectSubClasses(AbckitCoreFunction *method,
33 const std::vector<std::pair<AbckitCoreImportDescriptor *, size_t>> &impDescrs)
34 {
35 visitor_.EnumerateFunctionInsts(method, [&](AbckitInst *inst) {
36 for (const auto &[impDescr, idx] : impDescrs) {
37 ClassInfo classInfo;
38 if (IsLoadApi(impDescr, inst, classInfo)) {
39 subClasses_.emplace_back(classInfo);
40 }
41 }
42 });
43 }
44
IsLoadApi(AbckitCoreImportDescriptor * id,AbckitInst * inst,ClassInfo & subclassInfo)45 bool SubclassesScanner::IsLoadApi(AbckitCoreImportDescriptor *id, AbckitInst *inst, ClassInfo &subclassInfo)
46 {
47 if (dynG_->iGetOpcode(inst) != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR) {
48 return false;
49 }
50
51 if (dynG_->iGetImportDescriptor(inst) != id) {
52 return false;
53 }
54
55 bool found = false;
56 visitor_.EnumerateInstUsers(inst, [&](AbckitInst *user) {
57 if (dynG_->iGetOpcode(user) == ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINECLASSWITHBUFFER) {
58 auto method = implG_->iGetFunction(user);
59 auto klass = implI_->functionGetParentClass(method);
60 auto module = implI_->classGetModule(klass);
61 subclassInfo.className = visitor_.GetString(implI_->classGetName(klass));
62 subclassInfo.path = visitor_.GetString(implI_->moduleGetName(module));
63 found = true;
64 }
65 });
66
67 return found;
68 }
69
70 // CC-OFFNXT(G.INC.12-CPP) false positive. this function can not be made static.
GetImportDescriptors(AbckitCoreModule * mod,std::vector<std::pair<AbckitCoreImportDescriptor *,size_t>> & importDescriptors)71 void SubclassesScanner::GetImportDescriptors(
72 AbckitCoreModule *mod, std::vector<std::pair<AbckitCoreImportDescriptor *, size_t>> &importDescriptors)
73 {
74 visitor_.EnumerateModuleImports(mod, [&](AbckitCoreImportDescriptor *id) {
75 auto importName = visitor_.GetString(implI_->importDescriptorGetName(id));
76 auto *importedModule = implI_->importDescriptorGetImportedModule(id);
77 auto source = visitor_.GetString(implI_->moduleGetName(importedModule));
78 for (size_t i = 0; i < baseClasses_.size(); ++i) {
79 const auto baseClass = baseClasses_[i];
80 if (source != baseClass.path) {
81 continue;
82 }
83 if (importName == baseClass.className) {
84 importDescriptors.emplace_back(id, i);
85 }
86 }
87 });
88 }
89
IsEqualsSubClasses(const std::vector<ClassInfo> & otherSubClasses)90 bool SubclassesScanner::IsEqualsSubClasses(const std::vector<ClassInfo> &otherSubClasses)
91 {
92 for (auto &otherSubClass : otherSubClasses) {
93 auto iter = std::find_if(subClasses_.begin(), subClasses_.end(), [&otherSubClass](const ClassInfo &classInfo) {
94 return (otherSubClass.className == classInfo.className) && (otherSubClass.path == classInfo.path);
95 });
96 if (iter == subClasses_.end()) {
97 return false;
98 }
99 }
100 return true;
101 }
102