blob: b3f9bdd39a7e99551ca64dbf95e30d82412424aa [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
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700222 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700223 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 {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700246 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700247 }
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
Brian Carlstroma663ea52011-08-19 23:33:41 -0700291 // Opens a .dex file from a new allocated pointer. location is used
292 // to identify the source, for example "/system/framework/core.jar"
293 // or "contrived-test-42". When initializing a ClassLinker from an
294 // image, the location is used to match DexCaches the image to their
295 // corresponding DexFiles.N
296 static DexFile* OpenPtr(byte* ptr, size_t length, const std::string& location);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700297
298 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700299 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700300
Brian Carlstroma663ea52011-08-19 23:33:41 -0700301 const std::string& GetLocation() const {
302 return location_;
303 }
304
305 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700306 CHECK(header_ != NULL);
307 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700308 }
309
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700310 // Looks up a class definition by its class descriptor.
311 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
312
313 // Returns the number of string identifiers in the .dex file.
314 size_t NumStringIds() const {
315 CHECK(header_ != NULL);
316 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700317 }
318
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700319 // Returns the number of type identifiers in the .dex file.
320 size_t NumTypeIds() const {
321 CHECK(header_ != NULL);
322 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700323 }
324
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700325 // Returns the number of prototype identifiers in the .dex file.
326 size_t NumProtoIds() const {
327 CHECK(header_ != NULL);
328 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700329 }
330
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700331 // Returns the number of field identifiers in the .dex file.
332 size_t NumFieldIds() const {
333 CHECK(header_ != NULL);
334 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700335 }
336
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700337 // Returns the number of method identifiers in the .dex file.
338 size_t NumMethodIds() const {
339 CHECK(header_ != NULL);
340 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700341 }
342
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700343 // Returns the number of class definitions in the .dex file.
344 size_t NumClassDefs() const {
345 CHECK(header_ != NULL);
346 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700347 }
348
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700349 // Returns a pointer to the memory mapped class data.
350 // TODO: return a stream
351 const byte* GetClassData(const ClassDef& class_def) const {
352 if (class_def.class_data_off_ == 0) {
353 return NULL;
354 } else {
355 return base_ + class_def.class_data_off_;
356 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700357 }
358
Brian Carlstromf615a612011-07-23 12:50:34 -0700359 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700360 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
361 CHECK(class_data != NULL);
362 ClassDataHeader header;
363 memset(&header, 0, sizeof(ClassDataHeader));
364 if (*class_data != NULL) {
365 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
366 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
367 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
368 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
369 }
370 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700371 }
372
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700373 // Returns the class descriptor string of a class definition.
374 const char* GetClassDescriptor(const ClassDef& class_def) const {
375 return dexStringByTypeIdx(class_def.class_idx_);
376 }
377
378 // Returns the StringId at the specified index.
379 const StringId& GetStringId(uint32_t idx) const {
380 CHECK_LT(idx, NumStringIds());
381 return string_ids_[idx];
382 }
383
384 // Returns the TypeId at the specified index.
385 const TypeId& GetTypeId(uint32_t idx) const {
386 CHECK_LT(idx, NumTypeIds());
387 return type_ids_[idx];
388 }
389
390 // Returns the FieldId at the specified index.
391 const FieldId& GetFieldId(uint32_t idx) const {
392 CHECK_LT(idx, NumFieldIds());
393 return field_ids_[idx];
394 }
395
396 // Returns the MethodId at the specified index.
397 const MethodId& GetMethodId(uint32_t idx) const {
398 CHECK_LT(idx, NumMethodIds());
399 return method_ids_[idx];
400 }
401
402 // Returns the ProtoId at the specified index.
403 const ProtoId& GetProtoId(uint32_t idx) const {
404 CHECK_LT(idx, NumProtoIds());
405 return proto_ids_[idx];
406 }
407
408 // Returns the ClassDef at the specified index.
409 const ClassDef& GetClassDef(uint32_t idx) const {
410 CHECK_LT(idx, NumClassDefs());
411 return class_defs_[idx];
412 }
413
414 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
415 if (class_def.interfaces_off_ == 0) {
416 return NULL;
417 } else {
418 const byte* addr = base_ + class_def.interfaces_off_;
419 return reinterpret_cast<const TypeList*>(addr);
420 }
421 }
422
423 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700424 return GetCodeItem(method.code_off_);
425 }
426
427 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
428 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700429 return NULL; // native or abstract method
430 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700431 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700432 return reinterpret_cast<const CodeItem*>(addr);
433 }
434 }
435
436 // Returns the short form method descriptor for the given prototype.
437 const char* GetShorty(uint32_t proto_idx) const {
438 const ProtoId& proto_id = GetProtoId(proto_idx);
439 return dexStringById(proto_id.shorty_idx_);
440 }
441
442 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
443 if (proto_id.parameters_off_ == 0) {
444 return NULL;
445 } else {
446 const byte* addr = base_ + proto_id.parameters_off_;
447 return reinterpret_cast<const TypeList*>(addr);
448 }
449 }
450
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700451 char* CreateMethodDescriptor(uint32_t proto_idx,
452 int32_t* unicode_length) const;
453
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700454 const byte* GetEncodedArray(const ClassDef& class_def) const {
455 if (class_def.static_values_off_ == 0) {
456 return 0;
457 } else {
458 return base_ + class_def.static_values_off_;
459 }
460 }
461
462 int32_t GetStringLength(const StringId& string_id) const {
463 const byte* ptr = base_ + string_id.string_data_off_;
464 return DecodeUnsignedLeb128(&ptr);
465 }
466
467 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
468
469 // From libdex...
470
471 // Returns a pointer to the UTF-8 string data referred to by the
472 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700473 const char* GetStringData(const StringId& string_id, int32_t* length) const {
474 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700475 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700476 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700477 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700478 }
479
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700480 const char* GetStringData(const StringId& string_id) const {
481 int32_t length;
482 return GetStringData(string_id, &length);
483 }
484
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700485 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700486 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700487 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700488 return GetStringData(string_id, unicode_length);
489 }
490
491 const char* dexStringById(uint32_t idx) const {
492 int32_t unicode_length;
493 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700494 }
495
496 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700497 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
498 const TypeId& type_id = GetTypeId(idx);
499 return dexStringById(type_id.descriptor_idx_, unicode_length);
500 }
501
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700502 const char* dexStringByTypeIdx(uint32_t idx) const {
503 const TypeId& type_id = GetTypeId(idx);
504 return dexStringById(type_id.descriptor_idx_);
505 }
506
507 // TODO: encoded_field is actually a stream of bytes
508 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700509 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700510 uint32_t* last_idx) const {
511 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
512 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
513 field->field_idx_ = idx;
514 *last_idx = idx;
515 }
516
517 // TODO: encoded_method is actually a stream of bytes
518 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700519 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700520 uint32_t* last_idx) const {
521 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
522 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
523 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
524 method->method_idx_ = idx;
525 *last_idx = idx;
526 }
527
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700528 const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) const {
529 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
530 return reinterpret_cast<const TryItem*>
531 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
532 }
533
534 // Get the base of the encoded data for the given DexCode.
535 const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) const {
536 const byte* handler_data = reinterpret_cast<const byte*>
537 (dexGetTryItems(code_item, code_item.tries_size_));
538 return handler_data + offset;
539 }
540
541 // Find the handler associated with a given address, if any.
542 // Initializes the given iterator and returns true if a match is
543 // found. Returns end if there is no applicable handler.
544 CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) const {
545 CatchHandlerItem handler;
546 handler.address_ = -1;
547 int32_t offset = -1;
548
549 // Short-circuit the overwhelmingly common cases.
550 switch (code_item.tries_size_) {
551 case 0:
552 break;
553 case 1: {
554 const TryItem* tries = dexGetTryItems(code_item, 0);
555 uint32_t start = tries->start_addr_;
556 if (address < start)
557 break;
558
559 uint32_t end = start + tries->insn_count_;
560 if (address >= end)
561 break;
562
563 offset = tries->handler_off_;
564 break;
565 }
566 default:
567 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
568 }
569
570 if (offset >= 0) {
571 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
572 return CatchHandlerIterator(handler_data);
573 }
574 return CatchHandlerIterator();
575 }
576
577 int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
578 int32_t tries_size,
579 uint32_t address) const {
580 // Note: Signed type is important for max and min.
581 int32_t min = 0;
582 int32_t max = tries_size - 1;
583
584 while (max >= min) {
585 int32_t guess = (min + max) >> 1;
586 const TryItem* pTry = dexGetTryItems(code_item, guess);
587 uint32_t start = pTry->start_addr_;
588
589 if (address < start) {
590 max = guess - 1;
591 continue;
592 }
593
594 uint32_t end = start + pTry->insn_count_;
595 if (address >= end) {
596 min = guess + 1;
597 continue;
598 }
599
600 // We have a winner!
601 return (int32_t) pTry->handler_off_;
602 }
603
604 // No match.
605 return -1;
606 }
607
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700608
609 // TODO: const reference
610 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
611 CHECK_GE(class_def, class_defs_);
612 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
613 return class_def - class_defs_;
614 }
615
616 const char* dexGetSourceFile(const ClassDef& class_def) const {
617 if (class_def.source_file_idx_ == 0xffffffff) {
618 return NULL;
619 } else {
620 return dexStringById(class_def.source_file_idx_);
621 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700622 }
623
Carl Shapiro1fb86202011-06-27 17:43:13 -0700624 private:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700625 // Helper class to deallocate underlying storage.
626 class Closer {
627 public:
628 virtual ~Closer();
629 };
630
631 // Helper class to deallocate mmap-backed .dex files.
632 class MmapCloser : public Closer {
633 public:
634 MmapCloser(void* addr, size_t length);
635 virtual ~MmapCloser();
636 private:
637 void* addr_;
638 size_t length_;
639 };
640
641 // Helper class for deallocating new/delete-backed .dex files.
642 class PtrCloser : public Closer {
643 public:
644 PtrCloser(byte* addr);
645 virtual ~PtrCloser();
646 private:
647 byte* addr_;
648 };
649
650 // Opens a .dex file at a the given address.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700651 static DexFile* Open(const byte* dex_file, size_t length, const std::string& location, Closer* closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700652
Brian Carlstroma663ea52011-08-19 23:33:41 -0700653 DexFile(const byte* addr, size_t length, const std::string& location, Closer* closer)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700654 : base_(addr),
655 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700656 location_(location),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700657 closer_(closer),
658 header_(0),
659 string_ids_(0),
660 type_ids_(0),
661 field_ids_(0),
662 method_ids_(0),
663 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700664 class_defs_(0) {
665 CHECK(addr != NULL);
666 CHECK_GT(length, 0U);
667 CHECK(closer != NULL);
668 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700669
670 // Top-level initializer that calls other Init methods.
671 bool Init();
672
673 // Caches pointers into to the various file sections.
674 void InitMembers();
675
676 // Builds the index of descriptors to class definitions.
677 void InitIndex();
678
679 // Returns true if the byte string equals the magic value.
680 bool CheckMagic(const byte* magic);
681
682 // Returns true if the header magic is of the expected value.
683 bool IsMagicValid();
684
685 // The index of descriptors to class definitions.
Brian Carlstromf615a612011-07-23 12:50:34 -0700686 typedef std::map<const StringPiece, const DexFile::ClassDef*> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700687 Index index_;
688
689 // The base address of the memory mapping.
690 const byte* base_;
691
692 // The size of the underlying memory allocation in bytes.
693 size_t length_;
694
Brian Carlstroma663ea52011-08-19 23:33:41 -0700695 // Typically the dex file name when availble, alternatively some identifying string.
696 //
697 // The ClassLinker will use this to match DexFiles the boot class
698 // path to DexCache::GetLocation when loading from an image.
699 const std::string location_;
700
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700701 // Helper object to free the underlying allocation.
702 scoped_ptr<Closer> closer_;
703
704 // Points to the header section.
705 const Header* header_;
706
707 // Points to the base of the string identifier list.
708 const StringId* string_ids_;
709
710 // Points to the base of the type identifier list.
711 const TypeId* type_ids_;
712
713 // Points to the base of the field identifier list.
714 const FieldId* field_ids_;
715
716 // Points to the base of the method identifier list.
717 const MethodId* method_ids_;
718
719 // Points to the base of the prototype identifier list.
720 const ProtoId* proto_ids_;
721
722 // Points to the base of the class definition list.
723 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700724};
725
726} // namespace art
727
728#endif // ART_SRC_DEX_FILE_H_