• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "arrayview.h"
20 #include "buffer.h"
21 #include "common.h"
22 #include "dex_format.h"
23 #include "dex_leb128.h"
24 #include "hash_table.h"
25 #include "index_map.h"
26 #include "memview.h"
27 
28 #include <stdlib.h>
29 #include <map>
30 #include <memory>
31 #include <vector>
32 #include <string>
33 
34 // A simple, lightweight IR to abstract the key .dex structures
35 //
36 // 1. All the cross-IR references are modeled as plain pointers.
37 // 2. Newly allocated nodes are mem-zeroed first
38 //
39 // This IR can mirror any .dex file, although for JVMTI BCI
40 // it's expected to construct the IR for the single modified class only
41 // (and include only the nodes referenced from that class)
42 
43 #define SLICER_IR_TYPE     \
44   using Node::Node; \
45   friend struct DexFile;
46 
47 #define SLICER_IR_INDEXED_TYPE           \
48   using IndexedNode::IndexedNode; \
49   friend struct DexFile;
50 
51 namespace ir {
52 
53 // convenience notation
54 template <class T>
55 using own = std::unique_ptr<T>;
56 
57 struct Node;
58 struct IndexedNode;
59 struct EncodedValue;
60 struct EncodedArray;
61 struct String;
62 struct Type;
63 struct TypeList;
64 struct Proto;
65 struct FieldDecl;
66 struct EncodedField;
67 struct DebugInfo;
68 struct Code;
69 struct MethodDecl;
70 struct EncodedMethod;
71 struct AnnotationElement;
72 struct Annotation;
73 struct AnnotationSet;
74 struct AnnotationSetRefList;
75 struct FieldAnnotation;
76 struct MethodAnnotation;
77 struct ParamAnnotation;
78 struct AnnotationsDirectory;
79 struct Class;
80 struct DexFile;
81 
82 // The base class for all the .dex IR types:
83 //   This is not a polymorphic interface, but
84 //   a way to constrain the allocation and ownership
85 //   of .dex IR nodes.
86 struct Node {
newNode87   void* operator new(size_t size) {
88     return ::calloc(1, size);
89   }
90 
91   void* operator new[](size_t size) {
92     return ::calloc(1, size);
93   }
94 
deleteNode95   void operator delete(void* ptr) {
96     ::free(ptr);
97   }
98 
99   void operator delete[](void* ptr) {
100     ::free(ptr);
101   }
102 
103  public:
104   Node(const Node&) = delete;
105   Node& operator=(const Node&) = delete;
106 
107  protected:
108   Node() = default;
109   ~Node() = default;
110 };
111 
112 // a concession for the convenience of the .dex writer
113 //
114 // TODO: consider moving the indexing to the writer.
115 //
116 struct IndexedNode : public Node {
117   SLICER_IR_TYPE;
118 
119   // this is the index in the generated image
120   // (not the original index)
121   dex::u4 index;
122 
123   // original indexe
124   // (from the source .dex image or allocated post reader)
125   dex::u4 orig_index;
126 };
127 
128 struct EncodedValue : public Node {
129   SLICER_IR_TYPE;
130 
131   dex::u1 type;
132   union {
133     int8_t byte_value;
134     int16_t short_value;
135     uint16_t char_value;
136     int32_t int_value;
137     int64_t long_value;
138     float float_value;
139     double double_value;
140     String* string_value;
141     Type* type_value;
142     FieldDecl* field_value;
143     MethodDecl* method_value;
144     FieldDecl* enum_value;
145     EncodedArray* array_value;
146     Annotation* annotation_value;
147     bool bool_value;
148   } u;
149 
150   SLICER_EXTRA(slicer::MemView original);
151 };
152 
153 struct EncodedArray : public Node {
154   SLICER_IR_TYPE;
155 
156   std::vector<EncodedValue*> values;
157 };
158 
159 struct String : public IndexedNode {
160   SLICER_IR_INDEXED_TYPE;
161 
162   // opaque DEX "string_data_item"
163   slicer::MemView data;
164 
c_strString165   const char* c_str() const {
166     const dex::u1* strData = data.ptr<dex::u1>();
167     dex::ReadULeb128(&strData);
168     return reinterpret_cast<const char*>(strData);
169   }
170 };
171 
172 struct Type : public IndexedNode {
173   SLICER_IR_INDEXED_TYPE;
174 
175   enum class Category { Void, Scalar, WideScalar, Reference };
176 
177   String* descriptor;
178   Class* class_def;
179 
180   std::string Decl() const;
181   Category GetCategory() const;
182 };
183 
184 struct TypeList : public Node {
185   SLICER_IR_TYPE;
186 
187   std::vector<Type*> types;
188 };
189 
190 struct Proto : public IndexedNode {
191   SLICER_IR_INDEXED_TYPE;
192 
193   String* shorty;
194   Type* return_type;
195   TypeList* param_types;
196 
197   std::string Signature() const;
198 };
199 
200 struct FieldDecl : public IndexedNode {
201   SLICER_IR_INDEXED_TYPE;
202 
203   String* name;
204   Type* type;
205   Type* parent;
206 };
207 
208 struct EncodedField : public Node {
209   SLICER_IR_TYPE;
210 
211   FieldDecl* decl;
212   dex::u4 access_flags;
213 };
214 
215 struct DebugInfo : public Node {
216   SLICER_IR_TYPE;
217 
218   dex::u4 line_start;
219   std::vector<String*> param_names;
220 
221   // original debug info opcodes stream
222   // (must be "relocated" when creating a new .dex image)
223   slicer::MemView data;
224 };
225 
226 struct Code : public Node {
227   SLICER_IR_TYPE;
228 
229   dex::u2 registers;
230   dex::u2 ins_count;
231   dex::u2 outs_count;
232   slicer::ArrayView<const dex::u2> instructions;
233   slicer::ArrayView<const dex::TryBlock> try_blocks;
234   slicer::MemView catch_handlers;
235   DebugInfo* debug_info;
236 };
237 
238 struct MethodDecl : public IndexedNode {
239   SLICER_IR_INDEXED_TYPE;
240 
241   String* name;
242   Proto* prototype;
243   Type* parent;
244 };
245 
246 struct EncodedMethod : public Node {
247   SLICER_IR_TYPE;
248 
249   MethodDecl* decl;
250   Code* code;
251   dex::u4 access_flags;
252 };
253 
254 struct AnnotationElement : public Node {
255   SLICER_IR_TYPE;
256 
257   String* name;
258   EncodedValue* value;
259 };
260 
261 struct Annotation : public Node {
262   SLICER_IR_TYPE;
263 
264   Type* type;
265   std::vector<AnnotationElement*> elements;
266   dex::u1 visibility;
267 };
268 
269 struct AnnotationSet : public Node {
270   SLICER_IR_TYPE;
271 
272   std::vector<Annotation*> annotations;
273 };
274 
275 struct AnnotationSetRefList : public Node {
276   SLICER_IR_TYPE;
277 
278   std::vector<AnnotationSet*> annotations;
279 };
280 
281 struct FieldAnnotation : public Node {
282   SLICER_IR_TYPE;
283 
284   FieldDecl* field_decl;
285   AnnotationSet* annotations;
286 };
287 
288 struct MethodAnnotation : public Node {
289   SLICER_IR_TYPE;
290 
291   MethodDecl* method_decl;
292   AnnotationSet* annotations;
293 };
294 
295 struct ParamAnnotation : public Node {
296   SLICER_IR_TYPE;
297 
298   MethodDecl* method_decl;
299   AnnotationSetRefList* annotations;
300 };
301 
302 struct AnnotationsDirectory : public Node {
303   SLICER_IR_TYPE;
304 
305   AnnotationSet* class_annotation;
306   std::vector<FieldAnnotation*> field_annotations;
307   std::vector<MethodAnnotation*> method_annotations;
308   std::vector<ParamAnnotation*> param_annotations;
309 };
310 
311 struct Class : public IndexedNode {
312   SLICER_IR_INDEXED_TYPE;
313 
314   Type* type;
315   dex::u4 access_flags;
316   Type* super_class;
317   TypeList* interfaces;
318   String* source_file;
319   AnnotationsDirectory* annotations;
320   EncodedArray* static_init;
321 
322   std::vector<EncodedField*> static_fields;
323   std::vector<EncodedField*> instance_fields;
324   std::vector<EncodedMethod*> direct_methods;
325   std::vector<EncodedMethod*> virtual_methods;
326 };
327 
328 // ir::String hashing
329 struct StringsHasher {
GetKeyStringsHasher330   const char* GetKey(const String* string) const { return string->c_str(); }
331   uint32_t Hash(const char* string_key) const;
332   bool Compare(const char* string_key, const String* string) const;
333 };
334 
335 // ir::Proto hashing
336 struct ProtosHasher {
GetKeyProtosHasher337   std::string GetKey(const Proto* proto) const { return proto->Signature(); }
338   uint32_t Hash(const std::string& proto_key) const;
339   bool Compare(const std::string& proto_key, const Proto* proto) const;
340 };
341 
342 // ir::EncodedMethod hashing
343 struct MethodKey {
344   String* class_descriptor = nullptr;
345   String* method_name = nullptr;
346   Proto* prototype = nullptr;
347 };
348 
349 struct MethodsHasher {
350   MethodKey GetKey(const EncodedMethod* method) const;
351   uint32_t Hash(const MethodKey& method_key) const;
352   bool Compare(const MethodKey& method_key, const EncodedMethod* method) const;
353 };
354 
355 using StringsLookup = slicer::HashTable<const char*, String, StringsHasher>;
356 using PrototypesLookup = slicer::HashTable<const std::string&, Proto, ProtosHasher>;
357 using MethodsLookup = slicer::HashTable<const MethodKey&, EncodedMethod, MethodsHasher>;
358 
359 // The main container/root for a .dex IR
360 struct DexFile {
361   // indexed structures
362   std::vector<own<String>> strings;
363   std::vector<own<Type>> types;
364   std::vector<own<Proto>> protos;
365   std::vector<own<FieldDecl>> fields;
366   std::vector<own<MethodDecl>> methods;
367   std::vector<own<Class>> classes;
368 
369   // data segment structures
370   std::vector<own<EncodedField>> encoded_fields;
371   std::vector<own<EncodedMethod>> encoded_methods;
372   std::vector<own<TypeList>> type_lists;
373   std::vector<own<Code>> code;
374   std::vector<own<DebugInfo>> debug_info;
375   std::vector<own<EncodedValue>> encoded_values;
376   std::vector<own<EncodedArray>> encoded_arrays;
377   std::vector<own<Annotation>> annotations;
378   std::vector<own<AnnotationElement>> annotation_elements;
379   std::vector<own<AnnotationSet>> annotation_sets;
380   std::vector<own<AnnotationSetRefList>> annotation_set_ref_lists;
381   std::vector<own<AnnotationsDirectory>> annotations_directories;
382   std::vector<own<FieldAnnotation>> field_annotations;
383   std::vector<own<MethodAnnotation>> method_annotations;
384   std::vector<own<ParamAnnotation>> param_annotations;
385 
386   // original index to IR node mappings
387   //
388   // CONSIDER: we only need to carry around
389   //   the relocation for the referenced items
390   //
391   std::map<dex::u4, Type*> types_map;
392   std::map<dex::u4, String*> strings_map;
393   std::map<dex::u4, Proto*> protos_map;
394   std::map<dex::u4, FieldDecl*> fields_map;
395   std::map<dex::u4, MethodDecl*> methods_map;
396   std::map<dex::u4, Class*> classes_map;
397 
398   // original .dex header "magic" signature
399   slicer::MemView magic;
400 
401   // keep track of the used index values
402   // (so we can easily allocate new ones)
403   IndexMap strings_indexes;
404   IndexMap types_indexes;
405   IndexMap protos_indexes;
406   IndexMap fields_indexes;
407   IndexMap methods_indexes;
408   IndexMap classes_indexes;
409 
410   // lookup hash tables
411   StringsLookup strings_lookup;
412   MethodsLookup methods_lookup;
413   PrototypesLookup prototypes_lookup;
414 
415  public:
416   DexFile() = default;
417 
418   // No copy/move semantics
419   DexFile(const DexFile&) = delete;
420   DexFile& operator=(const DexFile&) = delete;
421 
422   template <class T>
AllocDexFile423   T* Alloc() {
424     T* p = new T();
425     Track(p);
426     return p;
427   }
428 
AttachBufferDexFile429   void AttachBuffer(slicer::Buffer&& buffer) {
430     buffers_.push_back(std::move(buffer));
431   }
432 
433   void Normalize();
434 
435  private:
436   void TopSortClassIndex(Class* irClass, dex::u4* nextIndex);
437   void SortClassIndexes();
438 
439   template <class T>
PushOwnDexFile440   void PushOwn(std::vector<own<T>>& v, T* p) {
441     v.push_back(own<T>(p));
442   }
443 
TrackDexFile444   void Track(String* p) { PushOwn(strings, p); }
TrackDexFile445   void Track(Type* p) { PushOwn(types, p); }
TrackDexFile446   void Track(Proto* p) { PushOwn(protos, p); }
TrackDexFile447   void Track(FieldDecl* p) { PushOwn(fields, p); }
TrackDexFile448   void Track(MethodDecl* p) { PushOwn(methods, p); }
TrackDexFile449   void Track(Class* p) { PushOwn(classes, p); }
450 
TrackDexFile451   void Track(EncodedField* p) { PushOwn(encoded_fields, p); }
TrackDexFile452   void Track(EncodedMethod* p) { PushOwn(encoded_methods, p); }
TrackDexFile453   void Track(TypeList* p) { PushOwn(type_lists, p); }
TrackDexFile454   void Track(Code* p) { PushOwn(code, p); }
TrackDexFile455   void Track(DebugInfo* p) { PushOwn(debug_info, p); }
TrackDexFile456   void Track(EncodedValue* p) { PushOwn(encoded_values, p); }
TrackDexFile457   void Track(EncodedArray* p) { PushOwn(encoded_arrays, p); }
TrackDexFile458   void Track(Annotation* p) { PushOwn(annotations, p); }
TrackDexFile459   void Track(AnnotationElement* p) { PushOwn(annotation_elements, p); }
TrackDexFile460   void Track(AnnotationSet* p) { PushOwn(annotation_sets, p); }
TrackDexFile461   void Track(AnnotationSetRefList* p) { PushOwn(annotation_set_ref_lists, p); }
TrackDexFile462   void Track(AnnotationsDirectory* p) { PushOwn(annotations_directories, p); }
TrackDexFile463   void Track(FieldAnnotation* p) { PushOwn(field_annotations, p); }
TrackDexFile464   void Track(MethodAnnotation* p) { PushOwn(method_annotations, p); }
TrackDexFile465   void Track(ParamAnnotation* p) { PushOwn(param_annotations, p); }
466 
467 private:
468   // additional memory buffers owned by this .dex IR
469   std::vector<slicer::Buffer> buffers_;
470 };
471 
472 }  // namespace ir
473 
474 #undef SLICER_IR_TYPE
475 #undef SLICER_IR_INDEXED_TYPE
476