xref: /aosp_15_r20/tools/dexter/slicer/dex_ir_builder.cc (revision f0dffb02cdb5c647d21204e89a92a1ffae2dad87)
1*f0dffb02SXin Li /*
2*f0dffb02SXin Li  * Copyright (C) 2017 The Android Open Source Project
3*f0dffb02SXin Li  *
4*f0dffb02SXin Li  * Licensed under the Apache License, Version 2.0 (the "License");
5*f0dffb02SXin Li  * you may not use this file except in compliance with the License.
6*f0dffb02SXin Li  * You may obtain a copy of the License at
7*f0dffb02SXin Li  *
8*f0dffb02SXin Li  *      http://www.apache.org/licenses/LICENSE-2.0
9*f0dffb02SXin Li  *
10*f0dffb02SXin Li  * Unless required by applicable law or agreed to in writing, software
11*f0dffb02SXin Li  * distributed under the License is distributed on an "AS IS" BASIS,
12*f0dffb02SXin Li  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f0dffb02SXin Li  * See the License for the specific language governing permissions and
14*f0dffb02SXin Li  * limitations under the License.
15*f0dffb02SXin Li  */
16*f0dffb02SXin Li 
17*f0dffb02SXin Li #include "slicer/dex_ir_builder.h"
18*f0dffb02SXin Li 
19*f0dffb02SXin Li #include <sstream>
20*f0dffb02SXin Li #include <string.h>
21*f0dffb02SXin Li 
22*f0dffb02SXin Li namespace ir {
23*f0dffb02SXin Li 
Match(MethodDecl * method_decl) const24*f0dffb02SXin Li bool MethodId::Match(MethodDecl* method_decl) const {
25*f0dffb02SXin Li   return ::strcmp(class_descriptor, method_decl->parent->descriptor->c_str()) == 0
26*f0dffb02SXin Li     && ::strcmp(method_name, method_decl->name->c_str()) == 0
27*f0dffb02SXin Li     && method_decl->prototype->Signature() == signature;
28*f0dffb02SXin Li }
29*f0dffb02SXin Li 
FindMethod(const MethodId & method_id) const30*f0dffb02SXin Li EncodedMethod* Builder::FindMethod(const MethodId& method_id) const {
31*f0dffb02SXin Li   // first, lookup the strings
32*f0dffb02SXin Li   auto ir_descriptor = FindAsciiString(method_id.class_descriptor);
33*f0dffb02SXin Li   auto ir_method_name = FindAsciiString(method_id.method_name);
34*f0dffb02SXin Li   if (ir_descriptor == nullptr || ir_method_name == nullptr) {
35*f0dffb02SXin Li     return nullptr;
36*f0dffb02SXin Li   }
37*f0dffb02SXin Li 
38*f0dffb02SXin Li   // look up the prototype
39*f0dffb02SXin Li   auto ir_prototype = FindPrototype(method_id.signature);
40*f0dffb02SXin Li   if (ir_prototype == nullptr) {
41*f0dffb02SXin Li     return nullptr;
42*f0dffb02SXin Li   }
43*f0dffb02SXin Li 
44*f0dffb02SXin Li   // look up the method itself
45*f0dffb02SXin Li   ir::MethodKey method_key;
46*f0dffb02SXin Li   method_key.class_descriptor = ir_descriptor;
47*f0dffb02SXin Li   method_key.method_name = ir_method_name;
48*f0dffb02SXin Li   method_key.prototype = ir_prototype;
49*f0dffb02SXin Li   return dex_ir_->methods_lookup.Lookup(method_key);
50*f0dffb02SXin Li }
51*f0dffb02SXin Li 
FindPrototype(const char * signature) const52*f0dffb02SXin Li Proto* Builder::FindPrototype(const char* signature) const {
53*f0dffb02SXin Li   return dex_ir_->prototypes_lookup.Lookup(signature);
54*f0dffb02SXin Li }
55*f0dffb02SXin Li 
FindAsciiString(const char * cstr) const56*f0dffb02SXin Li String* Builder::FindAsciiString(const char* cstr) const {
57*f0dffb02SXin Li     return dex_ir_->strings_lookup.Lookup(cstr);
58*f0dffb02SXin Li }
59*f0dffb02SXin Li 
GetAsciiString(const char * cstr)60*f0dffb02SXin Li String* Builder::GetAsciiString(const char* cstr) {
61*f0dffb02SXin Li   // look for the string first...
62*f0dffb02SXin Li   auto ir_string = FindAsciiString(cstr);
63*f0dffb02SXin Li   if(ir_string != nullptr) {
64*f0dffb02SXin Li     return ir_string;
65*f0dffb02SXin Li   }
66*f0dffb02SXin Li 
67*f0dffb02SXin Li   // create a new string data
68*f0dffb02SXin Li   dex::u4 len = strlen(cstr);
69*f0dffb02SXin Li   slicer::Buffer buff;
70*f0dffb02SXin Li   buff.PushULeb128(len);
71*f0dffb02SXin Li   buff.Push(cstr, len + 1);
72*f0dffb02SXin Li   buff.Seal(1);
73*f0dffb02SXin Li 
74*f0dffb02SXin Li   // create the new .dex IR string node
75*f0dffb02SXin Li   ir_string = dex_ir_->Alloc<String>();
76*f0dffb02SXin Li   ir_string->data = slicer::MemView(buff.data(), buff.size());
77*f0dffb02SXin Li 
78*f0dffb02SXin Li   // update the index -> ir node map
79*f0dffb02SXin Li   auto new_index = dex_ir_->strings_indexes.AllocateIndex();
80*f0dffb02SXin Li   auto& ir_node = dex_ir_->strings_map[new_index];
81*f0dffb02SXin Li   SLICER_CHECK_EQ(ir_node, nullptr);
82*f0dffb02SXin Li   ir_node = ir_string;
83*f0dffb02SXin Li   ir_string->orig_index = new_index;
84*f0dffb02SXin Li 
85*f0dffb02SXin Li   // attach the new string data to the .dex IR
86*f0dffb02SXin Li   dex_ir_->AttachBuffer(std::move(buff));
87*f0dffb02SXin Li 
88*f0dffb02SXin Li   // update the strings lookup table
89*f0dffb02SXin Li   dex_ir_->strings_lookup.Insert(ir_string);
90*f0dffb02SXin Li 
91*f0dffb02SXin Li   return ir_string;
92*f0dffb02SXin Li }
93*f0dffb02SXin Li 
GetType(String * descriptor)94*f0dffb02SXin Li Type* Builder::GetType(String* descriptor) {
95*f0dffb02SXin Li   // look for an existing type
96*f0dffb02SXin Li   for (const auto& ir_type : dex_ir_->types) {
97*f0dffb02SXin Li     if (ir_type->descriptor == descriptor) {
98*f0dffb02SXin Li       return ir_type.get();
99*f0dffb02SXin Li     }
100*f0dffb02SXin Li   }
101*f0dffb02SXin Li 
102*f0dffb02SXin Li   // create a new type
103*f0dffb02SXin Li   auto ir_type = dex_ir_->Alloc<Type>();
104*f0dffb02SXin Li   ir_type->descriptor = descriptor;
105*f0dffb02SXin Li 
106*f0dffb02SXin Li   // update the index -> ir node map
107*f0dffb02SXin Li   auto new_index = dex_ir_->types_indexes.AllocateIndex();
108*f0dffb02SXin Li   auto& ir_node = dex_ir_->types_map[new_index];
109*f0dffb02SXin Li   SLICER_CHECK_EQ(ir_node, nullptr);
110*f0dffb02SXin Li   ir_node = ir_type;
111*f0dffb02SXin Li   ir_type->orig_index = new_index;
112*f0dffb02SXin Li 
113*f0dffb02SXin Li   return ir_type;
114*f0dffb02SXin Li }
115*f0dffb02SXin Li 
GetTypeList(const std::vector<Type * > & types)116*f0dffb02SXin Li TypeList* Builder::GetTypeList(const std::vector<Type*>& types) {
117*f0dffb02SXin Li   if (types.empty()) {
118*f0dffb02SXin Li     return nullptr;
119*f0dffb02SXin Li   }
120*f0dffb02SXin Li 
121*f0dffb02SXin Li   // look for an existing TypeList
122*f0dffb02SXin Li   for (const auto& ir_type_list : dex_ir_->type_lists) {
123*f0dffb02SXin Li     if (ir_type_list->types == types) {
124*f0dffb02SXin Li       return ir_type_list.get();
125*f0dffb02SXin Li     }
126*f0dffb02SXin Li   }
127*f0dffb02SXin Li 
128*f0dffb02SXin Li   // create a new TypeList
129*f0dffb02SXin Li   auto ir_type_list = dex_ir_->Alloc<TypeList>();
130*f0dffb02SXin Li   ir_type_list->types = types;
131*f0dffb02SXin Li   return ir_type_list;
132*f0dffb02SXin Li }
133*f0dffb02SXin Li 
134*f0dffb02SXin Li // Helper for GetProto()
CreateShorty(Type * return_type,TypeList * param_types)135*f0dffb02SXin Li static std::string CreateShorty(Type* return_type, TypeList* param_types) {
136*f0dffb02SXin Li   std::stringstream ss;
137*f0dffb02SXin Li   ss << dex::DescriptorToShorty(return_type->descriptor->c_str());
138*f0dffb02SXin Li   if (param_types != nullptr) {
139*f0dffb02SXin Li     for (auto param_type : param_types->types) {
140*f0dffb02SXin Li       ss << dex::DescriptorToShorty(param_type->descriptor->c_str());
141*f0dffb02SXin Li     }
142*f0dffb02SXin Li   }
143*f0dffb02SXin Li   return ss.str();
144*f0dffb02SXin Li }
145*f0dffb02SXin Li 
GetProto(Type * return_type,TypeList * param_types)146*f0dffb02SXin Li Proto* Builder::GetProto(Type* return_type, TypeList* param_types) {
147*f0dffb02SXin Li   // create "shorty" descriptor automatically
148*f0dffb02SXin Li   auto shorty = GetAsciiString(CreateShorty(return_type, param_types).c_str());
149*f0dffb02SXin Li 
150*f0dffb02SXin Li   // look for an existing proto
151*f0dffb02SXin Li   for (const auto& ir_proto : dex_ir_->protos) {
152*f0dffb02SXin Li     if (ir_proto->shorty == shorty &&
153*f0dffb02SXin Li         ir_proto->return_type == return_type &&
154*f0dffb02SXin Li         ir_proto->param_types == param_types) {
155*f0dffb02SXin Li       return ir_proto.get();
156*f0dffb02SXin Li     }
157*f0dffb02SXin Li   }
158*f0dffb02SXin Li 
159*f0dffb02SXin Li   // create a new proto
160*f0dffb02SXin Li   auto ir_proto = dex_ir_->Alloc<Proto>();
161*f0dffb02SXin Li   ir_proto->shorty = shorty;
162*f0dffb02SXin Li   ir_proto->return_type = return_type;
163*f0dffb02SXin Li   ir_proto->param_types = param_types;
164*f0dffb02SXin Li 
165*f0dffb02SXin Li   // update the index -> ir node map
166*f0dffb02SXin Li   auto new_index = dex_ir_->protos_indexes.AllocateIndex();
167*f0dffb02SXin Li   auto& ir_node = dex_ir_->protos_map[new_index];
168*f0dffb02SXin Li   SLICER_CHECK_EQ(ir_node, nullptr);
169*f0dffb02SXin Li   ir_node = ir_proto;
170*f0dffb02SXin Li   ir_proto->orig_index = new_index;
171*f0dffb02SXin Li 
172*f0dffb02SXin Li   // update the prototypes lookup table
173*f0dffb02SXin Li   dex_ir_->prototypes_lookup.Insert(ir_proto);
174*f0dffb02SXin Li 
175*f0dffb02SXin Li   return ir_proto;
176*f0dffb02SXin Li }
177*f0dffb02SXin Li 
GetFieldDecl(String * name,Type * type,Type * parent)178*f0dffb02SXin Li FieldDecl* Builder::GetFieldDecl(String* name, Type* type, Type* parent) {
179*f0dffb02SXin Li   // look for an existing field
180*f0dffb02SXin Li   for (const auto& ir_field : dex_ir_->fields) {
181*f0dffb02SXin Li     if (ir_field->name == name &&
182*f0dffb02SXin Li         ir_field->type == type &&
183*f0dffb02SXin Li         ir_field->parent == parent) {
184*f0dffb02SXin Li       return ir_field.get();
185*f0dffb02SXin Li     }
186*f0dffb02SXin Li   }
187*f0dffb02SXin Li 
188*f0dffb02SXin Li   // create a new field declaration
189*f0dffb02SXin Li   auto ir_field = dex_ir_->Alloc<FieldDecl>();
190*f0dffb02SXin Li   ir_field->name = name;
191*f0dffb02SXin Li   ir_field->type = type;
192*f0dffb02SXin Li   ir_field->parent = parent;
193*f0dffb02SXin Li 
194*f0dffb02SXin Li   // update the index -> ir node map
195*f0dffb02SXin Li   auto new_index = dex_ir_->fields_indexes.AllocateIndex();
196*f0dffb02SXin Li   auto& ir_node = dex_ir_->fields_map[new_index];
197*f0dffb02SXin Li   SLICER_CHECK_EQ(ir_node, nullptr);
198*f0dffb02SXin Li   ir_node = ir_field;
199*f0dffb02SXin Li   ir_field->orig_index = new_index;
200*f0dffb02SXin Li 
201*f0dffb02SXin Li   return ir_field;
202*f0dffb02SXin Li }
203*f0dffb02SXin Li 
GetMethodDecl(String * name,Proto * proto,Type * parent)204*f0dffb02SXin Li MethodDecl* Builder::GetMethodDecl(String* name, Proto* proto, Type* parent) {
205*f0dffb02SXin Li   // look for an existing method
206*f0dffb02SXin Li   for (const auto& ir_method : dex_ir_->methods) {
207*f0dffb02SXin Li     if (ir_method->name == name &&
208*f0dffb02SXin Li         ir_method->prototype == proto &&
209*f0dffb02SXin Li         ir_method->parent == parent) {
210*f0dffb02SXin Li       return ir_method.get();
211*f0dffb02SXin Li     }
212*f0dffb02SXin Li   }
213*f0dffb02SXin Li 
214*f0dffb02SXin Li   // create a new method declaration
215*f0dffb02SXin Li   auto ir_method = dex_ir_->Alloc<MethodDecl>();
216*f0dffb02SXin Li   ir_method->name = name;
217*f0dffb02SXin Li   ir_method->prototype = proto;
218*f0dffb02SXin Li   ir_method->parent = parent;
219*f0dffb02SXin Li 
220*f0dffb02SXin Li   // update the index -> ir node map
221*f0dffb02SXin Li   auto new_index = dex_ir_->methods_indexes.AllocateIndex();
222*f0dffb02SXin Li   auto& ir_node = dex_ir_->methods_map[new_index];
223*f0dffb02SXin Li   SLICER_CHECK_EQ(ir_node, nullptr);
224*f0dffb02SXin Li   ir_node = ir_method;
225*f0dffb02SXin Li   ir_method->orig_index = new_index;
226*f0dffb02SXin Li 
227*f0dffb02SXin Li   return ir_method;
228*f0dffb02SXin Li }
229*f0dffb02SXin Li 
230*f0dffb02SXin Li } // namespace ir
231*f0dffb02SXin Li 
232