blob: 5127a17bd079e58ddc04d8ed1816b898cd8485cf [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 }
Ian Rogers7cfb93e2012-01-17 19:46:36 -0800110 if (S_ISDIR(sbuf.st_mode)) {
111 LOG(ERROR) << "attempt to mmap directory \"" << filename << "\"";
112 return NULL;
113 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700114 size_t length = sbuf.st_size;
Brian Carlstrom89521892011-12-07 22:05:07 -0800115 UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0));
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700116 if (map.get() == NULL) {
117 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700118 close(fd);
119 return NULL;
120 }
121 close(fd);
Brian Carlstrom89521892011-12-07 22:05:07 -0800122 return OpenMemory(location, map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700123}
124
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700125const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700126
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700127// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700128const DexFile* DexFile::OpenZip(const std::string& filename,
129 const std::string& strip_location_prefix) {
Brian Carlstrom89521892011-12-07 22:05:07 -0800130 std::string location(StripLocationPrefix(filename, strip_location_prefix));
131 if (location.empty()) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700132 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700133 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700134
Elliott Hughes90a33692011-08-30 13:27:07 -0700135 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
136 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700137 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700138 return NULL;
139 }
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800140 return DexFile::Open(*zip_archive.get(), location);
141}
142
143const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
144 UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
Elliott Hughes90a33692011-08-30 13:27:07 -0700145 if (zip_entry.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800146 LOG(ERROR) << "Failed to find classes.dex within " << location;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700147 return NULL;
148 }
149
Brian Carlstrom89521892011-12-07 22:05:07 -0800150 uint32_t length = zip_entry->GetUncompressedLength();
Elliott Hughes850162c2012-01-12 18:46:43 -0800151 std::string name("classes.dex extracted in memory from ");
152 name += location;
153 UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE));
Brian Carlstrom89521892011-12-07 22:05:07 -0800154 if (map.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800155 LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
Brian Carlstrom89521892011-12-07 22:05:07 -0800156 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700157 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800158
159 // Extract classes.dex
160 bool success = zip_entry->ExtractToMemory(*map.get());
161 if (!success) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800162 LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
Brian Carlstrom89521892011-12-07 22:05:07 -0800163 return NULL;
164 }
165
166 return OpenMemory(location, map.release());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700167}
168
Brian Carlstrom89521892011-12-07 22:05:07 -0800169const DexFile* DexFile::OpenMemory(const byte* base,
170 size_t length,
171 const std::string& location,
172 MemMap* mem_map) {
173 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
174 UniquePtr<DexFile> dex_file(new DexFile(base, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700175 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700176 return NULL;
177 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700178 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700179 }
180}
181
Jesse Wilson6bf19152011-09-29 13:12:33 -0400182DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700183 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
184 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
185 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
186 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400187}
188
189jobject DexFile::GetDexObject(JNIEnv* env) const {
190 MutexLock mu(dex_object_lock_);
191 if (dex_object_ != NULL) {
192 return dex_object_;
193 }
194
195 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
196 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
197 if (byte_buffer == NULL) {
198 return NULL;
199 }
200
201 jclass c = env->FindClass("com/android/dex/Dex");
202 if (c == NULL) {
203 return NULL;
204 }
205
206 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
207 if (mid == NULL) {
208 return NULL;
209 }
210
211 jvalue args[1];
212 args[0].l = byte_buffer;
213 jobject local = env->CallStaticObjectMethodA(c, mid, args);
214 if (local == NULL) {
215 return NULL;
216 }
217
218 dex_object_ = env->NewGlobalRef(local);
219 return dex_object_;
220}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700221
Brian Carlstromf615a612011-07-23 12:50:34 -0700222bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700223 InitMembers();
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800224 if (!CheckMagicAndVersion()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700225 return false;
226 }
227 InitIndex();
228 return true;
229}
230
Brian Carlstromf615a612011-07-23 12:50:34 -0700231void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700232 const byte* b = base_;
233 header_ = reinterpret_cast<const Header*>(b);
234 const Header* h = header_;
235 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
236 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
237 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
238 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
239 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
240 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
Brian Carlstrom89521892011-12-07 22:05:07 -0800241 DCHECK_EQ(length_, header_->file_size_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700242}
243
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800244bool DexFile::CheckMagicAndVersion() {
245 CHECK(header_->magic_ != NULL) << GetLocation();
246 if (!IsMagicValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800247 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800248 << " " << header_->magic_[0]
249 << " " << header_->magic_[1]
250 << " " << header_->magic_[2]
251 << " " << header_->magic_[3];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700252 return false;
253 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800254 if (!IsVersionValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800255 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800256 << " " << header_->magic_[4]
257 << " " << header_->magic_[5]
258 << " " << header_->magic_[6]
259 << " " << header_->magic_[7];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700260 return false;
261 }
262 return true;
263}
264
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800265bool DexFile::IsMagicValid(const byte* magic) {
266 return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
267}
268
269bool DexFile::IsVersionValid(const byte* magic) {
270 const byte* version = &magic[sizeof(kDexMagic)];
271 return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
272}
273
Ian Rogersd81871c2011-10-03 13:57:23 -0700274uint32_t DexFile::GetVersion() const {
275 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
276 return atoi(version);
277}
278
Ian Rogers0571d352011-11-03 19:51:38 -0700279int32_t DexFile::GetStringLength(const StringId& string_id) const {
280 const byte* ptr = base_ + string_id.string_data_off_;
281 return DecodeUnsignedLeb128(&ptr);
282}
283
284// Returns a pointer to the UTF-8 string data referred to by the given string_id.
285const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800286 CHECK(length != NULL) << GetLocation();
Ian Rogers0571d352011-11-03 19:51:38 -0700287 const byte* ptr = base_ + string_id.string_data_off_;
288 *length = DecodeUnsignedLeb128(&ptr);
289 return reinterpret_cast<const char*>(ptr);
290}
291
Brian Carlstromf615a612011-07-23 12:50:34 -0700292void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800293 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700294 for (size_t i = 0; i < NumClassDefs(); ++i) {
295 const ClassDef& class_def = GetClassDef(i);
296 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700297 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700298 }
299}
300
Brian Carlstrome24fa612011-09-29 00:53:55 -0700301bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700302 Index::const_iterator it = index_.find(descriptor);
303 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700304 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700305 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700306 idx = it->second;
307 return true;
308}
309
310const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
311 uint32_t idx;
312 if (FindClassDefIndex(descriptor, idx)) {
313 return &GetClassDef(idx);
314 }
315 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700316}
317
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800318const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
319 const DexFile::StringId& name,
320 const DexFile::TypeId& type) const {
321 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
322 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
323 const uint32_t name_idx = GetIndexForStringId(name);
324 const uint16_t type_idx = GetIndexForTypeId(type);
325 uint32_t lo = 0;
326 uint32_t hi = NumFieldIds() - 1;
327 while (hi >= lo) {
328 uint32_t mid = (hi + lo) / 2;
329 const DexFile::FieldId& field = GetFieldId(mid);
330 if (class_idx > field.class_idx_) {
331 lo = mid + 1;
332 } else if (class_idx < field.class_idx_) {
333 hi = mid - 1;
334 } else {
335 if (name_idx > field.name_idx_) {
336 lo = mid + 1;
337 } else if (name_idx < field.name_idx_) {
338 hi = mid - 1;
339 } else {
340 if (type_idx > field.type_idx_) {
341 lo = mid + 1;
342 } else if (type_idx < field.type_idx_) {
343 hi = mid - 1;
344 } else {
345 return &field;
346 }
347 }
348 }
349 }
350 return NULL;
351}
352
353const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700354 const DexFile::StringId& name,
355 const DexFile::ProtoId& signature) const {
356 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800357 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700358 const uint32_t name_idx = GetIndexForStringId(name);
359 const uint16_t proto_idx = GetIndexForProtoId(signature);
360 uint32_t lo = 0;
361 uint32_t hi = NumMethodIds() - 1;
362 while (hi >= lo) {
363 uint32_t mid = (hi + lo) / 2;
364 const DexFile::MethodId& method = GetMethodId(mid);
365 if (class_idx > method.class_idx_) {
366 lo = mid + 1;
367 } else if (class_idx < method.class_idx_) {
368 hi = mid - 1;
369 } else {
370 if (name_idx > method.name_idx_) {
371 lo = mid + 1;
372 } else if (name_idx < method.name_idx_) {
373 hi = mid - 1;
374 } else {
375 if (proto_idx > method.proto_idx_) {
376 lo = mid + 1;
377 } else if (proto_idx < method.proto_idx_) {
378 hi = mid - 1;
379 } else {
380 return &method;
381 }
382 }
383 }
384 }
385 return NULL;
386}
387
388const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
389 uint32_t lo = 0;
390 uint32_t hi = NumStringIds() - 1;
391 while (hi >= lo) {
392 uint32_t mid = (hi + lo) / 2;
393 int32_t length;
394 const DexFile::StringId& str_id = GetStringId(mid);
395 const char* str = GetStringDataAndLength(str_id, &length);
396 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
397 if (compare > 0) {
398 lo = mid + 1;
399 } else if (compare < 0) {
400 hi = mid - 1;
401 } else {
402 return &str_id;
403 }
404 }
405 return NULL;
406}
407
408const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
409 uint32_t lo = 0;
410 uint32_t hi = NumTypeIds() - 1;
411 while (hi >= lo) {
412 uint32_t mid = (hi + lo) / 2;
413 const TypeId& type_id = GetTypeId(mid);
414 if (string_idx > type_id.descriptor_idx_) {
415 lo = mid + 1;
416 } else if (string_idx < type_id.descriptor_idx_) {
417 hi = mid - 1;
418 } else {
419 return &type_id;
420 }
421 }
422 return NULL;
423}
424
425const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800426 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700427 uint32_t lo = 0;
428 uint32_t hi = NumProtoIds() - 1;
429 while (hi >= lo) {
430 uint32_t mid = (hi + lo) / 2;
431 const DexFile::ProtoId& proto = GetProtoId(mid);
432 int compare = return_type_idx - proto.return_type_idx_;
433 if (compare == 0) {
434 DexFileParameterIterator it(*this, proto);
435 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800436 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
437 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700438 it.Next();
439 i++;
440 }
441 if (compare == 0) {
442 if (it.HasNext()) {
443 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800444 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700445 compare = 1;
446 }
447 }
448 }
449 if (compare > 0) {
450 lo = mid + 1;
451 } else if (compare < 0) {
452 hi = mid - 1;
453 } else {
454 return &proto;
455 }
456 }
457 return NULL;
458}
459
460// Given a signature place the type ids into the given vector
461bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
462 const std::string& signature) const {
463 if (signature[0] != '(') {
464 return false;
465 }
466 size_t offset = 1;
467 size_t end = signature.size();
468 bool process_return = false;
469 while (offset < end) {
470 char c = signature[offset];
471 offset++;
472 if (c == ')') {
473 process_return = true;
474 continue;
475 }
476 std::string descriptor;
477 descriptor += c;
478 while (c == '[') { // process array prefix
479 if (offset >= end) { // expect some descriptor following [
480 return false;
481 }
482 c = signature[offset];
483 offset++;
484 descriptor += c;
485 }
486 if (c == 'L') { // process type descriptors
487 do {
488 if (offset >= end) { // unexpected early termination of descriptor
489 return false;
490 }
491 c = signature[offset];
492 offset++;
493 descriptor += c;
494 } while (c != ';');
495 }
496 const DexFile::StringId* string_id = FindStringId(descriptor);
497 if (string_id == NULL) {
498 return false;
499 }
500 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
501 if (type_id == NULL) {
502 return false;
503 }
504 uint16_t type_idx = GetIndexForTypeId(*type_id);
505 if (!process_return) {
506 param_type_idxs->push_back(type_idx);
507 } else {
508 *return_type_idx = type_idx;
509 return offset == end; // return true if the signature had reached a sensible end
510 }
511 }
512 return false; // failed to correctly parse return type
513}
514
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700515// Materializes the method descriptor for a method prototype. Method
516// descriptors are not stored directly in the dex file. Instead, one
517// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700518std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700519 const ProtoId& proto_id = GetProtoId(proto_idx);
520 std::string descriptor;
521 descriptor.push_back('(');
522 const TypeList* type_list = GetProtoParameters(proto_id);
523 size_t parameter_length = 0;
524 if (type_list != NULL) {
525 // A non-zero number of arguments. Append the type names.
526 for (size_t i = 0; i < type_list->Size(); ++i) {
527 const TypeItem& type_item = type_list->GetTypeItem(i);
528 uint32_t type_idx = type_item.type_idx_;
529 int32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700530 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700531 parameter_length += type_length;
532 descriptor.append(name);
533 }
534 }
535 descriptor.push_back(')');
536 uint32_t return_type_idx = proto_id.return_type_idx_;
537 int32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700538 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700539 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700540 if (unicode_length != NULL) {
541 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
542 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700543 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700544}
545
Carl Shapiro1fb86202011-06-27 17:43:13 -0700546
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800547int32_t DexFile::GetLineNumFromPC(const Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700548 // For native method, lineno should be -2 to indicate it is native. Note that
549 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700550 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700551 return -2;
552 }
553
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700554 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800555 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700556
557 // A method with no line number info should return -1
558 LineNumFromPcContext context(rel_pc, -1);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800559 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
560 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700561 return context.line_num_;
562}
563
Ian Rogers0571d352011-11-03 19:51:38 -0700564int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
Elliott Hughesba8eee12012-01-24 20:25:24 -0800565 uint32_t address) {
Ian Rogers0571d352011-11-03 19:51:38 -0700566 // Note: Signed type is important for max and min.
567 int32_t min = 0;
568 int32_t max = tries_size - 1;
569
570 while (max >= min) {
571 int32_t mid = (min + max) / 2;
572 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
573 uint32_t start = pTry->start_addr_;
574 if (address < start) {
575 max = mid - 1;
576 } else {
577 uint32_t end = start + pTry->insn_count_;
578 if (address >= end) {
579 min = mid + 1;
580 } else { // We have a winner!
581 return (int32_t) pTry->handler_off_;
582 }
583 }
584 }
585 // No match.
586 return -1;
587}
588
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800589void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700590 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
591 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700592 uint32_t line = DecodeUnsignedLeb128(&stream);
593 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
594 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
595 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700596 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700597
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800598 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700599 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800600 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700601 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800602 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800603 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700604 local_in_reg[arg_reg].start_address_ = 0;
605 local_in_reg[arg_reg].is_live_ = true;
606 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700607 arg_reg++;
608 }
609
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800610 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700611 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700612 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700613 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800614 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700615 return;
616 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800617 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700618 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800619 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700620 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700621 local_in_reg[arg_reg].name_ = name;
622 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800623 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700624 local_in_reg[arg_reg].start_address_ = address;
625 local_in_reg[arg_reg].is_live_ = true;
626 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700627 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700628 case 'D':
629 case 'J':
630 arg_reg += 2;
631 break;
632 default:
633 arg_reg += 1;
634 break;
635 }
636 }
637
Ian Rogers0571d352011-11-03 19:51:38 -0700638 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800639 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700640 return;
641 }
642
643 for (;;) {
644 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700645 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700646 uint16_t name_idx;
647 uint16_t descriptor_idx;
648 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700649
Shih-wei Liao195487c2011-08-20 13:29:04 -0700650 switch (opcode) {
651 case DBG_END_SEQUENCE:
652 return;
653
654 case DBG_ADVANCE_PC:
655 address += DecodeUnsignedLeb128(&stream);
656 break;
657
658 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700659 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700660 break;
661
662 case DBG_START_LOCAL:
663 case DBG_START_LOCAL_EXTENDED:
664 reg = DecodeUnsignedLeb128(&stream);
665 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700666 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800667 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700668 return;
669 }
670
jeffhaof8728872011-10-28 19:11:13 -0700671 name_idx = DecodeUnsignedLeb128P1(&stream);
672 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
673 if (opcode == DBG_START_LOCAL_EXTENDED) {
674 signature_idx = DecodeUnsignedLeb128P1(&stream);
675 }
676
Shih-wei Liao195487c2011-08-20 13:29:04 -0700677 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700678 if (need_locals) {
679 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700680
Ian Rogers0571d352011-11-03 19:51:38 -0700681 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
682 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700683 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700684 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700685 }
686 local_in_reg[reg].start_address_ = address;
687 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700688 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700689 break;
690
691 case DBG_END_LOCAL:
692 reg = DecodeUnsignedLeb128(&stream);
693 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700694 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800695 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700696 return;
697 }
698
Elliott Hughes30646832011-10-13 16:59:46 -0700699 if (need_locals) {
700 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
701 local_in_reg[reg].is_live_ = false;
702 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700703 break;
704
705 case DBG_RESTART_LOCAL:
706 reg = DecodeUnsignedLeb128(&stream);
707 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700708 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800709 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700710 return;
711 }
712
Elliott Hughes30646832011-10-13 16:59:46 -0700713 if (need_locals) {
714 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800715 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700716 return;
717 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700718
Elliott Hughes30646832011-10-13 16:59:46 -0700719 // If the register is live, the "restart" is superfluous,
720 // and we don't want to mess with the existing start address.
721 if (!local_in_reg[reg].is_live_) {
722 local_in_reg[reg].start_address_ = address;
723 local_in_reg[reg].is_live_ = true;
724 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700725 }
726 break;
727
728 case DBG_SET_PROLOGUE_END:
729 case DBG_SET_EPILOGUE_BEGIN:
730 case DBG_SET_FILE:
731 break;
732
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700733 default: {
734 int adjopcode = opcode - DBG_FIRST_SPECIAL;
735
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736 address += adjopcode / DBG_LINE_RANGE;
737 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
738
739 if (posCb != NULL) {
740 if (posCb(cnxt, address, line)) {
741 // early exit
742 return;
743 }
744 }
745 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700746 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700747 }
748 }
749}
750
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800751void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700752 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
753 void* cnxt) const {
754 const byte* stream = GetDebugInfoStream(code_item);
755 LocalInfo local_in_reg[code_item->registers_size_];
756
757 if (stream != NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800758 DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
Ian Rogers0571d352011-11-03 19:51:38 -0700759 }
760 for (int reg = 0; reg < code_item->registers_size_; reg++) {
761 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
762 }
763}
764
765bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800766 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(cnxt);
Ian Rogers0571d352011-11-03 19:51:38 -0700767
768 // We know that this callback will be called in
769 // ascending address order, so keep going until we find
770 // a match or we've just gone past it.
771 if (address > context->address_) {
772 // The line number from the previous positions callback
773 // wil be the final result.
774 return true;
775 } else {
776 context->line_num_ = line_num;
777 return address == context->address_;
778 }
779}
780
781// Decodes the header section from the class data bytes.
782void ClassDataItemIterator::ReadClassDataHeader() {
783 CHECK(ptr_pos_ != NULL);
784 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
785 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
786 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
787 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
788}
789
790void ClassDataItemIterator::ReadClassDataField() {
791 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
792 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
793}
794
795void ClassDataItemIterator::ReadClassDataMethod() {
796 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
797 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
798 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
799}
800
801// Read a signed integer. "zwidth" is the zero-based byte count.
802static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
803 int32_t val = 0;
804 for (int i = zwidth; i >= 0; --i) {
805 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
806 }
807 val >>= (3 - zwidth) * 8;
808 return val;
809}
810
811// Read an unsigned integer. "zwidth" is the zero-based byte count,
812// "fill_on_right" indicates which side we want to zero-fill from.
813static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
814 uint32_t val = 0;
815 if (!fill_on_right) {
816 for (int i = zwidth; i >= 0; --i) {
817 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
818 }
819 val >>= (3 - zwidth) * 8;
820 } else {
821 for (int i = zwidth; i >= 0; --i) {
822 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
823 }
824 }
825 return val;
826}
827
828// Read a signed long. "zwidth" is the zero-based byte count.
829static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
830 int64_t val = 0;
831 for (int i = zwidth; i >= 0; --i) {
832 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
833 }
834 val >>= (7 - zwidth) * 8;
835 return val;
836}
837
838// Read an unsigned long. "zwidth" is the zero-based byte count,
839// "fill_on_right" indicates which side we want to zero-fill from.
840static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
841 uint64_t val = 0;
842 if (!fill_on_right) {
843 for (int i = zwidth; i >= 0; --i) {
844 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
845 }
846 val >>= (7 - zwidth) * 8;
847 } else {
848 for (int i = zwidth; i >= 0; --i) {
849 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
850 }
851 }
852 return val;
853}
854
855EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
856 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
857 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
858 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
859 if (ptr_ == NULL) {
860 array_size_ = 0;
861 } else {
862 array_size_ = DecodeUnsignedLeb128(&ptr_);
863 }
864 if (array_size_ > 0) {
865 Next();
866 }
867}
868
869void EncodedStaticFieldValueIterator::Next() {
870 pos_++;
871 if (pos_ >= array_size_) {
872 return;
873 }
874 byte value_type = *ptr_++;
875 byte value_arg = value_type >> kEncodedValueArgShift;
876 size_t width = value_arg + 1; // assume and correct later
877 type_ = value_type & kEncodedValueTypeMask;
878 switch (type_) {
879 case kBoolean:
880 jval_.i = (value_arg != 0) ? 1 : 0;
881 width = 0;
882 break;
883 case kByte:
884 jval_.i = ReadSignedInt(ptr_, value_arg);
885 CHECK(IsInt(8, jval_.i));
886 break;
887 case kShort:
888 jval_.i = ReadSignedInt(ptr_, value_arg);
889 CHECK(IsInt(16, jval_.i));
890 break;
891 case kChar:
892 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
893 CHECK(IsUint(16, jval_.i));
894 break;
895 case kInt:
896 jval_.i = ReadSignedInt(ptr_, value_arg);
897 break;
898 case kLong:
899 jval_.j = ReadSignedLong(ptr_, value_arg);
900 break;
901 case kFloat:
902 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
903 break;
904 case kDouble:
905 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
906 break;
907 case kString:
908 case kType:
909 case kMethod:
910 case kEnum:
911 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
912 break;
913 case kField:
914 case kArray:
915 case kAnnotation:
916 UNIMPLEMENTED(FATAL) << ": type " << type_;
917 break;
918 case kNull:
919 jval_.l = NULL;
920 width = 0;
921 break;
922 default:
923 LOG(FATAL) << "Unreached";
924 }
925 ptr_ += width;
926}
927
928void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
929 switch (type_) {
930 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
931 case kByte: field->SetByte(NULL, jval_.b); break;
932 case kShort: field->SetShort(NULL, jval_.s); break;
933 case kChar: field->SetChar(NULL, jval_.c); break;
934 case kInt: field->SetInt(NULL, jval_.i); break;
935 case kLong: field->SetLong(NULL, jval_.j); break;
936 case kFloat: field->SetFloat(NULL, jval_.f); break;
937 case kDouble: field->SetDouble(NULL, jval_.d); break;
938 case kNull: field->SetObject(NULL, NULL); break;
939 case kString: {
940 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
941 field->SetObject(NULL, resolved);
942 break;
943 }
944 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
945 }
946}
947
948CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
949 handler_.address_ = -1;
950 int32_t offset = -1;
951
952 // Short-circuit the overwhelmingly common cases.
953 switch (code_item.tries_size_) {
954 case 0:
955 break;
956 case 1: {
957 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
958 uint32_t start = tries->start_addr_;
959 if (address >= start) {
960 uint32_t end = start + tries->insn_count_;
961 if (address < end) {
962 offset = tries->handler_off_;
963 }
964 }
965 break;
966 }
967 default:
968 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
969 }
970 if (offset >= 0) {
971 const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
972 Init(handler_data);
973 } else {
974 // Not found, initialize as empty
975 current_data_ = NULL;
976 remaining_count_ = -1;
977 catch_all_ = false;
978 DCHECK(!HasNext());
979 }
980}
981
982void CatchHandlerIterator::Init(const byte* handler_data) {
983 current_data_ = handler_data;
984 remaining_count_ = DecodeSignedLeb128(&current_data_);
985
986 // If remaining_count_ is non-positive, then it is the negative of
987 // the number of catch types, and the catches are followed by a
988 // catch-all handler.
989 if (remaining_count_ <= 0) {
990 catch_all_ = true;
991 remaining_count_ = -remaining_count_;
992 } else {
993 catch_all_ = false;
994 }
995 Next();
996}
997
998void CatchHandlerIterator::Next() {
999 if (remaining_count_ > 0) {
1000 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1001 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1002 remaining_count_--;
1003 return;
1004 }
1005
1006 if (catch_all_) {
1007 handler_.type_idx_ = DexFile::kDexNoIndex16;
1008 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1009 catch_all_ = false;
1010 return;
1011 }
1012
1013 // no more handler
1014 remaining_count_ = -1;
1015}
1016
Carl Shapiro1fb86202011-06-27 17:43:13 -07001017} // namespace art