xref: /aosp_15_r20/tools/dexter/slicer/reader.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/reader.h"
18*f0dffb02SXin Li 
19*f0dffb02SXin Li #include "slicer/chronometer.h"
20*f0dffb02SXin Li #include "slicer/dex_bytecode.h"
21*f0dffb02SXin Li #include "slicer/dex_leb128.h"
22*f0dffb02SXin Li 
23*f0dffb02SXin Li #include <assert.h>
24*f0dffb02SXin Li #include <string.h>
25*f0dffb02SXin Li #include <type_traits>
26*f0dffb02SXin Li #include <cstdlib>
27*f0dffb02SXin Li 
28*f0dffb02SXin Li namespace dex {
29*f0dffb02SXin Li 
Reader(const dex::u1 * image,size_t size)30*f0dffb02SXin Li Reader::Reader(const dex::u1* image, size_t size) : image_(image), size_(size) {
31*f0dffb02SXin Li   // init the header reference
32*f0dffb02SXin Li   header_ = ptr<dex::Header>(0);
33*f0dffb02SXin Li   ValidateHeader();
34*f0dffb02SXin Li 
35*f0dffb02SXin Li   // start with an "empty" .dex IR
36*f0dffb02SXin Li   dex_ir_ = std::make_shared<ir::DexFile>();
37*f0dffb02SXin Li   dex_ir_->magic = slicer::MemView(header_, sizeof(dex::Header::magic));
38*f0dffb02SXin Li }
39*f0dffb02SXin Li 
ClassDefs() const40*f0dffb02SXin Li slicer::ArrayView<const dex::ClassDef> Reader::ClassDefs() const {
41*f0dffb02SXin Li   return section<dex::ClassDef>(header_->class_defs_off,
42*f0dffb02SXin Li                                 header_->class_defs_size);
43*f0dffb02SXin Li }
44*f0dffb02SXin Li 
StringIds() const45*f0dffb02SXin Li slicer::ArrayView<const dex::StringId> Reader::StringIds() const {
46*f0dffb02SXin Li   return section<dex::StringId>(header_->string_ids_off,
47*f0dffb02SXin Li                                 header_->string_ids_size);
48*f0dffb02SXin Li }
49*f0dffb02SXin Li 
TypeIds() const50*f0dffb02SXin Li slicer::ArrayView<const dex::TypeId> Reader::TypeIds() const {
51*f0dffb02SXin Li   return section<dex::TypeId>(header_->type_ids_off,
52*f0dffb02SXin Li                               header_->type_ids_size);
53*f0dffb02SXin Li }
54*f0dffb02SXin Li 
FieldIds() const55*f0dffb02SXin Li slicer::ArrayView<const dex::FieldId> Reader::FieldIds() const {
56*f0dffb02SXin Li   return section<dex::FieldId>(header_->field_ids_off,
57*f0dffb02SXin Li                                header_->field_ids_size);
58*f0dffb02SXin Li }
59*f0dffb02SXin Li 
MethodIds() const60*f0dffb02SXin Li slicer::ArrayView<const dex::MethodId> Reader::MethodIds() const {
61*f0dffb02SXin Li   return section<dex::MethodId>(header_->method_ids_off,
62*f0dffb02SXin Li                                 header_->method_ids_size);
63*f0dffb02SXin Li }
64*f0dffb02SXin Li 
ProtoIds() const65*f0dffb02SXin Li slicer::ArrayView<const dex::ProtoId> Reader::ProtoIds() const {
66*f0dffb02SXin Li   return section<dex::ProtoId>(header_->proto_ids_off,
67*f0dffb02SXin Li                                header_->proto_ids_size);
68*f0dffb02SXin Li }
69*f0dffb02SXin Li 
MethodHandles() const70*f0dffb02SXin Li slicer::ArrayView<const dex::MethodHandle> Reader::MethodHandles() const {
71*f0dffb02SXin Li   const dex::MapList* ml = DexMapList();
72*f0dffb02SXin Li   if(ml == nullptr){
73*f0dffb02SXin Li     slicer::ArrayView<const dex::MethodHandle> ret;
74*f0dffb02SXin Li     return ret;
75*f0dffb02SXin Li   }
76*f0dffb02SXin Li 
77*f0dffb02SXin Li   // Find MethodHandle entry
78*f0dffb02SXin Li   const dex::MapItem* mi = nullptr;
79*f0dffb02SXin Li   for(int i = 0; i < ml->size; i++){
80*f0dffb02SXin Li     if(ml->list[i].type == dex::kMethodHandleItem){
81*f0dffb02SXin Li       mi = &(ml->list[i]);
82*f0dffb02SXin Li       break;
83*f0dffb02SXin Li     }
84*f0dffb02SXin Li   }
85*f0dffb02SXin Li 
86*f0dffb02SXin Li   if(mi == nullptr){
87*f0dffb02SXin Li     slicer::ArrayView<const dex::MethodHandle> ret;
88*f0dffb02SXin Li     return ret;
89*f0dffb02SXin Li   }
90*f0dffb02SXin Li 
91*f0dffb02SXin Li   return section<dex::MethodHandle>(mi->offset, mi->size);
92*f0dffb02SXin Li }
93*f0dffb02SXin Li 
DexMapList() const94*f0dffb02SXin Li const dex::MapList* Reader::DexMapList() const {
95*f0dffb02SXin Li   return dataPtr<dex::MapList>(header_->map_off);
96*f0dffb02SXin Li }
97*f0dffb02SXin Li 
GetStringMUTF8(dex::u4 index) const98*f0dffb02SXin Li const char* Reader::GetStringMUTF8(dex::u4 index) const {
99*f0dffb02SXin Li   if (index == dex::kNoIndex) {
100*f0dffb02SXin Li     return "<no_string>";
101*f0dffb02SXin Li   }
102*f0dffb02SXin Li   const dex::u1* strData = GetStringData(index);
103*f0dffb02SXin Li   dex::ReadULeb128(&strData);
104*f0dffb02SXin Li   return reinterpret_cast<const char*>(strData);
105*f0dffb02SXin Li }
106*f0dffb02SXin Li 
CreateFullIr()107*f0dffb02SXin Li void Reader::CreateFullIr() {
108*f0dffb02SXin Li   size_t classCount = ClassDefs().size();
109*f0dffb02SXin Li   for (size_t i = 0; i < classCount; ++i) {
110*f0dffb02SXin Li     CreateClassIr(i);
111*f0dffb02SXin Li   }
112*f0dffb02SXin Li }
113*f0dffb02SXin Li 
CreateClassIr(dex::u4 index)114*f0dffb02SXin Li void Reader::CreateClassIr(dex::u4 index) {
115*f0dffb02SXin Li   auto ir_class = GetClass(index);
116*f0dffb02SXin Li   SLICER_CHECK_NE(ir_class, nullptr);
117*f0dffb02SXin Li }
118*f0dffb02SXin Li 
119*f0dffb02SXin Li // Returns the index of the class with the specified
120*f0dffb02SXin Li // descriptor, or kNoIndex if not found
FindClassIndex(const char * class_descriptor) const121*f0dffb02SXin Li dex::u4 Reader::FindClassIndex(const char* class_descriptor) const {
122*f0dffb02SXin Li   auto classes = ClassDefs();
123*f0dffb02SXin Li   auto types = TypeIds();
124*f0dffb02SXin Li   for (dex::u4 i = 0; i < classes.size(); ++i) {
125*f0dffb02SXin Li     auto typeId = types[classes[i].class_idx];
126*f0dffb02SXin Li     const char* descriptor = GetStringMUTF8(typeId.descriptor_idx);
127*f0dffb02SXin Li     if (strcmp(class_descriptor, descriptor) == 0) {
128*f0dffb02SXin Li       return i;
129*f0dffb02SXin Li     }
130*f0dffb02SXin Li   }
131*f0dffb02SXin Li   return dex::kNoIndex;
132*f0dffb02SXin Li }
133*f0dffb02SXin Li 
134*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
135*f0dffb02SXin Li //
136*f0dffb02SXin Li // NOTES:
137*f0dffb02SXin Li //  1. the mapping between an index and the indexed
138*f0dffb02SXin Li //     .dex IR nodes is 1:1
139*f0dffb02SXin Li //  2. we do a single index lookup for both existing
140*f0dffb02SXin Li //     nodes as well as new nodes
141*f0dffb02SXin Li //  3. placeholder is an invalid, but non-null pointer value
142*f0dffb02SXin Li //     used to check that the mapping lookup/update is atomic
143*f0dffb02SXin Li //  4. there should be no recursion with the same index
144*f0dffb02SXin Li //     (we use the placeholder value to guard against this too)
145*f0dffb02SXin Li //
GetClass(dex::u4 index)146*f0dffb02SXin Li ir::Class* Reader::GetClass(dex::u4 index) {
147*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
148*f0dffb02SXin Li   auto& p = dex_ir_->classes_map[index];
149*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::Class*>(1);
150*f0dffb02SXin Li   if (p == nullptr) {
151*f0dffb02SXin Li     p = placeholder;
152*f0dffb02SXin Li     auto newClass = ParseClass(index);
153*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
154*f0dffb02SXin Li     p = newClass;
155*f0dffb02SXin Li     dex_ir_->classes_indexes.MarkUsedIndex(index);
156*f0dffb02SXin Li   }
157*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
158*f0dffb02SXin Li   return p;
159*f0dffb02SXin Li }
160*f0dffb02SXin Li 
161*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
162*f0dffb02SXin Li // (see the Reader::GetClass() comments)
GetType(dex::u4 index)163*f0dffb02SXin Li ir::Type* Reader::GetType(dex::u4 index) {
164*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
165*f0dffb02SXin Li   auto& p = dex_ir_->types_map[index];
166*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::Type*>(1);
167*f0dffb02SXin Li   if (p == nullptr) {
168*f0dffb02SXin Li     p = placeholder;
169*f0dffb02SXin Li     auto newType = ParseType(index);
170*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
171*f0dffb02SXin Li     p = newType;
172*f0dffb02SXin Li     dex_ir_->types_indexes.MarkUsedIndex(index);
173*f0dffb02SXin Li   }
174*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
175*f0dffb02SXin Li   return p;
176*f0dffb02SXin Li }
177*f0dffb02SXin Li 
178*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
179*f0dffb02SXin Li // (see the Reader::GetClass() comments)
GetFieldDecl(dex::u4 index)180*f0dffb02SXin Li ir::FieldDecl* Reader::GetFieldDecl(dex::u4 index) {
181*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
182*f0dffb02SXin Li   auto& p = dex_ir_->fields_map[index];
183*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::FieldDecl*>(1);
184*f0dffb02SXin Li   if (p == nullptr) {
185*f0dffb02SXin Li     p = placeholder;
186*f0dffb02SXin Li     auto newField = ParseFieldDecl(index);
187*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
188*f0dffb02SXin Li     p = newField;
189*f0dffb02SXin Li     dex_ir_->fields_indexes.MarkUsedIndex(index);
190*f0dffb02SXin Li   }
191*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
192*f0dffb02SXin Li   return p;
193*f0dffb02SXin Li }
194*f0dffb02SXin Li 
GetMethodHandle(dex::u4 index)195*f0dffb02SXin Li ir::MethodHandle* Reader::GetMethodHandle(dex::u4 index){
196*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
197*f0dffb02SXin Li   auto& p = dex_ir_->method_handles_map[index];
198*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::MethodHandle*>(1);
199*f0dffb02SXin Li   if(p == nullptr) {
200*f0dffb02SXin Li     p = placeholder;
201*f0dffb02SXin Li     auto newMethodHandle = ParseMethodHandle(index);
202*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
203*f0dffb02SXin Li     p = newMethodHandle;
204*f0dffb02SXin Li     dex_ir_->method_handle_indexes.MarkUsedIndex(index);
205*f0dffb02SXin Li   }
206*f0dffb02SXin Li 
207*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
208*f0dffb02SXin Li   return p;
209*f0dffb02SXin Li }
210*f0dffb02SXin Li 
211*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
212*f0dffb02SXin Li // (see the Reader::GetClass() comments)
GetMethodDecl(dex::u4 index)213*f0dffb02SXin Li ir::MethodDecl* Reader::GetMethodDecl(dex::u4 index) {
214*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
215*f0dffb02SXin Li   auto& p = dex_ir_->methods_map[index];
216*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::MethodDecl*>(1);
217*f0dffb02SXin Li   if (p == nullptr) {
218*f0dffb02SXin Li     p = placeholder;
219*f0dffb02SXin Li     auto newMethod = ParseMethodDecl(index);
220*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
221*f0dffb02SXin Li     p = newMethod;
222*f0dffb02SXin Li     dex_ir_->methods_indexes.MarkUsedIndex(index);
223*f0dffb02SXin Li   }
224*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
225*f0dffb02SXin Li   return p;
226*f0dffb02SXin Li }
227*f0dffb02SXin Li 
228*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
229*f0dffb02SXin Li // (see the Reader::GetClass() comments)
GetProto(dex::u4 index)230*f0dffb02SXin Li ir::Proto* Reader::GetProto(dex::u4 index) {
231*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
232*f0dffb02SXin Li   auto& p = dex_ir_->protos_map[index];
233*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::Proto*>(1);
234*f0dffb02SXin Li   if (p == nullptr) {
235*f0dffb02SXin Li     p = placeholder;
236*f0dffb02SXin Li     auto newProto = ParseProto(index);
237*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
238*f0dffb02SXin Li     p = newProto;
239*f0dffb02SXin Li     dex_ir_->protos_indexes.MarkUsedIndex(index);
240*f0dffb02SXin Li   }
241*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
242*f0dffb02SXin Li   return p;
243*f0dffb02SXin Li }
244*f0dffb02SXin Li 
245*f0dffb02SXin Li // map a .dex index to corresponding .dex IR node
246*f0dffb02SXin Li // (see the Reader::GetClass() comments)
GetString(dex::u4 index)247*f0dffb02SXin Li ir::String* Reader::GetString(dex::u4 index) {
248*f0dffb02SXin Li   SLICER_CHECK_NE(index, dex::kNoIndex);
249*f0dffb02SXin Li   auto& p = dex_ir_->strings_map[index];
250*f0dffb02SXin Li   auto placeholder = reinterpret_cast<ir::String*>(1);
251*f0dffb02SXin Li   if (p == nullptr) {
252*f0dffb02SXin Li     p = placeholder;
253*f0dffb02SXin Li     auto newString = ParseString(index);
254*f0dffb02SXin Li     SLICER_CHECK_EQ(p, placeholder);
255*f0dffb02SXin Li     p = newString;
256*f0dffb02SXin Li     dex_ir_->strings_indexes.MarkUsedIndex(index);
257*f0dffb02SXin Li   }
258*f0dffb02SXin Li   SLICER_CHECK_NE(p, placeholder);
259*f0dffb02SXin Li   return p;
260*f0dffb02SXin Li }
261*f0dffb02SXin Li 
ParseClass(dex::u4 index)262*f0dffb02SXin Li ir::Class* Reader::ParseClass(dex::u4 index) {
263*f0dffb02SXin Li   auto& dex_class_def = ClassDefs()[index];
264*f0dffb02SXin Li   auto ir_class = dex_ir_->Alloc<ir::Class>();
265*f0dffb02SXin Li 
266*f0dffb02SXin Li   ir_class->type = GetType(dex_class_def.class_idx);
267*f0dffb02SXin Li   assert(ir_class->type->class_def == nullptr);
268*f0dffb02SXin Li   ir_class->type->class_def = ir_class;
269*f0dffb02SXin Li 
270*f0dffb02SXin Li   ir_class->access_flags = dex_class_def.access_flags;
271*f0dffb02SXin Li   ir_class->interfaces = ExtractTypeList(dex_class_def.interfaces_off);
272*f0dffb02SXin Li 
273*f0dffb02SXin Li   if (dex_class_def.superclass_idx != dex::kNoIndex) {
274*f0dffb02SXin Li     ir_class->super_class = GetType(dex_class_def.superclass_idx);
275*f0dffb02SXin Li   }
276*f0dffb02SXin Li 
277*f0dffb02SXin Li   if (dex_class_def.source_file_idx != dex::kNoIndex) {
278*f0dffb02SXin Li     ir_class->source_file = GetString(dex_class_def.source_file_idx);
279*f0dffb02SXin Li   }
280*f0dffb02SXin Li 
281*f0dffb02SXin Li   if (dex_class_def.class_data_off != 0) {
282*f0dffb02SXin Li     const dex::u1* class_data = dataPtr<dex::u1>(dex_class_def.class_data_off);
283*f0dffb02SXin Li 
284*f0dffb02SXin Li     dex::u4 static_fields_count = dex::ReadULeb128(&class_data);
285*f0dffb02SXin Li     dex::u4 instance_fields_count = dex::ReadULeb128(&class_data);
286*f0dffb02SXin Li     dex::u4 direct_methods_count = dex::ReadULeb128(&class_data);
287*f0dffb02SXin Li     dex::u4 virtual_methods_count = dex::ReadULeb128(&class_data);
288*f0dffb02SXin Li 
289*f0dffb02SXin Li     dex::u4 base_index = dex::kNoIndex;
290*f0dffb02SXin Li     for (dex::u4 i = 0; i < static_fields_count; ++i) {
291*f0dffb02SXin Li       auto field = ParseEncodedField(&class_data, &base_index);
292*f0dffb02SXin Li       ir_class->static_fields.push_back(field);
293*f0dffb02SXin Li     }
294*f0dffb02SXin Li 
295*f0dffb02SXin Li     base_index = dex::kNoIndex;
296*f0dffb02SXin Li     for (dex::u4 i = 0; i < instance_fields_count; ++i) {
297*f0dffb02SXin Li       auto field = ParseEncodedField(&class_data, &base_index);
298*f0dffb02SXin Li       ir_class->instance_fields.push_back(field);
299*f0dffb02SXin Li     }
300*f0dffb02SXin Li 
301*f0dffb02SXin Li     base_index = dex::kNoIndex;
302*f0dffb02SXin Li     for (dex::u4 i = 0; i < direct_methods_count; ++i) {
303*f0dffb02SXin Li       auto method = ParseEncodedMethod(&class_data, &base_index);
304*f0dffb02SXin Li       ir_class->direct_methods.push_back(method);
305*f0dffb02SXin Li     }
306*f0dffb02SXin Li 
307*f0dffb02SXin Li     base_index = dex::kNoIndex;
308*f0dffb02SXin Li     for (dex::u4 i = 0; i < virtual_methods_count; ++i) {
309*f0dffb02SXin Li       auto method = ParseEncodedMethod(&class_data, &base_index);
310*f0dffb02SXin Li       ir_class->virtual_methods.push_back(method);
311*f0dffb02SXin Li     }
312*f0dffb02SXin Li   }
313*f0dffb02SXin Li 
314*f0dffb02SXin Li   ir_class->static_init = ExtractEncodedArray(dex_class_def.static_values_off);
315*f0dffb02SXin Li   ir_class->annotations = ExtractAnnotations(dex_class_def.annotations_off);
316*f0dffb02SXin Li   ir_class->orig_index = index;
317*f0dffb02SXin Li 
318*f0dffb02SXin Li   return ir_class;
319*f0dffb02SXin Li }
320*f0dffb02SXin Li 
ExtractAnnotations(dex::u4 offset)321*f0dffb02SXin Li ir::AnnotationsDirectory* Reader::ExtractAnnotations(dex::u4 offset) {
322*f0dffb02SXin Li   if (offset == 0) {
323*f0dffb02SXin Li     return nullptr;
324*f0dffb02SXin Li   }
325*f0dffb02SXin Li 
326*f0dffb02SXin Li   SLICER_CHECK_EQ(offset % 4, 0);
327*f0dffb02SXin Li 
328*f0dffb02SXin Li   // first check if we already extracted the same "annotations_directory_item"
329*f0dffb02SXin Li   auto& ir_annotations = annotations_directories_[offset];
330*f0dffb02SXin Li   if (ir_annotations == nullptr) {
331*f0dffb02SXin Li     ir_annotations = dex_ir_->Alloc<ir::AnnotationsDirectory>();
332*f0dffb02SXin Li 
333*f0dffb02SXin Li     auto dex_annotations = dataPtr<dex::AnnotationsDirectoryItem>(offset);
334*f0dffb02SXin Li 
335*f0dffb02SXin Li     ir_annotations->class_annotation =
336*f0dffb02SXin Li         ExtractAnnotationSet(dex_annotations->class_annotations_off);
337*f0dffb02SXin Li 
338*f0dffb02SXin Li     const dex::u1* ptr = reinterpret_cast<const dex::u1*>(dex_annotations + 1);
339*f0dffb02SXin Li 
340*f0dffb02SXin Li     for (dex::u4 i = 0; i < dex_annotations->fields_size; ++i) {
341*f0dffb02SXin Li       ir_annotations->field_annotations.push_back(ParseFieldAnnotation(&ptr));
342*f0dffb02SXin Li     }
343*f0dffb02SXin Li 
344*f0dffb02SXin Li     for (dex::u4 i = 0; i < dex_annotations->methods_size; ++i) {
345*f0dffb02SXin Li       ir_annotations->method_annotations.push_back(ParseMethodAnnotation(&ptr));
346*f0dffb02SXin Li     }
347*f0dffb02SXin Li 
348*f0dffb02SXin Li     for (dex::u4 i = 0; i < dex_annotations->parameters_size; ++i) {
349*f0dffb02SXin Li       ir_annotations->param_annotations.push_back(ParseParamAnnotation(&ptr));
350*f0dffb02SXin Li     }
351*f0dffb02SXin Li   }
352*f0dffb02SXin Li   return ir_annotations;
353*f0dffb02SXin Li }
354*f0dffb02SXin Li 
ExtractAnnotationItem(dex::u4 offset)355*f0dffb02SXin Li ir::Annotation* Reader::ExtractAnnotationItem(dex::u4 offset) {
356*f0dffb02SXin Li   SLICER_CHECK_NE(offset, 0);
357*f0dffb02SXin Li 
358*f0dffb02SXin Li   // first check if we already extracted the same "annotation_item"
359*f0dffb02SXin Li   auto& ir_annotation = annotations_[offset];
360*f0dffb02SXin Li   if (ir_annotation == nullptr) {
361*f0dffb02SXin Li     auto dexAnnotationItem = dataPtr<dex::AnnotationItem>(offset);
362*f0dffb02SXin Li     const dex::u1* ptr = dexAnnotationItem->annotation;
363*f0dffb02SXin Li     ir_annotation = ParseAnnotation(&ptr);
364*f0dffb02SXin Li     ir_annotation->visibility = dexAnnotationItem->visibility;
365*f0dffb02SXin Li   }
366*f0dffb02SXin Li   return ir_annotation;
367*f0dffb02SXin Li }
368*f0dffb02SXin Li 
ExtractAnnotationSet(dex::u4 offset)369*f0dffb02SXin Li ir::AnnotationSet* Reader::ExtractAnnotationSet(dex::u4 offset) {
370*f0dffb02SXin Li   if (offset == 0) {
371*f0dffb02SXin Li     return nullptr;
372*f0dffb02SXin Li   }
373*f0dffb02SXin Li 
374*f0dffb02SXin Li   SLICER_CHECK_EQ(offset % 4, 0);
375*f0dffb02SXin Li 
376*f0dffb02SXin Li   // first check if we already extracted the same "annotation_set_item"
377*f0dffb02SXin Li   auto& ir_annotation_set = annotation_sets_[offset];
378*f0dffb02SXin Li   if (ir_annotation_set == nullptr) {
379*f0dffb02SXin Li     ir_annotation_set = dex_ir_->Alloc<ir::AnnotationSet>();
380*f0dffb02SXin Li 
381*f0dffb02SXin Li     auto dex_annotation_set = dataPtr<dex::AnnotationSetItem>(offset);
382*f0dffb02SXin Li     for (dex::u4 i = 0; i < dex_annotation_set->size; ++i) {
383*f0dffb02SXin Li       auto ir_annotation = ExtractAnnotationItem(dex_annotation_set->entries[i]);
384*f0dffb02SXin Li       assert(ir_annotation != nullptr);
385*f0dffb02SXin Li       ir_annotation_set->annotations.push_back(ir_annotation);
386*f0dffb02SXin Li     }
387*f0dffb02SXin Li   }
388*f0dffb02SXin Li   return ir_annotation_set;
389*f0dffb02SXin Li }
390*f0dffb02SXin Li 
ExtractAnnotationSetRefList(dex::u4 offset)391*f0dffb02SXin Li ir::AnnotationSetRefList* Reader::ExtractAnnotationSetRefList(dex::u4 offset) {
392*f0dffb02SXin Li   SLICER_CHECK_EQ(offset % 4, 0);
393*f0dffb02SXin Li 
394*f0dffb02SXin Li   auto dex_annotation_set_ref_list = dataPtr<dex::AnnotationSetRefList>(offset);
395*f0dffb02SXin Li   auto ir_annotation_set_ref_list = dex_ir_->Alloc<ir::AnnotationSetRefList>();
396*f0dffb02SXin Li 
397*f0dffb02SXin Li   for (dex::u4 i = 0; i < dex_annotation_set_ref_list->size; ++i) {
398*f0dffb02SXin Li     dex::u4 entry_offset = dex_annotation_set_ref_list->list[i].annotations_off;
399*f0dffb02SXin Li     if (entry_offset != 0) {
400*f0dffb02SXin Li       auto ir_annotation_set = ExtractAnnotationSet(entry_offset);
401*f0dffb02SXin Li       SLICER_CHECK_NE(ir_annotation_set, nullptr);
402*f0dffb02SXin Li       ir_annotation_set_ref_list->annotations.push_back(ir_annotation_set);
403*f0dffb02SXin Li     }
404*f0dffb02SXin Li   }
405*f0dffb02SXin Li 
406*f0dffb02SXin Li   return ir_annotation_set_ref_list;
407*f0dffb02SXin Li }
408*f0dffb02SXin Li 
ParseFieldAnnotation(const dex::u1 ** pptr)409*f0dffb02SXin Li ir::FieldAnnotation* Reader::ParseFieldAnnotation(const dex::u1** pptr) {
410*f0dffb02SXin Li   auto dex_field_annotation = reinterpret_cast<const dex::FieldAnnotationsItem*>(*pptr);
411*f0dffb02SXin Li   auto ir_field_annotation = dex_ir_->Alloc<ir::FieldAnnotation>();
412*f0dffb02SXin Li 
413*f0dffb02SXin Li   ir_field_annotation->field_decl = GetFieldDecl(dex_field_annotation->field_idx);
414*f0dffb02SXin Li 
415*f0dffb02SXin Li   ir_field_annotation->annotations =
416*f0dffb02SXin Li       ExtractAnnotationSet(dex_field_annotation->annotations_off);
417*f0dffb02SXin Li   SLICER_CHECK_NE(ir_field_annotation->annotations, nullptr);
418*f0dffb02SXin Li 
419*f0dffb02SXin Li   *pptr += sizeof(dex::FieldAnnotationsItem);
420*f0dffb02SXin Li   return ir_field_annotation;
421*f0dffb02SXin Li }
422*f0dffb02SXin Li 
ParseMethodAnnotation(const dex::u1 ** pptr)423*f0dffb02SXin Li ir::MethodAnnotation* Reader::ParseMethodAnnotation(const dex::u1** pptr) {
424*f0dffb02SXin Li   auto dex_method_annotation =
425*f0dffb02SXin Li       reinterpret_cast<const dex::MethodAnnotationsItem*>(*pptr);
426*f0dffb02SXin Li   auto ir_method_annotation = dex_ir_->Alloc<ir::MethodAnnotation>();
427*f0dffb02SXin Li 
428*f0dffb02SXin Li   ir_method_annotation->method_decl = GetMethodDecl(dex_method_annotation->method_idx);
429*f0dffb02SXin Li 
430*f0dffb02SXin Li   ir_method_annotation->annotations =
431*f0dffb02SXin Li       ExtractAnnotationSet(dex_method_annotation->annotations_off);
432*f0dffb02SXin Li   SLICER_CHECK_NE(ir_method_annotation->annotations, nullptr);
433*f0dffb02SXin Li 
434*f0dffb02SXin Li   *pptr += sizeof(dex::MethodAnnotationsItem);
435*f0dffb02SXin Li   return ir_method_annotation;
436*f0dffb02SXin Li }
437*f0dffb02SXin Li 
ParseParamAnnotation(const dex::u1 ** pptr)438*f0dffb02SXin Li ir::ParamAnnotation* Reader::ParseParamAnnotation(const dex::u1** pptr) {
439*f0dffb02SXin Li   auto dex_param_annotation =
440*f0dffb02SXin Li       reinterpret_cast<const dex::ParameterAnnotationsItem*>(*pptr);
441*f0dffb02SXin Li   auto ir_param_annotation = dex_ir_->Alloc<ir::ParamAnnotation>();
442*f0dffb02SXin Li 
443*f0dffb02SXin Li   ir_param_annotation->method_decl = GetMethodDecl(dex_param_annotation->method_idx);
444*f0dffb02SXin Li 
445*f0dffb02SXin Li   ir_param_annotation->annotations =
446*f0dffb02SXin Li       ExtractAnnotationSetRefList(dex_param_annotation->annotations_off);
447*f0dffb02SXin Li   SLICER_CHECK_NE(ir_param_annotation->annotations, nullptr);
448*f0dffb02SXin Li 
449*f0dffb02SXin Li   *pptr += sizeof(dex::ParameterAnnotationsItem);
450*f0dffb02SXin Li   return ir_param_annotation;
451*f0dffb02SXin Li }
452*f0dffb02SXin Li 
ParseEncodedField(const dex::u1 ** pptr,dex::u4 * base_index)453*f0dffb02SXin Li ir::EncodedField* Reader::ParseEncodedField(const dex::u1** pptr, dex::u4* base_index) {
454*f0dffb02SXin Li   auto ir_encoded_field = dex_ir_->Alloc<ir::EncodedField>();
455*f0dffb02SXin Li 
456*f0dffb02SXin Li   auto field_index = dex::ReadULeb128(pptr);
457*f0dffb02SXin Li   SLICER_CHECK_NE(field_index, dex::kNoIndex);
458*f0dffb02SXin Li   if (*base_index != dex::kNoIndex) {
459*f0dffb02SXin Li     SLICER_CHECK_NE(field_index, 0);
460*f0dffb02SXin Li     field_index += *base_index;
461*f0dffb02SXin Li   }
462*f0dffb02SXin Li   *base_index = field_index;
463*f0dffb02SXin Li 
464*f0dffb02SXin Li   ir_encoded_field->decl = GetFieldDecl(field_index);
465*f0dffb02SXin Li   ir_encoded_field->access_flags = dex::ReadULeb128(pptr);
466*f0dffb02SXin Li 
467*f0dffb02SXin Li   return ir_encoded_field;
468*f0dffb02SXin Li }
469*f0dffb02SXin Li 
470*f0dffb02SXin Li // Parse an encoded variable-length integer value
471*f0dffb02SXin Li // (sign-extend signed types, zero-extend unsigned types)
472*f0dffb02SXin Li template <class T>
ParseIntValue(const dex::u1 ** pptr,size_t size)473*f0dffb02SXin Li static T ParseIntValue(const dex::u1** pptr, size_t size) {
474*f0dffb02SXin Li   static_assert(std::is_integral<T>::value, "must be an integral type");
475*f0dffb02SXin Li 
476*f0dffb02SXin Li   SLICER_CHECK_GT(size, 0);
477*f0dffb02SXin Li   SLICER_CHECK_LE(size, sizeof(T));
478*f0dffb02SXin Li 
479*f0dffb02SXin Li   T value = 0;
480*f0dffb02SXin Li   for (int i = 0; i < size; ++i) {
481*f0dffb02SXin Li     value |= T(*(*pptr)++) << (i * 8);
482*f0dffb02SXin Li   }
483*f0dffb02SXin Li 
484*f0dffb02SXin Li   // sign-extend?
485*f0dffb02SXin Li   if (std::is_signed<T>::value) {
486*f0dffb02SXin Li     size_t shift = (sizeof(T) - size) * 8;
487*f0dffb02SXin Li     value = T(value << shift) >> shift;
488*f0dffb02SXin Li   }
489*f0dffb02SXin Li 
490*f0dffb02SXin Li   return value;
491*f0dffb02SXin Li }
492*f0dffb02SXin Li 
493*f0dffb02SXin Li // Parse an encoded variable-length floating point value
494*f0dffb02SXin Li // (zero-extend to the right)
495*f0dffb02SXin Li template <class T>
ParseFloatValue(const dex::u1 ** pptr,size_t size)496*f0dffb02SXin Li static T ParseFloatValue(const dex::u1** pptr, size_t size) {
497*f0dffb02SXin Li   SLICER_CHECK_GT(size, 0);
498*f0dffb02SXin Li   SLICER_CHECK_LE(size, sizeof(T));
499*f0dffb02SXin Li 
500*f0dffb02SXin Li   T value = 0;
501*f0dffb02SXin Li   int start_byte = sizeof(T) - size;
502*f0dffb02SXin Li   for (dex::u1* p = reinterpret_cast<dex::u1*>(&value) + start_byte; size > 0;
503*f0dffb02SXin Li        --size) {
504*f0dffb02SXin Li     *p++ = *(*pptr)++;
505*f0dffb02SXin Li   }
506*f0dffb02SXin Li   return value;
507*f0dffb02SXin Li }
508*f0dffb02SXin Li 
ParseEncodedValue(const dex::u1 ** pptr)509*f0dffb02SXin Li ir::EncodedValue* Reader::ParseEncodedValue(const dex::u1** pptr) {
510*f0dffb02SXin Li   auto ir_encoded_value = dex_ir_->Alloc<ir::EncodedValue>();
511*f0dffb02SXin Li 
512*f0dffb02SXin Li   SLICER_EXTRA(auto base_ptr = *pptr);
513*f0dffb02SXin Li 
514*f0dffb02SXin Li   dex::u1 header = *(*pptr)++;
515*f0dffb02SXin Li   dex::u1 type = header & dex::kEncodedValueTypeMask;
516*f0dffb02SXin Li   dex::u1 arg = header >> dex::kEncodedValueArgShift;
517*f0dffb02SXin Li 
518*f0dffb02SXin Li   ir_encoded_value->type = type;
519*f0dffb02SXin Li 
520*f0dffb02SXin Li   switch (type) {
521*f0dffb02SXin Li     case dex::kEncodedByte:
522*f0dffb02SXin Li       ir_encoded_value->u.byte_value = ParseIntValue<int8_t>(pptr, arg + 1);
523*f0dffb02SXin Li       break;
524*f0dffb02SXin Li 
525*f0dffb02SXin Li     case dex::kEncodedShort:
526*f0dffb02SXin Li       ir_encoded_value->u.short_value = ParseIntValue<int16_t>(pptr, arg + 1);
527*f0dffb02SXin Li       break;
528*f0dffb02SXin Li 
529*f0dffb02SXin Li     case dex::kEncodedChar:
530*f0dffb02SXin Li       ir_encoded_value->u.char_value = ParseIntValue<uint16_t>(pptr, arg + 1);
531*f0dffb02SXin Li       break;
532*f0dffb02SXin Li 
533*f0dffb02SXin Li     case dex::kEncodedInt:
534*f0dffb02SXin Li       ir_encoded_value->u.int_value = ParseIntValue<int32_t>(pptr, arg + 1);
535*f0dffb02SXin Li       break;
536*f0dffb02SXin Li 
537*f0dffb02SXin Li     case dex::kEncodedLong:
538*f0dffb02SXin Li       ir_encoded_value->u.long_value = ParseIntValue<int64_t>(pptr, arg + 1);
539*f0dffb02SXin Li       break;
540*f0dffb02SXin Li 
541*f0dffb02SXin Li     case dex::kEncodedFloat:
542*f0dffb02SXin Li       ir_encoded_value->u.float_value = ParseFloatValue<float>(pptr, arg + 1);
543*f0dffb02SXin Li       break;
544*f0dffb02SXin Li 
545*f0dffb02SXin Li     case dex::kEncodedDouble:
546*f0dffb02SXin Li       ir_encoded_value->u.double_value = ParseFloatValue<double>(pptr, arg + 1);
547*f0dffb02SXin Li       break;
548*f0dffb02SXin Li 
549*f0dffb02SXin Li     case dex::kEncodedString: {
550*f0dffb02SXin Li       dex::u4 index = ParseIntValue<dex::u4>(pptr, arg + 1);
551*f0dffb02SXin Li       ir_encoded_value->u.string_value = GetString(index);
552*f0dffb02SXin Li     } break;
553*f0dffb02SXin Li 
554*f0dffb02SXin Li     case dex::kEncodedType: {
555*f0dffb02SXin Li       dex::u4 index = ParseIntValue<dex::u4>(pptr, arg + 1);
556*f0dffb02SXin Li       ir_encoded_value->u.type_value = GetType(index);
557*f0dffb02SXin Li     } break;
558*f0dffb02SXin Li 
559*f0dffb02SXin Li     case dex::kEncodedField: {
560*f0dffb02SXin Li       dex::u4 index = ParseIntValue<dex::u4>(pptr, arg + 1);
561*f0dffb02SXin Li       ir_encoded_value->u.field_value = GetFieldDecl(index);
562*f0dffb02SXin Li     } break;
563*f0dffb02SXin Li 
564*f0dffb02SXin Li     case dex::kEncodedMethod: {
565*f0dffb02SXin Li       dex::u4 index = ParseIntValue<dex::u4>(pptr, arg + 1);
566*f0dffb02SXin Li       ir_encoded_value->u.method_value = GetMethodDecl(index);
567*f0dffb02SXin Li     } break;
568*f0dffb02SXin Li 
569*f0dffb02SXin Li     case dex::kEncodedEnum: {
570*f0dffb02SXin Li       dex::u4 index = ParseIntValue<dex::u4>(pptr, arg + 1);
571*f0dffb02SXin Li       ir_encoded_value->u.enum_value = GetFieldDecl(index);
572*f0dffb02SXin Li     } break;
573*f0dffb02SXin Li 
574*f0dffb02SXin Li     case dex::kEncodedArray:
575*f0dffb02SXin Li       SLICER_CHECK_EQ(arg, 0);
576*f0dffb02SXin Li       ir_encoded_value->u.array_value = ParseEncodedArray(pptr);
577*f0dffb02SXin Li       break;
578*f0dffb02SXin Li 
579*f0dffb02SXin Li     case dex::kEncodedAnnotation:
580*f0dffb02SXin Li       SLICER_CHECK_EQ(arg, 0);
581*f0dffb02SXin Li       ir_encoded_value->u.annotation_value = ParseAnnotation(pptr);
582*f0dffb02SXin Li       break;
583*f0dffb02SXin Li 
584*f0dffb02SXin Li     case dex::kEncodedNull:
585*f0dffb02SXin Li       SLICER_CHECK_EQ(arg, 0);
586*f0dffb02SXin Li       break;
587*f0dffb02SXin Li 
588*f0dffb02SXin Li     case dex::kEncodedBoolean:
589*f0dffb02SXin Li       SLICER_CHECK_LT(arg, 2);
590*f0dffb02SXin Li       ir_encoded_value->u.bool_value = (arg == 1);
591*f0dffb02SXin Li       break;
592*f0dffb02SXin Li 
593*f0dffb02SXin Li     default:
594*f0dffb02SXin Li       SLICER_CHECK(!"unexpected value type");
595*f0dffb02SXin Li   }
596*f0dffb02SXin Li 
597*f0dffb02SXin Li   SLICER_EXTRA(ir_encoded_value->original = slicer::MemView(base_ptr, *pptr - base_ptr));
598*f0dffb02SXin Li 
599*f0dffb02SXin Li   return ir_encoded_value;
600*f0dffb02SXin Li }
601*f0dffb02SXin Li 
ParseAnnotation(const dex::u1 ** pptr)602*f0dffb02SXin Li ir::Annotation* Reader::ParseAnnotation(const dex::u1** pptr) {
603*f0dffb02SXin Li   auto ir_annotation = dex_ir_->Alloc<ir::Annotation>();
604*f0dffb02SXin Li 
605*f0dffb02SXin Li   dex::u4 type_index = dex::ReadULeb128(pptr);
606*f0dffb02SXin Li   dex::u4 elements_count = dex::ReadULeb128(pptr);
607*f0dffb02SXin Li 
608*f0dffb02SXin Li   ir_annotation->type = GetType(type_index);
609*f0dffb02SXin Li   ir_annotation->visibility = dex::kVisibilityEncoded;
610*f0dffb02SXin Li 
611*f0dffb02SXin Li   for (dex::u4 i = 0; i < elements_count; ++i) {
612*f0dffb02SXin Li     auto ir_element = dex_ir_->Alloc<ir::AnnotationElement>();
613*f0dffb02SXin Li 
614*f0dffb02SXin Li     ir_element->name = GetString(dex::ReadULeb128(pptr));
615*f0dffb02SXin Li     ir_element->value = ParseEncodedValue(pptr);
616*f0dffb02SXin Li 
617*f0dffb02SXin Li     ir_annotation->elements.push_back(ir_element);
618*f0dffb02SXin Li   }
619*f0dffb02SXin Li 
620*f0dffb02SXin Li   return ir_annotation;
621*f0dffb02SXin Li }
622*f0dffb02SXin Li 
ParseEncodedArray(const dex::u1 ** pptr)623*f0dffb02SXin Li ir::EncodedArray* Reader::ParseEncodedArray(const dex::u1** pptr) {
624*f0dffb02SXin Li   auto ir_encoded_array = dex_ir_->Alloc<ir::EncodedArray>();
625*f0dffb02SXin Li 
626*f0dffb02SXin Li   dex::u4 count = dex::ReadULeb128(pptr);
627*f0dffb02SXin Li   for (dex::u4 i = 0; i < count; ++i) {
628*f0dffb02SXin Li     ir_encoded_array->values.push_back(ParseEncodedValue(pptr));
629*f0dffb02SXin Li   }
630*f0dffb02SXin Li 
631*f0dffb02SXin Li   return ir_encoded_array;
632*f0dffb02SXin Li }
633*f0dffb02SXin Li 
ExtractEncodedArray(dex::u4 offset)634*f0dffb02SXin Li ir::EncodedArray* Reader::ExtractEncodedArray(dex::u4 offset) {
635*f0dffb02SXin Li   if (offset == 0) {
636*f0dffb02SXin Li     return nullptr;
637*f0dffb02SXin Li   }
638*f0dffb02SXin Li 
639*f0dffb02SXin Li   // first check if we already extracted the same "annotation_item"
640*f0dffb02SXin Li   auto& ir_encoded_array = encoded_arrays_[offset];
641*f0dffb02SXin Li   if (ir_encoded_array == nullptr) {
642*f0dffb02SXin Li     auto ptr = dataPtr<dex::u1>(offset);
643*f0dffb02SXin Li     ir_encoded_array = ParseEncodedArray(&ptr);
644*f0dffb02SXin Li   }
645*f0dffb02SXin Li   return ir_encoded_array;
646*f0dffb02SXin Li }
647*f0dffb02SXin Li 
ExtractDebugInfo(dex::u4 offset)648*f0dffb02SXin Li ir::DebugInfo* Reader::ExtractDebugInfo(dex::u4 offset) {
649*f0dffb02SXin Li   if (offset == 0) {
650*f0dffb02SXin Li     return nullptr;
651*f0dffb02SXin Li   }
652*f0dffb02SXin Li 
653*f0dffb02SXin Li   auto ir_debug_info = dex_ir_->Alloc<ir::DebugInfo>();
654*f0dffb02SXin Li   const dex::u1* ptr = dataPtr<dex::u1>(offset);
655*f0dffb02SXin Li 
656*f0dffb02SXin Li   ir_debug_info->line_start = dex::ReadULeb128(&ptr);
657*f0dffb02SXin Li 
658*f0dffb02SXin Li   // TODO: implicit this param for non-static methods?
659*f0dffb02SXin Li   dex::u4 param_count = dex::ReadULeb128(&ptr);
660*f0dffb02SXin Li   for (dex::u4 i = 0; i < param_count; ++i) {
661*f0dffb02SXin Li     dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
662*f0dffb02SXin Li     auto ir_string =
663*f0dffb02SXin Li         (name_index == dex::kNoIndex) ? nullptr : GetString(name_index);
664*f0dffb02SXin Li     ir_debug_info->param_names.push_back(ir_string);
665*f0dffb02SXin Li   }
666*f0dffb02SXin Li 
667*f0dffb02SXin Li   // parse the debug info opcodes and note the
668*f0dffb02SXin Li   // references to strings and types (to make sure the IR
669*f0dffb02SXin Li   // is the full closure of all referenced items)
670*f0dffb02SXin Li   //
671*f0dffb02SXin Li   // TODO: design a generic debug info iterator?
672*f0dffb02SXin Li   //
673*f0dffb02SXin Li   auto base_ptr = ptr;
674*f0dffb02SXin Li   dex::u1 opcode = 0;
675*f0dffb02SXin Li   while ((opcode = *ptr++) != dex::DBG_END_SEQUENCE) {
676*f0dffb02SXin Li     switch (opcode) {
677*f0dffb02SXin Li       case dex::DBG_ADVANCE_PC:
678*f0dffb02SXin Li         // addr_diff
679*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
680*f0dffb02SXin Li         break;
681*f0dffb02SXin Li 
682*f0dffb02SXin Li       case dex::DBG_ADVANCE_LINE:
683*f0dffb02SXin Li         // line_diff
684*f0dffb02SXin Li         dex::ReadSLeb128(&ptr);
685*f0dffb02SXin Li         break;
686*f0dffb02SXin Li 
687*f0dffb02SXin Li       case dex::DBG_START_LOCAL: {
688*f0dffb02SXin Li         // register_num
689*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
690*f0dffb02SXin Li 
691*f0dffb02SXin Li         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
692*f0dffb02SXin Li         if (name_index != dex::kNoIndex) {
693*f0dffb02SXin Li           GetString(name_index);
694*f0dffb02SXin Li         }
695*f0dffb02SXin Li 
696*f0dffb02SXin Li         dex::u4 type_index = dex::ReadULeb128(&ptr) - 1;
697*f0dffb02SXin Li         if (type_index != dex::kNoIndex) {
698*f0dffb02SXin Li           GetType(type_index);
699*f0dffb02SXin Li         }
700*f0dffb02SXin Li       } break;
701*f0dffb02SXin Li 
702*f0dffb02SXin Li       case dex::DBG_START_LOCAL_EXTENDED: {
703*f0dffb02SXin Li         // register_num
704*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
705*f0dffb02SXin Li 
706*f0dffb02SXin Li         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
707*f0dffb02SXin Li         if (name_index != dex::kNoIndex) {
708*f0dffb02SXin Li           GetString(name_index);
709*f0dffb02SXin Li         }
710*f0dffb02SXin Li 
711*f0dffb02SXin Li         dex::u4 type_index = dex::ReadULeb128(&ptr) - 1;
712*f0dffb02SXin Li         if (type_index != dex::kNoIndex) {
713*f0dffb02SXin Li           GetType(type_index);
714*f0dffb02SXin Li         }
715*f0dffb02SXin Li 
716*f0dffb02SXin Li         dex::u4 sig_index = dex::ReadULeb128(&ptr) - 1;
717*f0dffb02SXin Li         if (sig_index != dex::kNoIndex) {
718*f0dffb02SXin Li           GetString(sig_index);
719*f0dffb02SXin Li         }
720*f0dffb02SXin Li       } break;
721*f0dffb02SXin Li 
722*f0dffb02SXin Li       case dex::DBG_END_LOCAL:
723*f0dffb02SXin Li       case dex::DBG_RESTART_LOCAL:
724*f0dffb02SXin Li         // register_num
725*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
726*f0dffb02SXin Li         break;
727*f0dffb02SXin Li 
728*f0dffb02SXin Li       case dex::DBG_SET_FILE: {
729*f0dffb02SXin Li         dex::u4 name_index = dex::ReadULeb128(&ptr) - 1;
730*f0dffb02SXin Li         if (name_index != dex::kNoIndex) {
731*f0dffb02SXin Li           GetString(name_index);
732*f0dffb02SXin Li         }
733*f0dffb02SXin Li       } break;
734*f0dffb02SXin Li     }
735*f0dffb02SXin Li   }
736*f0dffb02SXin Li 
737*f0dffb02SXin Li   ir_debug_info->data = slicer::MemView(base_ptr, ptr - base_ptr);
738*f0dffb02SXin Li 
739*f0dffb02SXin Li   return ir_debug_info;
740*f0dffb02SXin Li }
741*f0dffb02SXin Li 
ExtractCode(dex::u4 offset)742*f0dffb02SXin Li ir::Code* Reader::ExtractCode(dex::u4 offset) {
743*f0dffb02SXin Li   if (offset == 0) {
744*f0dffb02SXin Li     return nullptr;
745*f0dffb02SXin Li   }
746*f0dffb02SXin Li 
747*f0dffb02SXin Li   SLICER_CHECK_EQ(offset % 4, 0);
748*f0dffb02SXin Li 
749*f0dffb02SXin Li   auto dex_code = dataPtr<dex::Code>(offset);
750*f0dffb02SXin Li   auto ir_code = dex_ir_->Alloc<ir::Code>();
751*f0dffb02SXin Li 
752*f0dffb02SXin Li   ir_code->registers = dex_code->registers_size;
753*f0dffb02SXin Li   ir_code->ins_count = dex_code->ins_size;
754*f0dffb02SXin Li   ir_code->outs_count = dex_code->outs_size;
755*f0dffb02SXin Li 
756*f0dffb02SXin Li   // instructions array
757*f0dffb02SXin Li   ir_code->instructions =
758*f0dffb02SXin Li       slicer::ArrayView<const dex::u2>(dex_code->insns, dex_code->insns_size);
759*f0dffb02SXin Li 
760*f0dffb02SXin Li   // parse the instructions to discover references to other
761*f0dffb02SXin Li   // IR nodes (see debug info stream parsing too)
762*f0dffb02SXin Li   ParseInstructions(ir_code->instructions);
763*f0dffb02SXin Li 
764*f0dffb02SXin Li   // try blocks & handlers
765*f0dffb02SXin Li   //
766*f0dffb02SXin Li   // TODO: a generic try/catch blocks iterator?
767*f0dffb02SXin Li   //
768*f0dffb02SXin Li   if (dex_code->tries_size != 0) {
769*f0dffb02SXin Li     dex::u4 aligned_count = (dex_code->insns_size + 1) / 2 * 2;
770*f0dffb02SXin Li     auto tries =
771*f0dffb02SXin Li         reinterpret_cast<const dex::TryBlock*>(dex_code->insns + aligned_count);
772*f0dffb02SXin Li     auto handlers_list =
773*f0dffb02SXin Li         reinterpret_cast<const dex::u1*>(tries + dex_code->tries_size);
774*f0dffb02SXin Li 
775*f0dffb02SXin Li     ir_code->try_blocks =
776*f0dffb02SXin Li         slicer::ArrayView<const dex::TryBlock>(tries, dex_code->tries_size);
777*f0dffb02SXin Li 
778*f0dffb02SXin Li     // parse the handlers list (and discover embedded references)
779*f0dffb02SXin Li     auto ptr = handlers_list;
780*f0dffb02SXin Li 
781*f0dffb02SXin Li     dex::u4 handlers_count = dex::ReadULeb128(&ptr);
782*f0dffb02SXin Li     SLICER_WEAK_CHECK(handlers_count <= dex_code->tries_size);
783*f0dffb02SXin Li 
784*f0dffb02SXin Li     for (dex::u4 handler_index = 0; handler_index < handlers_count; ++handler_index) {
785*f0dffb02SXin Li       int catch_count = dex::ReadSLeb128(&ptr);
786*f0dffb02SXin Li 
787*f0dffb02SXin Li       for (int catch_index = 0; catch_index < std::abs(catch_count); ++catch_index) {
788*f0dffb02SXin Li         dex::u4 type_index = dex::ReadULeb128(&ptr);
789*f0dffb02SXin Li         GetType(type_index);
790*f0dffb02SXin Li 
791*f0dffb02SXin Li         // address
792*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
793*f0dffb02SXin Li       }
794*f0dffb02SXin Li 
795*f0dffb02SXin Li       if (catch_count < 1) {
796*f0dffb02SXin Li         // catch_all_addr
797*f0dffb02SXin Li         dex::ReadULeb128(&ptr);
798*f0dffb02SXin Li       }
799*f0dffb02SXin Li     }
800*f0dffb02SXin Li 
801*f0dffb02SXin Li     ir_code->catch_handlers = slicer::MemView(handlers_list, ptr - handlers_list);
802*f0dffb02SXin Li   }
803*f0dffb02SXin Li 
804*f0dffb02SXin Li   ir_code->debug_info = ExtractDebugInfo(dex_code->debug_info_off);
805*f0dffb02SXin Li 
806*f0dffb02SXin Li   return ir_code;
807*f0dffb02SXin Li }
808*f0dffb02SXin Li 
ParseEncodedMethod(const dex::u1 ** pptr,dex::u4 * base_index)809*f0dffb02SXin Li ir::EncodedMethod* Reader::ParseEncodedMethod(const dex::u1** pptr, dex::u4* base_index) {
810*f0dffb02SXin Li   auto ir_encoded_method = dex_ir_->Alloc<ir::EncodedMethod>();
811*f0dffb02SXin Li 
812*f0dffb02SXin Li   auto method_index = dex::ReadULeb128(pptr);
813*f0dffb02SXin Li   SLICER_CHECK_NE(method_index, dex::kNoIndex);
814*f0dffb02SXin Li   if (*base_index != dex::kNoIndex) {
815*f0dffb02SXin Li     SLICER_CHECK_NE(method_index, 0);
816*f0dffb02SXin Li     method_index += *base_index;
817*f0dffb02SXin Li   }
818*f0dffb02SXin Li   *base_index = method_index;
819*f0dffb02SXin Li 
820*f0dffb02SXin Li   ir_encoded_method->decl = GetMethodDecl(method_index);
821*f0dffb02SXin Li   ir_encoded_method->access_flags = dex::ReadULeb128(pptr);
822*f0dffb02SXin Li 
823*f0dffb02SXin Li   dex::u4 code_offset = dex::ReadULeb128(pptr);
824*f0dffb02SXin Li   ir_encoded_method->code = ExtractCode(code_offset);
825*f0dffb02SXin Li 
826*f0dffb02SXin Li   // update the methods lookup table
827*f0dffb02SXin Li   dex_ir_->methods_lookup.Insert(ir_encoded_method);
828*f0dffb02SXin Li 
829*f0dffb02SXin Li   return ir_encoded_method;
830*f0dffb02SXin Li }
831*f0dffb02SXin Li 
ParseType(dex::u4 index)832*f0dffb02SXin Li ir::Type* Reader::ParseType(dex::u4 index) {
833*f0dffb02SXin Li   auto& dex_type = TypeIds()[index];
834*f0dffb02SXin Li   auto ir_type = dex_ir_->Alloc<ir::Type>();
835*f0dffb02SXin Li 
836*f0dffb02SXin Li   ir_type->descriptor = GetString(dex_type.descriptor_idx);
837*f0dffb02SXin Li   ir_type->orig_index = index;
838*f0dffb02SXin Li 
839*f0dffb02SXin Li   return ir_type;
840*f0dffb02SXin Li }
841*f0dffb02SXin Li 
ParseFieldDecl(dex::u4 index)842*f0dffb02SXin Li ir::FieldDecl* Reader::ParseFieldDecl(dex::u4 index) {
843*f0dffb02SXin Li   auto& dex_field = FieldIds()[index];
844*f0dffb02SXin Li   auto ir_field = dex_ir_->Alloc<ir::FieldDecl>();
845*f0dffb02SXin Li 
846*f0dffb02SXin Li   ir_field->name = GetString(dex_field.name_idx);
847*f0dffb02SXin Li   ir_field->type = GetType(dex_field.type_idx);
848*f0dffb02SXin Li   ir_field->parent = GetType(dex_field.class_idx);
849*f0dffb02SXin Li   ir_field->orig_index = index;
850*f0dffb02SXin Li 
851*f0dffb02SXin Li   return ir_field;
852*f0dffb02SXin Li }
853*f0dffb02SXin Li 
ParseMethodHandle(dex::u4 index)854*f0dffb02SXin Li ir::MethodHandle* Reader::ParseMethodHandle(dex::u4 index){
855*f0dffb02SXin Li   auto& dex_method_handle = MethodHandles()[index];
856*f0dffb02SXin Li   auto ir_method_handle = dex_ir_->Alloc<ir::MethodHandle>();
857*f0dffb02SXin Li 
858*f0dffb02SXin Li   ir_method_handle->method_handle_type = dex_method_handle.method_handle_type;
859*f0dffb02SXin Li 
860*f0dffb02SXin Li   if(ir_method_handle->IsField()){
861*f0dffb02SXin Li     ir_method_handle->field = GetFieldDecl(dex_method_handle.field_or_method_id);
862*f0dffb02SXin Li   }
863*f0dffb02SXin Li   else {
864*f0dffb02SXin Li     ir_method_handle->method = GetMethodDecl(dex_method_handle.field_or_method_id);
865*f0dffb02SXin Li   }
866*f0dffb02SXin Li 
867*f0dffb02SXin Li   return ir_method_handle;
868*f0dffb02SXin Li }
869*f0dffb02SXin Li 
ParseMethodDecl(dex::u4 index)870*f0dffb02SXin Li ir::MethodDecl* Reader::ParseMethodDecl(dex::u4 index) {
871*f0dffb02SXin Li   auto& dex_method = MethodIds()[index];
872*f0dffb02SXin Li   auto ir_method = dex_ir_->Alloc<ir::MethodDecl>();
873*f0dffb02SXin Li 
874*f0dffb02SXin Li   ir_method->name = GetString(dex_method.name_idx);
875*f0dffb02SXin Li   ir_method->prototype = GetProto(dex_method.proto_idx);
876*f0dffb02SXin Li   ir_method->parent = GetType(dex_method.class_idx);
877*f0dffb02SXin Li   ir_method->orig_index = index;
878*f0dffb02SXin Li 
879*f0dffb02SXin Li   return ir_method;
880*f0dffb02SXin Li }
881*f0dffb02SXin Li 
ExtractTypeList(dex::u4 offset)882*f0dffb02SXin Li ir::TypeList* Reader::ExtractTypeList(dex::u4 offset) {
883*f0dffb02SXin Li   if (offset == 0) {
884*f0dffb02SXin Li     return nullptr;
885*f0dffb02SXin Li   }
886*f0dffb02SXin Li 
887*f0dffb02SXin Li   // first check to see if we already extracted the same "type_list"
888*f0dffb02SXin Li   auto& ir_type_list = type_lists_[offset];
889*f0dffb02SXin Li   if (ir_type_list == nullptr) {
890*f0dffb02SXin Li     ir_type_list = dex_ir_->Alloc<ir::TypeList>();
891*f0dffb02SXin Li 
892*f0dffb02SXin Li     auto dex_type_list = dataPtr<dex::TypeList>(offset);
893*f0dffb02SXin Li     SLICER_WEAK_CHECK(dex_type_list->size > 0);
894*f0dffb02SXin Li 
895*f0dffb02SXin Li     for (dex::u4 i = 0; i < dex_type_list->size; ++i) {
896*f0dffb02SXin Li       ir_type_list->types.push_back(GetType(dex_type_list->list[i].type_idx));
897*f0dffb02SXin Li     }
898*f0dffb02SXin Li   }
899*f0dffb02SXin Li 
900*f0dffb02SXin Li   return ir_type_list;
901*f0dffb02SXin Li }
902*f0dffb02SXin Li 
ParseProto(dex::u4 index)903*f0dffb02SXin Li ir::Proto* Reader::ParseProto(dex::u4 index) {
904*f0dffb02SXin Li   auto& dex_proto = ProtoIds()[index];
905*f0dffb02SXin Li   auto ir_proto = dex_ir_->Alloc<ir::Proto>();
906*f0dffb02SXin Li 
907*f0dffb02SXin Li   ir_proto->shorty = GetString(dex_proto.shorty_idx);
908*f0dffb02SXin Li   ir_proto->return_type = GetType(dex_proto.return_type_idx);
909*f0dffb02SXin Li   ir_proto->param_types = ExtractTypeList(dex_proto.parameters_off);
910*f0dffb02SXin Li   ir_proto->orig_index = index;
911*f0dffb02SXin Li 
912*f0dffb02SXin Li   // update the prototypes lookup table
913*f0dffb02SXin Li   dex_ir_->prototypes_lookup.Insert(ir_proto);
914*f0dffb02SXin Li 
915*f0dffb02SXin Li   return ir_proto;
916*f0dffb02SXin Li }
917*f0dffb02SXin Li 
ParseString(dex::u4 index)918*f0dffb02SXin Li ir::String* Reader::ParseString(dex::u4 index) {
919*f0dffb02SXin Li   auto ir_string = dex_ir_->Alloc<ir::String>();
920*f0dffb02SXin Li 
921*f0dffb02SXin Li   auto data = GetStringData(index);
922*f0dffb02SXin Li   auto cstr = data;
923*f0dffb02SXin Li   dex::ReadULeb128(&cstr);
924*f0dffb02SXin Li   size_t size = (cstr - data) + ::strlen(reinterpret_cast<const char*>(cstr)) + 1;
925*f0dffb02SXin Li 
926*f0dffb02SXin Li   ir_string->data = slicer::MemView(data, size);
927*f0dffb02SXin Li   ir_string->orig_index = index;
928*f0dffb02SXin Li 
929*f0dffb02SXin Li   // update the strings lookup table
930*f0dffb02SXin Li   dex_ir_->strings_lookup.Insert(ir_string);
931*f0dffb02SXin Li 
932*f0dffb02SXin Li   return ir_string;
933*f0dffb02SXin Li }
934*f0dffb02SXin Li 
ParseInstructions(slicer::ArrayView<const dex::u2> code)935*f0dffb02SXin Li void Reader::ParseInstructions(slicer::ArrayView<const dex::u2> code) {
936*f0dffb02SXin Li   const dex::u2* ptr = code.begin();
937*f0dffb02SXin Li   while (ptr < code.end()) {
938*f0dffb02SXin Li     auto dex_instr = dex::DecodeInstruction(ptr);
939*f0dffb02SXin Li 
940*f0dffb02SXin Li     dex::u4 index = dex::kNoIndex;
941*f0dffb02SXin Li     dex::u4 index2 = dex::kNoIndex;
942*f0dffb02SXin Li     switch (dex::GetFormatFromOpcode(dex_instr.opcode)) {
943*f0dffb02SXin Li       case dex::k20bc:
944*f0dffb02SXin Li       case dex::k21c:
945*f0dffb02SXin Li       case dex::k31c:
946*f0dffb02SXin Li       case dex::k35c:
947*f0dffb02SXin Li       case dex::k3rc:
948*f0dffb02SXin Li         index = dex_instr.vB;
949*f0dffb02SXin Li         break;
950*f0dffb02SXin Li 
951*f0dffb02SXin Li       case dex::k45cc:
952*f0dffb02SXin Li       case dex::k4rcc:
953*f0dffb02SXin Li         index = dex_instr.vB;
954*f0dffb02SXin Li         index2 = dex_instr.arg[4];
955*f0dffb02SXin Li         break;
956*f0dffb02SXin Li 
957*f0dffb02SXin Li       case dex::k22c:
958*f0dffb02SXin Li         index = dex_instr.vC;
959*f0dffb02SXin Li         break;
960*f0dffb02SXin Li 
961*f0dffb02SXin Li       default:
962*f0dffb02SXin Li         break;
963*f0dffb02SXin Li     }
964*f0dffb02SXin Li 
965*f0dffb02SXin Li     switch (GetIndexTypeFromOpcode(dex_instr.opcode)) {
966*f0dffb02SXin Li       case dex::kIndexStringRef:
967*f0dffb02SXin Li         GetString(index);
968*f0dffb02SXin Li         break;
969*f0dffb02SXin Li 
970*f0dffb02SXin Li       case dex::kIndexTypeRef:
971*f0dffb02SXin Li         GetType(index);
972*f0dffb02SXin Li         break;
973*f0dffb02SXin Li 
974*f0dffb02SXin Li       case dex::kIndexFieldRef:
975*f0dffb02SXin Li         GetFieldDecl(index);
976*f0dffb02SXin Li         break;
977*f0dffb02SXin Li 
978*f0dffb02SXin Li       case dex::kIndexMethodRef:
979*f0dffb02SXin Li         GetMethodDecl(index);
980*f0dffb02SXin Li         break;
981*f0dffb02SXin Li 
982*f0dffb02SXin Li       case dex::kIndexMethodAndProtoRef:
983*f0dffb02SXin Li         GetMethodDecl(index);
984*f0dffb02SXin Li         GetProto(index2);
985*f0dffb02SXin Li         break;
986*f0dffb02SXin Li 
987*f0dffb02SXin Li       case dex::kIndexMethodHandleRef:
988*f0dffb02SXin Li         GetMethodHandle(index);
989*f0dffb02SXin Li         break;
990*f0dffb02SXin Li 
991*f0dffb02SXin Li       default:
992*f0dffb02SXin Li         break;
993*f0dffb02SXin Li     }
994*f0dffb02SXin Li 
995*f0dffb02SXin Li     auto isize = dex::GetWidthFromBytecode(ptr);
996*f0dffb02SXin Li     SLICER_CHECK_GT(isize, 0);
997*f0dffb02SXin Li     ptr += isize;
998*f0dffb02SXin Li   }
999*f0dffb02SXin Li   SLICER_CHECK_EQ(ptr, code.end());
1000*f0dffb02SXin Li }
1001*f0dffb02SXin Li 
1002*f0dffb02SXin Li // Basic .dex header structural checks
ValidateHeader()1003*f0dffb02SXin Li void Reader::ValidateHeader() {
1004*f0dffb02SXin Li   SLICER_CHECK_GT(size_, dex::Header::kV40Size);
1005*f0dffb02SXin Li 
1006*f0dffb02SXin Li   // Known issue: For performance reasons the initial size_ passed to jvmti events might be an
1007*f0dffb02SXin Li   // estimate. b/72402467
1008*f0dffb02SXin Li   SLICER_CHECK_LE(header_->file_size, size_);
1009*f0dffb02SXin Li   // Check that we support this version of dex header
1010*f0dffb02SXin Li   SLICER_CHECK(
1011*f0dffb02SXin Li       header_->header_size == dex::Header::kV40Size ||
1012*f0dffb02SXin Li       header_->header_size == dex::Header::kV41Size);
1013*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->endian_tag, dex::kEndianConstant);
1014*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->data_size % 4, 0);
1015*f0dffb02SXin Li 
1016*f0dffb02SXin Li   // If the dex file is within container with other dex files,
1017*f0dffb02SXin Li   // adjust the base address to the start of the container.
1018*f0dffb02SXin Li   SLICER_CHECK_LE(header_->ContainerSize() - header_->ContainerOff(), size_);
1019*f0dffb02SXin Li   image_ -= header_->ContainerOff();
1020*f0dffb02SXin Li   size_ = header_->ContainerSize();
1021*f0dffb02SXin Li 
1022*f0dffb02SXin Li   // Known issue: The fields might be slighly corrupted b/65452964
1023*f0dffb02SXin Li   // SLICER_CHECK_LE(header_->data_off + header_->data_size, size_);
1024*f0dffb02SXin Li 
1025*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->string_ids_off % 4, 0);
1026*f0dffb02SXin Li   SLICER_CHECK_LT(header_->type_ids_size, 65536);
1027*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->type_ids_off % 4, 0);
1028*f0dffb02SXin Li   SLICER_CHECK_LT(header_->proto_ids_size, 65536);
1029*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->proto_ids_off % 4, 0);
1030*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->field_ids_off % 4, 0);
1031*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->method_ids_off % 4, 0);
1032*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->class_defs_off % 4, 0);
1033*f0dffb02SXin Li   SLICER_CHECK_GE(header_->map_off, header_->data_off);
1034*f0dffb02SXin Li   SLICER_CHECK_LT(header_->map_off, size_);
1035*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->link_size, 0);
1036*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->link_off, 0);
1037*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->data_off % 4, 0);
1038*f0dffb02SXin Li   SLICER_CHECK_EQ(header_->map_off % 4, 0);
1039*f0dffb02SXin Li 
1040*f0dffb02SXin Li   // we seem to have .dex files with extra bytes at the end ...
1041*f0dffb02SXin Li   // Known issue: For performance reasons the initial size_ passed to jvmti events might be an
1042*f0dffb02SXin Li   // estimate. b/72402467
1043*f0dffb02SXin Li   SLICER_WEAK_CHECK(header_->data_off + header_->data_size <= size_);
1044*f0dffb02SXin Li 
1045*f0dffb02SXin Li   // but we should still have the whole data section
1046*f0dffb02SXin Li 
1047*f0dffb02SXin Li   // Known issue: The fields might be slightly corrupted b/65452964
1048*f0dffb02SXin Li   // Known issue: For performance reasons the initial size_ passed to jvmti events might be an
1049*f0dffb02SXin Li   // estimate. b/72402467
1050*f0dffb02SXin Li   // SLICER_CHECK_LE(header_->data_off + header_->data_size, size_);
1051*f0dffb02SXin Li 
1052*f0dffb02SXin Li   // validate the map
1053*f0dffb02SXin Li   // (map section size = sizeof(MapList::size) + sizeof(MapList::list[size])
1054*f0dffb02SXin Li   auto map_list = ptr<dex::MapList>(header_->map_off);
1055*f0dffb02SXin Li   SLICER_CHECK_GT(map_list->size, 0);
1056*f0dffb02SXin Li   auto map_section_size =
1057*f0dffb02SXin Li       sizeof(dex::u4) + sizeof(dex::MapItem) * map_list->size;
1058*f0dffb02SXin Li   SLICER_CHECK_LE(header_->map_off + map_section_size, size_);
1059*f0dffb02SXin Li }
1060*f0dffb02SXin Li 
1061*f0dffb02SXin Li }  // namespace dex
1062