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