blob: a45455dc887e9c418bddfd0bc3acd9275052ec45 [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 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700190 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
191 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700192 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700193 return NULL;
194 }
195
Brian Carlstrom89521892011-12-07 22:05:07 -0800196 uint32_t length = zip_entry->GetUncompressedLength();
197 UniquePtr<MemMap> map(MemMap::MapAnonymous("classes.dex extracted in memory",
198 NULL,
199 length,
200 PROT_READ | PROT_WRITE));
201 if (map.get() == NULL) {
202 LOG(ERROR) << "mmap classes.dex for \"" << filename << "\" failed";
203 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700204 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800205
206 // Extract classes.dex
207 bool success = zip_entry->ExtractToMemory(*map.get());
208 if (!success) {
209 LOG(ERROR) << "Failed to extract classes.dex from '" << filename << "' to memory";
210 return NULL;
211 }
212
213 return OpenMemory(location, map.release());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700214}
215
Brian Carlstrom89521892011-12-07 22:05:07 -0800216const DexFile* DexFile::OpenMemory(const byte* base,
217 size_t length,
218 const std::string& location,
219 MemMap* mem_map) {
220 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
221 UniquePtr<DexFile> dex_file(new DexFile(base, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700222 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700223 return NULL;
224 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700225 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700226 }
227}
228
Jesse Wilson6bf19152011-09-29 13:12:33 -0400229DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700230 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
231 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
232 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
233 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400234}
235
236jobject DexFile::GetDexObject(JNIEnv* env) const {
237 MutexLock mu(dex_object_lock_);
238 if (dex_object_ != NULL) {
239 return dex_object_;
240 }
241
242 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
243 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
244 if (byte_buffer == NULL) {
245 return NULL;
246 }
247
248 jclass c = env->FindClass("com/android/dex/Dex");
249 if (c == NULL) {
250 return NULL;
251 }
252
253 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
254 if (mid == NULL) {
255 return NULL;
256 }
257
258 jvalue args[1];
259 args[0].l = byte_buffer;
260 jobject local = env->CallStaticObjectMethodA(c, mid, args);
261 if (local == NULL) {
262 return NULL;
263 }
264
265 dex_object_ = env->NewGlobalRef(local);
266 return dex_object_;
267}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700268
Brian Carlstromf615a612011-07-23 12:50:34 -0700269bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700270 InitMembers();
271 if (!IsMagicValid()) {
272 return false;
273 }
274 InitIndex();
275 return true;
276}
277
Brian Carlstromf615a612011-07-23 12:50:34 -0700278void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700279 const byte* b = base_;
280 header_ = reinterpret_cast<const Header*>(b);
281 const Header* h = header_;
282 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
283 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
284 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
285 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
286 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
287 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
Brian Carlstrom89521892011-12-07 22:05:07 -0800288 DCHECK_EQ(length_, header_->file_size_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700289}
290
Brian Carlstromf615a612011-07-23 12:50:34 -0700291bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700292 return CheckMagic(header_->magic_);
293}
294
Brian Carlstromf615a612011-07-23 12:50:34 -0700295bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800296 CHECK(magic != NULL) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700297 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800298 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700299 << " " << magic[0]
300 << " " << magic[1]
301 << " " << magic[2]
302 << " " << magic[3];
303 return false;
304 }
305 const byte* version = &magic[sizeof(kDexMagic)];
306 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800307 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700308 << " " << version[0]
309 << " " << version[1]
310 << " " << version[2]
311 << " " << version[3];
312 return false;
313 }
314 return true;
315}
316
Ian Rogersd81871c2011-10-03 13:57:23 -0700317uint32_t DexFile::GetVersion() const {
318 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
319 return atoi(version);
320}
321
Ian Rogers0571d352011-11-03 19:51:38 -0700322int32_t DexFile::GetStringLength(const StringId& string_id) const {
323 const byte* ptr = base_ + string_id.string_data_off_;
324 return DecodeUnsignedLeb128(&ptr);
325}
326
327// Returns a pointer to the UTF-8 string data referred to by the given string_id.
328const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800329 CHECK(length != NULL) << GetLocation();
Ian Rogers0571d352011-11-03 19:51:38 -0700330 const byte* ptr = base_ + string_id.string_data_off_;
331 *length = DecodeUnsignedLeb128(&ptr);
332 return reinterpret_cast<const char*>(ptr);
333}
334
Brian Carlstromf615a612011-07-23 12:50:34 -0700335void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800336 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700337 for (size_t i = 0; i < NumClassDefs(); ++i) {
338 const ClassDef& class_def = GetClassDef(i);
339 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700340 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700341 }
342}
343
Brian Carlstrome24fa612011-09-29 00:53:55 -0700344bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700345 Index::const_iterator it = index_.find(descriptor);
346 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700347 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700348 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700349 idx = it->second;
350 return true;
351}
352
353const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
354 uint32_t idx;
355 if (FindClassDefIndex(descriptor, idx)) {
356 return &GetClassDef(idx);
357 }
358 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700359}
360
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800361const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
362 const DexFile::StringId& name,
363 const DexFile::TypeId& type) const {
364 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
365 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
366 const uint32_t name_idx = GetIndexForStringId(name);
367 const uint16_t type_idx = GetIndexForTypeId(type);
368 uint32_t lo = 0;
369 uint32_t hi = NumFieldIds() - 1;
370 while (hi >= lo) {
371 uint32_t mid = (hi + lo) / 2;
372 const DexFile::FieldId& field = GetFieldId(mid);
373 if (class_idx > field.class_idx_) {
374 lo = mid + 1;
375 } else if (class_idx < field.class_idx_) {
376 hi = mid - 1;
377 } else {
378 if (name_idx > field.name_idx_) {
379 lo = mid + 1;
380 } else if (name_idx < field.name_idx_) {
381 hi = mid - 1;
382 } else {
383 if (type_idx > field.type_idx_) {
384 lo = mid + 1;
385 } else if (type_idx < field.type_idx_) {
386 hi = mid - 1;
387 } else {
388 return &field;
389 }
390 }
391 }
392 }
393 return NULL;
394}
395
396const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700397 const DexFile::StringId& name,
398 const DexFile::ProtoId& signature) const {
399 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800400 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700401 const uint32_t name_idx = GetIndexForStringId(name);
402 const uint16_t proto_idx = GetIndexForProtoId(signature);
403 uint32_t lo = 0;
404 uint32_t hi = NumMethodIds() - 1;
405 while (hi >= lo) {
406 uint32_t mid = (hi + lo) / 2;
407 const DexFile::MethodId& method = GetMethodId(mid);
408 if (class_idx > method.class_idx_) {
409 lo = mid + 1;
410 } else if (class_idx < method.class_idx_) {
411 hi = mid - 1;
412 } else {
413 if (name_idx > method.name_idx_) {
414 lo = mid + 1;
415 } else if (name_idx < method.name_idx_) {
416 hi = mid - 1;
417 } else {
418 if (proto_idx > method.proto_idx_) {
419 lo = mid + 1;
420 } else if (proto_idx < method.proto_idx_) {
421 hi = mid - 1;
422 } else {
423 return &method;
424 }
425 }
426 }
427 }
428 return NULL;
429}
430
431const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
432 uint32_t lo = 0;
433 uint32_t hi = NumStringIds() - 1;
434 while (hi >= lo) {
435 uint32_t mid = (hi + lo) / 2;
436 int32_t length;
437 const DexFile::StringId& str_id = GetStringId(mid);
438 const char* str = GetStringDataAndLength(str_id, &length);
439 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
440 if (compare > 0) {
441 lo = mid + 1;
442 } else if (compare < 0) {
443 hi = mid - 1;
444 } else {
445 return &str_id;
446 }
447 }
448 return NULL;
449}
450
451const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
452 uint32_t lo = 0;
453 uint32_t hi = NumTypeIds() - 1;
454 while (hi >= lo) {
455 uint32_t mid = (hi + lo) / 2;
456 const TypeId& type_id = GetTypeId(mid);
457 if (string_idx > type_id.descriptor_idx_) {
458 lo = mid + 1;
459 } else if (string_idx < type_id.descriptor_idx_) {
460 hi = mid - 1;
461 } else {
462 return &type_id;
463 }
464 }
465 return NULL;
466}
467
468const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800469 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700470 uint32_t lo = 0;
471 uint32_t hi = NumProtoIds() - 1;
472 while (hi >= lo) {
473 uint32_t mid = (hi + lo) / 2;
474 const DexFile::ProtoId& proto = GetProtoId(mid);
475 int compare = return_type_idx - proto.return_type_idx_;
476 if (compare == 0) {
477 DexFileParameterIterator it(*this, proto);
478 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800479 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
480 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700481 it.Next();
482 i++;
483 }
484 if (compare == 0) {
485 if (it.HasNext()) {
486 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800487 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700488 compare = 1;
489 }
490 }
491 }
492 if (compare > 0) {
493 lo = mid + 1;
494 } else if (compare < 0) {
495 hi = mid - 1;
496 } else {
497 return &proto;
498 }
499 }
500 return NULL;
501}
502
503// Given a signature place the type ids into the given vector
504bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
505 const std::string& signature) const {
506 if (signature[0] != '(') {
507 return false;
508 }
509 size_t offset = 1;
510 size_t end = signature.size();
511 bool process_return = false;
512 while (offset < end) {
513 char c = signature[offset];
514 offset++;
515 if (c == ')') {
516 process_return = true;
517 continue;
518 }
519 std::string descriptor;
520 descriptor += c;
521 while (c == '[') { // process array prefix
522 if (offset >= end) { // expect some descriptor following [
523 return false;
524 }
525 c = signature[offset];
526 offset++;
527 descriptor += c;
528 }
529 if (c == 'L') { // process type descriptors
530 do {
531 if (offset >= end) { // unexpected early termination of descriptor
532 return false;
533 }
534 c = signature[offset];
535 offset++;
536 descriptor += c;
537 } while (c != ';');
538 }
539 const DexFile::StringId* string_id = FindStringId(descriptor);
540 if (string_id == NULL) {
541 return false;
542 }
543 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
544 if (type_id == NULL) {
545 return false;
546 }
547 uint16_t type_idx = GetIndexForTypeId(*type_id);
548 if (!process_return) {
549 param_type_idxs->push_back(type_idx);
550 } else {
551 *return_type_idx = type_idx;
552 return offset == end; // return true if the signature had reached a sensible end
553 }
554 }
555 return false; // failed to correctly parse return type
556}
557
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700558// Materializes the method descriptor for a method prototype. Method
559// descriptors are not stored directly in the dex file. Instead, one
560// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700561std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700562 const ProtoId& proto_id = GetProtoId(proto_idx);
563 std::string descriptor;
564 descriptor.push_back('(');
565 const TypeList* type_list = GetProtoParameters(proto_id);
566 size_t parameter_length = 0;
567 if (type_list != NULL) {
568 // A non-zero number of arguments. Append the type names.
569 for (size_t i = 0; i < type_list->Size(); ++i) {
570 const TypeItem& type_item = type_list->GetTypeItem(i);
571 uint32_t type_idx = type_item.type_idx_;
572 int32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700573 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700574 parameter_length += type_length;
575 descriptor.append(name);
576 }
577 }
578 descriptor.push_back(')');
579 uint32_t return_type_idx = proto_id.return_type_idx_;
580 int32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700581 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700582 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700583 if (unicode_length != NULL) {
584 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
585 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700586 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700587}
588
Carl Shapiro1fb86202011-06-27 17:43:13 -0700589
Shih-wei Liao195487c2011-08-20 13:29:04 -0700590int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700591 // For native method, lineno should be -2 to indicate it is native. Note that
592 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700593 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700594 return -2;
595 }
596
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700597 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800598 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700599
600 // A method with no line number info should return -1
601 LineNumFromPcContext context(rel_pc, -1);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800602 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
603 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700604 return context.line_num_;
605}
606
Ian Rogers0571d352011-11-03 19:51:38 -0700607int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
608 uint32_t address){
609 // Note: Signed type is important for max and min.
610 int32_t min = 0;
611 int32_t max = tries_size - 1;
612
613 while (max >= min) {
614 int32_t mid = (min + max) / 2;
615 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
616 uint32_t start = pTry->start_addr_;
617 if (address < start) {
618 max = mid - 1;
619 } else {
620 uint32_t end = start + pTry->insn_count_;
621 if (address >= end) {
622 min = mid + 1;
623 } else { // We have a winner!
624 return (int32_t) pTry->handler_off_;
625 }
626 }
627 }
628 // No match.
629 return -1;
630}
631
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800632void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700633 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
634 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700635 uint32_t line = DecodeUnsignedLeb128(&stream);
636 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
637 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
638 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700639 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700640
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800641 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700642 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800643 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700644 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800645 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800646 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700647 local_in_reg[arg_reg].start_address_ = 0;
648 local_in_reg[arg_reg].is_live_ = true;
649 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700650 arg_reg++;
651 }
652
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800653 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700654 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700655 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700656 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800657 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700658 return;
659 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800660 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700661 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800662 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700663 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700664 local_in_reg[arg_reg].name_ = name;
665 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800666 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700667 local_in_reg[arg_reg].start_address_ = address;
668 local_in_reg[arg_reg].is_live_ = true;
669 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700670 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700671 case 'D':
672 case 'J':
673 arg_reg += 2;
674 break;
675 default:
676 arg_reg += 1;
677 break;
678 }
679 }
680
Ian Rogers0571d352011-11-03 19:51:38 -0700681 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800682 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700683 return;
684 }
685
686 for (;;) {
687 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700688 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700689 uint16_t name_idx;
690 uint16_t descriptor_idx;
691 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700692
Shih-wei Liao195487c2011-08-20 13:29:04 -0700693 switch (opcode) {
694 case DBG_END_SEQUENCE:
695 return;
696
697 case DBG_ADVANCE_PC:
698 address += DecodeUnsignedLeb128(&stream);
699 break;
700
701 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700702 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700703 break;
704
705 case DBG_START_LOCAL:
706 case DBG_START_LOCAL_EXTENDED:
707 reg = DecodeUnsignedLeb128(&stream);
708 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700709 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800710 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700711 return;
712 }
713
jeffhaof8728872011-10-28 19:11:13 -0700714 name_idx = DecodeUnsignedLeb128P1(&stream);
715 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
716 if (opcode == DBG_START_LOCAL_EXTENDED) {
717 signature_idx = DecodeUnsignedLeb128P1(&stream);
718 }
719
Shih-wei Liao195487c2011-08-20 13:29:04 -0700720 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700721 if (need_locals) {
722 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700723
Ian Rogers0571d352011-11-03 19:51:38 -0700724 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
725 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700726 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700727 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700728 }
729 local_in_reg[reg].start_address_ = address;
730 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700731 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700732 break;
733
734 case DBG_END_LOCAL:
735 reg = DecodeUnsignedLeb128(&stream);
736 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700737 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800738 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700739 return;
740 }
741
Elliott Hughes30646832011-10-13 16:59:46 -0700742 if (need_locals) {
743 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
744 local_in_reg[reg].is_live_ = false;
745 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700746 break;
747
748 case DBG_RESTART_LOCAL:
749 reg = DecodeUnsignedLeb128(&stream);
750 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700751 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800752 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700753 return;
754 }
755
Elliott Hughes30646832011-10-13 16:59:46 -0700756 if (need_locals) {
757 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800758 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700759 return;
760 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700761
Elliott Hughes30646832011-10-13 16:59:46 -0700762 // If the register is live, the "restart" is superfluous,
763 // and we don't want to mess with the existing start address.
764 if (!local_in_reg[reg].is_live_) {
765 local_in_reg[reg].start_address_ = address;
766 local_in_reg[reg].is_live_ = true;
767 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700768 }
769 break;
770
771 case DBG_SET_PROLOGUE_END:
772 case DBG_SET_EPILOGUE_BEGIN:
773 case DBG_SET_FILE:
774 break;
775
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700776 default: {
777 int adjopcode = opcode - DBG_FIRST_SPECIAL;
778
Shih-wei Liao195487c2011-08-20 13:29:04 -0700779 address += adjopcode / DBG_LINE_RANGE;
780 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
781
782 if (posCb != NULL) {
783 if (posCb(cnxt, address, line)) {
784 // early exit
785 return;
786 }
787 }
788 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700789 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700790 }
791 }
792}
793
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800794void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700795 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
796 void* cnxt) const {
797 const byte* stream = GetDebugInfoStream(code_item);
798 LocalInfo local_in_reg[code_item->registers_size_];
799
800 if (stream != NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800801 DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
Ian Rogers0571d352011-11-03 19:51:38 -0700802 }
803 for (int reg = 0; reg < code_item->registers_size_; reg++) {
804 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
805 }
806}
807
808bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
809 LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
810
811 // We know that this callback will be called in
812 // ascending address order, so keep going until we find
813 // a match or we've just gone past it.
814 if (address > context->address_) {
815 // The line number from the previous positions callback
816 // wil be the final result.
817 return true;
818 } else {
819 context->line_num_ = line_num;
820 return address == context->address_;
821 }
822}
823
824// Decodes the header section from the class data bytes.
825void ClassDataItemIterator::ReadClassDataHeader() {
826 CHECK(ptr_pos_ != NULL);
827 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
828 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
829 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
830 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
831}
832
833void ClassDataItemIterator::ReadClassDataField() {
834 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
835 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
836}
837
838void ClassDataItemIterator::ReadClassDataMethod() {
839 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
840 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
841 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
842}
843
844// Read a signed integer. "zwidth" is the zero-based byte count.
845static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
846 int32_t val = 0;
847 for (int i = zwidth; i >= 0; --i) {
848 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
849 }
850 val >>= (3 - zwidth) * 8;
851 return val;
852}
853
854// Read an unsigned integer. "zwidth" is the zero-based byte count,
855// "fill_on_right" indicates which side we want to zero-fill from.
856static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
857 uint32_t val = 0;
858 if (!fill_on_right) {
859 for (int i = zwidth; i >= 0; --i) {
860 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
861 }
862 val >>= (3 - zwidth) * 8;
863 } else {
864 for (int i = zwidth; i >= 0; --i) {
865 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
866 }
867 }
868 return val;
869}
870
871// Read a signed long. "zwidth" is the zero-based byte count.
872static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
873 int64_t val = 0;
874 for (int i = zwidth; i >= 0; --i) {
875 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
876 }
877 val >>= (7 - zwidth) * 8;
878 return val;
879}
880
881// Read an unsigned long. "zwidth" is the zero-based byte count,
882// "fill_on_right" indicates which side we want to zero-fill from.
883static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
884 uint64_t val = 0;
885 if (!fill_on_right) {
886 for (int i = zwidth; i >= 0; --i) {
887 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
888 }
889 val >>= (7 - zwidth) * 8;
890 } else {
891 for (int i = zwidth; i >= 0; --i) {
892 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
893 }
894 }
895 return val;
896}
897
898EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
899 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
900 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
901 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
902 if (ptr_ == NULL) {
903 array_size_ = 0;
904 } else {
905 array_size_ = DecodeUnsignedLeb128(&ptr_);
906 }
907 if (array_size_ > 0) {
908 Next();
909 }
910}
911
912void EncodedStaticFieldValueIterator::Next() {
913 pos_++;
914 if (pos_ >= array_size_) {
915 return;
916 }
917 byte value_type = *ptr_++;
918 byte value_arg = value_type >> kEncodedValueArgShift;
919 size_t width = value_arg + 1; // assume and correct later
920 type_ = value_type & kEncodedValueTypeMask;
921 switch (type_) {
922 case kBoolean:
923 jval_.i = (value_arg != 0) ? 1 : 0;
924 width = 0;
925 break;
926 case kByte:
927 jval_.i = ReadSignedInt(ptr_, value_arg);
928 CHECK(IsInt(8, jval_.i));
929 break;
930 case kShort:
931 jval_.i = ReadSignedInt(ptr_, value_arg);
932 CHECK(IsInt(16, jval_.i));
933 break;
934 case kChar:
935 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
936 CHECK(IsUint(16, jval_.i));
937 break;
938 case kInt:
939 jval_.i = ReadSignedInt(ptr_, value_arg);
940 break;
941 case kLong:
942 jval_.j = ReadSignedLong(ptr_, value_arg);
943 break;
944 case kFloat:
945 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
946 break;
947 case kDouble:
948 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
949 break;
950 case kString:
951 case kType:
952 case kMethod:
953 case kEnum:
954 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
955 break;
956 case kField:
957 case kArray:
958 case kAnnotation:
959 UNIMPLEMENTED(FATAL) << ": type " << type_;
960 break;
961 case kNull:
962 jval_.l = NULL;
963 width = 0;
964 break;
965 default:
966 LOG(FATAL) << "Unreached";
967 }
968 ptr_ += width;
969}
970
971void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
972 switch (type_) {
973 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
974 case kByte: field->SetByte(NULL, jval_.b); break;
975 case kShort: field->SetShort(NULL, jval_.s); break;
976 case kChar: field->SetChar(NULL, jval_.c); break;
977 case kInt: field->SetInt(NULL, jval_.i); break;
978 case kLong: field->SetLong(NULL, jval_.j); break;
979 case kFloat: field->SetFloat(NULL, jval_.f); break;
980 case kDouble: field->SetDouble(NULL, jval_.d); break;
981 case kNull: field->SetObject(NULL, NULL); break;
982 case kString: {
983 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
984 field->SetObject(NULL, resolved);
985 break;
986 }
987 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
988 }
989}
990
991CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
992 handler_.address_ = -1;
993 int32_t offset = -1;
994
995 // Short-circuit the overwhelmingly common cases.
996 switch (code_item.tries_size_) {
997 case 0:
998 break;
999 case 1: {
1000 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1001 uint32_t start = tries->start_addr_;
1002 if (address >= start) {
1003 uint32_t end = start + tries->insn_count_;
1004 if (address < end) {
1005 offset = tries->handler_off_;
1006 }
1007 }
1008 break;
1009 }
1010 default:
1011 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1012 }
1013 if (offset >= 0) {
1014 const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
1015 Init(handler_data);
1016 } else {
1017 // Not found, initialize as empty
1018 current_data_ = NULL;
1019 remaining_count_ = -1;
1020 catch_all_ = false;
1021 DCHECK(!HasNext());
1022 }
1023}
1024
1025void CatchHandlerIterator::Init(const byte* handler_data) {
1026 current_data_ = handler_data;
1027 remaining_count_ = DecodeSignedLeb128(&current_data_);
1028
1029 // If remaining_count_ is non-positive, then it is the negative of
1030 // the number of catch types, and the catches are followed by a
1031 // catch-all handler.
1032 if (remaining_count_ <= 0) {
1033 catch_all_ = true;
1034 remaining_count_ = -remaining_count_;
1035 } else {
1036 catch_all_ = false;
1037 }
1038 Next();
1039}
1040
1041void CatchHandlerIterator::Next() {
1042 if (remaining_count_ > 0) {
1043 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1044 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1045 remaining_count_--;
1046 return;
1047 }
1048
1049 if (catch_all_) {
1050 handler_.type_idx_ = DexFile::kDexNoIndex16;
1051 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1052 catch_all_ = false;
1053 return;
1054 }
1055
1056 // no more handler
1057 remaining_count_ = -1;
1058}
1059
Carl Shapiro1fb86202011-06-27 17:43:13 -07001060} // namespace art