blob: 070901be79c60ec9710e40037e82f31a9410df76 [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>
Elliott Hughes0c424cb2011-08-26 10:16:25 -07007#include <string>
Brian Carlstrom74eb46a2011-08-02 20:10:14 -07008#include <vector>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07009
Elliott Hughes90a33692011-08-30 13:27:07 -070010#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070011#include "globals.h"
Jesse Wilson6bf19152011-09-29 13:12:33 -040012#include "jni.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070013#include "leb128.h"
14#include "logging.h"
Brian Carlstrom33f741e2011-10-03 11:24:05 -070015#include "mem_map.h"
Jesse Wilson6bf19152011-09-29 13:12:33 -040016#include "mutex.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070017#include "stringpiece.h"
18#include "strutil.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -070019#include "utils.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070020
21namespace art {
22
Carl Shapiro5fafe2b2011-07-09 15:34:41 -070023union JValue;
Shih-wei Liao195487c2011-08-20 13:29:04 -070024class String;
25class Method;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070026
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070027// TODO: move all of the macro functionality into the DexCache class.
Brian Carlstromf615a612011-07-23 12:50:34 -070028class DexFile {
Carl Shapiro1fb86202011-06-27 17:43:13 -070029 public:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070030 static const byte kDexMagic[];
31 static const byte kDexMagicVersion[];
32 static const size_t kSha1DigestSize = 20;
Carl Shapiro80d4dde2011-06-28 16:24:07 -070033
Brian Carlstromb7bbba42011-10-13 14:58:47 -070034 // name of the DexFile entry within a zip archive
35 static const char* kClassesDex;
36
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070037 static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
38 static const byte kEncodedValueArgShift = 5;
39
40 // The value of an invalid index.
41 static const uint32_t kDexNoIndex = 0xFFFFFFFF;
42
43 enum ValueType {
44 kByte = 0x00,
45 kShort = 0x02,
46 kChar = 0x03,
47 kInt = 0x04,
48 kLong = 0x06,
49 kFloat = 0x10,
50 kDouble = 0x11,
51 kString = 0x17,
52 kType = 0x18,
53 kField = 0x19,
54 kMethod = 0x1a,
55 kEnum = 0x1b,
56 kArray = 0x1c,
57 kAnnotation = 0x1d,
58 kNull = 0x1e,
59 kBoolean = 0x1f
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070060 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070061
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070062 // Raw header_item.
63 struct Header {
64 uint8_t magic_[8];
65 uint32_t checksum_;
66 uint8_t signature_[kSha1DigestSize];
67 uint32_t file_size_; // length of entire file
68 uint32_t header_size_; // offset to start of next section
69 uint32_t endian_tag_;
70 uint32_t link_size_;
71 uint32_t link_off_;
72 uint32_t map_off_;
73 uint32_t string_ids_size_;
74 uint32_t string_ids_off_;
75 uint32_t type_ids_size_;
76 uint32_t type_ids_off_;
77 uint32_t proto_ids_size_;
78 uint32_t proto_ids_off_;
79 uint32_t field_ids_size_;
80 uint32_t field_ids_off_;
81 uint32_t method_ids_size_;
82 uint32_t method_ids_off_;
83 uint32_t class_defs_size_;
84 uint32_t class_defs_off_;
85 uint32_t data_size_;
86 uint32_t data_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070087 private:
88 DISALLOW_COPY_AND_ASSIGN(Header);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070089 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070090
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070091 // Raw string_id_item.
92 struct StringId {
93 uint32_t string_data_off_; // offset in bytes from the base address
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070094 private:
95 DISALLOW_COPY_AND_ASSIGN(StringId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070096 };
97
98 // Raw type_id_item.
99 struct TypeId {
100 uint32_t descriptor_idx_; // index into string_ids
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700101 private:
102 DISALLOW_COPY_AND_ASSIGN(TypeId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700103 };
104
105 // Raw field_id_item.
106 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700107 uint16_t class_idx_; // index into type_ids_ list for defining class
108 uint16_t type_idx_; // index into type_ids_ for field type
109 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700110 private:
111 DISALLOW_COPY_AND_ASSIGN(FieldId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700112 };
113
114 // Raw method_id_item.
115 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700116 uint16_t class_idx_; // index into type_ids_ list for defining class
117 uint16_t proto_idx_; // index into proto_ids_ for method prototype
118 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700119 private:
120 DISALLOW_COPY_AND_ASSIGN(MethodId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700121 };
122
123 // Raw proto_id_item.
124 struct ProtoId {
125 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
126 uint32_t return_type_idx_; // index into type_ids list for return type
127 uint32_t parameters_off_; // file offset to type_list for parameter types
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700128 private:
129 DISALLOW_COPY_AND_ASSIGN(ProtoId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700130 };
131
132 // Raw class_def_item.
133 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700134 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700135 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700136 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700137 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700138 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700139 uint32_t annotations_off_; // file offset to annotations_directory_item
140 uint32_t class_data_off_; // file offset to class_data_item
141 uint32_t static_values_off_; // file offset to EncodedArray
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700142 private:
143 DISALLOW_COPY_AND_ASSIGN(ClassDef);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700144 };
145
146 // Raw type_item.
147 struct TypeItem {
148 uint16_t type_idx_; // index into type_ids section
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700149 private:
150 DISALLOW_COPY_AND_ASSIGN(TypeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700151 };
152
153 // Raw type_list.
154 class TypeList {
155 public:
156 uint32_t Size() const {
157 return size_;
158 }
159
160 const TypeItem& GetTypeItem(uint32_t idx) const {
161 CHECK_LT(idx, this->size_);
162 return this->list_[idx];
163 }
164
165 private:
166 uint32_t size_; // size of the list, in entries
167 TypeItem list_[1]; // elements of the list
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700168 DISALLOW_COPY_AND_ASSIGN(TypeList);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700169 };
170
171 class ParameterIterator { // TODO: stream
172 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700173 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
174 : dex_file_(dex_file), size_(0), pos_(0) {
175 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700176 if (type_list_ != NULL) {
177 size_ = type_list_->Size();
178 }
179 }
180 bool HasNext() const { return pos_ != size_; }
181 void Next() { ++pos_; }
182 const char* GetDescriptor() {
183 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700184 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700185 }
186 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700187 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700188 const TypeList* type_list_;
189 uint32_t size_;
190 uint32_t pos_;
191 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
192 };
193
194 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
195 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700196 }
197
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700198 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
199 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700200 }
201
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700202 // Raw code_item.
203 struct CodeItem {
204 uint16_t registers_size_;
205 uint16_t ins_size_;
206 uint16_t outs_size_;
207 uint16_t tries_size_;
208 uint32_t debug_info_off_; // file offset to debug info stream
209 uint32_t insns_size_; // size of the insns array, in 2 byte code units
210 uint16_t insns_[1];
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700211 private:
212 DISALLOW_COPY_AND_ASSIGN(CodeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700213 };
214
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700215 struct CatchHandlerItem {
216 uint32_t type_idx_; // type index of the caught exception type
217 uint32_t address_; // handler address
218 };
219
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700220 // Raw try_item.
221 struct TryItem {
222 uint32_t start_addr_;
223 uint16_t insn_count_;
224 uint16_t handler_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700225 private:
226 DISALLOW_COPY_AND_ASSIGN(TryItem);
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700227 };
228
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700229 class CatchHandlerIterator {
230 public:
231 CatchHandlerIterator() {
232 remaining_count_ = -1;
233 catch_all_ = false;
234 }
235
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700236 explicit CatchHandlerIterator(const byte* handler_data) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700237 current_data_ = handler_data;
jeffhaoba5ebb92011-08-25 17:24:37 -0700238 remaining_count_ = DecodeSignedLeb128(&current_data_);
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700239
240 // If remaining_count_ is non-positive, then it is the negative of
241 // the number of catch types, and the catches are followed by a
242 // catch-all handler.
243 if (remaining_count_ <= 0) {
244 catch_all_ = true;
245 remaining_count_ = -remaining_count_;
246 } else {
247 catch_all_ = false;
248 }
249 Next();
250 }
251
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700252 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700253 return handler_;
254 }
255
jeffhaoba5ebb92011-08-25 17:24:37 -0700256 const byte* GetData() const {
257 return current_data_;
258 }
259
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700260 void Next() {
261 if (remaining_count_ > 0) {
262 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
263 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
264 remaining_count_--;
265 return;
266 }
267
268 if (catch_all_) {
269 handler_.type_idx_ = kDexNoIndex;
270 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
271 catch_all_ = false;
272 return;
273 }
274
275 // no more handler
276 remaining_count_ = -1;
277 }
278
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700279 bool HasNext() const {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700280 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700281 }
282
283 private:
284 CatchHandlerItem handler_;
Ian Rogersbdb03912011-09-14 00:55:44 -0700285 const byte *current_data_; // the current handler in dex file.
286 int32_t remaining_count_; // number of handlers not read.
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700287 bool catch_all_; // is there a handler that will catch all exceptions in case
288 // that all typed handler does not match.
289 };
290
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700291 // Partially decoded form of class_data_item.
292 struct ClassDataHeader {
293 uint32_t static_fields_size_; // the number of static fields
294 uint32_t instance_fields_size_; // the number of instance fields
295 uint32_t direct_methods_size_; // the number of direct methods
296 uint32_t virtual_methods_size_; // the number of virtual methods
297 };
298
299 // Decoded form of encoded_field.
300 struct Field {
301 uint32_t field_idx_; // index into the field_ids list for the identity of this field
302 uint32_t access_flags_; // access flags for the field
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700303 Field() {}
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700304 private:
305 DISALLOW_COPY_AND_ASSIGN(Field);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700306 };
307
308 // Decoded form of encoded_method.
309 struct Method {
310 uint32_t method_idx_;
311 uint32_t access_flags_;
312 uint32_t code_off_;
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700313 Method() {}
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700314 private:
315 DISALLOW_COPY_AND_ASSIGN(Method);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700316 };
317
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700318 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
319 typedef std::vector<const DexFile*> ClassPath;
320
321 // Search a collection of DexFiles for a descriptor
322 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700323 const ClassPath& class_path);
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700324
Brian Carlstrom78128a62011-09-15 17:21:19 -0700325 // Opens a collection of .dex files
326 static void OpenDexFiles(std::vector<const char*>& dex_filenames,
327 std::vector<const DexFile*>& dex_files,
328 const std::string& strip_location_prefix);
329
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700330 // Opens .dex file, guessing the container format based on file extension
Brian Carlstrom16192862011-09-12 17:50:06 -0700331 static const DexFile* Open(const std::string& filename,
332 const std::string& strip_location_prefix);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700333 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700334 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700335
Brian Carlstroma663ea52011-08-19 23:33:41 -0700336 const std::string& GetLocation() const {
337 return location_;
338 }
339
Jesse Wilson6bf19152011-09-29 13:12:33 -0400340 // Returns a com.android.dex.Dex object corresponding to the mapped-in dex file.
341 // Used by managed code to implement annotations.
342 jobject GetDexObject(JNIEnv* env) const;
343
Brian Carlstroma663ea52011-08-19 23:33:41 -0700344 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700345 CHECK(header_ != NULL);
346 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700347 }
348
Brian Carlstrome24fa612011-09-29 00:53:55 -0700349 // Looks up a class definition index by its class descriptor.
350 bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
351
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700352 // Looks up a class definition by its class descriptor.
353 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
354
355 // Returns the number of string identifiers in the .dex file.
356 size_t NumStringIds() const {
357 CHECK(header_ != NULL);
358 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700359 }
360
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700361 // Returns the number of type identifiers in the .dex file.
362 size_t NumTypeIds() const {
363 CHECK(header_ != NULL);
364 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700365 }
366
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700367 // Returns the number of prototype identifiers in the .dex file.
368 size_t NumProtoIds() const {
369 CHECK(header_ != NULL);
370 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700371 }
372
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700373 // Returns the number of field identifiers in the .dex file.
374 size_t NumFieldIds() const {
375 CHECK(header_ != NULL);
376 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700377 }
378
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700379 // Returns the number of method identifiers in the .dex file.
380 size_t NumMethodIds() const {
381 CHECK(header_ != NULL);
382 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700383 }
384
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700385 // Returns the number of class definitions in the .dex file.
386 size_t NumClassDefs() const {
387 CHECK(header_ != NULL);
388 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700389 }
390
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700391 // Returns a pointer to the memory mapped class data.
392 // TODO: return a stream
393 const byte* GetClassData(const ClassDef& class_def) const {
394 if (class_def.class_data_off_ == 0) {
395 return NULL;
396 } else {
397 return base_ + class_def.class_data_off_;
398 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700399 }
400
Brian Carlstromf615a612011-07-23 12:50:34 -0700401 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700402 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
403 CHECK(class_data != NULL);
404 ClassDataHeader header;
405 memset(&header, 0, sizeof(ClassDataHeader));
406 if (*class_data != NULL) {
407 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
408 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
409 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
410 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
411 }
412 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700413 }
414
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700415 // Returns the class descriptor string of a class definition.
416 const char* GetClassDescriptor(const ClassDef& class_def) const {
417 return dexStringByTypeIdx(class_def.class_idx_);
418 }
419
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700420 // Returns the type descriptor string of a type id.
421 const char* GetTypeDescriptor(const TypeId& type_id) const {
422 return dexStringById(type_id.descriptor_idx_);
423 }
424
Brian Carlstromb9edb842011-08-28 16:31:06 -0700425 // Returns the class descriptor string of a field id.
426 const char* GetFieldClassDescriptor(const FieldId& field_id) const {
427 const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
428 return GetTypeDescriptor(type_id);
429 }
430
431 // Returns the name of a field id.
432 const char* GetFieldName(const FieldId& field_id) const {
433 return dexStringById(field_id.name_idx_);
434 }
435
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700436 // Returns the class descriptor string of a method id.
437 const char* GetMethodClassDescriptor(const MethodId& method_id) const {
438 const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
439 return GetTypeDescriptor(type_id);
440 }
441
jeffhao98eacac2011-09-14 16:11:53 -0700442 // Returns the prototype of a method id.
Brian Carlstromaded5f72011-10-07 17:15:04 -0700443 const ProtoId& GetMethodPrototype(const MethodId& method_id) const {
444 return GetProtoId(method_id.proto_idx_);
445 }
446
447 // Returns the signature of a method id.
448 const std::string GetMethodSignature(const MethodId& method_id) const {
449 return CreateMethodDescriptor(method_id.proto_idx_, NULL);
jeffhao98eacac2011-09-14 16:11:53 -0700450 }
451
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700452 // Returns the name of a method id.
453 const char* GetMethodName(const MethodId& method_id) const {
454 return dexStringById(method_id.name_idx_);
455 }
456
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700457 // Returns the StringId at the specified index.
458 const StringId& GetStringId(uint32_t idx) const {
459 CHECK_LT(idx, NumStringIds());
460 return string_ids_[idx];
461 }
462
463 // Returns the TypeId at the specified index.
464 const TypeId& GetTypeId(uint32_t idx) const {
465 CHECK_LT(idx, NumTypeIds());
466 return type_ids_[idx];
467 }
468
469 // Returns the FieldId at the specified index.
470 const FieldId& GetFieldId(uint32_t idx) const {
471 CHECK_LT(idx, NumFieldIds());
472 return field_ids_[idx];
473 }
474
475 // Returns the MethodId at the specified index.
476 const MethodId& GetMethodId(uint32_t idx) const {
477 CHECK_LT(idx, NumMethodIds());
478 return method_ids_[idx];
479 }
480
481 // Returns the ProtoId at the specified index.
482 const ProtoId& GetProtoId(uint32_t idx) const {
483 CHECK_LT(idx, NumProtoIds());
484 return proto_ids_[idx];
485 }
486
487 // Returns the ClassDef at the specified index.
488 const ClassDef& GetClassDef(uint32_t idx) const {
489 CHECK_LT(idx, NumClassDefs());
490 return class_defs_[idx];
491 }
492
493 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
494 if (class_def.interfaces_off_ == 0) {
495 return NULL;
496 } else {
497 const byte* addr = base_ + class_def.interfaces_off_;
498 return reinterpret_cast<const TypeList*>(addr);
499 }
500 }
501
502 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700503 return GetCodeItem(method.code_off_);
504 }
505
506 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
507 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700508 return NULL; // native or abstract method
509 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700510 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700511 return reinterpret_cast<const CodeItem*>(addr);
512 }
513 }
514
515 // Returns the short form method descriptor for the given prototype.
516 const char* GetShorty(uint32_t proto_idx) const {
517 const ProtoId& proto_id = GetProtoId(proto_idx);
518 return dexStringById(proto_id.shorty_idx_);
519 }
520
521 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
522 if (proto_id.parameters_off_ == 0) {
523 return NULL;
524 } else {
525 const byte* addr = base_ + proto_id.parameters_off_;
526 return reinterpret_cast<const TypeList*>(addr);
527 }
528 }
529
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700530 std::string CreateMethodDescriptor(uint32_t proto_idx, int32_t* unicode_length) const;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700531
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700532 const byte* GetEncodedArray(const ClassDef& class_def) const {
533 if (class_def.static_values_off_ == 0) {
534 return 0;
535 } else {
536 return base_ + class_def.static_values_off_;
537 }
538 }
539
540 int32_t GetStringLength(const StringId& string_id) const {
541 const byte* ptr = base_ + string_id.string_data_off_;
542 return DecodeUnsignedLeb128(&ptr);
543 }
544
545 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
546
547 // From libdex...
548
549 // Returns a pointer to the UTF-8 string data referred to by the
550 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700551 const char* GetStringData(const StringId& string_id, int32_t* length) const {
552 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700553 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700554 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700555 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700556 }
557
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700558 const char* GetStringData(const StringId& string_id) const {
559 int32_t length;
560 return GetStringData(string_id, &length);
561 }
562
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700563 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700564 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700565 if (idx == kDexNoIndex) {
566 *unicode_length = 0;
567 return NULL;
568 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700569 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700570 return GetStringData(string_id, unicode_length);
571 }
572
573 const char* dexStringById(uint32_t idx) const {
574 int32_t unicode_length;
575 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700576 }
577
578 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700579 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
580 const TypeId& type_id = GetTypeId(idx);
581 return dexStringById(type_id.descriptor_idx_, unicode_length);
582 }
583
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700584 const char* dexStringByTypeIdx(uint32_t idx) const {
585 const TypeId& type_id = GetTypeId(idx);
586 return dexStringById(type_id.descriptor_idx_);
587 }
588
589 // TODO: encoded_field is actually a stream of bytes
590 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700591 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700592 uint32_t* last_idx) const {
593 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
594 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
595 field->field_idx_ = idx;
596 *last_idx = idx;
597 }
598
599 // TODO: encoded_method is actually a stream of bytes
600 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700601 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700602 uint32_t* last_idx) const {
603 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
604 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
605 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
606 method->method_idx_ = idx;
607 *last_idx = idx;
608 }
609
jeffhaoba5ebb92011-08-25 17:24:37 -0700610 static const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700611 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
612 return reinterpret_cast<const TryItem*>
613 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
614 }
615
616 // Get the base of the encoded data for the given DexCode.
jeffhaoba5ebb92011-08-25 17:24:37 -0700617 static const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700618 const byte* handler_data = reinterpret_cast<const byte*>
619 (dexGetTryItems(code_item, code_item.tries_size_));
620 return handler_data + offset;
621 }
622
623 // Find the handler associated with a given address, if any.
624 // Initializes the given iterator and returns true if a match is
625 // found. Returns end if there is no applicable handler.
jeffhaoba5ebb92011-08-25 17:24:37 -0700626 static CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700627 CatchHandlerItem handler;
628 handler.address_ = -1;
629 int32_t offset = -1;
630
631 // Short-circuit the overwhelmingly common cases.
632 switch (code_item.tries_size_) {
633 case 0:
634 break;
635 case 1: {
636 const TryItem* tries = dexGetTryItems(code_item, 0);
637 uint32_t start = tries->start_addr_;
638 if (address < start)
639 break;
640
641 uint32_t end = start + tries->insn_count_;
642 if (address >= end)
643 break;
644
645 offset = tries->handler_off_;
646 break;
647 }
648 default:
649 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
650 }
651
652 if (offset >= 0) {
653 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
654 return CatchHandlerIterator(handler_data);
655 }
656 return CatchHandlerIterator();
657 }
658
jeffhaoba5ebb92011-08-25 17:24:37 -0700659 static int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
660 int32_t tries_size,
661 uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700662 // Note: Signed type is important for max and min.
663 int32_t min = 0;
664 int32_t max = tries_size - 1;
665
666 while (max >= min) {
667 int32_t guess = (min + max) >> 1;
668 const TryItem* pTry = dexGetTryItems(code_item, guess);
669 uint32_t start = pTry->start_addr_;
670
671 if (address < start) {
672 max = guess - 1;
673 continue;
674 }
675
676 uint32_t end = start + pTry->insn_count_;
677 if (address >= end) {
678 min = guess + 1;
679 continue;
680 }
681
682 // We have a winner!
683 return (int32_t) pTry->handler_off_;
684 }
685
686 // No match.
687 return -1;
688 }
689
Shih-wei Liao195487c2011-08-20 13:29:04 -0700690 // Get the pointer to the start of the debugging data
691 const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
692 if (code_item->debug_info_off_ == 0) {
693 return NULL;
694 } else {
695 return base_ + code_item->debug_info_off_;
696 }
697 }
698
699 // Callback for "new position table entry".
700 // Returning true causes the decoder to stop early.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700701 typedef bool (*DexDebugNewPositionCb)(void* cnxt, uint32_t address, uint32_t line_num);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700702
703 // Callback for "new locals table entry". "signature" is an empty string
704 // if no signature is available for an entry.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700705 typedef void (*DexDebugNewLocalCb)(void* cnxt, uint16_t reg,
Shih-wei Liao195487c2011-08-20 13:29:04 -0700706 uint32_t startAddress,
707 uint32_t endAddress,
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700708 const char* name,
709 const char* descriptor,
710 const char* signature);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700711
Brian Carlstrom78128a62011-09-15 17:21:19 -0700712 static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700713 LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700714
715 // We know that this callback will be called in
716 // ascending address order, so keep going until we find
717 // a match or we've just gone past it.
718 if (address > context->address_) {
719 // The line number from the previous positions callback
720 // wil be the final result.
721 return true;
722 } else {
723 context->line_num_ = line_num;
724 return address == context->address_;
725 }
726 }
727
728
729 // Debug info opcodes and constants
730 enum {
731 DBG_END_SEQUENCE = 0x00,
732 DBG_ADVANCE_PC = 0x01,
733 DBG_ADVANCE_LINE = 0x02,
734 DBG_START_LOCAL = 0x03,
735 DBG_START_LOCAL_EXTENDED = 0x04,
736 DBG_END_LOCAL = 0x05,
737 DBG_RESTART_LOCAL = 0x06,
738 DBG_SET_PROLOGUE_END = 0x07,
739 DBG_SET_EPILOGUE_BEGIN = 0x08,
740 DBG_SET_FILE = 0x09,
741 DBG_FIRST_SPECIAL = 0x0a,
742 DBG_LINE_BASE = -4,
743 DBG_LINE_RANGE = 15,
744 };
745
746 struct LocalInfo {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700747 LocalInfo() : name_(NULL), start_address_(0), is_live_(false) {}
Shih-wei Liao195487c2011-08-20 13:29:04 -0700748
749 // E.g., list
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700750 const char* name_;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700751
752 // E.g., Ljava/util/LinkedList;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700753 const char* descriptor_;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700754
755 // E.g., java.util.LinkedList<java.lang.Integer>
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700756 const char* signature_;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700757
758 // PC location where the local is first defined.
759 uint16_t start_address_;
760
761 // Is the local defined and live.
762 bool is_live_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700763
764 private:
765 DISALLOW_COPY_AND_ASSIGN(LocalInfo);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700766 };
767
768 struct LineNumFromPcContext {
769 LineNumFromPcContext(uint32_t address, uint32_t line_num) :
770 address_(address), line_num_(line_num) {}
771 uint32_t address_;
772 uint32_t line_num_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700773 private:
774 DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700775 };
776
Brian Carlstrom78128a62011-09-15 17:21:19 -0700777 void InvokeLocalCbIfLive(void* cnxt, int reg, uint32_t end_address,
778 LocalInfo* local_in_reg, DexDebugNewLocalCb local_cb) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700779 if (local_cb != NULL && local_in_reg[reg].is_live_) {
780 local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
781 local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
782 local_in_reg[reg].signature_);
783 }
784 }
785
786 // Determine the source file line number based on the program counter.
787 // "pc" is an offset, in 16-bit units, from the start of the method's code.
788 //
789 // Returns -1 if no match was found (possibly because the source files were
790 // compiled without "-g", so no line number information is present).
791 // Returns -2 for native methods (as expected in exception traces).
792 //
793 // This is used by runtime; therefore use art::Method not art::DexFile::Method.
794 int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
795
796 void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
797 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
798 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
799
Elliott Hughes30646832011-10-13 16:59:46 -0700800 void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
Shih-wei Liao195487c2011-08-20 13:29:04 -0700801 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
802 void* cnxt) const {
803 const byte* stream = dexGetDebugInfoStream(code_item);
804 LocalInfo local_in_reg[code_item->registers_size_];
805
806 if (stream != NULL) {
807 dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
808 }
809 for (int reg = 0; reg < code_item->registers_size_; reg++) {
810 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_, local_in_reg, local_cb);
811 }
812 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700813
814 // TODO: const reference
815 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
816 CHECK_GE(class_def, class_defs_);
817 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
818 return class_def - class_defs_;
819 }
820
821 const char* dexGetSourceFile(const ClassDef& class_def) const {
822 if (class_def.source_file_idx_ == 0xffffffff) {
823 return NULL;
824 } else {
825 return dexStringById(class_def.source_file_idx_);
826 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700827 }
828
jeffhaob4df5142011-09-19 20:25:32 -0700829 void ChangePermissions(int prot) const;
830
Carl Shapiro1fb86202011-06-27 17:43:13 -0700831 private:
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700832
833 // Opens a .dex file
834 static const DexFile* OpenFile(const std::string& filename,
835 const std::string& original_location,
836 const std::string& strip_location_prefix);
837
838 // Opens a dex file from within a .jar, .zip, or .apk file
839 static const DexFile* OpenZip(const std::string& filename,
840 const std::string& strip_location_prefix);
841
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700842 // Opens a .dex file at the given address.
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700843 static const DexFile* OpenMemory(const byte* dex_file,
844 size_t length,
845 const std::string& location,
846 MemMap* mem_map);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700847
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700848 DexFile(const byte* addr, size_t length, const std::string& location, MemMap* mem_map)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700849 : base_(addr),
850 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700851 location_(location),
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700852 mem_map_(mem_map),
Jesse Wilson6bf19152011-09-29 13:12:33 -0400853 dex_object_lock_("a dex_object_lock_"),
854 dex_object_(NULL),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700855 header_(0),
856 string_ids_(0),
857 type_ids_(0),
858 field_ids_(0),
859 method_ids_(0),
860 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700861 class_defs_(0) {
862 CHECK(addr != NULL);
863 CHECK_GT(length, 0U);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700864 CHECK(mem_map != NULL);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700865 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700866
867 // Top-level initializer that calls other Init methods.
868 bool Init();
869
870 // Caches pointers into to the various file sections.
871 void InitMembers();
872
873 // Builds the index of descriptors to class definitions.
874 void InitIndex();
875
876 // Returns true if the byte string equals the magic value.
877 bool CheckMagic(const byte* magic);
878
879 // Returns true if the header magic is of the expected value.
880 bool IsMagicValid();
881
Brian Carlstrome24fa612011-09-29 00:53:55 -0700882 // The index of descriptors to class definition indexes.
883 typedef std::map<const StringPiece, uint32_t> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700884 Index index_;
885
886 // The base address of the memory mapping.
887 const byte* base_;
888
889 // The size of the underlying memory allocation in bytes.
890 size_t length_;
891
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700892 // Typically the dex file name when available, alternatively some identifying string.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700893 //
894 // The ClassLinker will use this to match DexFiles the boot class
895 // path to DexCache::GetLocation when loading from an image.
896 const std::string location_;
897
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700898 // Manages the underlying memory allocation.
899 UniquePtr<MemMap> mem_map_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700900
Jesse Wilson6bf19152011-09-29 13:12:33 -0400901 // A cached com.android.dex.Dex instance, possibly NULL. Use GetDexObject.
902 mutable Mutex dex_object_lock_;
903 mutable jobject dex_object_;
904
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700905 // Points to the header section.
906 const Header* header_;
907
908 // Points to the base of the string identifier list.
909 const StringId* string_ids_;
910
911 // Points to the base of the type identifier list.
912 const TypeId* type_ids_;
913
914 // Points to the base of the field identifier list.
915 const FieldId* field_ids_;
916
917 // Points to the base of the method identifier list.
918 const MethodId* method_ids_;
919
920 // Points to the base of the prototype identifier list.
921 const ProtoId* proto_ids_;
922
923 // Points to the base of the class definition list.
924 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700925};
926
927} // namespace art
928
929#endif // ART_SRC_DEX_FILE_H_