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 #pragma once 18 19 #include "common.h" 20 #include "dex_format.h" 21 #include "dex_ir.h" 22 23 #include <assert.h> 24 #include <stdlib.h> 25 #include <map> 26 #include <memory> 27 28 namespace dex { 29 30 // Provides both a low level iteration over the .dex 31 // structures and incremental .dex IR creation. 32 // 33 // NOTES: 34 // - only little-endian .dex files and host machines are supported 35 // - aggresive structure validation & minimal semantic validation 36 // 37 class Reader { 38 public: 39 Reader(const dex::u1* image, size_t size); 40 ~Reader() = default; 41 42 // No copy/move semantics 43 Reader(const Reader&) = delete; 44 Reader& operator=(const Reader&) = delete; 45 46 public: 47 // Low level dex format interface Header()48 const dex::Header* Header() const { return header_; } 49 const char* GetStringMUTF8(dex::u4 index) const; 50 slicer::ArrayView<const dex::ClassDef> ClassDefs() const; 51 slicer::ArrayView<const dex::StringId> StringIds() const; 52 slicer::ArrayView<const dex::TypeId> TypeIds() const; 53 slicer::ArrayView<const dex::FieldId> FieldIds() const; 54 slicer::ArrayView<const dex::MethodId> MethodIds() const; 55 slicer::ArrayView<const dex::ProtoId> ProtoIds() const; 56 const dex::MapList* DexMapList() const; 57 58 // IR creation interface GetIr()59 std::shared_ptr<ir::DexFile> GetIr() const { return dex_ir_; } 60 void CreateFullIr(); 61 void CreateClassIr(dex::u4 index); 62 dex::u4 FindClassIndex(const char* class_descriptor) const; 63 64 private: 65 // Internal access to IR nodes for indexed .dex structures 66 ir::Class* GetClass(dex::u4 index); 67 ir::Type* GetType(dex::u4 index); 68 ir::FieldDecl* GetFieldDecl(dex::u4 index); 69 ir::MethodDecl* GetMethodDecl(dex::u4 index); 70 ir::Proto* GetProto(dex::u4 index); 71 ir::String* GetString(dex::u4 index); 72 73 // Parsing annotations 74 ir::AnnotationsDirectory* ExtractAnnotations(dex::u4 offset); 75 ir::Annotation* ExtractAnnotationItem(dex::u4 offset); 76 ir::AnnotationSet* ExtractAnnotationSet(dex::u4 offset); 77 ir::AnnotationSetRefList* ExtractAnnotationSetRefList(dex::u4 offset); 78 ir::FieldAnnotation* ParseFieldAnnotation(const dex::u1** pptr); 79 ir::MethodAnnotation* ParseMethodAnnotation(const dex::u1** pptr); 80 ir::ParamAnnotation* ParseParamAnnotation(const dex::u1** pptr); 81 ir::EncodedField* ParseEncodedField(const dex::u1** pptr, dex::u4* baseIndex); 82 ir::Annotation* ParseAnnotation(const dex::u1** pptr); 83 84 // Parse encoded values and arrays 85 ir::EncodedValue* ParseEncodedValue(const dex::u1** pptr); 86 ir::EncodedArray* ParseEncodedArray(const dex::u1** pptr); 87 ir::EncodedArray* ExtractEncodedArray(dex::u4 offset); 88 89 // Parse root .dex structures 90 ir::Class* ParseClass(dex::u4 index); 91 ir::EncodedMethod* ParseEncodedMethod(const dex::u1** pptr, dex::u4* baseIndex); 92 ir::Type* ParseType(dex::u4 index); 93 ir::FieldDecl* ParseFieldDecl(dex::u4 index); 94 ir::MethodDecl* ParseMethodDecl(dex::u4 index); 95 ir::TypeList* ExtractTypeList(dex::u4 offset); 96 ir::Proto* ParseProto(dex::u4 index); 97 ir::String* ParseString(dex::u4 index); 98 99 // Parse code and debug information 100 ir::DebugInfo* ExtractDebugInfo(dex::u4 offset); 101 ir::Code* ExtractCode(dex::u4 offset); 102 void ParseInstructions(slicer::ArrayView<const dex::u2> code); 103 104 // Convert a file pointer (absolute offset) to an in-memory pointer 105 template <class T> ptr(int offset)106 const T* ptr(int offset) const { 107 SLICER_CHECK(offset >= 0 && offset + sizeof(T) <= size_); 108 return reinterpret_cast<const T*>(image_ + offset); 109 } 110 111 // Convert a data section file pointer (absolute offset) to an in-memory pointer 112 // (offset should be inside the data section) 113 template <class T> dataPtr(int offset)114 const T* dataPtr(int offset) const { 115 SLICER_CHECK(offset >= header_->data_off && offset + sizeof(T) <= size_); 116 return reinterpret_cast<const T*>(image_ + offset); 117 } 118 119 // Map an indexed section to an ArrayView<T> 120 template <class T> section(int offset,int count)121 slicer::ArrayView<const T> section(int offset, int count) const { 122 return slicer::ArrayView<const T>(ptr<T>(offset), count); 123 } 124 125 // Simple accessor for a MUTF8 string data GetStringData(dex::u4 index)126 const dex::u1* GetStringData(dex::u4 index) const { 127 auto& stringId = StringIds()[index]; 128 return dataPtr<dex::u1>(stringId.string_data_off); 129 } 130 131 void ValidateHeader(); 132 133 private: 134 // the in-memory .dex image 135 const dex::u1* image_; 136 size_t size_; 137 138 // .dex image header 139 const dex::Header* header_; 140 141 // .dex IR associated with the reader 142 std::shared_ptr<ir::DexFile> dex_ir_; 143 144 // maps for de-duplicating items identified by file pointers 145 std::map<dex::u4, ir::TypeList*> type_lists_; 146 std::map<dex::u4, ir::Annotation*> annotations_; 147 std::map<dex::u4, ir::AnnotationSet*> annotation_sets_; 148 std::map<dex::u4, ir::AnnotationsDirectory*> annotations_directories_; 149 std::map<dex::u4, ir::EncodedArray*> encoded_arrays_; 150 }; 151 152 } // namespace dex 153