blob: 45cd33eacb91bfdbe86f1c742595ec428942f0bb [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 Carlstrom7e49dca2011-07-22 18:07:34 -070034 static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
35 static const byte kEncodedValueArgShift = 5;
36
37 // The value of an invalid index.
38 static const uint32_t kDexNoIndex = 0xFFFFFFFF;
39
40 enum ValueType {
41 kByte = 0x00,
42 kShort = 0x02,
43 kChar = 0x03,
44 kInt = 0x04,
45 kLong = 0x06,
46 kFloat = 0x10,
47 kDouble = 0x11,
48 kString = 0x17,
49 kType = 0x18,
50 kField = 0x19,
51 kMethod = 0x1a,
52 kEnum = 0x1b,
53 kArray = 0x1c,
54 kAnnotation = 0x1d,
55 kNull = 0x1e,
56 kBoolean = 0x1f
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070057 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070058
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070059 // Raw header_item.
60 struct Header {
61 uint8_t magic_[8];
62 uint32_t checksum_;
63 uint8_t signature_[kSha1DigestSize];
64 uint32_t file_size_; // length of entire file
65 uint32_t header_size_; // offset to start of next section
66 uint32_t endian_tag_;
67 uint32_t link_size_;
68 uint32_t link_off_;
69 uint32_t map_off_;
70 uint32_t string_ids_size_;
71 uint32_t string_ids_off_;
72 uint32_t type_ids_size_;
73 uint32_t type_ids_off_;
74 uint32_t proto_ids_size_;
75 uint32_t proto_ids_off_;
76 uint32_t field_ids_size_;
77 uint32_t field_ids_off_;
78 uint32_t method_ids_size_;
79 uint32_t method_ids_off_;
80 uint32_t class_defs_size_;
81 uint32_t class_defs_off_;
82 uint32_t data_size_;
83 uint32_t data_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070084 private:
85 DISALLOW_COPY_AND_ASSIGN(Header);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070086 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070087
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070088 // Raw string_id_item.
89 struct StringId {
90 uint32_t string_data_off_; // offset in bytes from the base address
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070091 private:
92 DISALLOW_COPY_AND_ASSIGN(StringId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070093 };
94
95 // Raw type_id_item.
96 struct TypeId {
97 uint32_t descriptor_idx_; // index into string_ids
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070098 private:
99 DISALLOW_COPY_AND_ASSIGN(TypeId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700100 };
101
102 // Raw field_id_item.
103 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700104 uint16_t class_idx_; // index into type_ids_ list for defining class
105 uint16_t type_idx_; // index into type_ids_ for field type
106 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700107 private:
108 DISALLOW_COPY_AND_ASSIGN(FieldId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700109 };
110
111 // Raw method_id_item.
112 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700113 uint16_t class_idx_; // index into type_ids_ list for defining class
114 uint16_t proto_idx_; // index into proto_ids_ for method prototype
115 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700116 private:
117 DISALLOW_COPY_AND_ASSIGN(MethodId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700118 };
119
120 // Raw proto_id_item.
121 struct ProtoId {
122 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
123 uint32_t return_type_idx_; // index into type_ids list for return type
124 uint32_t parameters_off_; // file offset to type_list for parameter types
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700125 private:
126 DISALLOW_COPY_AND_ASSIGN(ProtoId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700127 };
128
129 // Raw class_def_item.
130 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700131 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700132 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700133 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700134 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700135 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700136 uint32_t annotations_off_; // file offset to annotations_directory_item
137 uint32_t class_data_off_; // file offset to class_data_item
138 uint32_t static_values_off_; // file offset to EncodedArray
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700139 private:
140 DISALLOW_COPY_AND_ASSIGN(ClassDef);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700141 };
142
143 // Raw type_item.
144 struct TypeItem {
145 uint16_t type_idx_; // index into type_ids section
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700146 private:
147 DISALLOW_COPY_AND_ASSIGN(TypeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700148 };
149
150 // Raw type_list.
151 class TypeList {
152 public:
153 uint32_t Size() const {
154 return size_;
155 }
156
157 const TypeItem& GetTypeItem(uint32_t idx) const {
158 CHECK_LT(idx, this->size_);
159 return this->list_[idx];
160 }
161
162 private:
163 uint32_t size_; // size of the list, in entries
164 TypeItem list_[1]; // elements of the list
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700165 DISALLOW_COPY_AND_ASSIGN(TypeList);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700166 };
167
168 class ParameterIterator { // TODO: stream
169 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700170 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
171 : dex_file_(dex_file), size_(0), pos_(0) {
172 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700173 if (type_list_ != NULL) {
174 size_ = type_list_->Size();
175 }
176 }
177 bool HasNext() const { return pos_ != size_; }
178 void Next() { ++pos_; }
179 const char* GetDescriptor() {
180 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700181 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700182 }
183 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700184 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700185 const TypeList* type_list_;
186 uint32_t size_;
187 uint32_t pos_;
188 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
189 };
190
191 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
192 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700193 }
194
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700195 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
196 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700197 }
198
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700199 // Raw code_item.
200 struct CodeItem {
201 uint16_t registers_size_;
202 uint16_t ins_size_;
203 uint16_t outs_size_;
204 uint16_t tries_size_;
205 uint32_t debug_info_off_; // file offset to debug info stream
206 uint32_t insns_size_; // size of the insns array, in 2 byte code units
207 uint16_t insns_[1];
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700208 private:
209 DISALLOW_COPY_AND_ASSIGN(CodeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700210 };
211
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700212 struct CatchHandlerItem {
213 uint32_t type_idx_; // type index of the caught exception type
214 uint32_t address_; // handler address
215 };
216
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700217 // Raw try_item.
218 struct TryItem {
219 uint32_t start_addr_;
220 uint16_t insn_count_;
221 uint16_t handler_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700222 private:
223 DISALLOW_COPY_AND_ASSIGN(TryItem);
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700224 };
225
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700226 class CatchHandlerIterator {
227 public:
228 CatchHandlerIterator() {
229 remaining_count_ = -1;
230 catch_all_ = false;
231 }
232
233 CatchHandlerIterator(const byte* handler_data) {
234 current_data_ = handler_data;
jeffhaoba5ebb92011-08-25 17:24:37 -0700235 remaining_count_ = DecodeSignedLeb128(&current_data_);
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700236
237 // If remaining_count_ is non-positive, then it is the negative of
238 // the number of catch types, and the catches are followed by a
239 // catch-all handler.
240 if (remaining_count_ <= 0) {
241 catch_all_ = true;
242 remaining_count_ = -remaining_count_;
243 } else {
244 catch_all_ = false;
245 }
246 Next();
247 }
248
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700249 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700250 return handler_;
251 }
252
jeffhaoba5ebb92011-08-25 17:24:37 -0700253 const byte* GetData() const {
254 return current_data_;
255 }
256
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700257 void Next() {
258 if (remaining_count_ > 0) {
259 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
260 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
261 remaining_count_--;
262 return;
263 }
264
265 if (catch_all_) {
266 handler_.type_idx_ = kDexNoIndex;
267 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
268 catch_all_ = false;
269 return;
270 }
271
272 // no more handler
273 remaining_count_ = -1;
274 }
275
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700276 bool HasNext() const {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700277 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700278 }
279
280 private:
281 CatchHandlerItem handler_;
Ian Rogersbdb03912011-09-14 00:55:44 -0700282 const byte *current_data_; // the current handler in dex file.
283 int32_t remaining_count_; // number of handlers not read.
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700284 bool catch_all_; // is there a handler that will catch all exceptions in case
285 // that all typed handler does not match.
286 };
287
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700288 // Partially decoded form of class_data_item.
289 struct ClassDataHeader {
290 uint32_t static_fields_size_; // the number of static fields
291 uint32_t instance_fields_size_; // the number of instance fields
292 uint32_t direct_methods_size_; // the number of direct methods
293 uint32_t virtual_methods_size_; // the number of virtual methods
294 };
295
296 // Decoded form of encoded_field.
297 struct Field {
298 uint32_t field_idx_; // index into the field_ids list for the identity of this field
299 uint32_t access_flags_; // access flags for the field
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700300 Field() {};
301 private:
302 DISALLOW_COPY_AND_ASSIGN(Field);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700303 };
304
305 // Decoded form of encoded_method.
306 struct Method {
307 uint32_t method_idx_;
308 uint32_t access_flags_;
309 uint32_t code_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700310 Method() {};
311 private:
312 DISALLOW_COPY_AND_ASSIGN(Method);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700313 };
314
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700315 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
316 typedef std::vector<const DexFile*> ClassPath;
317
318 // Search a collection of DexFiles for a descriptor
319 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700320 const ClassPath& class_path);
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700321
Brian Carlstrom78128a62011-09-15 17:21:19 -0700322 // Opens a collection of .dex files
323 static void OpenDexFiles(std::vector<const char*>& dex_filenames,
324 std::vector<const DexFile*>& dex_files,
325 const std::string& strip_location_prefix);
326
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700327 // Opens .dex file, guessing the container format based on file extension
Brian Carlstrom16192862011-09-12 17:50:06 -0700328 static const DexFile* Open(const std::string& filename,
329 const std::string& strip_location_prefix);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700330 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700331 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700332
Brian Carlstroma663ea52011-08-19 23:33:41 -0700333 const std::string& GetLocation() const {
334 return location_;
335 }
336
Jesse Wilson6bf19152011-09-29 13:12:33 -0400337 // Returns a com.android.dex.Dex object corresponding to the mapped-in dex file.
338 // Used by managed code to implement annotations.
339 jobject GetDexObject(JNIEnv* env) const;
340
Brian Carlstroma663ea52011-08-19 23:33:41 -0700341 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700342 CHECK(header_ != NULL);
343 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700344 }
345
Brian Carlstrome24fa612011-09-29 00:53:55 -0700346 // Looks up a class definition index by its class descriptor.
347 bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
348
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700349 // Looks up a class definition by its class descriptor.
350 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
351
352 // Returns the number of string identifiers in the .dex file.
353 size_t NumStringIds() const {
354 CHECK(header_ != NULL);
355 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700356 }
357
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700358 // Returns the number of type identifiers in the .dex file.
359 size_t NumTypeIds() const {
360 CHECK(header_ != NULL);
361 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700362 }
363
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700364 // Returns the number of prototype identifiers in the .dex file.
365 size_t NumProtoIds() const {
366 CHECK(header_ != NULL);
367 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700368 }
369
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700370 // Returns the number of field identifiers in the .dex file.
371 size_t NumFieldIds() const {
372 CHECK(header_ != NULL);
373 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700374 }
375
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700376 // Returns the number of method identifiers in the .dex file.
377 size_t NumMethodIds() const {
378 CHECK(header_ != NULL);
379 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700380 }
381
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700382 // Returns the number of class definitions in the .dex file.
383 size_t NumClassDefs() const {
384 CHECK(header_ != NULL);
385 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700386 }
387
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700388 // Returns a pointer to the memory mapped class data.
389 // TODO: return a stream
390 const byte* GetClassData(const ClassDef& class_def) const {
391 if (class_def.class_data_off_ == 0) {
392 return NULL;
393 } else {
394 return base_ + class_def.class_data_off_;
395 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700396 }
397
Brian Carlstromf615a612011-07-23 12:50:34 -0700398 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700399 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
400 CHECK(class_data != NULL);
401 ClassDataHeader header;
402 memset(&header, 0, sizeof(ClassDataHeader));
403 if (*class_data != NULL) {
404 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
405 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
406 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
407 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
408 }
409 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700410 }
411
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700412 // Returns the class descriptor string of a class definition.
413 const char* GetClassDescriptor(const ClassDef& class_def) const {
414 return dexStringByTypeIdx(class_def.class_idx_);
415 }
416
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700417 // Returns the type descriptor string of a type id.
418 const char* GetTypeDescriptor(const TypeId& type_id) const {
419 return dexStringById(type_id.descriptor_idx_);
420 }
421
Brian Carlstromb9edb842011-08-28 16:31:06 -0700422 // Returns the class descriptor string of a field id.
423 const char* GetFieldClassDescriptor(const FieldId& field_id) const {
424 const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
425 return GetTypeDescriptor(type_id);
426 }
427
428 // Returns the name of a field id.
429 const char* GetFieldName(const FieldId& field_id) const {
430 return dexStringById(field_id.name_idx_);
431 }
432
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700433 // Returns the class descriptor string of a method id.
434 const char* GetMethodClassDescriptor(const MethodId& method_id) const {
435 const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
436 return GetTypeDescriptor(type_id);
437 }
438
jeffhao98eacac2011-09-14 16:11:53 -0700439 // Returns the prototype of a method id.
440 const char* GetMethodPrototype(const MethodId& method_id) const {
441 return dexStringById(method_id.proto_idx_);
442 }
443
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700444 // Returns the name of a method id.
445 const char* GetMethodName(const MethodId& method_id) const {
446 return dexStringById(method_id.name_idx_);
447 }
448
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700449 // Returns the StringId at the specified index.
450 const StringId& GetStringId(uint32_t idx) const {
451 CHECK_LT(idx, NumStringIds());
452 return string_ids_[idx];
453 }
454
455 // Returns the TypeId at the specified index.
456 const TypeId& GetTypeId(uint32_t idx) const {
457 CHECK_LT(idx, NumTypeIds());
458 return type_ids_[idx];
459 }
460
461 // Returns the FieldId at the specified index.
462 const FieldId& GetFieldId(uint32_t idx) const {
463 CHECK_LT(idx, NumFieldIds());
464 return field_ids_[idx];
465 }
466
467 // Returns the MethodId at the specified index.
468 const MethodId& GetMethodId(uint32_t idx) const {
469 CHECK_LT(idx, NumMethodIds());
470 return method_ids_[idx];
471 }
472
473 // Returns the ProtoId at the specified index.
474 const ProtoId& GetProtoId(uint32_t idx) const {
475 CHECK_LT(idx, NumProtoIds());
476 return proto_ids_[idx];
477 }
478
479 // Returns the ClassDef at the specified index.
480 const ClassDef& GetClassDef(uint32_t idx) const {
481 CHECK_LT(idx, NumClassDefs());
482 return class_defs_[idx];
483 }
484
485 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
486 if (class_def.interfaces_off_ == 0) {
487 return NULL;
488 } else {
489 const byte* addr = base_ + class_def.interfaces_off_;
490 return reinterpret_cast<const TypeList*>(addr);
491 }
492 }
493
494 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700495 return GetCodeItem(method.code_off_);
496 }
497
498 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
499 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700500 return NULL; // native or abstract method
501 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700502 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700503 return reinterpret_cast<const CodeItem*>(addr);
504 }
505 }
506
507 // Returns the short form method descriptor for the given prototype.
508 const char* GetShorty(uint32_t proto_idx) const {
509 const ProtoId& proto_id = GetProtoId(proto_idx);
510 return dexStringById(proto_id.shorty_idx_);
511 }
512
513 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
514 if (proto_id.parameters_off_ == 0) {
515 return NULL;
516 } else {
517 const byte* addr = base_ + proto_id.parameters_off_;
518 return reinterpret_cast<const TypeList*>(addr);
519 }
520 }
521
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700522 std::string CreateMethodDescriptor(uint32_t proto_idx, int32_t* unicode_length) const;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700523
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700524 const byte* GetEncodedArray(const ClassDef& class_def) const {
525 if (class_def.static_values_off_ == 0) {
526 return 0;
527 } else {
528 return base_ + class_def.static_values_off_;
529 }
530 }
531
532 int32_t GetStringLength(const StringId& string_id) const {
533 const byte* ptr = base_ + string_id.string_data_off_;
534 return DecodeUnsignedLeb128(&ptr);
535 }
536
537 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
538
539 // From libdex...
540
541 // Returns a pointer to the UTF-8 string data referred to by the
542 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700543 const char* GetStringData(const StringId& string_id, int32_t* length) const {
544 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700545 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700546 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700547 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700548 }
549
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700550 const char* GetStringData(const StringId& string_id) const {
551 int32_t length;
552 return GetStringData(string_id, &length);
553 }
554
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700555 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700556 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700557 if (idx == kDexNoIndex) {
558 *unicode_length = 0;
559 return NULL;
560 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700561 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700562 return GetStringData(string_id, unicode_length);
563 }
564
565 const char* dexStringById(uint32_t idx) const {
566 int32_t unicode_length;
567 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700568 }
569
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700570 String* dexArtStringById(int32_t idx) const;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700571
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700572 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700573 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
574 const TypeId& type_id = GetTypeId(idx);
575 return dexStringById(type_id.descriptor_idx_, unicode_length);
576 }
577
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700578 const char* dexStringByTypeIdx(uint32_t idx) const {
579 const TypeId& type_id = GetTypeId(idx);
580 return dexStringById(type_id.descriptor_idx_);
581 }
582
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700583 String* dexArtStringByTypeIdx(int32_t idx) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700584 const TypeId& type_id = GetTypeId(idx);
585 return dexArtStringById(type_id.descriptor_idx_);
586 }
587
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700588 // TODO: encoded_field is actually a stream of bytes
589 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700590 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700591 uint32_t* last_idx) const {
592 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
593 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
594 field->field_idx_ = idx;
595 *last_idx = idx;
596 }
597
598 // TODO: encoded_method is actually a stream of bytes
599 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700600 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700601 uint32_t* last_idx) const {
602 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
603 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
604 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
605 method->method_idx_ = idx;
606 *last_idx = idx;
607 }
608
jeffhaoba5ebb92011-08-25 17:24:37 -0700609 static const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700610 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
611 return reinterpret_cast<const TryItem*>
612 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
613 }
614
615 // Get the base of the encoded data for the given DexCode.
jeffhaoba5ebb92011-08-25 17:24:37 -0700616 static const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700617 const byte* handler_data = reinterpret_cast<const byte*>
618 (dexGetTryItems(code_item, code_item.tries_size_));
619 return handler_data + offset;
620 }
621
622 // Find the handler associated with a given address, if any.
623 // Initializes the given iterator and returns true if a match is
624 // found. Returns end if there is no applicable handler.
jeffhaoba5ebb92011-08-25 17:24:37 -0700625 static CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700626 CatchHandlerItem handler;
627 handler.address_ = -1;
628 int32_t offset = -1;
629
630 // Short-circuit the overwhelmingly common cases.
631 switch (code_item.tries_size_) {
632 case 0:
633 break;
634 case 1: {
635 const TryItem* tries = dexGetTryItems(code_item, 0);
636 uint32_t start = tries->start_addr_;
637 if (address < start)
638 break;
639
640 uint32_t end = start + tries->insn_count_;
641 if (address >= end)
642 break;
643
644 offset = tries->handler_off_;
645 break;
646 }
647 default:
648 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
649 }
650
651 if (offset >= 0) {
652 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
653 return CatchHandlerIterator(handler_data);
654 }
655 return CatchHandlerIterator();
656 }
657
jeffhaoba5ebb92011-08-25 17:24:37 -0700658 static int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
659 int32_t tries_size,
660 uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700661 // Note: Signed type is important for max and min.
662 int32_t min = 0;
663 int32_t max = tries_size - 1;
664
665 while (max >= min) {
666 int32_t guess = (min + max) >> 1;
667 const TryItem* pTry = dexGetTryItems(code_item, guess);
668 uint32_t start = pTry->start_addr_;
669
670 if (address < start) {
671 max = guess - 1;
672 continue;
673 }
674
675 uint32_t end = start + pTry->insn_count_;
676 if (address >= end) {
677 min = guess + 1;
678 continue;
679 }
680
681 // We have a winner!
682 return (int32_t) pTry->handler_off_;
683 }
684
685 // No match.
686 return -1;
687 }
688
Shih-wei Liao195487c2011-08-20 13:29:04 -0700689 // Get the pointer to the start of the debugging data
690 const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
691 if (code_item->debug_info_off_ == 0) {
692 return NULL;
693 } else {
694 return base_ + code_item->debug_info_off_;
695 }
696 }
697
698 // Callback for "new position table entry".
699 // Returning true causes the decoder to stop early.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700700 typedef bool (*DexDebugNewPositionCb)(void* cnxt, uint32_t address, uint32_t line_num);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700701
702 // Callback for "new locals table entry". "signature" is an empty string
703 // if no signature is available for an entry.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700704 typedef void (*DexDebugNewLocalCb)(void* cnxt, uint16_t reg,
Shih-wei Liao195487c2011-08-20 13:29:04 -0700705 uint32_t startAddress,
706 uint32_t endAddress,
707 const String* name,
708 const String* descriptor,
709 const String* signature);
710
Brian Carlstrom78128a62011-09-15 17:21:19 -0700711 static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700712 LineNumFromPcContext *context = (LineNumFromPcContext *)cnxt;
713
714 // We know that this callback will be called in
715 // ascending address order, so keep going until we find
716 // a match or we've just gone past it.
717 if (address > context->address_) {
718 // The line number from the previous positions callback
719 // wil be the final result.
720 return true;
721 } else {
722 context->line_num_ = line_num;
723 return address == context->address_;
724 }
725 }
726
727
728 // Debug info opcodes and constants
729 enum {
730 DBG_END_SEQUENCE = 0x00,
731 DBG_ADVANCE_PC = 0x01,
732 DBG_ADVANCE_LINE = 0x02,
733 DBG_START_LOCAL = 0x03,
734 DBG_START_LOCAL_EXTENDED = 0x04,
735 DBG_END_LOCAL = 0x05,
736 DBG_RESTART_LOCAL = 0x06,
737 DBG_SET_PROLOGUE_END = 0x07,
738 DBG_SET_EPILOGUE_BEGIN = 0x08,
739 DBG_SET_FILE = 0x09,
740 DBG_FIRST_SPECIAL = 0x0a,
741 DBG_LINE_BASE = -4,
742 DBG_LINE_RANGE = 15,
743 };
744
745 struct LocalInfo {
746 LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0), is_live_(false) {}
747
748 // E.g., list
749 const String* name_;
750
751 // E.g., Ljava/util/LinkedList;
752 const String* descriptor_;
753
754 // E.g., java.util.LinkedList<java.lang.Integer>
755 const String* signature_;
756
757 // PC location where the local is first defined.
758 uint16_t start_address_;
759
760 // Is the local defined and live.
761 bool is_live_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700762
763 private:
764 DISALLOW_COPY_AND_ASSIGN(LocalInfo);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700765 };
766
767 struct LineNumFromPcContext {
768 LineNumFromPcContext(uint32_t address, uint32_t line_num) :
769 address_(address), line_num_(line_num) {}
770 uint32_t address_;
771 uint32_t line_num_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700772 private:
773 DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700774 };
775
Brian Carlstrom78128a62011-09-15 17:21:19 -0700776 void InvokeLocalCbIfLive(void* cnxt, int reg, uint32_t end_address,
777 LocalInfo* local_in_reg, DexDebugNewLocalCb local_cb) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700778 if (local_cb != NULL && local_in_reg[reg].is_live_) {
779 local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
780 local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
781 local_in_reg[reg].signature_);
782 }
783 }
784
785 // Determine the source file line number based on the program counter.
786 // "pc" is an offset, in 16-bit units, from the start of the method's code.
787 //
788 // Returns -1 if no match was found (possibly because the source files were
789 // compiled without "-g", so no line number information is present).
790 // Returns -2 for native methods (as expected in exception traces).
791 //
792 // This is used by runtime; therefore use art::Method not art::DexFile::Method.
793 int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
794
795 void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
796 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
797 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
798
799 void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method *method,
800 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
801 void* cnxt) const {
802 const byte* stream = dexGetDebugInfoStream(code_item);
803 LocalInfo local_in_reg[code_item->registers_size_];
804
805 if (stream != NULL) {
806 dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
807 }
808 for (int reg = 0; reg < code_item->registers_size_; reg++) {
809 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_, local_in_reg, local_cb);
810 }
811 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700812
813 // TODO: const reference
814 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
815 CHECK_GE(class_def, class_defs_);
816 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
817 return class_def - class_defs_;
818 }
819
820 const char* dexGetSourceFile(const ClassDef& class_def) const {
821 if (class_def.source_file_idx_ == 0xffffffff) {
822 return NULL;
823 } else {
824 return dexStringById(class_def.source_file_idx_);
825 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700826 }
827
jeffhaob4df5142011-09-19 20:25:32 -0700828 void ChangePermissions(int prot) const;
829
Carl Shapiro1fb86202011-06-27 17:43:13 -0700830 private:
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700831
832 // Opens a .dex file
833 static const DexFile* OpenFile(const std::string& filename,
834 const std::string& original_location,
835 const std::string& strip_location_prefix);
836
837 // Opens a dex file from within a .jar, .zip, or .apk file
838 static const DexFile* OpenZip(const std::string& filename,
839 const std::string& strip_location_prefix);
840
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700841 // Opens a .dex file at the given address.
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700842 static const DexFile* OpenMemory(const byte* dex_file,
843 size_t length,
844 const std::string& location,
845 MemMap* mem_map);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700846
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700847 DexFile(const byte* addr, size_t length, const std::string& location, MemMap* mem_map)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700848 : base_(addr),
849 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700850 location_(location),
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700851 mem_map_(mem_map),
Jesse Wilson6bf19152011-09-29 13:12:33 -0400852 dex_object_lock_("a dex_object_lock_"),
853 dex_object_(NULL),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700854 header_(0),
855 string_ids_(0),
856 type_ids_(0),
857 field_ids_(0),
858 method_ids_(0),
859 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700860 class_defs_(0) {
861 CHECK(addr != NULL);
862 CHECK_GT(length, 0U);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700863 CHECK(mem_map != NULL);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700864 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700865
866 // Top-level initializer that calls other Init methods.
867 bool Init();
868
869 // Caches pointers into to the various file sections.
870 void InitMembers();
871
872 // Builds the index of descriptors to class definitions.
873 void InitIndex();
874
875 // Returns true if the byte string equals the magic value.
876 bool CheckMagic(const byte* magic);
877
878 // Returns true if the header magic is of the expected value.
879 bool IsMagicValid();
880
Brian Carlstrome24fa612011-09-29 00:53:55 -0700881 // The index of descriptors to class definition indexes.
882 typedef std::map<const StringPiece, uint32_t> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700883 Index index_;
884
885 // The base address of the memory mapping.
886 const byte* base_;
887
888 // The size of the underlying memory allocation in bytes.
889 size_t length_;
890
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700891 // Typically the dex file name when available, alternatively some identifying string.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700892 //
893 // The ClassLinker will use this to match DexFiles the boot class
894 // path to DexCache::GetLocation when loading from an image.
895 const std::string location_;
896
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700897 // Manages the underlying memory allocation.
898 UniquePtr<MemMap> mem_map_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700899
Jesse Wilson6bf19152011-09-29 13:12:33 -0400900 // A cached com.android.dex.Dex instance, possibly NULL. Use GetDexObject.
901 mutable Mutex dex_object_lock_;
902 mutable jobject dex_object_;
903
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700904 // Points to the header section.
905 const Header* header_;
906
907 // Points to the base of the string identifier list.
908 const StringId* string_ids_;
909
910 // Points to the base of the type identifier list.
911 const TypeId* type_ids_;
912
913 // Points to the base of the field identifier list.
914 const FieldId* field_ids_;
915
916 // Points to the base of the method identifier list.
917 const MethodId* method_ids_;
918
919 // Points to the base of the prototype identifier list.
920 const ProtoId* proto_ids_;
921
922 // Points to the base of the class definition list.
923 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700924};
925
926} // namespace art
927
928#endif // ART_SRC_DEX_FILE_H_