blob: 81a60fc2860ba563a7fd89283cbda1e7a9f00d23 [file] [log] [blame]
Carl Shapiro1fb86202011-06-27 17:43:13 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "dex_file.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07004
5#include <fcntl.h>
Brian Carlstrom1f870082011-08-23 16:02:11 -07006#include <limits.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -07007#include <stdio.h>
Ian Rogersd81871c2011-10-03 13:57:23 -07008#include <stdlib.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07009#include <string.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070010#include <sys/file.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070011#include <sys/mman.h>
12#include <sys/stat.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070013
Elliott Hughes90a33692011-08-30 13:27:07 -070014#include <map>
15
16#include "UniquePtr.h"
Ian Rogers0571d352011-11-03 19:51:38 -070017#include "class_linker.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070018#include "globals.h"
Ian Rogers0571d352011-11-03 19:51:38 -070019#include "leb128.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "logging.h"
21#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070022#include "os.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070023#include "stringprintf.h"
24#include "thread.h"
Ian Rogers0571d352011-11-03 19:51:38 -070025#include "utf.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070027#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070028
29namespace art {
30
Brian Carlstromf615a612011-07-23 12:50:34 -070031const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
32const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070033
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070034DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070035 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070036 for (size_t i = 0; i != class_path.size(); ++i) {
37 const DexFile* dex_file = class_path[i];
38 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
39 if (dex_class_def != NULL) {
40 return ClassPathEntry(dex_file, dex_class_def);
41 }
42 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070043 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070044 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
45 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070046}
47
Brian Carlstromae826982011-11-09 01:33:42 -080048void DexFile::OpenDexFiles(const std::vector<const char*>& dex_filenames,
Brian Carlstrom78128a62011-09-15 17:21:19 -070049 std::vector<const DexFile*>& dex_files,
50 const std::string& strip_location_prefix) {
51 for (size_t i = 0; i < dex_filenames.size(); i++) {
52 const char* dex_filename = dex_filenames[i];
53 const DexFile* dex_file = Open(dex_filename, strip_location_prefix);
54 if (dex_file == NULL) {
55 fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
56 exit(EXIT_FAILURE);
57 }
58 dex_files.push_back(dex_file);
59 }
60}
61
Brian Carlstrom16192862011-09-12 17:50:06 -070062const DexFile* DexFile::Open(const std::string& filename,
63 const std::string& strip_location_prefix) {
jeffhao262bf462011-10-20 18:36:32 -070064 if (IsValidZipFilename(filename)) {
Brian Carlstrom16192862011-09-12 17:50:06 -070065 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070066 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -070067 if (!IsValidDexFilename(filename)) {
68 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
69 }
70 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070071}
72
jeffhaob4df5142011-09-19 20:25:32 -070073void DexFile::ChangePermissions(int prot) const {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070074 if (mprotect(mem_map_->GetAddress(), mem_map_->GetLength(), prot) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -080075 PLOG(FATAL) << "Failed to change dex file permissions to " << prot << " for " << GetLocation();
jeffhaob4df5142011-09-19 20:25:32 -070076 }
77}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070078
Brian Carlstrom89521892011-12-07 22:05:07 -080079const std::string StripLocationPrefix(const std::string& original_location,
80 const std::string& strip_location_prefix) {
81 StringPiece location = original_location;
82 if (!location.starts_with(strip_location_prefix)) {
83 LOG(ERROR) << location << " does not start with " << strip_location_prefix;
84 return "";
85 }
86 location.remove_prefix(strip_location_prefix.size());
87 return location.ToString();
88}
89
Brian Carlstrom16192862011-09-12 17:50:06 -070090const DexFile* DexFile::OpenFile(const std::string& filename,
91 const std::string& original_location,
92 const std::string& strip_location_prefix) {
Brian Carlstrom89521892011-12-07 22:05:07 -080093 std::string location(StripLocationPrefix(original_location, strip_location_prefix));
94 if (location.empty()) {
Brian Carlstrom16192862011-09-12 17:50:06 -070095 return NULL;
96 }
Brian Carlstrom89521892011-12-07 22:05:07 -080097
Brian Carlstromb0460ea2011-07-29 10:08:05 -070098 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070099 if (fd == -1) {
100 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
101 return NULL;
102 }
103 struct stat sbuf;
104 memset(&sbuf, 0, sizeof(sbuf));
105 if (fstat(fd, &sbuf) == -1) {
106 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
107 close(fd);
108 return NULL;
109 }
110 size_t length = sbuf.st_size;
Brian Carlstrom89521892011-12-07 22:05:07 -0800111 UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0));
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700112 if (map.get() == NULL) {
113 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700114 close(fd);
115 return NULL;
116 }
117 close(fd);
Brian Carlstrom89521892011-12-07 22:05:07 -0800118 return OpenMemory(location, map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700119}
120
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700121const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700122
123class LockedFd {
124 public:
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700125 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700126 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
127 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700128 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700129 return NULL;
130 }
131 fchmod(fd, mode);
132
133 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
134 int result = flock(fd, LOCK_EX | LOCK_NB);
135 if (result == -1) {
136 LOG(WARNING) << "sleeping while locking file " << name;
137 result = flock(fd, LOCK_EX);
138 }
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700139 if (result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700140 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700141 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700142 return NULL;
143 }
144 return new LockedFd(fd);
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700145 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700146
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700147 int GetFd() const {
148 return fd_;
149 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700150
151 ~LockedFd() {
152 if (fd_ != -1) {
153 int result = flock(fd_, LOCK_UN);
154 if (result == -1) {
155 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
156 }
157 close(fd_);
158 }
159 }
160
161 private:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700162 explicit LockedFd(int fd) : fd_(fd) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700163
164 int fd_;
165};
166
167class TmpFile {
168 public:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700169 explicit TmpFile(const std::string& name) : name_(name) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700170 ~TmpFile() {
171 unlink(name_.c_str());
172 }
173 private:
174 const std::string name_;
175};
176
177// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700178const DexFile* DexFile::OpenZip(const std::string& filename,
179 const std::string& strip_location_prefix) {
Brian Carlstrom89521892011-12-07 22:05:07 -0800180 std::string location(StripLocationPrefix(filename, strip_location_prefix));
181 if (location.empty()) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700182 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700183 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700184
Elliott Hughes90a33692011-08-30 13:27:07 -0700185 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
186 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700187 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700188 return NULL;
189 }
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800190 return DexFile::Open(*zip_archive.get(), location);
191}
192
193const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
194 UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
Elliott Hughes90a33692011-08-30 13:27:07 -0700195 if (zip_entry.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800196 LOG(ERROR) << "Failed to find classes.dex within " << location;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700197 return NULL;
198 }
199
Brian Carlstrom89521892011-12-07 22:05:07 -0800200 uint32_t length = zip_entry->GetUncompressedLength();
201 UniquePtr<MemMap> map(MemMap::MapAnonymous("classes.dex extracted in memory",
202 NULL,
203 length,
204 PROT_READ | PROT_WRITE));
205 if (map.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800206 LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
Brian Carlstrom89521892011-12-07 22:05:07 -0800207 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700208 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800209
210 // Extract classes.dex
211 bool success = zip_entry->ExtractToMemory(*map.get());
212 if (!success) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800213 LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
Brian Carlstrom89521892011-12-07 22:05:07 -0800214 return NULL;
215 }
216
217 return OpenMemory(location, map.release());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700218}
219
Brian Carlstrom89521892011-12-07 22:05:07 -0800220const DexFile* DexFile::OpenMemory(const byte* base,
221 size_t length,
222 const std::string& location,
223 MemMap* mem_map) {
224 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
225 UniquePtr<DexFile> dex_file(new DexFile(base, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700226 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700227 return NULL;
228 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700229 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700230 }
231}
232
Jesse Wilson6bf19152011-09-29 13:12:33 -0400233DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700234 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
235 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
236 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
237 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400238}
239
240jobject DexFile::GetDexObject(JNIEnv* env) const {
241 MutexLock mu(dex_object_lock_);
242 if (dex_object_ != NULL) {
243 return dex_object_;
244 }
245
246 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
247 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
248 if (byte_buffer == NULL) {
249 return NULL;
250 }
251
252 jclass c = env->FindClass("com/android/dex/Dex");
253 if (c == NULL) {
254 return NULL;
255 }
256
257 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
258 if (mid == NULL) {
259 return NULL;
260 }
261
262 jvalue args[1];
263 args[0].l = byte_buffer;
264 jobject local = env->CallStaticObjectMethodA(c, mid, args);
265 if (local == NULL) {
266 return NULL;
267 }
268
269 dex_object_ = env->NewGlobalRef(local);
270 return dex_object_;
271}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700272
Brian Carlstromf615a612011-07-23 12:50:34 -0700273bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700274 InitMembers();
275 if (!IsMagicValid()) {
276 return false;
277 }
278 InitIndex();
279 return true;
280}
281
Brian Carlstromf615a612011-07-23 12:50:34 -0700282void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700283 const byte* b = base_;
284 header_ = reinterpret_cast<const Header*>(b);
285 const Header* h = header_;
286 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
287 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
288 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
289 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
290 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
291 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
Brian Carlstrom89521892011-12-07 22:05:07 -0800292 DCHECK_EQ(length_, header_->file_size_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700293}
294
Brian Carlstromf615a612011-07-23 12:50:34 -0700295bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700296 return CheckMagic(header_->magic_);
297}
298
Brian Carlstromf615a612011-07-23 12:50:34 -0700299bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800300 CHECK(magic != NULL) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700301 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800302 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700303 << " " << magic[0]
304 << " " << magic[1]
305 << " " << magic[2]
306 << " " << magic[3];
307 return false;
308 }
309 const byte* version = &magic[sizeof(kDexMagic)];
310 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800311 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700312 << " " << version[0]
313 << " " << version[1]
314 << " " << version[2]
315 << " " << version[3];
316 return false;
317 }
318 return true;
319}
320
Ian Rogersd81871c2011-10-03 13:57:23 -0700321uint32_t DexFile::GetVersion() const {
322 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
323 return atoi(version);
324}
325
Ian Rogers0571d352011-11-03 19:51:38 -0700326int32_t DexFile::GetStringLength(const StringId& string_id) const {
327 const byte* ptr = base_ + string_id.string_data_off_;
328 return DecodeUnsignedLeb128(&ptr);
329}
330
331// Returns a pointer to the UTF-8 string data referred to by the given string_id.
332const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800333 CHECK(length != NULL) << GetLocation();
Ian Rogers0571d352011-11-03 19:51:38 -0700334 const byte* ptr = base_ + string_id.string_data_off_;
335 *length = DecodeUnsignedLeb128(&ptr);
336 return reinterpret_cast<const char*>(ptr);
337}
338
Brian Carlstromf615a612011-07-23 12:50:34 -0700339void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800340 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700341 for (size_t i = 0; i < NumClassDefs(); ++i) {
342 const ClassDef& class_def = GetClassDef(i);
343 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700344 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700345 }
346}
347
Brian Carlstrome24fa612011-09-29 00:53:55 -0700348bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700349 Index::const_iterator it = index_.find(descriptor);
350 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700351 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700352 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700353 idx = it->second;
354 return true;
355}
356
357const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
358 uint32_t idx;
359 if (FindClassDefIndex(descriptor, idx)) {
360 return &GetClassDef(idx);
361 }
362 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700363}
364
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800365const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
366 const DexFile::StringId& name,
367 const DexFile::TypeId& type) const {
368 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
369 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
370 const uint32_t name_idx = GetIndexForStringId(name);
371 const uint16_t type_idx = GetIndexForTypeId(type);
372 uint32_t lo = 0;
373 uint32_t hi = NumFieldIds() - 1;
374 while (hi >= lo) {
375 uint32_t mid = (hi + lo) / 2;
376 const DexFile::FieldId& field = GetFieldId(mid);
377 if (class_idx > field.class_idx_) {
378 lo = mid + 1;
379 } else if (class_idx < field.class_idx_) {
380 hi = mid - 1;
381 } else {
382 if (name_idx > field.name_idx_) {
383 lo = mid + 1;
384 } else if (name_idx < field.name_idx_) {
385 hi = mid - 1;
386 } else {
387 if (type_idx > field.type_idx_) {
388 lo = mid + 1;
389 } else if (type_idx < field.type_idx_) {
390 hi = mid - 1;
391 } else {
392 return &field;
393 }
394 }
395 }
396 }
397 return NULL;
398}
399
400const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700401 const DexFile::StringId& name,
402 const DexFile::ProtoId& signature) const {
403 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800404 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700405 const uint32_t name_idx = GetIndexForStringId(name);
406 const uint16_t proto_idx = GetIndexForProtoId(signature);
407 uint32_t lo = 0;
408 uint32_t hi = NumMethodIds() - 1;
409 while (hi >= lo) {
410 uint32_t mid = (hi + lo) / 2;
411 const DexFile::MethodId& method = GetMethodId(mid);
412 if (class_idx > method.class_idx_) {
413 lo = mid + 1;
414 } else if (class_idx < method.class_idx_) {
415 hi = mid - 1;
416 } else {
417 if (name_idx > method.name_idx_) {
418 lo = mid + 1;
419 } else if (name_idx < method.name_idx_) {
420 hi = mid - 1;
421 } else {
422 if (proto_idx > method.proto_idx_) {
423 lo = mid + 1;
424 } else if (proto_idx < method.proto_idx_) {
425 hi = mid - 1;
426 } else {
427 return &method;
428 }
429 }
430 }
431 }
432 return NULL;
433}
434
435const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
436 uint32_t lo = 0;
437 uint32_t hi = NumStringIds() - 1;
438 while (hi >= lo) {
439 uint32_t mid = (hi + lo) / 2;
440 int32_t length;
441 const DexFile::StringId& str_id = GetStringId(mid);
442 const char* str = GetStringDataAndLength(str_id, &length);
443 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
444 if (compare > 0) {
445 lo = mid + 1;
446 } else if (compare < 0) {
447 hi = mid - 1;
448 } else {
449 return &str_id;
450 }
451 }
452 return NULL;
453}
454
455const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
456 uint32_t lo = 0;
457 uint32_t hi = NumTypeIds() - 1;
458 while (hi >= lo) {
459 uint32_t mid = (hi + lo) / 2;
460 const TypeId& type_id = GetTypeId(mid);
461 if (string_idx > type_id.descriptor_idx_) {
462 lo = mid + 1;
463 } else if (string_idx < type_id.descriptor_idx_) {
464 hi = mid - 1;
465 } else {
466 return &type_id;
467 }
468 }
469 return NULL;
470}
471
472const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800473 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700474 uint32_t lo = 0;
475 uint32_t hi = NumProtoIds() - 1;
476 while (hi >= lo) {
477 uint32_t mid = (hi + lo) / 2;
478 const DexFile::ProtoId& proto = GetProtoId(mid);
479 int compare = return_type_idx - proto.return_type_idx_;
480 if (compare == 0) {
481 DexFileParameterIterator it(*this, proto);
482 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800483 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
484 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700485 it.Next();
486 i++;
487 }
488 if (compare == 0) {
489 if (it.HasNext()) {
490 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800491 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700492 compare = 1;
493 }
494 }
495 }
496 if (compare > 0) {
497 lo = mid + 1;
498 } else if (compare < 0) {
499 hi = mid - 1;
500 } else {
501 return &proto;
502 }
503 }
504 return NULL;
505}
506
507// Given a signature place the type ids into the given vector
508bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
509 const std::string& signature) const {
510 if (signature[0] != '(') {
511 return false;
512 }
513 size_t offset = 1;
514 size_t end = signature.size();
515 bool process_return = false;
516 while (offset < end) {
517 char c = signature[offset];
518 offset++;
519 if (c == ')') {
520 process_return = true;
521 continue;
522 }
523 std::string descriptor;
524 descriptor += c;
525 while (c == '[') { // process array prefix
526 if (offset >= end) { // expect some descriptor following [
527 return false;
528 }
529 c = signature[offset];
530 offset++;
531 descriptor += c;
532 }
533 if (c == 'L') { // process type descriptors
534 do {
535 if (offset >= end) { // unexpected early termination of descriptor
536 return false;
537 }
538 c = signature[offset];
539 offset++;
540 descriptor += c;
541 } while (c != ';');
542 }
543 const DexFile::StringId* string_id = FindStringId(descriptor);
544 if (string_id == NULL) {
545 return false;
546 }
547 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
548 if (type_id == NULL) {
549 return false;
550 }
551 uint16_t type_idx = GetIndexForTypeId(*type_id);
552 if (!process_return) {
553 param_type_idxs->push_back(type_idx);
554 } else {
555 *return_type_idx = type_idx;
556 return offset == end; // return true if the signature had reached a sensible end
557 }
558 }
559 return false; // failed to correctly parse return type
560}
561
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700562// Materializes the method descriptor for a method prototype. Method
563// descriptors are not stored directly in the dex file. Instead, one
564// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700565std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700566 const ProtoId& proto_id = GetProtoId(proto_idx);
567 std::string descriptor;
568 descriptor.push_back('(');
569 const TypeList* type_list = GetProtoParameters(proto_id);
570 size_t parameter_length = 0;
571 if (type_list != NULL) {
572 // A non-zero number of arguments. Append the type names.
573 for (size_t i = 0; i < type_list->Size(); ++i) {
574 const TypeItem& type_item = type_list->GetTypeItem(i);
575 uint32_t type_idx = type_item.type_idx_;
576 int32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700577 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700578 parameter_length += type_length;
579 descriptor.append(name);
580 }
581 }
582 descriptor.push_back(')');
583 uint32_t return_type_idx = proto_id.return_type_idx_;
584 int32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700585 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700586 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700587 if (unicode_length != NULL) {
588 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
589 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700590 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700591}
592
Carl Shapiro1fb86202011-06-27 17:43:13 -0700593
Shih-wei Liao195487c2011-08-20 13:29:04 -0700594int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700595 // For native method, lineno should be -2 to indicate it is native. Note that
596 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700597 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700598 return -2;
599 }
600
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700601 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800602 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700603
604 // A method with no line number info should return -1
605 LineNumFromPcContext context(rel_pc, -1);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800606 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
607 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700608 return context.line_num_;
609}
610
Ian Rogers0571d352011-11-03 19:51:38 -0700611int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
612 uint32_t address){
613 // Note: Signed type is important for max and min.
614 int32_t min = 0;
615 int32_t max = tries_size - 1;
616
617 while (max >= min) {
618 int32_t mid = (min + max) / 2;
619 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
620 uint32_t start = pTry->start_addr_;
621 if (address < start) {
622 max = mid - 1;
623 } else {
624 uint32_t end = start + pTry->insn_count_;
625 if (address >= end) {
626 min = mid + 1;
627 } else { // We have a winner!
628 return (int32_t) pTry->handler_off_;
629 }
630 }
631 }
632 // No match.
633 return -1;
634}
635
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800636void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700637 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
638 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700639 uint32_t line = DecodeUnsignedLeb128(&stream);
640 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
641 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
642 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700643 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700644
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800645 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700646 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800647 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700648 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800649 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800650 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700651 local_in_reg[arg_reg].start_address_ = 0;
652 local_in_reg[arg_reg].is_live_ = true;
653 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700654 arg_reg++;
655 }
656
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800657 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700658 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700659 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700660 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800661 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700662 return;
663 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800664 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700665 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800666 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700667 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700668 local_in_reg[arg_reg].name_ = name;
669 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800670 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700671 local_in_reg[arg_reg].start_address_ = address;
672 local_in_reg[arg_reg].is_live_ = true;
673 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700674 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700675 case 'D':
676 case 'J':
677 arg_reg += 2;
678 break;
679 default:
680 arg_reg += 1;
681 break;
682 }
683 }
684
Ian Rogers0571d352011-11-03 19:51:38 -0700685 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800686 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700687 return;
688 }
689
690 for (;;) {
691 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700692 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700693 uint16_t name_idx;
694 uint16_t descriptor_idx;
695 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700696
Shih-wei Liao195487c2011-08-20 13:29:04 -0700697 switch (opcode) {
698 case DBG_END_SEQUENCE:
699 return;
700
701 case DBG_ADVANCE_PC:
702 address += DecodeUnsignedLeb128(&stream);
703 break;
704
705 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700706 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700707 break;
708
709 case DBG_START_LOCAL:
710 case DBG_START_LOCAL_EXTENDED:
711 reg = DecodeUnsignedLeb128(&stream);
712 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700713 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800714 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700715 return;
716 }
717
jeffhaof8728872011-10-28 19:11:13 -0700718 name_idx = DecodeUnsignedLeb128P1(&stream);
719 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
720 if (opcode == DBG_START_LOCAL_EXTENDED) {
721 signature_idx = DecodeUnsignedLeb128P1(&stream);
722 }
723
Shih-wei Liao195487c2011-08-20 13:29:04 -0700724 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700725 if (need_locals) {
726 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700727
Ian Rogers0571d352011-11-03 19:51:38 -0700728 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
729 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700730 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700731 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700732 }
733 local_in_reg[reg].start_address_ = address;
734 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700735 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736 break;
737
738 case DBG_END_LOCAL:
739 reg = DecodeUnsignedLeb128(&stream);
740 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700741 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800742 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700743 return;
744 }
745
Elliott Hughes30646832011-10-13 16:59:46 -0700746 if (need_locals) {
747 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
748 local_in_reg[reg].is_live_ = false;
749 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700750 break;
751
752 case DBG_RESTART_LOCAL:
753 reg = DecodeUnsignedLeb128(&stream);
754 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700755 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800756 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700757 return;
758 }
759
Elliott Hughes30646832011-10-13 16:59:46 -0700760 if (need_locals) {
761 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800762 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700763 return;
764 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700765
Elliott Hughes30646832011-10-13 16:59:46 -0700766 // If the register is live, the "restart" is superfluous,
767 // and we don't want to mess with the existing start address.
768 if (!local_in_reg[reg].is_live_) {
769 local_in_reg[reg].start_address_ = address;
770 local_in_reg[reg].is_live_ = true;
771 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700772 }
773 break;
774
775 case DBG_SET_PROLOGUE_END:
776 case DBG_SET_EPILOGUE_BEGIN:
777 case DBG_SET_FILE:
778 break;
779
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700780 default: {
781 int adjopcode = opcode - DBG_FIRST_SPECIAL;
782
Shih-wei Liao195487c2011-08-20 13:29:04 -0700783 address += adjopcode / DBG_LINE_RANGE;
784 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
785
786 if (posCb != NULL) {
787 if (posCb(cnxt, address, line)) {
788 // early exit
789 return;
790 }
791 }
792 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700793 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700794 }
795 }
796}
797
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800798void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700799 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
800 void* cnxt) const {
801 const byte* stream = GetDebugInfoStream(code_item);
802 LocalInfo local_in_reg[code_item->registers_size_];
803
804 if (stream != NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800805 DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
Ian Rogers0571d352011-11-03 19:51:38 -0700806 }
807 for (int reg = 0; reg < code_item->registers_size_; reg++) {
808 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
809 }
810}
811
812bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
813 LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
814
815 // We know that this callback will be called in
816 // ascending address order, so keep going until we find
817 // a match or we've just gone past it.
818 if (address > context->address_) {
819 // The line number from the previous positions callback
820 // wil be the final result.
821 return true;
822 } else {
823 context->line_num_ = line_num;
824 return address == context->address_;
825 }
826}
827
828// Decodes the header section from the class data bytes.
829void ClassDataItemIterator::ReadClassDataHeader() {
830 CHECK(ptr_pos_ != NULL);
831 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
832 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
833 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
834 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
835}
836
837void ClassDataItemIterator::ReadClassDataField() {
838 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
839 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
840}
841
842void ClassDataItemIterator::ReadClassDataMethod() {
843 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
844 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
845 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
846}
847
848// Read a signed integer. "zwidth" is the zero-based byte count.
849static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
850 int32_t val = 0;
851 for (int i = zwidth; i >= 0; --i) {
852 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
853 }
854 val >>= (3 - zwidth) * 8;
855 return val;
856}
857
858// Read an unsigned integer. "zwidth" is the zero-based byte count,
859// "fill_on_right" indicates which side we want to zero-fill from.
860static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
861 uint32_t val = 0;
862 if (!fill_on_right) {
863 for (int i = zwidth; i >= 0; --i) {
864 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
865 }
866 val >>= (3 - zwidth) * 8;
867 } else {
868 for (int i = zwidth; i >= 0; --i) {
869 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
870 }
871 }
872 return val;
873}
874
875// Read a signed long. "zwidth" is the zero-based byte count.
876static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
877 int64_t val = 0;
878 for (int i = zwidth; i >= 0; --i) {
879 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
880 }
881 val >>= (7 - zwidth) * 8;
882 return val;
883}
884
885// Read an unsigned long. "zwidth" is the zero-based byte count,
886// "fill_on_right" indicates which side we want to zero-fill from.
887static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
888 uint64_t val = 0;
889 if (!fill_on_right) {
890 for (int i = zwidth; i >= 0; --i) {
891 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
892 }
893 val >>= (7 - zwidth) * 8;
894 } else {
895 for (int i = zwidth; i >= 0; --i) {
896 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
897 }
898 }
899 return val;
900}
901
902EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
903 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
904 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
905 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
906 if (ptr_ == NULL) {
907 array_size_ = 0;
908 } else {
909 array_size_ = DecodeUnsignedLeb128(&ptr_);
910 }
911 if (array_size_ > 0) {
912 Next();
913 }
914}
915
916void EncodedStaticFieldValueIterator::Next() {
917 pos_++;
918 if (pos_ >= array_size_) {
919 return;
920 }
921 byte value_type = *ptr_++;
922 byte value_arg = value_type >> kEncodedValueArgShift;
923 size_t width = value_arg + 1; // assume and correct later
924 type_ = value_type & kEncodedValueTypeMask;
925 switch (type_) {
926 case kBoolean:
927 jval_.i = (value_arg != 0) ? 1 : 0;
928 width = 0;
929 break;
930 case kByte:
931 jval_.i = ReadSignedInt(ptr_, value_arg);
932 CHECK(IsInt(8, jval_.i));
933 break;
934 case kShort:
935 jval_.i = ReadSignedInt(ptr_, value_arg);
936 CHECK(IsInt(16, jval_.i));
937 break;
938 case kChar:
939 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
940 CHECK(IsUint(16, jval_.i));
941 break;
942 case kInt:
943 jval_.i = ReadSignedInt(ptr_, value_arg);
944 break;
945 case kLong:
946 jval_.j = ReadSignedLong(ptr_, value_arg);
947 break;
948 case kFloat:
949 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
950 break;
951 case kDouble:
952 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
953 break;
954 case kString:
955 case kType:
956 case kMethod:
957 case kEnum:
958 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
959 break;
960 case kField:
961 case kArray:
962 case kAnnotation:
963 UNIMPLEMENTED(FATAL) << ": type " << type_;
964 break;
965 case kNull:
966 jval_.l = NULL;
967 width = 0;
968 break;
969 default:
970 LOG(FATAL) << "Unreached";
971 }
972 ptr_ += width;
973}
974
975void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
976 switch (type_) {
977 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
978 case kByte: field->SetByte(NULL, jval_.b); break;
979 case kShort: field->SetShort(NULL, jval_.s); break;
980 case kChar: field->SetChar(NULL, jval_.c); break;
981 case kInt: field->SetInt(NULL, jval_.i); break;
982 case kLong: field->SetLong(NULL, jval_.j); break;
983 case kFloat: field->SetFloat(NULL, jval_.f); break;
984 case kDouble: field->SetDouble(NULL, jval_.d); break;
985 case kNull: field->SetObject(NULL, NULL); break;
986 case kString: {
987 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
988 field->SetObject(NULL, resolved);
989 break;
990 }
991 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
992 }
993}
994
995CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
996 handler_.address_ = -1;
997 int32_t offset = -1;
998
999 // Short-circuit the overwhelmingly common cases.
1000 switch (code_item.tries_size_) {
1001 case 0:
1002 break;
1003 case 1: {
1004 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1005 uint32_t start = tries->start_addr_;
1006 if (address >= start) {
1007 uint32_t end = start + tries->insn_count_;
1008 if (address < end) {
1009 offset = tries->handler_off_;
1010 }
1011 }
1012 break;
1013 }
1014 default:
1015 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1016 }
1017 if (offset >= 0) {
1018 const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
1019 Init(handler_data);
1020 } else {
1021 // Not found, initialize as empty
1022 current_data_ = NULL;
1023 remaining_count_ = -1;
1024 catch_all_ = false;
1025 DCHECK(!HasNext());
1026 }
1027}
1028
1029void CatchHandlerIterator::Init(const byte* handler_data) {
1030 current_data_ = handler_data;
1031 remaining_count_ = DecodeSignedLeb128(&current_data_);
1032
1033 // If remaining_count_ is non-positive, then it is the negative of
1034 // the number of catch types, and the catches are followed by a
1035 // catch-all handler.
1036 if (remaining_count_ <= 0) {
1037 catch_all_ = true;
1038 remaining_count_ = -remaining_count_;
1039 } else {
1040 catch_all_ = false;
1041 }
1042 Next();
1043}
1044
1045void CatchHandlerIterator::Next() {
1046 if (remaining_count_ > 0) {
1047 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1048 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1049 remaining_count_--;
1050 return;
1051 }
1052
1053 if (catch_all_) {
1054 handler_.type_idx_ = DexFile::kDexNoIndex16;
1055 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1056 catch_all_ = false;
1057 return;
1058 }
1059
1060 // no more handler
1061 remaining_count_ = -1;
1062}
1063
Carl Shapiro1fb86202011-06-27 17:43:13 -07001064} // namespace art