xref: /aosp_15_r20/tools/dexter/slicer/export/slicer/reader.h (revision f0dffb02cdb5c647d21204e89a92a1ffae2dad87)
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