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