• 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 "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