• 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 "class.h"
17 
18 #include "utils/logger.h"
19 
20 #include "configs/guard_context.h"
21 #include "program.h"
22 #include "util/assert_util.h"
23 
24 namespace {
25 constexpr std::string_view TAG = "[Class]";
26 constexpr size_t LITERAL_ITEM_LEN = 2;               // 每两组元素表示一条数据tag-value
27 constexpr size_t LITERAL_METHOD_GROUP_LEN = 6;       // 每6组元素表示1个方法
28 constexpr size_t CALL_RUNTIME_LITERAL_ITEM_LEN = 2;  // 1组2个元素 记录运行信息
29 }  // namespace
30 
Build()31 void panda::guard::Class::Build()
32 {
33     LOG(INFO, PANDAGUARD) << TAG << "class build for " << this->constructor_.idx_ << " start";
34 
35     LOG(INFO, PANDAGUARD) << TAG << "isComponent:" << (this->component ? "true" : "false");
36 
37     this->constructor_.defineInsList_ = this->defineInsList_;
38     this->constructor_.scope_ = this->scope_;
39     this->constructor_.Init();
40 
41     // init class base info
42     this->name_ = this->constructor_.name_;
43     this->SetNameCacheScope(this->name_);
44     this->constructor_.export_ = this->moduleRecord_->IsExportVar(this->constructor_.name_);
45     this->export_ = this->constructor_.export_;
46 
47     this->constructor_.Create();
48 
49     auto &literalArrayTable = program_->prog_->literalarray_table;
50     auto it = literalArrayTable.find(this->literalArrayIdx_);
51     PANDA_GUARD_ASSERT_PRINT(it == literalArrayTable.end(), TAG, ErrorCode::GENERIC_ERROR,
52                              "get bad literalArrayIdx:" << literalArrayIdx_);
53     CreateMethods(it->second);
54 
55     LOG(INFO, PANDAGUARD) << TAG << "class build for " << this->constructor_.idx_ << " end";
56 }
57 
GetMethodCnt() const58 size_t panda::guard::Class::GetMethodCnt() const
59 {
60     return this->methods_.size() + this->outerMethods_.size();
61 }
62 
GetPropertyCnt() const63 size_t panda::guard::Class::GetPropertyCnt() const
64 {
65     size_t cnt = 0;
66     for (const auto &method : this->methods_) {
67         cnt += method.properties_.size();
68     }
69 
70     for (const auto &method : this->outerMethods_) {
71         cnt += method.properties_.size();
72     }
73 
74     return cnt;
75 }
76 
ForEachMethodIns(const std::function<InsTraver> & callback)77 void panda::guard::Class::ForEachMethodIns(const std::function<InsTraver> &callback)
78 {
79     this->ForEachFunction([&callback](Function &func) { func.ForEachIns(callback); });
80 }
81 
ForEachFunction(const std::function<FunctionTraver> & callback)82 void panda::guard::Class::ForEachFunction(const std::function<FunctionTraver> &callback)
83 {
84     callback(this->constructor_);
85     for (auto &method : this->methods_) {
86         callback(method);
87     }
88 
89     for (auto &method : this->outerMethods_) {
90         callback(method);
91     }
92 }
93 
ExtractNames(std::set<std::string> & strings) const94 void panda::guard::Class::ExtractNames(std::set<std::string> &strings) const
95 {
96     this->constructor_.ExtractNames(strings);
97 
98     for (const auto &method : this->methods_) {
99         method.ExtractNames(strings);
100     }
101 
102     for (const auto &method : this->outerMethods_) {
103         method.ExtractNames(strings);
104     }
105 }
106 
CreateMethods(const pandasm::LiteralArray & literalArray)107 void panda::guard::Class::CreateMethods(const pandasm::LiteralArray &literalArray)
108 {
109     LOG(INFO, PANDAGUARD) << TAG << "literalArray size:" << literalArray.literals_.size();
110     size_t staticMethodIndexLiteralIndex = literalArray.literals_.size() - 1;
111     size_t methodItemCount = literalArray.literals_.size() - LITERAL_ITEM_LEN;
112     if (callRunTimeInst_) {
113         staticMethodIndexLiteralIndex -= CALL_RUNTIME_LITERAL_ITEM_LEN;
114         methodItemCount -= CALL_RUNTIME_LITERAL_ITEM_LEN;
115     }
116 
117     const auto &staticMethodIndexLiteral = literalArray.literals_[staticMethodIndexLiteralIndex];
118     PANDA_GUARD_ASSERT_PRINT(staticMethodIndexLiteral.tag_ != panda::panda_file::LiteralTag::INTEGER, TAG,
119                              ErrorCode::GENERIC_ERROR, "bad tag for staticMethodIndex");
120 
121     const uint32_t staticMethodIndex = std::get<uint32_t>(staticMethodIndexLiteral.value_);
122     const size_t methodCount = methodItemCount / LITERAL_METHOD_GROUP_LEN;
123     LOG(INFO, PANDAGUARD) << TAG << "methodCount:" << methodCount;
124 
125     for (size_t i = 0; i < methodCount; i++) {
126         CreateMethod(literalArray, i * LITERAL_METHOD_GROUP_LEN, i >= staticMethodIndex);
127     }
128 }
129 
CreateMethod(const pandasm::LiteralArray & literalArray,size_t index,bool isStatic)130 void panda::guard::Class::CreateMethod(const pandasm::LiteralArray &literalArray, size_t index, bool isStatic)
131 {
132     const size_t methodNameLiteralIndex = index + 1;
133     const auto &methodNameLiteral = literalArray.literals_[methodNameLiteralIndex];
134     PANDA_GUARD_ASSERT_PRINT(methodNameLiteral.tag_ != panda::panda_file::LiteralTag::STRING, TAG,
135                              ErrorCode::GENERIC_ERROR, "bad tag for methodName");
136 
137     const std::string methodName = std::get<std::string>(methodNameLiteral.value_);
138     LOG(INFO, PANDAGUARD) << TAG << "methodName:" << methodName;
139 
140     const size_t methodIdxLiteralIndex = methodNameLiteralIndex + LITERAL_ITEM_LEN;
141     PANDA_GUARD_ASSERT_PRINT(methodIdxLiteralIndex >= literalArray.literals_.size(), TAG, ErrorCode::GENERIC_ERROR,
142                              "methodIdxLiteralIndex offset overflow");
143     const auto &[tag_, value_] = literalArray.literals_[methodIdxLiteralIndex];
144     PANDA_GUARD_ASSERT_PRINT(tag_ != panda::panda_file::LiteralTag::METHOD, TAG, ErrorCode::GENERIC_ERROR,
145                              "bad tag for methodIdx");
146 
147     const std::string methodIdx = std::get<std::string>(value_);
148     LOG(INFO, PANDAGUARD) << TAG << "methodIdx:" << methodIdx;
149 
150     Method method(this->program_, methodIdx);
151     method.literalArrayIdx_ = this->literalArrayIdx_;
152     method.className_ = this->name_;
153     method.idxIndex_ = methodIdxLiteralIndex;
154     method.nameIndex_ = methodNameLiteralIndex;
155     method.static_ = isStatic;
156     method.scope_ = this->scope_;
157     method.export_ = this->export_;
158 
159     method.Init();
160     method.Create();
161     PANDA_GUARD_ASSERT_PRINT(method.name_ != methodName, TAG, ErrorCode::GENERIC_ERROR,
162                              "get different name for method:" << method.idx_);
163 
164     this->methods_.push_back(method);
165 }
166 
Update()167 void panda::guard::Class::Update()
168 {
169     LOG(INFO, PANDAGUARD) << TAG << "class update for " << this->name_ << " start";
170     this->constructor_.Obfuscate();
171     this->obfName_ = this->constructor_.obfName_;
172 
173     for (auto &method : this->methods_) {
174         method.Obfuscate();
175     }
176 
177     for (auto &method : this->outerMethods_) {
178         method.Obfuscate();
179     }
180 
181     LOG(INFO, PANDAGUARD) << TAG << "class update for " << this->name_ << " end";
182 }
183 
WriteNameCache(const std::string & filePath)184 void panda::guard::Class::WriteNameCache(const std::string &filePath)
185 {
186     if (!this->obfuscated) {
187         return;
188     }
189     this->WriteFileCache(filePath);
190     this->WritePropertyCache();
191 
192     this->constructor_.WriteNameCache(filePath);
193     for (auto &property : this->constructor_.properties_) {
194         property.WriteNameCache(filePath);
195     }
196 
197     for (auto &method : this->methods_) {
198         method.WriteNameCache(filePath);
199     }
200 
201     for (auto &method : this->outerMethods_) {
202         method.WriteNameCache(filePath);
203     }
204 }
205 
WriteFileCache(const std::string & filePath)206 void panda::guard::Class::WriteFileCache(const std::string &filePath)
207 {
208     if (!constructor_.nameNeedUpdate_) {
209         return;
210     }
211 
212     GuardContext::GetInstance()->GetNameCache()->AddObfIdentifierName(filePath, this->GetNameCacheScope(),
213                                                                       this->obfName_);
214 }
215 
WritePropertyCache()216 void panda::guard::Class::WritePropertyCache()
217 {
218     TopLevelOptionEntity::WritePropertyCache(*this);
219 }
220