blob: ee5cc45c303547650321ccb2a9c43769f3d9c7e9 [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;
Shih-wei Liao195487c2011-08-20 13:29:04 -070020class String;
21class Method;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070022
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070023// TODO: move all of the macro functionality into the DexCache class.
Brian Carlstromf615a612011-07-23 12:50:34 -070024class DexFile {
Carl Shapiro1fb86202011-06-27 17:43:13 -070025 public:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026 static const byte kDexMagic[];
27 static const byte kDexMagicVersion[];
28 static const size_t kSha1DigestSize = 20;
Carl Shapiro80d4dde2011-06-28 16:24:07 -070029
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070030 static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
31 static const byte kEncodedValueArgShift = 5;
32
33 // The value of an invalid index.
34 static const uint32_t kDexNoIndex = 0xFFFFFFFF;
35
36 enum ValueType {
37 kByte = 0x00,
38 kShort = 0x02,
39 kChar = 0x03,
40 kInt = 0x04,
41 kLong = 0x06,
42 kFloat = 0x10,
43 kDouble = 0x11,
44 kString = 0x17,
45 kType = 0x18,
46 kField = 0x19,
47 kMethod = 0x1a,
48 kEnum = 0x1b,
49 kArray = 0x1c,
50 kAnnotation = 0x1d,
51 kNull = 0x1e,
52 kBoolean = 0x1f
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070053 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070054
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070055 // Raw header_item.
56 struct Header {
57 uint8_t magic_[8];
58 uint32_t checksum_;
59 uint8_t signature_[kSha1DigestSize];
60 uint32_t file_size_; // length of entire file
61 uint32_t header_size_; // offset to start of next section
62 uint32_t endian_tag_;
63 uint32_t link_size_;
64 uint32_t link_off_;
65 uint32_t map_off_;
66 uint32_t string_ids_size_;
67 uint32_t string_ids_off_;
68 uint32_t type_ids_size_;
69 uint32_t type_ids_off_;
70 uint32_t proto_ids_size_;
71 uint32_t proto_ids_off_;
72 uint32_t field_ids_size_;
73 uint32_t field_ids_off_;
74 uint32_t method_ids_size_;
75 uint32_t method_ids_off_;
76 uint32_t class_defs_size_;
77 uint32_t class_defs_off_;
78 uint32_t data_size_;
79 uint32_t data_off_;
80 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070081
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070082 // Raw string_id_item.
83 struct StringId {
84 uint32_t string_data_off_; // offset in bytes from the base address
85 };
86
87 // Raw type_id_item.
88 struct TypeId {
89 uint32_t descriptor_idx_; // index into string_ids
90 };
91
92 // Raw field_id_item.
93 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -070094 uint16_t class_idx_; // index into type_ids_ list for defining class
95 uint16_t type_idx_; // index into type_ids_ for field type
96 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070097 };
98
99 // Raw method_id_item.
100 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700101 uint16_t class_idx_; // index into type_ids_ list for defining class
102 uint16_t proto_idx_; // index into proto_ids_ for method prototype
103 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700104 };
105
106 // Raw proto_id_item.
107 struct ProtoId {
108 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
109 uint32_t return_type_idx_; // index into type_ids list for return type
110 uint32_t parameters_off_; // file offset to type_list for parameter types
111 };
112
113 // Raw class_def_item.
114 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700115 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700116 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700117 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700118 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700119 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700120 uint32_t annotations_off_; // file offset to annotations_directory_item
121 uint32_t class_data_off_; // file offset to class_data_item
122 uint32_t static_values_off_; // file offset to EncodedArray
123 };
124
125 // Raw type_item.
126 struct TypeItem {
127 uint16_t type_idx_; // index into type_ids section
128 };
129
130 // Raw type_list.
131 class TypeList {
132 public:
133 uint32_t Size() const {
134 return size_;
135 }
136
137 const TypeItem& GetTypeItem(uint32_t idx) const {
138 CHECK_LT(idx, this->size_);
139 return this->list_[idx];
140 }
141
142 private:
143 uint32_t size_; // size of the list, in entries
144 TypeItem list_[1]; // elements of the list
145 };
146
147 class ParameterIterator { // TODO: stream
148 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700149 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
150 : dex_file_(dex_file), size_(0), pos_(0) {
151 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700152 if (type_list_ != NULL) {
153 size_ = type_list_->Size();
154 }
155 }
156 bool HasNext() const { return pos_ != size_; }
157 void Next() { ++pos_; }
158 const char* GetDescriptor() {
159 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700160 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700161 }
162 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700163 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700164 const TypeList* type_list_;
165 uint32_t size_;
166 uint32_t pos_;
167 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
168 };
169
170 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
171 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700172 }
173
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700174 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
175 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700176 }
177
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700178 // Raw code_item.
179 struct CodeItem {
180 uint16_t registers_size_;
181 uint16_t ins_size_;
182 uint16_t outs_size_;
183 uint16_t tries_size_;
184 uint32_t debug_info_off_; // file offset to debug info stream
185 uint32_t insns_size_; // size of the insns array, in 2 byte code units
186 uint16_t insns_[1];
187 };
188
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700189 struct CatchHandlerItem {
190 uint32_t type_idx_; // type index of the caught exception type
191 uint32_t address_; // handler address
192 };
193
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700194 // Raw try_item.
195 struct TryItem {
196 uint32_t start_addr_;
197 uint16_t insn_count_;
198 uint16_t handler_off_;
199 };
200
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700201 class CatchHandlerIterator {
202 public:
203 CatchHandlerIterator() {
204 remaining_count_ = -1;
205 catch_all_ = false;
206 }
207
208 CatchHandlerIterator(const byte* handler_data) {
209 current_data_ = handler_data;
210 remaining_count_ = DecodeUnsignedLeb128(&current_data_);
211
212 // If remaining_count_ is non-positive, then it is the negative of
213 // the number of catch types, and the catches are followed by a
214 // catch-all handler.
215 if (remaining_count_ <= 0) {
216 catch_all_ = true;
217 remaining_count_ = -remaining_count_;
218 } else {
219 catch_all_ = false;
220 }
221 Next();
222 }
223
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700224 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700225 return handler_;
226 }
227
228 void Next() {
229 if (remaining_count_ > 0) {
230 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
231 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
232 remaining_count_--;
233 return;
234 }
235
236 if (catch_all_) {
237 handler_.type_idx_ = kDexNoIndex;
238 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
239 catch_all_ = false;
240 return;
241 }
242
243 // no more handler
244 remaining_count_ = -1;
245 }
246
247 bool End() const {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700248 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700249 }
250
251 private:
252 CatchHandlerItem handler_;
253 const byte *current_data_; // the current handlder in dex file.
254 int32_t remaining_count_; // number of handler not read.
255 bool catch_all_; // is there a handler that will catch all exceptions in case
256 // that all typed handler does not match.
257 };
258
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700259 // Partially decoded form of class_data_item.
260 struct ClassDataHeader {
261 uint32_t static_fields_size_; // the number of static fields
262 uint32_t instance_fields_size_; // the number of instance fields
263 uint32_t direct_methods_size_; // the number of direct methods
264 uint32_t virtual_methods_size_; // the number of virtual methods
265 };
266
267 // Decoded form of encoded_field.
268 struct Field {
269 uint32_t field_idx_; // index into the field_ids list for the identity of this field
270 uint32_t access_flags_; // access flags for the field
271 };
272
273 // Decoded form of encoded_method.
274 struct Method {
275 uint32_t method_idx_;
276 uint32_t access_flags_;
277 uint32_t code_off_;
278 };
279
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700280 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
281 typedef std::vector<const DexFile*> ClassPath;
282
283 // Search a collection of DexFiles for a descriptor
284 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
285 ClassPath& class_path);
286
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700287 // Opens a .dex file from the file system.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700288 static DexFile* OpenFile(const std::string& filename);
289
290 // Opens a .jar, .zip, or .apk file from the file system.
291 static DexFile* OpenZip(const std::string& filename);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700292
Brian Carlstroma663ea52011-08-19 23:33:41 -0700293 // Opens a .dex file from a new allocated pointer. location is used
294 // to identify the source, for example "/system/framework/core.jar"
295 // or "contrived-test-42". When initializing a ClassLinker from an
296 // image, the location is used to match DexCaches the image to their
297 // corresponding DexFiles.N
298 static DexFile* OpenPtr(byte* ptr, size_t length, const std::string& location);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700299
300 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700301 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700302
Brian Carlstroma663ea52011-08-19 23:33:41 -0700303 const std::string& GetLocation() const {
304 return location_;
305 }
306
307 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700308 CHECK(header_ != NULL);
309 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700310 }
311
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700312 // Looks up a class definition by its class descriptor.
313 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
314
315 // Returns the number of string identifiers in the .dex file.
316 size_t NumStringIds() const {
317 CHECK(header_ != NULL);
318 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700319 }
320
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700321 // Returns the number of type identifiers in the .dex file.
322 size_t NumTypeIds() const {
323 CHECK(header_ != NULL);
324 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700325 }
326
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700327 // Returns the number of prototype identifiers in the .dex file.
328 size_t NumProtoIds() const {
329 CHECK(header_ != NULL);
330 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700331 }
332
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700333 // Returns the number of field identifiers in the .dex file.
334 size_t NumFieldIds() const {
335 CHECK(header_ != NULL);
336 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700337 }
338
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700339 // Returns the number of method identifiers in the .dex file.
340 size_t NumMethodIds() const {
341 CHECK(header_ != NULL);
342 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700343 }
344
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700345 // Returns the number of class definitions in the .dex file.
346 size_t NumClassDefs() const {
347 CHECK(header_ != NULL);
348 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700349 }
350
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700351 // Returns a pointer to the memory mapped class data.
352 // TODO: return a stream
353 const byte* GetClassData(const ClassDef& class_def) const {
354 if (class_def.class_data_off_ == 0) {
355 return NULL;
356 } else {
357 return base_ + class_def.class_data_off_;
358 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700359 }
360
Brian Carlstromf615a612011-07-23 12:50:34 -0700361 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700362 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
363 CHECK(class_data != NULL);
364 ClassDataHeader header;
365 memset(&header, 0, sizeof(ClassDataHeader));
366 if (*class_data != NULL) {
367 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
368 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
369 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
370 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
371 }
372 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700373 }
374
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700375 // Returns the class descriptor string of a class definition.
376 const char* GetClassDescriptor(const ClassDef& class_def) const {
377 return dexStringByTypeIdx(class_def.class_idx_);
378 }
379
380 // Returns the StringId at the specified index.
381 const StringId& GetStringId(uint32_t idx) const {
382 CHECK_LT(idx, NumStringIds());
383 return string_ids_[idx];
384 }
385
386 // Returns the TypeId at the specified index.
387 const TypeId& GetTypeId(uint32_t idx) const {
388 CHECK_LT(idx, NumTypeIds());
389 return type_ids_[idx];
390 }
391
392 // Returns the FieldId at the specified index.
393 const FieldId& GetFieldId(uint32_t idx) const {
394 CHECK_LT(idx, NumFieldIds());
395 return field_ids_[idx];
396 }
397
398 // Returns the MethodId at the specified index.
399 const MethodId& GetMethodId(uint32_t idx) const {
400 CHECK_LT(idx, NumMethodIds());
401 return method_ids_[idx];
402 }
403
404 // Returns the ProtoId at the specified index.
405 const ProtoId& GetProtoId(uint32_t idx) const {
406 CHECK_LT(idx, NumProtoIds());
407 return proto_ids_[idx];
408 }
409
410 // Returns the ClassDef at the specified index.
411 const ClassDef& GetClassDef(uint32_t idx) const {
412 CHECK_LT(idx, NumClassDefs());
413 return class_defs_[idx];
414 }
415
416 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
417 if (class_def.interfaces_off_ == 0) {
418 return NULL;
419 } else {
420 const byte* addr = base_ + class_def.interfaces_off_;
421 return reinterpret_cast<const TypeList*>(addr);
422 }
423 }
424
425 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700426 return GetCodeItem(method.code_off_);
427 }
428
429 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
430 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700431 return NULL; // native or abstract method
432 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700433 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700434 return reinterpret_cast<const CodeItem*>(addr);
435 }
436 }
437
438 // Returns the short form method descriptor for the given prototype.
439 const char* GetShorty(uint32_t proto_idx) const {
440 const ProtoId& proto_id = GetProtoId(proto_idx);
441 return dexStringById(proto_id.shorty_idx_);
442 }
443
444 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
445 if (proto_id.parameters_off_ == 0) {
446 return NULL;
447 } else {
448 const byte* addr = base_ + proto_id.parameters_off_;
449 return reinterpret_cast<const TypeList*>(addr);
450 }
451 }
452
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700453 char* CreateMethodDescriptor(uint32_t proto_idx,
454 int32_t* unicode_length) const;
455
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700456 const byte* GetEncodedArray(const ClassDef& class_def) const {
457 if (class_def.static_values_off_ == 0) {
458 return 0;
459 } else {
460 return base_ + class_def.static_values_off_;
461 }
462 }
463
464 int32_t GetStringLength(const StringId& string_id) const {
465 const byte* ptr = base_ + string_id.string_data_off_;
466 return DecodeUnsignedLeb128(&ptr);
467 }
468
469 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
470
471 // From libdex...
472
473 // Returns a pointer to the UTF-8 string data referred to by the
474 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700475 const char* GetStringData(const StringId& string_id, int32_t* length) const {
476 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700477 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700478 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700479 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700480 }
481
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700482 const char* GetStringData(const StringId& string_id) const {
483 int32_t length;
484 return GetStringData(string_id, &length);
485 }
486
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700487 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700488 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700489 if (idx == kDexNoIndex) {
490 *unicode_length = 0;
491 return NULL;
492 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700493 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700494 return GetStringData(string_id, unicode_length);
495 }
496
497 const char* dexStringById(uint32_t idx) const {
498 int32_t unicode_length;
499 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700500 }
501
Shih-wei Liao195487c2011-08-20 13:29:04 -0700502 String* dexArtStringById(uint32_t idx) const;
503
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700504 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700505 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
506 const TypeId& type_id = GetTypeId(idx);
507 return dexStringById(type_id.descriptor_idx_, unicode_length);
508 }
509
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700510 const char* dexStringByTypeIdx(uint32_t idx) const {
511 const TypeId& type_id = GetTypeId(idx);
512 return dexStringById(type_id.descriptor_idx_);
513 }
514
Shih-wei Liao195487c2011-08-20 13:29:04 -0700515 String* dexArtStringByTypeIdx(uint32_t idx) const {
516 const TypeId& type_id = GetTypeId(idx);
517 return dexArtStringById(type_id.descriptor_idx_);
518 }
519
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700520 // TODO: encoded_field is actually a stream of bytes
521 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700522 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700523 uint32_t* last_idx) const {
524 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
525 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
526 field->field_idx_ = idx;
527 *last_idx = idx;
528 }
529
530 // TODO: encoded_method is actually a stream of bytes
531 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700532 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700533 uint32_t* last_idx) const {
534 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
535 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
536 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
537 method->method_idx_ = idx;
538 *last_idx = idx;
539 }
540
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700541 const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) const {
542 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
543 return reinterpret_cast<const TryItem*>
544 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
545 }
546
547 // Get the base of the encoded data for the given DexCode.
548 const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) const {
549 const byte* handler_data = reinterpret_cast<const byte*>
550 (dexGetTryItems(code_item, code_item.tries_size_));
551 return handler_data + offset;
552 }
553
554 // Find the handler associated with a given address, if any.
555 // Initializes the given iterator and returns true if a match is
556 // found. Returns end if there is no applicable handler.
557 CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) const {
558 CatchHandlerItem handler;
559 handler.address_ = -1;
560 int32_t offset = -1;
561
562 // Short-circuit the overwhelmingly common cases.
563 switch (code_item.tries_size_) {
564 case 0:
565 break;
566 case 1: {
567 const TryItem* tries = dexGetTryItems(code_item, 0);
568 uint32_t start = tries->start_addr_;
569 if (address < start)
570 break;
571
572 uint32_t end = start + tries->insn_count_;
573 if (address >= end)
574 break;
575
576 offset = tries->handler_off_;
577 break;
578 }
579 default:
580 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
581 }
582
583 if (offset >= 0) {
584 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
585 return CatchHandlerIterator(handler_data);
586 }
587 return CatchHandlerIterator();
588 }
589
590 int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
591 int32_t tries_size,
592 uint32_t address) const {
593 // Note: Signed type is important for max and min.
594 int32_t min = 0;
595 int32_t max = tries_size - 1;
596
597 while (max >= min) {
598 int32_t guess = (min + max) >> 1;
599 const TryItem* pTry = dexGetTryItems(code_item, guess);
600 uint32_t start = pTry->start_addr_;
601
602 if (address < start) {
603 max = guess - 1;
604 continue;
605 }
606
607 uint32_t end = start + pTry->insn_count_;
608 if (address >= end) {
609 min = guess + 1;
610 continue;
611 }
612
613 // We have a winner!
614 return (int32_t) pTry->handler_off_;
615 }
616
617 // No match.
618 return -1;
619 }
620
Shih-wei Liao195487c2011-08-20 13:29:04 -0700621 // Get the pointer to the start of the debugging data
622 const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
623 if (code_item->debug_info_off_ == 0) {
624 return NULL;
625 } else {
626 return base_ + code_item->debug_info_off_;
627 }
628 }
629
630 // Callback for "new position table entry".
631 // Returning true causes the decoder to stop early.
632 typedef bool (*DexDebugNewPositionCb)(void *cnxt, uint32_t address, uint32_t line_num);
633
634 // Callback for "new locals table entry". "signature" is an empty string
635 // if no signature is available for an entry.
636 typedef void (*DexDebugNewLocalCb)(void *cnxt, uint16_t reg,
637 uint32_t startAddress,
638 uint32_t endAddress,
639 const String* name,
640 const String* descriptor,
641 const String* signature);
642
643 static bool LineNumForPcCb(void *cnxt, uint32_t address, uint32_t line_num) {
644 LineNumFromPcContext *context = (LineNumFromPcContext *)cnxt;
645
646 // We know that this callback will be called in
647 // ascending address order, so keep going until we find
648 // a match or we've just gone past it.
649 if (address > context->address_) {
650 // The line number from the previous positions callback
651 // wil be the final result.
652 return true;
653 } else {
654 context->line_num_ = line_num;
655 return address == context->address_;
656 }
657 }
658
659
660 // Debug info opcodes and constants
661 enum {
662 DBG_END_SEQUENCE = 0x00,
663 DBG_ADVANCE_PC = 0x01,
664 DBG_ADVANCE_LINE = 0x02,
665 DBG_START_LOCAL = 0x03,
666 DBG_START_LOCAL_EXTENDED = 0x04,
667 DBG_END_LOCAL = 0x05,
668 DBG_RESTART_LOCAL = 0x06,
669 DBG_SET_PROLOGUE_END = 0x07,
670 DBG_SET_EPILOGUE_BEGIN = 0x08,
671 DBG_SET_FILE = 0x09,
672 DBG_FIRST_SPECIAL = 0x0a,
673 DBG_LINE_BASE = -4,
674 DBG_LINE_RANGE = 15,
675 };
676
677 struct LocalInfo {
678 LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0), is_live_(false) {}
679
680 // E.g., list
681 const String* name_;
682
683 // E.g., Ljava/util/LinkedList;
684 const String* descriptor_;
685
686 // E.g., java.util.LinkedList<java.lang.Integer>
687 const String* signature_;
688
689 // PC location where the local is first defined.
690 uint16_t start_address_;
691
692 // Is the local defined and live.
693 bool is_live_;
694 };
695
696 struct LineNumFromPcContext {
697 LineNumFromPcContext(uint32_t address, uint32_t line_num) :
698 address_(address), line_num_(line_num) {}
699 uint32_t address_;
700 uint32_t line_num_;
701 };
702
703 void InvokeLocalCbIfLive(void *cnxt, int reg, uint32_t end_address,
704 LocalInfo *local_in_reg, DexDebugNewLocalCb local_cb) const {
705 if (local_cb != NULL && local_in_reg[reg].is_live_) {
706 local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
707 local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
708 local_in_reg[reg].signature_);
709 }
710 }
711
712 // Determine the source file line number based on the program counter.
713 // "pc" is an offset, in 16-bit units, from the start of the method's code.
714 //
715 // Returns -1 if no match was found (possibly because the source files were
716 // compiled without "-g", so no line number information is present).
717 // Returns -2 for native methods (as expected in exception traces).
718 //
719 // This is used by runtime; therefore use art::Method not art::DexFile::Method.
720 int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
721
722 void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
723 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
724 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
725
726 void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method *method,
727 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
728 void* cnxt) const {
729 const byte* stream = dexGetDebugInfoStream(code_item);
730 LocalInfo local_in_reg[code_item->registers_size_];
731
732 if (stream != NULL) {
733 dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
734 }
735 for (int reg = 0; reg < code_item->registers_size_; reg++) {
736 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_, local_in_reg, local_cb);
737 }
738 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700739
740 // TODO: const reference
741 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
742 CHECK_GE(class_def, class_defs_);
743 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
744 return class_def - class_defs_;
745 }
746
747 const char* dexGetSourceFile(const ClassDef& class_def) const {
748 if (class_def.source_file_idx_ == 0xffffffff) {
749 return NULL;
750 } else {
751 return dexStringById(class_def.source_file_idx_);
752 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700753 }
754
Carl Shapiro1fb86202011-06-27 17:43:13 -0700755 private:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700756 // Helper class to deallocate underlying storage.
757 class Closer {
758 public:
759 virtual ~Closer();
760 };
761
762 // Helper class to deallocate mmap-backed .dex files.
763 class MmapCloser : public Closer {
764 public:
765 MmapCloser(void* addr, size_t length);
766 virtual ~MmapCloser();
767 private:
768 void* addr_;
769 size_t length_;
770 };
771
772 // Helper class for deallocating new/delete-backed .dex files.
773 class PtrCloser : public Closer {
774 public:
775 PtrCloser(byte* addr);
776 virtual ~PtrCloser();
777 private:
778 byte* addr_;
779 };
780
781 // Opens a .dex file at a the given address.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700782 static DexFile* Open(const byte* dex_file, size_t length, const std::string& location, Closer* closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700783
Brian Carlstroma663ea52011-08-19 23:33:41 -0700784 DexFile(const byte* addr, size_t length, const std::string& location, Closer* closer)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700785 : base_(addr),
786 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700787 location_(location),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700788 closer_(closer),
789 header_(0),
790 string_ids_(0),
791 type_ids_(0),
792 field_ids_(0),
793 method_ids_(0),
794 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700795 class_defs_(0) {
796 CHECK(addr != NULL);
797 CHECK_GT(length, 0U);
798 CHECK(closer != NULL);
799 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700800
801 // Top-level initializer that calls other Init methods.
802 bool Init();
803
804 // Caches pointers into to the various file sections.
805 void InitMembers();
806
807 // Builds the index of descriptors to class definitions.
808 void InitIndex();
809
810 // Returns true if the byte string equals the magic value.
811 bool CheckMagic(const byte* magic);
812
813 // Returns true if the header magic is of the expected value.
814 bool IsMagicValid();
815
816 // The index of descriptors to class definitions.
Brian Carlstromf615a612011-07-23 12:50:34 -0700817 typedef std::map<const StringPiece, const DexFile::ClassDef*> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700818 Index index_;
819
820 // The base address of the memory mapping.
821 const byte* base_;
822
823 // The size of the underlying memory allocation in bytes.
824 size_t length_;
825
Brian Carlstroma663ea52011-08-19 23:33:41 -0700826 // Typically the dex file name when availble, alternatively some identifying string.
827 //
828 // The ClassLinker will use this to match DexFiles the boot class
829 // path to DexCache::GetLocation when loading from an image.
830 const std::string location_;
831
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700832 // Helper object to free the underlying allocation.
833 scoped_ptr<Closer> closer_;
834
835 // Points to the header section.
836 const Header* header_;
837
838 // Points to the base of the string identifier list.
839 const StringId* string_ids_;
840
841 // Points to the base of the type identifier list.
842 const TypeId* type_ids_;
843
844 // Points to the base of the field identifier list.
845 const FieldId* field_ids_;
846
847 // Points to the base of the method identifier list.
848 const MethodId* method_ids_;
849
850 // Points to the base of the prototype identifier list.
851 const ProtoId* proto_ids_;
852
853 // Points to the base of the class definition list.
854 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700855};
856
857} // namespace art
858
859#endif // ART_SRC_DEX_FILE_H_