blob: 373ec519ba11d60c9525c5d68626925b64645cf9 [file] [log] [blame]
Carl Shapiro1fb86202011-06-27 17:43:13 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_DEX_FILE_H_
4#define ART_SRC_DEX_FILE_H_
5
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07006#include <map>
Brian Carlstrom74eb46a2011-08-02 20:10:14 -07007#include <vector>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07008
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07009#include "globals.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070010#include "leb128.h"
11#include "logging.h"
12#include "scoped_ptr.h"
13#include "stringpiece.h"
14#include "strutil.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -070015#include "utils.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070016
17namespace art {
18
Carl Shapiro5fafe2b2011-07-09 15:34:41 -070019union JValue;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070020
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070021// TODO: move all of the macro functionality into the DexCache class.
Brian Carlstromf615a612011-07-23 12:50:34 -070022class DexFile {
Carl Shapiro1fb86202011-06-27 17:43:13 -070023 public:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070024 static const byte kDexMagic[];
25 static const byte kDexMagicVersion[];
26 static const size_t kSha1DigestSize = 20;
Carl Shapiro80d4dde2011-06-28 16:24:07 -070027
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070028 static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
29 static const byte kEncodedValueArgShift = 5;
30
31 // The value of an invalid index.
32 static const uint32_t kDexNoIndex = 0xFFFFFFFF;
33
34 enum ValueType {
35 kByte = 0x00,
36 kShort = 0x02,
37 kChar = 0x03,
38 kInt = 0x04,
39 kLong = 0x06,
40 kFloat = 0x10,
41 kDouble = 0x11,
42 kString = 0x17,
43 kType = 0x18,
44 kField = 0x19,
45 kMethod = 0x1a,
46 kEnum = 0x1b,
47 kArray = 0x1c,
48 kAnnotation = 0x1d,
49 kNull = 0x1e,
50 kBoolean = 0x1f
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070051 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070052
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070053 // Raw header_item.
54 struct Header {
55 uint8_t magic_[8];
56 uint32_t checksum_;
57 uint8_t signature_[kSha1DigestSize];
58 uint32_t file_size_; // length of entire file
59 uint32_t header_size_; // offset to start of next section
60 uint32_t endian_tag_;
61 uint32_t link_size_;
62 uint32_t link_off_;
63 uint32_t map_off_;
64 uint32_t string_ids_size_;
65 uint32_t string_ids_off_;
66 uint32_t type_ids_size_;
67 uint32_t type_ids_off_;
68 uint32_t proto_ids_size_;
69 uint32_t proto_ids_off_;
70 uint32_t field_ids_size_;
71 uint32_t field_ids_off_;
72 uint32_t method_ids_size_;
73 uint32_t method_ids_off_;
74 uint32_t class_defs_size_;
75 uint32_t class_defs_off_;
76 uint32_t data_size_;
77 uint32_t data_off_;
78 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070079
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070080 // Raw string_id_item.
81 struct StringId {
82 uint32_t string_data_off_; // offset in bytes from the base address
83 };
84
85 // Raw type_id_item.
86 struct TypeId {
87 uint32_t descriptor_idx_; // index into string_ids
88 };
89
90 // Raw field_id_item.
91 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -070092 uint16_t class_idx_; // index into type_ids_ list for defining class
93 uint16_t type_idx_; // index into type_ids_ for field type
94 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070095 };
96
97 // Raw method_id_item.
98 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -070099 uint16_t class_idx_; // index into type_ids_ list for defining class
100 uint16_t proto_idx_; // index into proto_ids_ for method prototype
101 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700102 };
103
104 // Raw proto_id_item.
105 struct ProtoId {
106 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
107 uint32_t return_type_idx_; // index into type_ids list for return type
108 uint32_t parameters_off_; // file offset to type_list for parameter types
109 };
110
111 // Raw class_def_item.
112 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700113 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700114 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700115 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700116 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700117 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700118 uint32_t annotations_off_; // file offset to annotations_directory_item
119 uint32_t class_data_off_; // file offset to class_data_item
120 uint32_t static_values_off_; // file offset to EncodedArray
121 };
122
123 // Raw type_item.
124 struct TypeItem {
125 uint16_t type_idx_; // index into type_ids section
126 };
127
128 // Raw type_list.
129 class TypeList {
130 public:
131 uint32_t Size() const {
132 return size_;
133 }
134
135 const TypeItem& GetTypeItem(uint32_t idx) const {
136 CHECK_LT(idx, this->size_);
137 return this->list_[idx];
138 }
139
140 private:
141 uint32_t size_; // size of the list, in entries
142 TypeItem list_[1]; // elements of the list
143 };
144
145 class ParameterIterator { // TODO: stream
146 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700147 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
148 : dex_file_(dex_file), size_(0), pos_(0) {
149 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700150 if (type_list_ != NULL) {
151 size_ = type_list_->Size();
152 }
153 }
154 bool HasNext() const { return pos_ != size_; }
155 void Next() { ++pos_; }
156 const char* GetDescriptor() {
157 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700158 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700159 }
160 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700161 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700162 const TypeList* type_list_;
163 uint32_t size_;
164 uint32_t pos_;
165 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
166 };
167
168 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
169 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700170 }
171
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700172 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
173 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700174 }
175
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700176 // Raw code_item.
177 struct CodeItem {
178 uint16_t registers_size_;
179 uint16_t ins_size_;
180 uint16_t outs_size_;
181 uint16_t tries_size_;
182 uint32_t debug_info_off_; // file offset to debug info stream
183 uint32_t insns_size_; // size of the insns array, in 2 byte code units
184 uint16_t insns_[1];
185 };
186
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700187 struct CatchHandlerItem {
188 uint32_t type_idx_; // type index of the caught exception type
189 uint32_t address_; // handler address
190 };
191
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700192 // Raw try_item.
193 struct TryItem {
194 uint32_t start_addr_;
195 uint16_t insn_count_;
196 uint16_t handler_off_;
197 };
198
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700199 class CatchHandlerIterator {
200 public:
201 CatchHandlerIterator() {
202 remaining_count_ = -1;
203 catch_all_ = false;
204 }
205
206 CatchHandlerIterator(const byte* handler_data) {
207 current_data_ = handler_data;
208 remaining_count_ = DecodeUnsignedLeb128(&current_data_);
209
210 // If remaining_count_ is non-positive, then it is the negative of
211 // the number of catch types, and the catches are followed by a
212 // catch-all handler.
213 if (remaining_count_ <= 0) {
214 catch_all_ = true;
215 remaining_count_ = -remaining_count_;
216 } else {
217 catch_all_ = false;
218 }
219 Next();
220 }
221
222 CatchHandlerItem& Get() {
223 return handler_;
224 }
225
226 void Next() {
227 if (remaining_count_ > 0) {
228 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
229 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
230 remaining_count_--;
231 return;
232 }
233
234 if (catch_all_) {
235 handler_.type_idx_ = kDexNoIndex;
236 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
237 catch_all_ = false;
238 return;
239 }
240
241 // no more handler
242 remaining_count_ = -1;
243 }
244
245 bool End() const {
246 return remaining_count_ < 0 && catch_all_ == false;
247 }
248
249 private:
250 CatchHandlerItem handler_;
251 const byte *current_data_; // the current handlder in dex file.
252 int32_t remaining_count_; // number of handler not read.
253 bool catch_all_; // is there a handler that will catch all exceptions in case
254 // that all typed handler does not match.
255 };
256
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700257 // Partially decoded form of class_data_item.
258 struct ClassDataHeader {
259 uint32_t static_fields_size_; // the number of static fields
260 uint32_t instance_fields_size_; // the number of instance fields
261 uint32_t direct_methods_size_; // the number of direct methods
262 uint32_t virtual_methods_size_; // the number of virtual methods
263 };
264
265 // Decoded form of encoded_field.
266 struct Field {
267 uint32_t field_idx_; // index into the field_ids list for the identity of this field
268 uint32_t access_flags_; // access flags for the field
269 };
270
271 // Decoded form of encoded_method.
272 struct Method {
273 uint32_t method_idx_;
274 uint32_t access_flags_;
275 uint32_t code_off_;
276 };
277
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700278 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
279 typedef std::vector<const DexFile*> ClassPath;
280
281 // Search a collection of DexFiles for a descriptor
282 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
283 ClassPath& class_path);
284
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700285 // Opens a .dex file from the file system.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700286 static DexFile* OpenFile(const std::string& filename);
287
288 // Opens a .jar, .zip, or .apk file from the file system.
289 static DexFile* OpenZip(const std::string& filename);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700290
291 // Opens a .dex file from a new allocated pointer
Brian Carlstromf615a612011-07-23 12:50:34 -0700292 static DexFile* OpenPtr(byte* ptr, size_t length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700293
294 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700295 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700296
297 const Header& GetHeader() {
298 CHECK(header_ != NULL);
299 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700300 }
301
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700302 // Looks up a class definition by its class descriptor.
303 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
304
305 // Returns the number of string identifiers in the .dex file.
306 size_t NumStringIds() const {
307 CHECK(header_ != NULL);
308 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700309 }
310
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700311 // Returns the number of type identifiers in the .dex file.
312 size_t NumTypeIds() const {
313 CHECK(header_ != NULL);
314 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700315 }
316
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700317 // Returns the number of prototype identifiers in the .dex file.
318 size_t NumProtoIds() const {
319 CHECK(header_ != NULL);
320 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700321 }
322
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700323 // Returns the number of field identifiers in the .dex file.
324 size_t NumFieldIds() const {
325 CHECK(header_ != NULL);
326 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700327 }
328
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329 // Returns the number of method identifiers in the .dex file.
330 size_t NumMethodIds() const {
331 CHECK(header_ != NULL);
332 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700333 }
334
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700335 // Returns the number of class definitions in the .dex file.
336 size_t NumClassDefs() const {
337 CHECK(header_ != NULL);
338 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700339 }
340
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700341 // Returns a pointer to the memory mapped class data.
342 // TODO: return a stream
343 const byte* GetClassData(const ClassDef& class_def) const {
344 if (class_def.class_data_off_ == 0) {
345 return NULL;
346 } else {
347 return base_ + class_def.class_data_off_;
348 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700349 }
350
Brian Carlstromf615a612011-07-23 12:50:34 -0700351 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700352 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
353 CHECK(class_data != NULL);
354 ClassDataHeader header;
355 memset(&header, 0, sizeof(ClassDataHeader));
356 if (*class_data != NULL) {
357 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
358 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
359 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
360 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
361 }
362 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700363 }
364
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700365 // Returns the class descriptor string of a class definition.
366 const char* GetClassDescriptor(const ClassDef& class_def) const {
367 return dexStringByTypeIdx(class_def.class_idx_);
368 }
369
370 // Returns the StringId at the specified index.
371 const StringId& GetStringId(uint32_t idx) const {
372 CHECK_LT(idx, NumStringIds());
373 return string_ids_[idx];
374 }
375
376 // Returns the TypeId at the specified index.
377 const TypeId& GetTypeId(uint32_t idx) const {
378 CHECK_LT(idx, NumTypeIds());
379 return type_ids_[idx];
380 }
381
382 // Returns the FieldId at the specified index.
383 const FieldId& GetFieldId(uint32_t idx) const {
384 CHECK_LT(idx, NumFieldIds());
385 return field_ids_[idx];
386 }
387
388 // Returns the MethodId at the specified index.
389 const MethodId& GetMethodId(uint32_t idx) const {
390 CHECK_LT(idx, NumMethodIds());
391 return method_ids_[idx];
392 }
393
394 // Returns the ProtoId at the specified index.
395 const ProtoId& GetProtoId(uint32_t idx) const {
396 CHECK_LT(idx, NumProtoIds());
397 return proto_ids_[idx];
398 }
399
400 // Returns the ClassDef at the specified index.
401 const ClassDef& GetClassDef(uint32_t idx) const {
402 CHECK_LT(idx, NumClassDefs());
403 return class_defs_[idx];
404 }
405
406 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
407 if (class_def.interfaces_off_ == 0) {
408 return NULL;
409 } else {
410 const byte* addr = base_ + class_def.interfaces_off_;
411 return reinterpret_cast<const TypeList*>(addr);
412 }
413 }
414
415 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700416 return GetCodeItem(method.code_off_);
417 }
418
419 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
420 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700421 return NULL; // native or abstract method
422 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700423 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700424 return reinterpret_cast<const CodeItem*>(addr);
425 }
426 }
427
428 // Returns the short form method descriptor for the given prototype.
429 const char* GetShorty(uint32_t proto_idx) const {
430 const ProtoId& proto_id = GetProtoId(proto_idx);
431 return dexStringById(proto_id.shorty_idx_);
432 }
433
434 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
435 if (proto_id.parameters_off_ == 0) {
436 return NULL;
437 } else {
438 const byte* addr = base_ + proto_id.parameters_off_;
439 return reinterpret_cast<const TypeList*>(addr);
440 }
441 }
442
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700443 char* CreateMethodDescriptor(uint32_t proto_idx,
444 int32_t* unicode_length) const;
445
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700446 const byte* GetEncodedArray(const ClassDef& class_def) const {
447 if (class_def.static_values_off_ == 0) {
448 return 0;
449 } else {
450 return base_ + class_def.static_values_off_;
451 }
452 }
453
454 int32_t GetStringLength(const StringId& string_id) const {
455 const byte* ptr = base_ + string_id.string_data_off_;
456 return DecodeUnsignedLeb128(&ptr);
457 }
458
459 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
460
461 // From libdex...
462
463 // Returns a pointer to the UTF-8 string data referred to by the
464 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700465 const char* GetStringData(const StringId& string_id, int32_t* length) const {
466 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700467 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700468 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700469 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700470 }
471
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700472 const char* GetStringData(const StringId& string_id) const {
473 int32_t length;
474 return GetStringData(string_id, &length);
475 }
476
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700477 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700478 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700479 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700480 return GetStringData(string_id, unicode_length);
481 }
482
483 const char* dexStringById(uint32_t idx) const {
484 int32_t unicode_length;
485 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700486 }
487
488 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700489 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
490 const TypeId& type_id = GetTypeId(idx);
491 return dexStringById(type_id.descriptor_idx_, unicode_length);
492 }
493
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700494 const char* dexStringByTypeIdx(uint32_t idx) const {
495 const TypeId& type_id = GetTypeId(idx);
496 return dexStringById(type_id.descriptor_idx_);
497 }
498
499 // TODO: encoded_field is actually a stream of bytes
500 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700501 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700502 uint32_t* last_idx) const {
503 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
504 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
505 field->field_idx_ = idx;
506 *last_idx = idx;
507 }
508
509 // TODO: encoded_method is actually a stream of bytes
510 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700511 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700512 uint32_t* last_idx) const {
513 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
514 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
515 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
516 method->method_idx_ = idx;
517 *last_idx = idx;
518 }
519
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700520 const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) const {
521 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
522 return reinterpret_cast<const TryItem*>
523 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
524 }
525
526 // Get the base of the encoded data for the given DexCode.
527 const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) const {
528 const byte* handler_data = reinterpret_cast<const byte*>
529 (dexGetTryItems(code_item, code_item.tries_size_));
530 return handler_data + offset;
531 }
532
533 // Find the handler associated with a given address, if any.
534 // Initializes the given iterator and returns true if a match is
535 // found. Returns end if there is no applicable handler.
536 CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) const {
537 CatchHandlerItem handler;
538 handler.address_ = -1;
539 int32_t offset = -1;
540
541 // Short-circuit the overwhelmingly common cases.
542 switch (code_item.tries_size_) {
543 case 0:
544 break;
545 case 1: {
546 const TryItem* tries = dexGetTryItems(code_item, 0);
547 uint32_t start = tries->start_addr_;
548 if (address < start)
549 break;
550
551 uint32_t end = start + tries->insn_count_;
552 if (address >= end)
553 break;
554
555 offset = tries->handler_off_;
556 break;
557 }
558 default:
559 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
560 }
561
562 if (offset >= 0) {
563 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
564 return CatchHandlerIterator(handler_data);
565 }
566 return CatchHandlerIterator();
567 }
568
569 int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
570 int32_t tries_size,
571 uint32_t address) const {
572 // Note: Signed type is important for max and min.
573 int32_t min = 0;
574 int32_t max = tries_size - 1;
575
576 while (max >= min) {
577 int32_t guess = (min + max) >> 1;
578 const TryItem* pTry = dexGetTryItems(code_item, guess);
579 uint32_t start = pTry->start_addr_;
580
581 if (address < start) {
582 max = guess - 1;
583 continue;
584 }
585
586 uint32_t end = start + pTry->insn_count_;
587 if (address >= end) {
588 min = guess + 1;
589 continue;
590 }
591
592 // We have a winner!
593 return (int32_t) pTry->handler_off_;
594 }
595
596 // No match.
597 return -1;
598 }
599
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700600
601 // TODO: const reference
602 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
603 CHECK_GE(class_def, class_defs_);
604 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
605 return class_def - class_defs_;
606 }
607
608 const char* dexGetSourceFile(const ClassDef& class_def) const {
609 if (class_def.source_file_idx_ == 0xffffffff) {
610 return NULL;
611 } else {
612 return dexStringById(class_def.source_file_idx_);
613 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700614 }
615
Carl Shapiro1fb86202011-06-27 17:43:13 -0700616 private:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700617 // Helper class to deallocate underlying storage.
618 class Closer {
619 public:
620 virtual ~Closer();
621 };
622
623 // Helper class to deallocate mmap-backed .dex files.
624 class MmapCloser : public Closer {
625 public:
626 MmapCloser(void* addr, size_t length);
627 virtual ~MmapCloser();
628 private:
629 void* addr_;
630 size_t length_;
631 };
632
633 // Helper class for deallocating new/delete-backed .dex files.
634 class PtrCloser : public Closer {
635 public:
636 PtrCloser(byte* addr);
637 virtual ~PtrCloser();
638 private:
639 byte* addr_;
640 };
641
642 // Opens a .dex file at a the given address.
Brian Carlstromf615a612011-07-23 12:50:34 -0700643 static DexFile* Open(const byte* dex_file, size_t length, Closer* closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700644
Brian Carlstromf615a612011-07-23 12:50:34 -0700645 DexFile(const byte* addr, size_t length, Closer* closer)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700646 : base_(addr),
647 length_(length),
648 closer_(closer),
649 header_(0),
650 string_ids_(0),
651 type_ids_(0),
652 field_ids_(0),
653 method_ids_(0),
654 proto_ids_(0),
655 class_defs_(0) {}
656
657 // Top-level initializer that calls other Init methods.
658 bool Init();
659
660 // Caches pointers into to the various file sections.
661 void InitMembers();
662
663 // Builds the index of descriptors to class definitions.
664 void InitIndex();
665
666 // Returns true if the byte string equals the magic value.
667 bool CheckMagic(const byte* magic);
668
669 // Returns true if the header magic is of the expected value.
670 bool IsMagicValid();
671
672 // The index of descriptors to class definitions.
Brian Carlstromf615a612011-07-23 12:50:34 -0700673 typedef std::map<const StringPiece, const DexFile::ClassDef*> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700674 Index index_;
675
676 // The base address of the memory mapping.
677 const byte* base_;
678
679 // The size of the underlying memory allocation in bytes.
680 size_t length_;
681
682 // Helper object to free the underlying allocation.
683 scoped_ptr<Closer> closer_;
684
685 // Points to the header section.
686 const Header* header_;
687
688 // Points to the base of the string identifier list.
689 const StringId* string_ids_;
690
691 // Points to the base of the type identifier list.
692 const TypeId* type_ids_;
693
694 // Points to the base of the field identifier list.
695 const FieldId* field_ids_;
696
697 // Points to the base of the method identifier list.
698 const MethodId* method_ids_;
699
700 // Points to the base of the prototype identifier list.
701 const ProtoId* proto_ids_;
702
703 // Points to the base of the class definition list.
704 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700705};
706
707} // namespace art
708
709#endif // ART_SRC_DEX_FILE_H_