blob: ea2ac4dba6f7437bd4136ca1452b7e87e7d5bcf0 [file] [log] [blame]
Carl Shapiro1fb86202011-06-27 17:43:13 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_RAW_DEX_FILE_H_
4#define ART_SRC_RAW_DEX_FILE_H_
5
6#include "src/globals.h"
7#include "src/leb128.h"
8#include "src/logging.h"
Carl Shapiro80d4dde2011-06-28 16:24:07 -07009#include "src/scoped_ptr.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070010#include "src/strutil.h"
11
12#include <map>
13
14namespace art {
15
16class RawDexFile {
17 public:
18 static const byte kDexMagic[];
19 static const byte kDexMagicVersion[];
20 static const size_t kSha1DigestSize = 20;
21
22 // Raw header_item.
23 struct Header {
Carl Shapiro80d4dde2011-06-28 16:24:07 -070024 uint8_t magic_[8];
25 uint32_t checksum_;
26 uint8_t signature_[kSha1DigestSize];
Carl Shapiro1fb86202011-06-27 17:43:13 -070027 uint32_t file_size_; // length of entire file
28 uint32_t header_size_; // offset to start of next section
29 uint32_t endian_tag_;
30 uint32_t link_size_;
31 uint32_t link_off_;
32 uint32_t map_off_;
33 uint32_t string_ids_size_;
34 uint32_t string_ids_off_;
35 uint32_t type_ids_size_;
36 uint32_t type_ids_off_;
37 uint32_t proto_ids_size_;
38 uint32_t proto_ids_off_;
39 uint32_t field_ids_size_;
40 uint32_t field_ids_off_;
41 uint32_t method_ids_size_;
42 uint32_t method_ids_off_;
43 uint32_t class_defs_size_;
44 uint32_t class_defs_off_;
45 uint32_t data_size_;
46 uint32_t data_off_;
47 };
48
49 // Raw string_id_item.
50 struct StringId {
51 uint32_t string_data_off_; // offset in bytes from the base address
52 };
53
54 // Raw type_id_item.
55 struct TypeId {
56 uint32_t descriptor_idx_; // index into string_ids
57 };
58
59 // Raw field_id_item.
60 struct FieldId {
Carl Shapiro3ee755d2011-06-28 12:11:04 -070061 uint16_t class_idx_; // index into typeIds list for defining class
62 uint16_t type_idx_; // index into typeIds for field type
Carl Shapiro1fb86202011-06-27 17:43:13 -070063 uint32_t name_idx_; // index into stringIds for field name
64 };
65
66 // Raw method_id_item.
67 struct MethodId {
Carl Shapiro3ee755d2011-06-28 12:11:04 -070068 uint16_t class_idx_; // index into typeIds list for defining class
69 uint16_t proto_idx_; // index into protoIds for method prototype
Carl Shapiro1fb86202011-06-27 17:43:13 -070070 uint32_t name_idx_; // index into stringIds for method name
71 };
72
73 // Raw proto_id_item.
74 struct ProtoId {
75 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
76 uint32_t return_type_idx_; // index into type_ids list for return type
77 uint32_t parameters_off_; // file offset to type_list for parameter types
78 };
79
80 // Raw class_def_item.
81 struct ClassDef {
82 uint32_t class_idx_; // index into typeIds for this class
83 uint32_t access_flags_;
84 uint32_t superclass_idx_; // index into typeIds for superclass
85 uint32_t interfaces_off_; // file offset to TypeList
86 uint32_t source_file_idx_; // index into stringIds for source file name
87 uint32_t annotations_off_; // file offset to annotations_directory_item
88 uint32_t class_data_off_; // file offset to class_data_item
89 uint32_t static_values_off_; // file offset to EncodedArray
90 };
91
92 // Raw type_item.
93 struct TypeItem {
94 uint16_t type_idx_; // index into type_ids section
95 };
96
97 // Raw type_list.
98 class TypeList {
99 public:
100 uint32_t Size() const {
101 return size_;
102 }
103
104 const TypeItem& GetTypeItem(uint32_t idx) const {
105 CHECK_LT(idx, this->size_);
106 return this->list_[idx];
107 }
108
109 private:
110 uint32_t size_; // size of the list, in entries
111 TypeItem list_[1]; // elements of the list
112 };
113
114 // Raw code_item.
115 struct Code {
116 uint16_t registers_size_;
117 uint16_t ins_size_;
118 uint16_t outs_size_;
119 uint16_t tries_size_;
120 uint32_t debug_info_off_; // file offset to debug info stream
121 uint32_t insns_size_; // size of the insns array, in 2 byte code units
122 uint16_t insns_[1];
123 };
124
125 // Partially decoded form of class_data_item.
126 struct ClassDataHeader {
127 uint32_t static_fields_size_; // the number of static fields
128 uint32_t instance_fields_size_; // the number of instance fields
129 uint32_t direct_methods_size_; // the number of direct methods
130 uint32_t virtual_methods_size_; // the number of virtual methods
131 };
132
133 // Decoded form of encoded_field.
134 struct Field {
135 uint32_t field_idx_; // index into the field_ids list for the identity of this field
136 uint32_t access_flags_; // access flags for the field
137 };
138
139 // Decoded form of encoded_method.
140 struct Method {
141 uint32_t method_idx_;
142 uint32_t access_flags_;
143 uint32_t code_off_;
144 };
145
Carl Shapiro80d4dde2011-06-28 16:24:07 -0700146 // Helper class to deallocate underlying storage.
147 class Closer {
148 public:
149 virtual ~Closer();
150 };
151
152 // Opens a .dex file from the file system.
153 static RawDexFile* OpenFile(const char* filename);
154
155 // Opens a .dex file from a base64 encoded array.
156 static RawDexFile* OpenBase64(const char* base64);
157
158 // Opens a .dex file at a the given address.
159 static RawDexFile* Open(const byte* dex_file, Closer* closer);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700160
161 // Closes a .dex file.
Carl Shapiro80d4dde2011-06-28 16:24:07 -0700162 virtual ~RawDexFile();
Carl Shapiro1fb86202011-06-27 17:43:13 -0700163
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700164 const Header& GetHeader() {
165 CHECK(header_ != NULL);
166 return *header_;
167 }
168
Carl Shapiro1fb86202011-06-27 17:43:13 -0700169 // Looks up a class definition by its class descriptor.
170 const ClassDef* FindClassDef(const char* descriptor);
171
172 // Returns the number of string identifiers in the .dex file.
173 size_t NumStringIds() const {
174 CHECK(header_ != NULL);
175 return header_->string_ids_size_;
176 }
177
178 // Returns the number of type identifiers in the .dex file.
179 size_t NumTypeIds() const {
180 CHECK(header_ != NULL);
181 return header_->type_ids_size_;
182 }
183
184 // Returns the number of prototype identifiers in the .dex file.
185 size_t NumProtoIds() const {
186 CHECK(header_ != NULL);
187 return header_->proto_ids_size_;
188 }
189
190 // Returns the number of field identifiers in the .dex file.
191 size_t NumFieldIds() const {
192 CHECK(header_ != NULL);
193 return header_->field_ids_size_;
194 }
195
196 // Returns the number of method identifiers in the .dex file.
197 size_t NumMethodIds() const {
198 CHECK(header_ != NULL);
199 return header_->method_ids_size_;
200 }
201
202 // Returns the number of class definitions in the .dex file.
203 size_t NumClassDefs() const {
204 CHECK(header_ != NULL);
205 return header_->class_defs_size_;
206 }
207
208 // Returns a pointer to the memory mapped class data.
209 const byte* GetClassData(const ClassDef& class_def) const {
210 if (class_def.class_data_off_ == 0) {
211 LG << "class_def.class_data_off_ == 0";
212 return NULL;
213 }
214 return base_ + class_def.class_data_off_;
215 }
216
217 // Decodes the header section from the raw class data bytes.
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700218 ClassDataHeader ReadClassDataHeader(const byte** class_data) {
219 ClassDataHeader header;
220 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
221 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
222 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
223 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
224 return header;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700225 }
226
227 // Returns the class descriptor string of a class definition.
228 const char* GetClassDescriptor(const ClassDef& class_def) const {
229 return dexStringByTypeIdx(class_def.class_idx_);
230 }
231
232 // Returns the StringId at the specified index.
233 const StringId& GetStringId(uint32_t idx) const {
234 CHECK_LT(idx, NumStringIds());
235 return string_ids_[idx];
236 }
237
238 // Returns the TypeId at the specified index.
239 const TypeId& GetTypeId(uint32_t idx) const {
240 CHECK_LT(idx, NumTypeIds());
241 return type_ids_[idx];
242 }
243
244 // Returns the FieldId at the specified index.
245 const FieldId& GetFieldId(uint32_t idx) const {
246 CHECK_LT(idx, NumFieldIds());
247 return field_ids_[idx];
248 }
249
250 // Returns the MethodId at the specified index.
251 const MethodId& GetMethodId(uint32_t idx) const {
252 CHECK_LT(idx, NumMethodIds());
253 return method_ids_[idx];
254 }
255
256 // Returns the ProtoId at the specified index.
257 const ProtoId& GetProtoId(uint32_t idx) const {
258 CHECK_LT(idx, NumProtoIds());
259 return proto_ids_[idx];
260 }
261
262 // Returns the ClassDef at the specified index.
263 const ClassDef& GetClassDef(uint32_t idx) const {
264 CHECK_LT(idx, NumClassDefs());
265 return class_defs_[idx];
266 }
267
268 const TypeList* GetInterfacesList(const ClassDef& class_def) {
269 if (class_def.interfaces_off_ == 0) {
270 return NULL;
271 } else {
272 const byte* addr = base_ + class_def.interfaces_off_;
273 return reinterpret_cast<const TypeList*>(addr);
274 }
275 }
276
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700277 const Code* GetCode(const Method& method) const {
278 if (method.code_off_ == 0) {
279 return NULL; // native or abstract method
280 } else {
281 const byte* addr = base_ + method.code_off_;
282 return reinterpret_cast<const Code*>(addr);
283 }
284 }
285
286 // Returns the short form method descriptor for the given prototype.
287 const char* GetShorty(uint32_t proto_idx) {
288 const ProtoId& proto_id = GetProtoId(proto_idx);
289 return dexStringById(proto_id.shorty_idx_);
290 }
291
Carl Shapiro1fb86202011-06-27 17:43:13 -0700292 // From libdex...
293
294 // Returns a pointer to the UTF-8 string data referred to by the
295 // given string_id.
296 const char* dexGetStringData(const StringId& string_id) const {
297 const byte* ptr = base_ + string_id.string_data_off_;
298 // Skip the uleb128 length.
299 while (*(ptr++) > 0x7f) /* empty */ ;
300 return (const char*) ptr;
301 }
302
303 // return the UTF-8 encoded string with the specified string_id index
304 const char* dexStringById(uint32_t idx) const {
305 const StringId& string_id = GetStringId(idx);
306 return dexGetStringData(string_id);
307 }
308
309 // Get the descriptor string associated with a given type index.
310 const char* dexStringByTypeIdx(uint32_t idx) const {
311 const TypeId& type_id = GetTypeId(idx);
312 return dexStringById(type_id.descriptor_idx_);
313 }
314
Carl Shapiro3ee755d2011-06-28 12:11:04 -0700315 void dexReadClassDataField(const byte** encoded_field,
316 RawDexFile::Field* field,
317 uint32_t* last_idx) const {
318 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
319 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
320 field->field_idx_ = idx;
321 *last_idx = idx;
322 }
323
324 void dexReadClassDataMethod(const byte** encoded_method,
325 RawDexFile::Method* method,
326 uint32_t* last_idx) const {
327 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
328 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
329 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
330 method->method_idx_ = idx;
331 *last_idx = idx;
332 }
333
334
335 // TODO: const reference
336 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
337 CHECK_GE(class_def, class_defs_);
338 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
339 return class_def - class_defs_;
340 }
341
342 const char* dexGetSourceFile(const ClassDef& class_def) const {
343 if (class_def.source_file_idx_ == 0xffffffff) {
344 return NULL;
345 } else {
346 return dexStringById(class_def.source_file_idx_);
347 }
348 }
349
Carl Shapiro1fb86202011-06-27 17:43:13 -0700350 private:
Carl Shapiro80d4dde2011-06-28 16:24:07 -0700351 RawDexFile(const byte* addr, Closer* closer)
Carl Shapiro1fb86202011-06-27 17:43:13 -0700352 : base_(addr),
Carl Shapiro80d4dde2011-06-28 16:24:07 -0700353 closer_(closer),
Carl Shapiro1fb86202011-06-27 17:43:13 -0700354 header_(0),
355 string_ids_(0),
356 type_ids_(0),
357 field_ids_(0),
358 method_ids_(0),
359 proto_ids_(0),
360 class_defs_(0) {}
361
362 // Top-level initializer that calls other Init methods.
363 bool Init();
364
365 // Caches pointers into to the various file sections.
366 void InitMembers();
367
368 // Builds the index of descriptors to class definitions.
369 void InitIndex();
370
371 // Returns true if the byte string equals the magic value.
372 bool CheckMagic(const byte* magic);
373
374 // Returns true if the header magic is of the expected value.
375 bool IsMagicValid();
376
377 // The index of descriptors to class definitions.
378 typedef std::map<const char*, const RawDexFile::ClassDef*, CStringLt> Index;
379 Index index_;
380
381 // The base address of the memory mapping.
382 const byte* base_;
383
Carl Shapiro80d4dde2011-06-28 16:24:07 -0700384 // Helper object to free the underlying allocation.
385 scoped_ptr<Closer> closer_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700386
387 // Points to the header section.
388 const Header* header_;
389
390 // Points to the base of the string identifier list.
391 const StringId* string_ids_;
392
393 // Points to the base of the type identifier list.
394 const TypeId* type_ids_;
395
396 // Points to the base of the field identifier list.
397 const FieldId* field_ids_;
398
399 // Points to the base of the method identifier list.
400 const MethodId* method_ids_;
401
402 // Points to the base of the prototype identifier list.
403 const ProtoId* proto_ids_;
404
405 // Points to the base of the class definition list.
406 const ClassDef* class_defs_;
407};
408
409} // namespace art
410
411#endif // ART_SRC_RAW_DEX_FILE_H_