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 slicer::ArrayView<const dex::MethodHandle> MethodHandles() const; 57 const dex::MapList* DexMapList() const; 58 59 // IR creation interface GetIr()60 std::shared_ptr<ir::DexFile> GetIr() const { return dex_ir_; } 61 void CreateFullIr(); 62 void CreateClassIr(dex::u4 index); 63 dex::u4 FindClassIndex(const char* class_descriptor) const; 64 65 private: 66 // Internal access to IR nodes for indexed .dex structures 67 ir::Class* GetClass(dex::u4 index); 68 ir::Type* GetType(dex::u4 index); 69 ir::FieldDecl* GetFieldDecl(dex::u4 index); 70 ir::MethodDecl* GetMethodDecl(dex::u4 index); 71 ir::Proto* GetProto(dex::u4 index); 72 ir::String* GetString(dex::u4 index); 73 ir::MethodHandle* GetMethodHandle(dex::u4 index); 74 75 // Parsing annotations 76 ir::AnnotationsDirectory* ExtractAnnotations(dex::u4 offset); 77 ir::Annotation* ExtractAnnotationItem(dex::u4 offset); 78 ir::AnnotationSet* ExtractAnnotationSet(dex::u4 offset); 79 ir::AnnotationSetRefList* ExtractAnnotationSetRefList(dex::u4 offset); 80 ir::FieldAnnotation* ParseFieldAnnotation(const dex::u1** pptr); 81 ir::MethodAnnotation* ParseMethodAnnotation(const dex::u1** pptr); 82 ir::ParamAnnotation* ParseParamAnnotation(const dex::u1** pptr); 83 ir::EncodedField* ParseEncodedField(const dex::u1** pptr, dex::u4* baseIndex); 84 ir::Annotation* ParseAnnotation(const dex::u1** pptr); 85 ir::MethodHandle* ParseMethodHandle(dex::u4 index); 86 87 // Parse encoded values and arrays 88 ir::EncodedValue* ParseEncodedValue(const dex::u1** pptr); 89 ir::EncodedArray* ParseEncodedArray(const dex::u1** pptr); 90 ir::EncodedArray* ExtractEncodedArray(dex::u4 offset); 91 92 // Parse root .dex structures 93 ir::Class* ParseClass(dex::u4 index); 94 ir::EncodedMethod* ParseEncodedMethod(const dex::u1** pptr, dex::u4* baseIndex); 95 ir::Type* ParseType(dex::u4 index); 96 ir::FieldDecl* ParseFieldDecl(dex::u4 index); 97 ir::MethodDecl* ParseMethodDecl(dex::u4 index); 98 ir::TypeList* ExtractTypeList(dex::u4 offset); 99 ir::Proto* ParseProto(dex::u4 index); 100 ir::String* ParseString(dex::u4 index); 101 102 // Parse code and debug information 103 ir::DebugInfo* ExtractDebugInfo(dex::u4 offset); 104 ir::Code* ExtractCode(dex::u4 offset); 105 void ParseInstructions(slicer::ArrayView<const dex::u2> code); 106 107 // Convert a file pointer (absolute offset) to an in-memory pointer 108 template <class T> ptr(int offset)109 const T* ptr(int offset) const { 110 SLICER_CHECK_GE(offset, 0 && offset + sizeof(T) <= size_); 111 return reinterpret_cast<const T*>(image_ + offset); 112 } 113 114 // Convert a data section file pointer (absolute offset) to an in-memory pointer 115 // (offset should be inside the data section) 116 template <class T> dataPtr(int offset)117 const T* dataPtr(int offset) const { 118 SLICER_CHECK_GE(offset, header_->data_off && offset + sizeof(T) <= size_); 119 return reinterpret_cast<const T*>(image_ + offset); 120 } 121 122 // Map an indexed section to an ArrayView<T> 123 template <class T> section(int offset,int count)124 slicer::ArrayView<const T> section(int offset, int count) const { 125 return slicer::ArrayView<const T>(ptr<T>(offset), count); 126 } 127 128 // Simple accessor for a MUTF8 string data GetStringData(dex::u4 index)129 const dex::u1* GetStringData(dex::u4 index) const { 130 auto& stringId = StringIds()[index]; 131 return dataPtr<dex::u1>(stringId.string_data_off); 132 } 133 134 void ValidateHeader(); 135 136 private: 137 // the in-memory .dex image 138 const dex::u1* image_; 139 size_t size_; 140 141 // .dex image header 142 const dex::Header* header_; 143 144 // .dex IR associated with the reader 145 std::shared_ptr<ir::DexFile> dex_ir_; 146 147 // maps for de-duplicating items identified by file pointers 148 std::map<dex::u4, ir::TypeList*> type_lists_; 149 std::map<dex::u4, ir::Annotation*> annotations_; 150 std::map<dex::u4, ir::AnnotationSet*> annotation_sets_; 151 std::map<dex::u4, ir::AnnotationsDirectory*> annotations_directories_; 152 std::map<dex::u4, ir::EncodedArray*> encoded_arrays_; 153 }; 154 155 } // namespace dex 156