blob: e313d74bdb077bc373d70daf9cc84f42ff0129aa [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"
Jesse Wilson6bf19152011-09-29 13:12:33 -040015#include "mutex.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070016#include "stringpiece.h"
17#include "strutil.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -070018#include "utils.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070019
20namespace art {
21
Carl Shapiro5fafe2b2011-07-09 15:34:41 -070022union JValue;
Shih-wei Liao195487c2011-08-20 13:29:04 -070023class String;
24class Method;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070025
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026// TODO: move all of the macro functionality into the DexCache class.
Brian Carlstromf615a612011-07-23 12:50:34 -070027class DexFile {
Carl Shapiro1fb86202011-06-27 17:43:13 -070028 public:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070029 static const byte kDexMagic[];
30 static const byte kDexMagicVersion[];
31 static const size_t kSha1DigestSize = 20;
Carl Shapiro80d4dde2011-06-28 16:24:07 -070032
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070033 static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
34 static const byte kEncodedValueArgShift = 5;
35
36 // The value of an invalid index.
37 static const uint32_t kDexNoIndex = 0xFFFFFFFF;
38
39 enum ValueType {
40 kByte = 0x00,
41 kShort = 0x02,
42 kChar = 0x03,
43 kInt = 0x04,
44 kLong = 0x06,
45 kFloat = 0x10,
46 kDouble = 0x11,
47 kString = 0x17,
48 kType = 0x18,
49 kField = 0x19,
50 kMethod = 0x1a,
51 kEnum = 0x1b,
52 kArray = 0x1c,
53 kAnnotation = 0x1d,
54 kNull = 0x1e,
55 kBoolean = 0x1f
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070056 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070057
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070058 // Raw header_item.
59 struct Header {
60 uint8_t magic_[8];
61 uint32_t checksum_;
62 uint8_t signature_[kSha1DigestSize];
63 uint32_t file_size_; // length of entire file
64 uint32_t header_size_; // offset to start of next section
65 uint32_t endian_tag_;
66 uint32_t link_size_;
67 uint32_t link_off_;
68 uint32_t map_off_;
69 uint32_t string_ids_size_;
70 uint32_t string_ids_off_;
71 uint32_t type_ids_size_;
72 uint32_t type_ids_off_;
73 uint32_t proto_ids_size_;
74 uint32_t proto_ids_off_;
75 uint32_t field_ids_size_;
76 uint32_t field_ids_off_;
77 uint32_t method_ids_size_;
78 uint32_t method_ids_off_;
79 uint32_t class_defs_size_;
80 uint32_t class_defs_off_;
81 uint32_t data_size_;
82 uint32_t data_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070083 private:
84 DISALLOW_COPY_AND_ASSIGN(Header);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070085 };
Carl Shapiro1fb86202011-06-27 17:43:13 -070086
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070087 // Raw string_id_item.
88 struct StringId {
89 uint32_t string_data_off_; // offset in bytes from the base address
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070090 private:
91 DISALLOW_COPY_AND_ASSIGN(StringId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070092 };
93
94 // Raw type_id_item.
95 struct TypeId {
96 uint32_t descriptor_idx_; // index into string_ids
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -070097 private:
98 DISALLOW_COPY_AND_ASSIGN(TypeId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070099 };
100
101 // Raw field_id_item.
102 struct FieldId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700103 uint16_t class_idx_; // index into type_ids_ list for defining class
104 uint16_t type_idx_; // index into type_ids_ for field type
105 uint32_t name_idx_; // index into string_ids_ for field name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700106 private:
107 DISALLOW_COPY_AND_ASSIGN(FieldId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700108 };
109
110 // Raw method_id_item.
111 struct MethodId {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700112 uint16_t class_idx_; // index into type_ids_ list for defining class
113 uint16_t proto_idx_; // index into proto_ids_ for method prototype
114 uint32_t name_idx_; // index into string_ids_ for method name
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700115 private:
116 DISALLOW_COPY_AND_ASSIGN(MethodId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700117 };
118
119 // Raw proto_id_item.
120 struct ProtoId {
121 uint32_t shorty_idx_; // index into string_ids for shorty descriptor
122 uint32_t return_type_idx_; // index into type_ids list for return type
123 uint32_t parameters_off_; // file offset to type_list for parameter types
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700124 private:
125 DISALLOW_COPY_AND_ASSIGN(ProtoId);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700126 };
127
128 // Raw class_def_item.
129 struct ClassDef {
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700130 uint32_t class_idx_; // index into type_ids_ for this class
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700131 uint32_t access_flags_;
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700132 uint32_t superclass_idx_; // index into type_ids_ for superclass
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700133 uint32_t interfaces_off_; // file offset to TypeList
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700134 uint32_t source_file_idx_; // index into string_ids_ for source file name
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700135 uint32_t annotations_off_; // file offset to annotations_directory_item
136 uint32_t class_data_off_; // file offset to class_data_item
137 uint32_t static_values_off_; // file offset to EncodedArray
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700138 private:
139 DISALLOW_COPY_AND_ASSIGN(ClassDef);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700140 };
141
142 // Raw type_item.
143 struct TypeItem {
144 uint16_t type_idx_; // index into type_ids section
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700145 private:
146 DISALLOW_COPY_AND_ASSIGN(TypeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700147 };
148
149 // Raw type_list.
150 class TypeList {
151 public:
152 uint32_t Size() const {
153 return size_;
154 }
155
156 const TypeItem& GetTypeItem(uint32_t idx) const {
157 CHECK_LT(idx, this->size_);
158 return this->list_[idx];
159 }
160
161 private:
162 uint32_t size_; // size of the list, in entries
163 TypeItem list_[1]; // elements of the list
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700164 DISALLOW_COPY_AND_ASSIGN(TypeList);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700165 };
166
167 class ParameterIterator { // TODO: stream
168 public:
Brian Carlstromf615a612011-07-23 12:50:34 -0700169 ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
170 : dex_file_(dex_file), size_(0), pos_(0) {
171 type_list_ = dex_file_.GetProtoParameters(proto_id);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700172 if (type_list_ != NULL) {
173 size_ = type_list_->Size();
174 }
175 }
176 bool HasNext() const { return pos_ != size_; }
177 void Next() { ++pos_; }
178 const char* GetDescriptor() {
179 uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
Brian Carlstromf615a612011-07-23 12:50:34 -0700180 return dex_file_.dexStringByTypeIdx(type_idx);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700181 }
182 private:
Brian Carlstromf615a612011-07-23 12:50:34 -0700183 const DexFile& dex_file_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700184 const TypeList* type_list_;
185 uint32_t size_;
186 uint32_t pos_;
187 DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
188 };
189
190 ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
191 return new ParameterIterator(*this, proto_id);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700192 }
193
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700194 const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
195 return dexStringByTypeIdx(proto_id.return_type_idx_);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700196 }
197
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700198 // Raw code_item.
199 struct CodeItem {
200 uint16_t registers_size_;
201 uint16_t ins_size_;
202 uint16_t outs_size_;
203 uint16_t tries_size_;
204 uint32_t debug_info_off_; // file offset to debug info stream
205 uint32_t insns_size_; // size of the insns array, in 2 byte code units
206 uint16_t insns_[1];
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700207 private:
208 DISALLOW_COPY_AND_ASSIGN(CodeItem);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700209 };
210
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700211 struct CatchHandlerItem {
212 uint32_t type_idx_; // type index of the caught exception type
213 uint32_t address_; // handler address
214 };
215
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700216 // Raw try_item.
217 struct TryItem {
218 uint32_t start_addr_;
219 uint16_t insn_count_;
220 uint16_t handler_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700221 private:
222 DISALLOW_COPY_AND_ASSIGN(TryItem);
Carl Shapiro2eaa9682011-08-04 19:26:11 -0700223 };
224
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700225 class CatchHandlerIterator {
226 public:
227 CatchHandlerIterator() {
228 remaining_count_ = -1;
229 catch_all_ = false;
230 }
231
232 CatchHandlerIterator(const byte* handler_data) {
233 current_data_ = handler_data;
jeffhaoba5ebb92011-08-25 17:24:37 -0700234 remaining_count_ = DecodeSignedLeb128(&current_data_);
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700235
236 // If remaining_count_ is non-positive, then it is the negative of
237 // the number of catch types, and the catches are followed by a
238 // catch-all handler.
239 if (remaining_count_ <= 0) {
240 catch_all_ = true;
241 remaining_count_ = -remaining_count_;
242 } else {
243 catch_all_ = false;
244 }
245 Next();
246 }
247
Shih-wei Liaofe909f22011-08-12 19:20:26 -0700248 const CatchHandlerItem& Get() const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700249 return handler_;
250 }
251
jeffhaoba5ebb92011-08-25 17:24:37 -0700252 const byte* GetData() const {
253 return current_data_;
254 }
255
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700256 void Next() {
257 if (remaining_count_ > 0) {
258 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
259 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
260 remaining_count_--;
261 return;
262 }
263
264 if (catch_all_) {
265 handler_.type_idx_ = kDexNoIndex;
266 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
267 catch_all_ = false;
268 return;
269 }
270
271 // no more handler
272 remaining_count_ = -1;
273 }
274
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700275 bool HasNext() const {
Shih-wei Liao4e5c0b92011-08-11 22:50:08 -0700276 return remaining_count_ == -1 && catch_all_ == false;
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700277 }
278
279 private:
280 CatchHandlerItem handler_;
Ian Rogersbdb03912011-09-14 00:55:44 -0700281 const byte *current_data_; // the current handler in dex file.
282 int32_t remaining_count_; // number of handlers not read.
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700283 bool catch_all_; // is there a handler that will catch all exceptions in case
284 // that all typed handler does not match.
285 };
286
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700287 // Partially decoded form of class_data_item.
288 struct ClassDataHeader {
289 uint32_t static_fields_size_; // the number of static fields
290 uint32_t instance_fields_size_; // the number of instance fields
291 uint32_t direct_methods_size_; // the number of direct methods
292 uint32_t virtual_methods_size_; // the number of virtual methods
293 };
294
295 // Decoded form of encoded_field.
296 struct Field {
297 uint32_t field_idx_; // index into the field_ids list for the identity of this field
298 uint32_t access_flags_; // access flags for the field
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700299 Field() {};
300 private:
301 DISALLOW_COPY_AND_ASSIGN(Field);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700302 };
303
304 // Decoded form of encoded_method.
305 struct Method {
306 uint32_t method_idx_;
307 uint32_t access_flags_;
308 uint32_t code_off_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700309 Method() {};
310 private:
311 DISALLOW_COPY_AND_ASSIGN(Method);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700312 };
313
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700314 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
315 typedef std::vector<const DexFile*> ClassPath;
316
317 // Search a collection of DexFiles for a descriptor
318 static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700319 const ClassPath& class_path);
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700320
Brian Carlstrom78128a62011-09-15 17:21:19 -0700321 // Opens a collection of .dex files
322 static void OpenDexFiles(std::vector<const char*>& dex_filenames,
323 std::vector<const DexFile*>& dex_files,
324 const std::string& strip_location_prefix);
325
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700326 // Opens .dex file, guessing the format based on file extension
Brian Carlstrom16192862011-09-12 17:50:06 -0700327 static const DexFile* Open(const std::string& filename,
328 const std::string& strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700329
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700330 // Opens a .dex file from the file system.
Brian Carlstrom16192862011-09-12 17:50:06 -0700331 static const DexFile* OpenFile(const std::string& filename,
332 const std::string& original_location,
333 const std::string& strip_location_prefix);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700334
335 // Opens a .jar, .zip, or .apk file from the file system.
Brian Carlstrom16192862011-09-12 17:50:06 -0700336 static const DexFile* OpenZip(const std::string& filename,
337 const std::string& strip_location_prefix);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700338
Brian Carlstroma663ea52011-08-19 23:33:41 -0700339 // Opens a .dex file from a new allocated pointer. location is used
340 // to identify the source, for example "/system/framework/core.jar"
341 // or "contrived-test-42". When initializing a ClassLinker from an
342 // image, the location is used to match DexCaches the image to their
343 // corresponding DexFiles.N
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700344 static const DexFile* OpenPtr(byte* ptr, size_t length, const std::string& location);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700345
346 // Closes a .dex file.
Brian Carlstromf615a612011-07-23 12:50:34 -0700347 virtual ~DexFile();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700348
Brian Carlstroma663ea52011-08-19 23:33:41 -0700349 const std::string& GetLocation() const {
350 return location_;
351 }
352
Jesse Wilson6bf19152011-09-29 13:12:33 -0400353 // Returns a com.android.dex.Dex object corresponding to the mapped-in dex file.
354 // Used by managed code to implement annotations.
355 jobject GetDexObject(JNIEnv* env) const;
356
Brian Carlstroma663ea52011-08-19 23:33:41 -0700357 const Header& GetHeader() const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700358 CHECK(header_ != NULL);
359 return *header_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700360 }
361
Brian Carlstrome24fa612011-09-29 00:53:55 -0700362 // Looks up a class definition index by its class descriptor.
363 bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
364
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700365 // Looks up a class definition by its class descriptor.
366 const ClassDef* FindClassDef(const StringPiece& descriptor) const;
367
368 // Returns the number of string identifiers in the .dex file.
369 size_t NumStringIds() const {
370 CHECK(header_ != NULL);
371 return header_->string_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700372 }
373
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700374 // Returns the number of type identifiers in the .dex file.
375 size_t NumTypeIds() const {
376 CHECK(header_ != NULL);
377 return header_->type_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700378 }
379
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700380 // Returns the number of prototype identifiers in the .dex file.
381 size_t NumProtoIds() const {
382 CHECK(header_ != NULL);
383 return header_->proto_ids_size_;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700384 }
385
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700386 // Returns the number of field identifiers in the .dex file.
387 size_t NumFieldIds() const {
388 CHECK(header_ != NULL);
389 return header_->field_ids_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700390 }
391
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700392 // Returns the number of method identifiers in the .dex file.
393 size_t NumMethodIds() const {
394 CHECK(header_ != NULL);
395 return header_->method_ids_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700396 }
397
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700398 // Returns the number of class definitions in the .dex file.
399 size_t NumClassDefs() const {
400 CHECK(header_ != NULL);
401 return header_->class_defs_size_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700402 }
403
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700404 // Returns a pointer to the memory mapped class data.
405 // TODO: return a stream
406 const byte* GetClassData(const ClassDef& class_def) const {
407 if (class_def.class_data_off_ == 0) {
408 return NULL;
409 } else {
410 return base_ + class_def.class_data_off_;
411 }
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700412 }
413
Brian Carlstromf615a612011-07-23 12:50:34 -0700414 // Decodes the header section from the class data bytes.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700415 ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
416 CHECK(class_data != NULL);
417 ClassDataHeader header;
418 memset(&header, 0, sizeof(ClassDataHeader));
419 if (*class_data != NULL) {
420 header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
421 header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
422 header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
423 header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
424 }
425 return header;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700426 }
427
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700428 // Returns the class descriptor string of a class definition.
429 const char* GetClassDescriptor(const ClassDef& class_def) const {
430 return dexStringByTypeIdx(class_def.class_idx_);
431 }
432
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700433 // Returns the type descriptor string of a type id.
434 const char* GetTypeDescriptor(const TypeId& type_id) const {
435 return dexStringById(type_id.descriptor_idx_);
436 }
437
Brian Carlstromb9edb842011-08-28 16:31:06 -0700438 // Returns the class descriptor string of a field id.
439 const char* GetFieldClassDescriptor(const FieldId& field_id) const {
440 const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
441 return GetTypeDescriptor(type_id);
442 }
443
444 // Returns the name of a field id.
445 const char* GetFieldName(const FieldId& field_id) const {
446 return dexStringById(field_id.name_idx_);
447 }
448
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700449 // Returns the class descriptor string of a method id.
450 const char* GetMethodClassDescriptor(const MethodId& method_id) const {
451 const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
452 return GetTypeDescriptor(type_id);
453 }
454
jeffhao98eacac2011-09-14 16:11:53 -0700455 // Returns the prototype of a method id.
456 const char* GetMethodPrototype(const MethodId& method_id) const {
457 return dexStringById(method_id.proto_idx_);
458 }
459
Brian Carlstrom7540ff42011-09-04 16:38:46 -0700460 // Returns the name of a method id.
461 const char* GetMethodName(const MethodId& method_id) const {
462 return dexStringById(method_id.name_idx_);
463 }
464
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700465 // Returns the StringId at the specified index.
466 const StringId& GetStringId(uint32_t idx) const {
467 CHECK_LT(idx, NumStringIds());
468 return string_ids_[idx];
469 }
470
471 // Returns the TypeId at the specified index.
472 const TypeId& GetTypeId(uint32_t idx) const {
473 CHECK_LT(idx, NumTypeIds());
474 return type_ids_[idx];
475 }
476
477 // Returns the FieldId at the specified index.
478 const FieldId& GetFieldId(uint32_t idx) const {
479 CHECK_LT(idx, NumFieldIds());
480 return field_ids_[idx];
481 }
482
483 // Returns the MethodId at the specified index.
484 const MethodId& GetMethodId(uint32_t idx) const {
485 CHECK_LT(idx, NumMethodIds());
486 return method_ids_[idx];
487 }
488
489 // Returns the ProtoId at the specified index.
490 const ProtoId& GetProtoId(uint32_t idx) const {
491 CHECK_LT(idx, NumProtoIds());
492 return proto_ids_[idx];
493 }
494
495 // Returns the ClassDef at the specified index.
496 const ClassDef& GetClassDef(uint32_t idx) const {
497 CHECK_LT(idx, NumClassDefs());
498 return class_defs_[idx];
499 }
500
501 const TypeList* GetInterfacesList(const ClassDef& class_def) const {
502 if (class_def.interfaces_off_ == 0) {
503 return NULL;
504 } else {
505 const byte* addr = base_ + class_def.interfaces_off_;
506 return reinterpret_cast<const TypeList*>(addr);
507 }
508 }
509
510 const CodeItem* GetCodeItem(const Method& method) const {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700511 return GetCodeItem(method.code_off_);
512 }
513
514 const CodeItem* GetCodeItem(const uint32_t code_off_) const {
515 if (code_off_ == 0) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700516 return NULL; // native or abstract method
517 } else {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700518 const byte* addr = base_ + code_off_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700519 return reinterpret_cast<const CodeItem*>(addr);
520 }
521 }
522
523 // Returns the short form method descriptor for the given prototype.
524 const char* GetShorty(uint32_t proto_idx) const {
525 const ProtoId& proto_id = GetProtoId(proto_idx);
526 return dexStringById(proto_id.shorty_idx_);
527 }
528
529 const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
530 if (proto_id.parameters_off_ == 0) {
531 return NULL;
532 } else {
533 const byte* addr = base_ + proto_id.parameters_off_;
534 return reinterpret_cast<const TypeList*>(addr);
535 }
536 }
537
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700538 std::string CreateMethodDescriptor(uint32_t proto_idx, int32_t* unicode_length) const;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700539
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700540 const byte* GetEncodedArray(const ClassDef& class_def) const {
541 if (class_def.static_values_off_ == 0) {
542 return 0;
543 } else {
544 return base_ + class_def.static_values_off_;
545 }
546 }
547
548 int32_t GetStringLength(const StringId& string_id) const {
549 const byte* ptr = base_ + string_id.string_data_off_;
550 return DecodeUnsignedLeb128(&ptr);
551 }
552
553 ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
554
555 // From libdex...
556
557 // Returns a pointer to the UTF-8 string data referred to by the
558 // given string_id.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700559 const char* GetStringData(const StringId& string_id, int32_t* length) const {
560 CHECK(length != NULL);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700561 const byte* ptr = base_ + string_id.string_data_off_;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700562 *length = DecodeUnsignedLeb128(&ptr);
Brian Carlstrom0b138b22011-07-27 15:19:17 -0700563 return reinterpret_cast<const char*>(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700564 }
565
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700566 const char* GetStringData(const StringId& string_id) const {
567 int32_t length;
568 return GetStringData(string_id, &length);
569 }
570
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700571 // return the UTF-8 encoded string with the specified string_id index
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700572 const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700573 if (idx == kDexNoIndex) {
574 *unicode_length = 0;
575 return NULL;
576 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700577 const StringId& string_id = GetStringId(idx);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700578 return GetStringData(string_id, unicode_length);
579 }
580
581 const char* dexStringById(uint32_t idx) const {
582 int32_t unicode_length;
583 return dexStringById(idx, &unicode_length);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700584 }
585
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700586 String* dexArtStringById(int32_t idx) const;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700587
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700588 // Get the descriptor string associated with a given type index.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700589 const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
590 const TypeId& type_id = GetTypeId(idx);
591 return dexStringById(type_id.descriptor_idx_, unicode_length);
592 }
593
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700594 const char* dexStringByTypeIdx(uint32_t idx) const {
595 const TypeId& type_id = GetTypeId(idx);
596 return dexStringById(type_id.descriptor_idx_);
597 }
598
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700599 String* dexArtStringByTypeIdx(int32_t idx) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700600 const TypeId& type_id = GetTypeId(idx);
601 return dexArtStringById(type_id.descriptor_idx_);
602 }
603
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700604 // TODO: encoded_field is actually a stream of bytes
605 void dexReadClassDataField(const byte** encoded_field,
Brian Carlstromf615a612011-07-23 12:50:34 -0700606 DexFile::Field* field,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700607 uint32_t* last_idx) const {
608 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
609 field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
610 field->field_idx_ = idx;
611 *last_idx = idx;
612 }
613
614 // TODO: encoded_method is actually a stream of bytes
615 void dexReadClassDataMethod(const byte** encoded_method,
Brian Carlstromf615a612011-07-23 12:50:34 -0700616 DexFile::Method* method,
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700617 uint32_t* last_idx) const {
618 uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
619 method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
620 method->code_off_ = DecodeUnsignedLeb128(encoded_method);
621 method->method_idx_ = idx;
622 *last_idx = idx;
623 }
624
jeffhaoba5ebb92011-08-25 17:24:37 -0700625 static const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700626 const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_];
627 return reinterpret_cast<const TryItem*>
628 (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
629 }
630
631 // Get the base of the encoded data for the given DexCode.
jeffhaoba5ebb92011-08-25 17:24:37 -0700632 static const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700633 const byte* handler_data = reinterpret_cast<const byte*>
634 (dexGetTryItems(code_item, code_item.tries_size_));
635 return handler_data + offset;
636 }
637
638 // Find the handler associated with a given address, if any.
639 // Initializes the given iterator and returns true if a match is
640 // found. Returns end if there is no applicable handler.
jeffhaoba5ebb92011-08-25 17:24:37 -0700641 static CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700642 CatchHandlerItem handler;
643 handler.address_ = -1;
644 int32_t offset = -1;
645
646 // Short-circuit the overwhelmingly common cases.
647 switch (code_item.tries_size_) {
648 case 0:
649 break;
650 case 1: {
651 const TryItem* tries = dexGetTryItems(code_item, 0);
652 uint32_t start = tries->start_addr_;
653 if (address < start)
654 break;
655
656 uint32_t end = start + tries->insn_count_;
657 if (address >= end)
658 break;
659
660 offset = tries->handler_off_;
661 break;
662 }
663 default:
664 offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
665 }
666
667 if (offset >= 0) {
668 const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
669 return CatchHandlerIterator(handler_data);
670 }
671 return CatchHandlerIterator();
672 }
673
jeffhaoba5ebb92011-08-25 17:24:37 -0700674 static int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
675 int32_t tries_size,
676 uint32_t address) {
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700677 // Note: Signed type is important for max and min.
678 int32_t min = 0;
679 int32_t max = tries_size - 1;
680
681 while (max >= min) {
682 int32_t guess = (min + max) >> 1;
683 const TryItem* pTry = dexGetTryItems(code_item, guess);
684 uint32_t start = pTry->start_addr_;
685
686 if (address < start) {
687 max = guess - 1;
688 continue;
689 }
690
691 uint32_t end = start + pTry->insn_count_;
692 if (address >= end) {
693 min = guess + 1;
694 continue;
695 }
696
697 // We have a winner!
698 return (int32_t) pTry->handler_off_;
699 }
700
701 // No match.
702 return -1;
703 }
704
Shih-wei Liao195487c2011-08-20 13:29:04 -0700705 // Get the pointer to the start of the debugging data
706 const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
707 if (code_item->debug_info_off_ == 0) {
708 return NULL;
709 } else {
710 return base_ + code_item->debug_info_off_;
711 }
712 }
713
714 // Callback for "new position table entry".
715 // Returning true causes the decoder to stop early.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700716 typedef bool (*DexDebugNewPositionCb)(void* cnxt, uint32_t address, uint32_t line_num);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700717
718 // Callback for "new locals table entry". "signature" is an empty string
719 // if no signature is available for an entry.
Brian Carlstrom78128a62011-09-15 17:21:19 -0700720 typedef void (*DexDebugNewLocalCb)(void* cnxt, uint16_t reg,
Shih-wei Liao195487c2011-08-20 13:29:04 -0700721 uint32_t startAddress,
722 uint32_t endAddress,
723 const String* name,
724 const String* descriptor,
725 const String* signature);
726
Brian Carlstrom78128a62011-09-15 17:21:19 -0700727 static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700728 LineNumFromPcContext *context = (LineNumFromPcContext *)cnxt;
729
730 // We know that this callback will be called in
731 // ascending address order, so keep going until we find
732 // a match or we've just gone past it.
733 if (address > context->address_) {
734 // The line number from the previous positions callback
735 // wil be the final result.
736 return true;
737 } else {
738 context->line_num_ = line_num;
739 return address == context->address_;
740 }
741 }
742
743
744 // Debug info opcodes and constants
745 enum {
746 DBG_END_SEQUENCE = 0x00,
747 DBG_ADVANCE_PC = 0x01,
748 DBG_ADVANCE_LINE = 0x02,
749 DBG_START_LOCAL = 0x03,
750 DBG_START_LOCAL_EXTENDED = 0x04,
751 DBG_END_LOCAL = 0x05,
752 DBG_RESTART_LOCAL = 0x06,
753 DBG_SET_PROLOGUE_END = 0x07,
754 DBG_SET_EPILOGUE_BEGIN = 0x08,
755 DBG_SET_FILE = 0x09,
756 DBG_FIRST_SPECIAL = 0x0a,
757 DBG_LINE_BASE = -4,
758 DBG_LINE_RANGE = 15,
759 };
760
761 struct LocalInfo {
762 LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0), is_live_(false) {}
763
764 // E.g., list
765 const String* name_;
766
767 // E.g., Ljava/util/LinkedList;
768 const String* descriptor_;
769
770 // E.g., java.util.LinkedList<java.lang.Integer>
771 const String* signature_;
772
773 // PC location where the local is first defined.
774 uint16_t start_address_;
775
776 // Is the local defined and live.
777 bool is_live_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700778
779 private:
780 DISALLOW_COPY_AND_ASSIGN(LocalInfo);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700781 };
782
783 struct LineNumFromPcContext {
784 LineNumFromPcContext(uint32_t address, uint32_t line_num) :
785 address_(address), line_num_(line_num) {}
786 uint32_t address_;
787 uint32_t line_num_;
Brian Carlstromd2fbb2b2011-08-23 11:57:08 -0700788 private:
789 DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700790 };
791
Brian Carlstrom78128a62011-09-15 17:21:19 -0700792 void InvokeLocalCbIfLive(void* cnxt, int reg, uint32_t end_address,
793 LocalInfo* local_in_reg, DexDebugNewLocalCb local_cb) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700794 if (local_cb != NULL && local_in_reg[reg].is_live_) {
795 local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
796 local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
797 local_in_reg[reg].signature_);
798 }
799 }
800
801 // Determine the source file line number based on the program counter.
802 // "pc" is an offset, in 16-bit units, from the start of the method's code.
803 //
804 // Returns -1 if no match was found (possibly because the source files were
805 // compiled without "-g", so no line number information is present).
806 // Returns -2 for native methods (as expected in exception traces).
807 //
808 // This is used by runtime; therefore use art::Method not art::DexFile::Method.
809 int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
810
811 void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
812 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
813 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
814
815 void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method *method,
816 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
817 void* cnxt) const {
818 const byte* stream = dexGetDebugInfoStream(code_item);
819 LocalInfo local_in_reg[code_item->registers_size_];
820
821 if (stream != NULL) {
822 dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
823 }
824 for (int reg = 0; reg < code_item->registers_size_; reg++) {
825 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_, local_in_reg, local_cb);
826 }
827 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700828
829 // TODO: const reference
830 uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
831 CHECK_GE(class_def, class_defs_);
832 CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
833 return class_def - class_defs_;
834 }
835
836 const char* dexGetSourceFile(const ClassDef& class_def) const {
837 if (class_def.source_file_idx_ == 0xffffffff) {
838 return NULL;
839 } else {
840 return dexStringById(class_def.source_file_idx_);
841 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700842 }
843
jeffhaob4df5142011-09-19 20:25:32 -0700844 void ChangePermissions(int prot) const;
845
Carl Shapiro1fb86202011-06-27 17:43:13 -0700846 private:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700847 // Helper class to deallocate underlying storage.
848 class Closer {
849 public:
850 virtual ~Closer();
jeffhaob4df5142011-09-19 20:25:32 -0700851 virtual void ChangePermissions(int prot) = 0;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700852 };
853
854 // Helper class to deallocate mmap-backed .dex files.
855 class MmapCloser : public Closer {
856 public:
857 MmapCloser(void* addr, size_t length);
858 virtual ~MmapCloser();
jeffhaob4df5142011-09-19 20:25:32 -0700859 virtual void ChangePermissions(int prot);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700860 private:
861 void* addr_;
862 size_t length_;
863 };
864
865 // Helper class for deallocating new/delete-backed .dex files.
866 class PtrCloser : public Closer {
867 public:
868 PtrCloser(byte* addr);
869 virtual ~PtrCloser();
jeffhaob4df5142011-09-19 20:25:32 -0700870 virtual void ChangePermissions(int prot);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700871 private:
872 byte* addr_;
873 };
874
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700875 // Opens a .dex file at the given address.
876 static const DexFile* Open(const byte* dex_file,
877 size_t length,
878 const std::string& location,
879 Closer* closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700880
Brian Carlstroma663ea52011-08-19 23:33:41 -0700881 DexFile(const byte* addr, size_t length, const std::string& location, Closer* closer)
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700882 : base_(addr),
883 length_(length),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700884 location_(location),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700885 closer_(closer),
Jesse Wilson6bf19152011-09-29 13:12:33 -0400886 dex_object_lock_("a dex_object_lock_"),
887 dex_object_(NULL),
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700888 header_(0),
889 string_ids_(0),
890 type_ids_(0),
891 field_ids_(0),
892 method_ids_(0),
893 proto_ids_(0),
Brian Carlstroma663ea52011-08-19 23:33:41 -0700894 class_defs_(0) {
895 CHECK(addr != NULL);
896 CHECK_GT(length, 0U);
897 CHECK(closer != NULL);
898 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700899
900 // Top-level initializer that calls other Init methods.
901 bool Init();
902
903 // Caches pointers into to the various file sections.
904 void InitMembers();
905
906 // Builds the index of descriptors to class definitions.
907 void InitIndex();
908
909 // Returns true if the byte string equals the magic value.
910 bool CheckMagic(const byte* magic);
911
912 // Returns true if the header magic is of the expected value.
913 bool IsMagicValid();
914
Brian Carlstrome24fa612011-09-29 00:53:55 -0700915 // The index of descriptors to class definition indexes.
916 typedef std::map<const StringPiece, uint32_t> Index;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700917 Index index_;
918
919 // The base address of the memory mapping.
920 const byte* base_;
921
922 // The size of the underlying memory allocation in bytes.
923 size_t length_;
924
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700925 // Typically the dex file name when available, alternatively some identifying string.
Brian Carlstroma663ea52011-08-19 23:33:41 -0700926 //
927 // The ClassLinker will use this to match DexFiles the boot class
928 // path to DexCache::GetLocation when loading from an image.
929 const std::string location_;
930
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700931 // Helper object to free the underlying allocation.
Elliott Hughes90a33692011-08-30 13:27:07 -0700932 UniquePtr<Closer> closer_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700933
Jesse Wilson6bf19152011-09-29 13:12:33 -0400934 // A cached com.android.dex.Dex instance, possibly NULL. Use GetDexObject.
935 mutable Mutex dex_object_lock_;
936 mutable jobject dex_object_;
937
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700938 // Points to the header section.
939 const Header* header_;
940
941 // Points to the base of the string identifier list.
942 const StringId* string_ids_;
943
944 // Points to the base of the type identifier list.
945 const TypeId* type_ids_;
946
947 // Points to the base of the field identifier list.
948 const FieldId* field_ids_;
949
950 // Points to the base of the method identifier list.
951 const MethodId* method_ids_;
952
953 // Points to the base of the prototype identifier list.
954 const ProtoId* proto_ids_;
955
956 // Points to the base of the class definition list.
957 const ClassDef* class_defs_;
Carl Shapiro1fb86202011-06-27 17:43:13 -0700958};
959
960} // namespace art
961
962#endif // ART_SRC_DEX_FILE_H_