blob: 1431f1e279077d859525593cc0413ee4045e0e9d [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_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070080 private:
81 DISALLOW_COPY_AND_ASSIGN(Header);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070082 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070083
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070084 // Raw string_id_item.
85 struct StringId {
86 uint32_t string_data_off_; // offset in bytes from the base address
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070087 private:
88 DISALLOW_COPY_AND_ASSIGN(StringId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070089 };
90
91 // Raw type_id_item.
92 struct TypeId {
93 uint32_t descriptor_idx_; // index into string_ids
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070094 private:
95 DISALLOW_COPY_AND_ASSIGN(TypeId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070096 };
97
98 // Raw field_id_item.
99 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700100 uint16_t class_idx_; // index into type_ids_ list for defining class
101 uint16_t type_idx_; // index into type_ids_ for field type
102 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700103 private:
104 DISALLOW_COPY_AND_ASSIGN(FieldId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700105 };
106
107 // Raw method_id_item.
108 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700109 uint16_t class_idx_; // index into type_ids_ list for defining class
110 uint16_t proto_idx_; // index into proto_ids_ for method prototype
111 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700112 private:
113 DISALLOW_COPY_AND_ASSIGN(MethodId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700114 };
115
116 // Raw proto_id_item.
117 struct ProtoId {
118 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
119 uint32_t return_type_idx_; // index into type_ids list for return type
120 uint32_t parameters_off_; // file offset to type_list for parameter types
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700121 private:
122 DISALLOW_COPY_AND_ASSIGN(ProtoId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700123 };
124
125 // Raw class_def_item.
126 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700127 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700128 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700129 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700130 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700131 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700132 uint32_t annotations_off_; // file offset to annotations_directory_item
133 uint32_t class_data_off_; // file offset to class_data_item
134 uint32_t static_values_off_; // file offset to EncodedArray
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700135 private:
136 DISALLOW_COPY_AND_ASSIGN(ClassDef);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700137 };
138
139 // Raw type_item.
140 struct TypeItem {
141 uint16_t type_idx_; // index into type_ids section
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700142 private:
143 DISALLOW_COPY_AND_ASSIGN(TypeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700144 };
145
146 // Raw type_list.
147 class TypeList {
148 public:
149 uint32_t Size() const {
150 return size_;
151 }
152
153 const TypeItem& GetTypeItem(uint32_t idx) const {
154 CHECK_LT(idx, this->size_);
155 return this->list_[idx];
156 }
157
158 private:
159 uint32_t size_; // size of the list, in entries
160 TypeItem list_[1]; // elements of the list
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700161 DISALLOW_COPY_AND_ASSIGN(TypeList);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700162 };
163
164 class ParameterIterator { // TODO: stream
165 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700166 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
167 : dex_file_(dex_file), size_(0), pos_(0) {
168 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700169 if (type_list_ != NULL) {
170 size_ = type_list_->Size();
171 }
172 }
173 bool HasNext() const { return pos_ != size_; }
174 void Next() { ++pos_; }
175 const char* GetDescriptor() {
176 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700177 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700178 }
179 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700180 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700181 const TypeList* type_list_;
182 uint32_t size_;
183 uint32_t pos_;
184 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
185 };
186
187 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
188 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700189 }
190
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700191 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
192 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700193 }
194
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700195 // Raw code_item.
196 struct CodeItem {
197 uint16_t registers_size_;
198 uint16_t ins_size_;
199 uint16_t outs_size_;
200 uint16_t tries_size_;
201 uint32_t debug_info_off_; // file offset to debug info stream
202 uint32_t insns_size_; // size of the insns array, in 2 byte code units
203 uint16_t insns_[1];
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700204 private:
205 DISALLOW_COPY_AND_ASSIGN(CodeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700206 };
207
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700208 struct CatchHandlerItem {
209 uint32_t type_idx_; // type index of the caught exception type
210 uint32_t address_; // handler address
211 };
212
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700213 // Raw try_item.
214 struct TryItem {
215 uint32_t start_addr_;
216 uint16_t insn_count_;
217 uint16_t handler_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700218 private:
219 DISALLOW_COPY_AND_ASSIGN(TryItem);
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700220 };
221
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700222 class CatchHandlerIterator {
223 public:
224 CatchHandlerIterator() {
225 remaining_count_ = -1;
226 catch_all_ = false;
227 }
228
229 CatchHandlerIterator(const byte* handler_data) {
230 current_data_ = handler_data;
231 remaining_count_ = DecodeUnsignedLeb128(&current_data_);
232
233 // If remaining_count_ is non-positive, then it is the negative of
234 // the number of catch types, and the catches are followed by a
235 // catch-all handler.
236 if (remaining_count_ <= 0) {
237 catch_all_ = true;
238 remaining_count_ = -remaining_count_;
239 } else {
240 catch_all_ = false;
241 }
242 Next();
243 }
244
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700245 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700246 return handler_;
247 }
248
249 void Next() {
250 if (remaining_count_ > 0) {
251 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
252 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
253 remaining_count_--;
254 return;
255 }
256
257 if (catch_all_) {
258 handler_.type_idx_ = kDexNoIndex;
259 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
260 catch_all_ = false;
261 return;
262 }
263
264 // no more handler
265 remaining_count_ = -1;
266 }
267
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700268 bool HasNext() const {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700269 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700270 }
271
272 private:
273 CatchHandlerItem handler_;
274 const byte *current_data_; // the current handlder in dex file.
275 int32_t remaining_count_; // number of handler not read.
276 bool catch_all_; // is there a handler that will catch all exceptions in case
277 // that all typed handler does not match.
278 };
279
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700280 // Partially decoded form of class_data_item.
281 struct ClassDataHeader {
282 uint32_t static_fields_size_; // the number of static fields
283 uint32_t instance_fields_size_; // the number of instance fields
284 uint32_t direct_methods_size_; // the number of direct methods
285 uint32_t virtual_methods_size_; // the number of virtual methods
286 };
287
288 // Decoded form of encoded_field.
289 struct Field {
290 uint32_t field_idx_; // index into the field_ids list for the identity of this field
291 uint32_t access_flags_; // access flags for the field
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700292 Field() {};
293 private:
294 DISALLOW_COPY_AND_ASSIGN(Field);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700295 };
296
297 // Decoded form of encoded_method.
298 struct Method {
299 uint32_t method_idx_;
300 uint32_t access_flags_;
301 uint32_t code_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700302 Method() {};
303 private:
304 DISALLOW_COPY_AND_ASSIGN(Method);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700305 };
306
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700307 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
308 typedef std::vector<const DexFile*> ClassPath;
309
310 // Search a collection of DexFiles for a descriptor
311 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
312 ClassPath& class_path);
313
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700314 // Opens a .dex file from the file system.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700315 static DexFile* OpenFile(const std::string& filename);
316
317 // Opens a .jar, .zip, or .apk file from the file system.
318 static DexFile* OpenZip(const std::string& filename);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700319
Brian Carlstroma663ea52011-08-19 23:33:41 -0700320 // Opens a .dex file from a new allocated pointer. location is used
321 // to identify the source, for example "/system/framework/core.jar"
322 // or "contrived-test-42". When initializing a ClassLinker from an
323 // image, the location is used to match DexCaches the image to their
324 // corresponding DexFiles.N
325 static DexFile* OpenPtr(byte* ptr, size_t length, const std::string& location);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700326
327 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700328 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329
Brian Carlstroma663ea52011-08-19 23:33:41 -0700330 const std::string& GetLocation() const {
331 return location_;
332 }
333
334 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700335 CHECK(header_ != NULL);
336 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700337 }
338
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700339 // Looks up a class definition by its class descriptor.
340 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
341
342 // Returns the number of string identifiers in the .dex file.
343 size_t NumStringIds() const {
344 CHECK(header_ != NULL);
345 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700346 }
347
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700348 // Returns the number of type identifiers in the .dex file.
349 size_t NumTypeIds() const {
350 CHECK(header_ != NULL);
351 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700352 }
353
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700354 // Returns the number of prototype identifiers in the .dex file.
355 size_t NumProtoIds() const {
356 CHECK(header_ != NULL);
357 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700358 }
359
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700360 // Returns the number of field identifiers in the .dex file.
361 size_t NumFieldIds() const {
362 CHECK(header_ != NULL);
363 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700364 }
365
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700366 // Returns the number of method identifiers in the .dex file.
367 size_t NumMethodIds() const {
368 CHECK(header_ != NULL);
369 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700370 }
371
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700372 // Returns the number of class definitions in the .dex file.
373 size_t NumClassDefs() const {
374 CHECK(header_ != NULL);
375 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700376 }
377
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700378 // Returns a pointer to the memory mapped class data.
379 // TODO: return a stream
380 const byte* GetClassData(const ClassDef& class_def) const {
381 if (class_def.class_data_off_ == 0) {
382 return NULL;
383 } else {
384 return base_ + class_def.class_data_off_;
385 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700386 }
387
Brian Carlstromf615a612011-07-23 12:50:34 -0700388 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700389 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
390 CHECK(class_data != NULL);
391 ClassDataHeader header;
392 memset(&header, 0, sizeof(ClassDataHeader));
393 if (*class_data != NULL) {
394 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
395 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
396 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
397 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
398 }
399 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700400 }
401
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700402 // Returns the class descriptor string of a class definition.
403 const char* GetClassDescriptor(const ClassDef& class_def) const {
404 return dexStringByTypeIdx(class_def.class_idx_);
405 }
406
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700407 // Returns the type descriptor string of a type id.
408 const char* GetTypeDescriptor(const TypeId& type_id) const {
409 return dexStringById(type_id.descriptor_idx_);
410 }
411
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700412 // Returns the StringId at the specified index.
413 const StringId& GetStringId(uint32_t idx) const {
414 CHECK_LT(idx, NumStringIds());
415 return string_ids_[idx];
416 }
417
418 // Returns the TypeId at the specified index.
419 const TypeId& GetTypeId(uint32_t idx) const {
420 CHECK_LT(idx, NumTypeIds());
421 return type_ids_[idx];
422 }
423
424 // Returns the FieldId at the specified index.
425 const FieldId& GetFieldId(uint32_t idx) const {
426 CHECK_LT(idx, NumFieldIds());
427 return field_ids_[idx];
428 }
429
430 // Returns the MethodId at the specified index.
431 const MethodId& GetMethodId(uint32_t idx) const {
432 CHECK_LT(idx, NumMethodIds());
433 return method_ids_[idx];
434 }
435
436 // Returns the ProtoId at the specified index.
437 const ProtoId& GetProtoId(uint32_t idx) const {
438 CHECK_LT(idx, NumProtoIds());
439 return proto_ids_[idx];
440 }
441
442 // Returns the ClassDef at the specified index.
443 const ClassDef& GetClassDef(uint32_t idx) const {
444 CHECK_LT(idx, NumClassDefs());
445 return class_defs_[idx];
446 }
447
448 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
449 if (class_def.interfaces_off_ == 0) {
450 return NULL;
451 } else {
452 const byte* addr = base_ + class_def.interfaces_off_;
453 return reinterpret_cast<const TypeList*>(addr);
454 }
455 }
456
457 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700458 return GetCodeItem(method.code_off_);
459 }
460
461 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
462 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700463 return NULL; // native or abstract method
464 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700465 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700466 return reinterpret_cast<const CodeItem*>(addr);
467 }
468 }
469
470 // Returns the short form method descriptor for the given prototype.
471 const char* GetShorty(uint32_t proto_idx) const {
472 const ProtoId& proto_id = GetProtoId(proto_idx);
473 return dexStringById(proto_id.shorty_idx_);
474 }
475
476 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
477 if (proto_id.parameters_off_ == 0) {
478 return NULL;
479 } else {
480 const byte* addr = base_ + proto_id.parameters_off_;
481 return reinterpret_cast<const TypeList*>(addr);
482 }
483 }
484
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700485 char* CreateMethodDescriptor(uint32_t proto_idx,
486 int32_t* unicode_length) const;
487
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700488 const byte* GetEncodedArray(const ClassDef& class_def) const {
489 if (class_def.static_values_off_ == 0) {
490 return 0;
491 } else {
492 return base_ + class_def.static_values_off_;
493 }
494 }
495
496 int32_t GetStringLength(const StringId& string_id) const {
497 const byte* ptr = base_ + string_id.string_data_off_;
498 return DecodeUnsignedLeb128(&ptr);
499 }
500
501 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
502
503 // From libdex...
504
505 // Returns a pointer to the UTF-8 string data referred to by the
506 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700507 const char* GetStringData(const StringId& string_id, int32_t* length) const {
508 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700509 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700510 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700511 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700512 }
513
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700514 const char* GetStringData(const StringId& string_id) const {
515 int32_t length;
516 return GetStringData(string_id, &length);
517 }
518
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700519 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700520 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700521 if (idx == kDexNoIndex) {
522 *unicode_length = 0;
523 return NULL;
524 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700525 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700526 return GetStringData(string_id, unicode_length);
527 }
528
529 const char* dexStringById(uint32_t idx) const {
530 int32_t unicode_length;
531 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700532 }
533
Shih-wei Liao195487c2011-08-20 13:29:04 -0700534 String* dexArtStringById(uint32_t idx) const;
535
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700536 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700537 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
538 const TypeId& type_id = GetTypeId(idx);
539 return dexStringById(type_id.descriptor_idx_, unicode_length);
540 }
541
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700542 const char* dexStringByTypeIdx(uint32_t idx) const {
543 const TypeId& type_id = GetTypeId(idx);
544 return dexStringById(type_id.descriptor_idx_);
545 }
546
Shih-wei Liao195487c2011-08-20 13:29:04 -0700547 String* dexArtStringByTypeIdx(uint32_t idx) const {
548 const TypeId& type_id = GetTypeId(idx);
549 return dexArtStringById(type_id.descriptor_idx_);
550 }
551
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700552 // TODO: encoded_field is actually a stream of bytes
553 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700554 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700555 uint32_t* last_idx) const {
556 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
557 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
558 field->field_idx_ = idx;
559 *last_idx = idx;
560 }
561
562 // TODO: encoded_method is actually a stream of bytes
563 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700564 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700565 uint32_t* last_idx) const {
566 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
567 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
568 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
569 method->method_idx_ = idx;
570 *last_idx = idx;
571 }
572
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700573 const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) const {
574 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
575 return reinterpret_cast<const TryItem*>
576 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
577 }
578
579 // Get the base of the encoded data for the given DexCode.
580 const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) const {
581 const byte* handler_data = reinterpret_cast<const byte*>
582 (dexGetTryItems(code_item, code_item.tries_size_));
583 return handler_data + offset;
584 }
585
586 // Find the handler associated with a given address, if any.
587 // Initializes the given iterator and returns true if a match is
588 // found. Returns end if there is no applicable handler.
589 CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) const {
590 CatchHandlerItem handler;
591 handler.address_ = -1;
592 int32_t offset = -1;
593
594 // Short-circuit the overwhelmingly common cases.
595 switch (code_item.tries_size_) {
596 case 0:
597 break;
598 case 1: {
599 const TryItem* tries = dexGetTryItems(code_item, 0);
600 uint32_t start = tries->start_addr_;
601 if (address < start)
602 break;
603
604 uint32_t end = start + tries->insn_count_;
605 if (address >= end)
606 break;
607
608 offset = tries->handler_off_;
609 break;
610 }
611 default:
612 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
613 }
614
615 if (offset >= 0) {
616 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
617 return CatchHandlerIterator(handler_data);
618 }
619 return CatchHandlerIterator();
620 }
621
622 int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
623 int32_t tries_size,
624 uint32_t address) const {
625 // Note: Signed type is important for max and min.
626 int32_t min = 0;
627 int32_t max = tries_size - 1;
628
629 while (max >= min) {
630 int32_t guess = (min + max) >> 1;
631 const TryItem* pTry = dexGetTryItems(code_item, guess);
632 uint32_t start = pTry->start_addr_;
633
634 if (address < start) {
635 max = guess - 1;
636 continue;
637 }
638
639 uint32_t end = start + pTry->insn_count_;
640 if (address >= end) {
641 min = guess + 1;
642 continue;
643 }
644
645 // We have a winner!
646 return (int32_t) pTry->handler_off_;
647 }
648
649 // No match.
650 return -1;
651 }
652
Shih-wei Liao195487c2011-08-20 13:29:04 -0700653 // Get the pointer to the start of the debugging data
654 const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
655 if (code_item->debug_info_off_ == 0) {
656 return NULL;
657 } else {
658 return base_ + code_item->debug_info_off_;
659 }
660 }
661
662 // Callback for "new position table entry".
663 // Returning true causes the decoder to stop early.
664 typedef bool (*DexDebugNewPositionCb)(void *cnxt, uint32_t address, uint32_t line_num);
665
666 // Callback for "new locals table entry". "signature" is an empty string
667 // if no signature is available for an entry.
668 typedef void (*DexDebugNewLocalCb)(void *cnxt, uint16_t reg,
669 uint32_t startAddress,
670 uint32_t endAddress,
671 const String* name,
672 const String* descriptor,
673 const String* signature);
674
675 static bool LineNumForPcCb(void *cnxt, uint32_t address, uint32_t line_num) {
676 LineNumFromPcContext *context = (LineNumFromPcContext *)cnxt;
677
678 // We know that this callback will be called in
679 // ascending address order, so keep going until we find
680 // a match or we've just gone past it.
681 if (address > context->address_) {
682 // The line number from the previous positions callback
683 // wil be the final result.
684 return true;
685 } else {
686 context->line_num_ = line_num;
687 return address == context->address_;
688 }
689 }
690
691
692 // Debug info opcodes and constants
693 enum {
694 DBG_END_SEQUENCE = 0x00,
695 DBG_ADVANCE_PC = 0x01,
696 DBG_ADVANCE_LINE = 0x02,
697 DBG_START_LOCAL = 0x03,
698 DBG_START_LOCAL_EXTENDED = 0x04,
699 DBG_END_LOCAL = 0x05,
700 DBG_RESTART_LOCAL = 0x06,
701 DBG_SET_PROLOGUE_END = 0x07,
702 DBG_SET_EPILOGUE_BEGIN = 0x08,
703 DBG_SET_FILE = 0x09,
704 DBG_FIRST_SPECIAL = 0x0a,
705 DBG_LINE_BASE = -4,
706 DBG_LINE_RANGE = 15,
707 };
708
709 struct LocalInfo {
710 LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0), is_live_(false) {}
711
712 // E.g., list
713 const String* name_;
714
715 // E.g., Ljava/util/LinkedList;
716 const String* descriptor_;
717
718 // E.g., java.util.LinkedList<java.lang.Integer>
719 const String* signature_;
720
721 // PC location where the local is first defined.
722 uint16_t start_address_;
723
724 // Is the local defined and live.
725 bool is_live_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700726
727 private:
728 DISALLOW_COPY_AND_ASSIGN(LocalInfo);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700729 };
730
731 struct LineNumFromPcContext {
732 LineNumFromPcContext(uint32_t address, uint32_t line_num) :
733 address_(address), line_num_(line_num) {}
734 uint32_t address_;
735 uint32_t line_num_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700736 private:
737 DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700738 };
739
740 void InvokeLocalCbIfLive(void *cnxt, int reg, uint32_t end_address,
741 LocalInfo *local_in_reg, DexDebugNewLocalCb local_cb) const {
742 if (local_cb != NULL && local_in_reg[reg].is_live_) {
743 local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
744 local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
745 local_in_reg[reg].signature_);
746 }
747 }
748
749 // Determine the source file line number based on the program counter.
750 // "pc" is an offset, in 16-bit units, from the start of the method's code.
751 //
752 // Returns -1 if no match was found (possibly because the source files were
753 // compiled without "-g", so no line number information is present).
754 // Returns -2 for native methods (as expected in exception traces).
755 //
756 // This is used by runtime; therefore use art::Method not art::DexFile::Method.
757 int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
758
759 void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
760 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
761 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
762
763 void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method *method,
764 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
765 void* cnxt) const {
766 const byte* stream = dexGetDebugInfoStream(code_item);
767 LocalInfo local_in_reg[code_item->registers_size_];
768
769 if (stream != NULL) {
770 dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
771 }
772 for (int reg = 0; reg < code_item->registers_size_; reg++) {
773 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_, local_in_reg, local_cb);
774 }
775 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700776
777 // TODO: const reference
778 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
779 CHECK_GE(class_def, class_defs_);
780 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
781 return class_def - class_defs_;
782 }
783
784 const char* dexGetSourceFile(const ClassDef& class_def) const {
785 if (class_def.source_file_idx_ == 0xffffffff) {
786 return NULL;
787 } else {
788 return dexStringById(class_def.source_file_idx_);
789 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700790 }
791
Carl Shapiro1fb86202011-06-27 17:43:13 -0700792 private:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700793 // Helper class to deallocate underlying storage.
794 class Closer {
795 public:
796 virtual ~Closer();
797 };
798
799 // Helper class to deallocate mmap-backed .dex files.
800 class MmapCloser : public Closer {
801 public:
802 MmapCloser(void* addr, size_t length);
803 virtual ~MmapCloser();
804 private:
805 void* addr_;
806 size_t length_;
807 };
808
809 // Helper class for deallocating new/delete-backed .dex files.
810 class PtrCloser : public Closer {
811 public:
812 PtrCloser(byte* addr);
813 virtual ~PtrCloser();
814 private:
815 byte* addr_;
816 };
817
818 // Opens a .dex file at a the given address.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700819 static DexFile* Open(const byte* dex_file, size_t length, const std::string& location, Closer* closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700820
Brian Carlstroma663ea52011-08-19 23:33:41 -0700821 DexFile(const byte* addr, size_t length, const std::string& location, Closer* closer)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700822 : base_(addr),
823 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700824 location_(location),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700825 closer_(closer),
826 header_(0),
827 string_ids_(0),
828 type_ids_(0),
829 field_ids_(0),
830 method_ids_(0),
831 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700832 class_defs_(0) {
833 CHECK(addr != NULL);
834 CHECK_GT(length, 0U);
835 CHECK(closer != NULL);
836 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700837
838 // Top-level initializer that calls other Init methods.
839 bool Init();
840
841 // Caches pointers into to the various file sections.
842 void InitMembers();
843
844 // Builds the index of descriptors to class definitions.
845 void InitIndex();
846
847 // Returns true if the byte string equals the magic value.
848 bool CheckMagic(const byte* magic);
849
850 // Returns true if the header magic is of the expected value.
851 bool IsMagicValid();
852
853 // The index of descriptors to class definitions.
Brian Carlstromf615a612011-07-23 12:50:34 -0700854 typedef std::map<const StringPiece, const DexFile::ClassDef*> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700855 Index index_;
856
857 // The base address of the memory mapping.
858 const byte* base_;
859
860 // The size of the underlying memory allocation in bytes.
861 size_t length_;
862
Brian Carlstroma663ea52011-08-19 23:33:41 -0700863 // Typically the dex file name when availble, alternatively some identifying string.
864 //
865 // The ClassLinker will use this to match DexFiles the boot class
866 // path to DexCache::GetLocation when loading from an image.
867 const std::string location_;
868
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700869 // Helper object to free the underlying allocation.
870 scoped_ptr<Closer> closer_;
871
872 // Points to the header section.
873 const Header* header_;
874
875 // Points to the base of the string identifier list.
876 const StringId* string_ids_;
877
878 // Points to the base of the type identifier list.
879 const TypeId* type_ids_;
880
881 // Points to the base of the field identifier list.
882 const FieldId* field_ids_;
883
884 // Points to the base of the method identifier list.
885 const MethodId* method_ids_;
886
887 // Points to the base of the prototype identifier list.
888 const ProtoId* proto_ids_;
889
890 // Points to the base of the class definition list.
891 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700892};
893
894} // namespace art
895
896#endif // ART_SRC_DEX_FILE_H_