blob: 8b87ee7c307c6f6518efe34cff2054d276b6d473 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Carl Shapiro1fb86202011-06-27 17:43:13 -070016
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "dex_file.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070018
19#include <fcntl.h>
Brian Carlstrom1f870082011-08-23 16:02:11 -070020#include <limits.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070021#include <stdio.h>
Ian Rogersd81871c2011-10-03 13:57:23 -070022#include <stdlib.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070023#include <string.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070024#include <sys/file.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070025#include <sys/stat.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026
Elliott Hughes07ed66b2012-12-12 18:34:25 -080027#include "base/logging.h"
Elliott Hughese222ee02012-12-13 14:41:43 -080028#include "base/stringprintf.h"
Ian Rogers0571d352011-11-03 19:51:38 -070029#include "class_linker.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070030#include "dex_file-inl.h"
jeffhao10037c82012-01-23 15:06:23 -080031#include "dex_file_verifier.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070032#include "globals.h"
Ian Rogers0571d352011-11-03 19:51:38 -070033#include "leb128.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/abstract_method-inl.h"
35#include "mirror/field.h"
36#include "mirror/field-inl.h"
37#include "mirror/string.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070038#include "os.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070039#include "safe_map.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070040#include "thread.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070041#include "UniquePtr.h"
Ian Rogers0571d352011-11-03 19:51:38 -070042#include "utf.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070043#include "utils.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070044#include "well_known_classes.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070045#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070046
47namespace art {
48
Brian Carlstromf615a612011-07-23 12:50:34 -070049const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
50const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070051
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070052DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070053 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070054 for (size_t i = 0; i != class_path.size(); ++i) {
55 const DexFile* dex_file = class_path[i];
56 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
57 if (dex_class_def != NULL) {
58 return ClassPathEntry(dex_file, dex_class_def);
59 }
60 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070061 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070062 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
63 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070064}
65
Brian Carlstrom5b332c82012-02-01 15:02:31 -080066bool DexFile::GetChecksum(const std::string& filename, uint32_t& checksum) {
67 if (IsValidZipFilename(filename)) {
68 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
69 if (zip_archive.get() == NULL) {
70 return false;
Brian Carlstrom78128a62011-09-15 17:21:19 -070071 }
Brian Carlstrom5b332c82012-02-01 15:02:31 -080072 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
73 if (zip_entry.get() == NULL) {
74 return false;
75 }
76 checksum = zip_entry->GetCrc32();
77 return true;
Brian Carlstrom78128a62011-09-15 17:21:19 -070078 }
Brian Carlstrom5b332c82012-02-01 15:02:31 -080079 if (IsValidDexFilename(filename)) {
Brian Carlstrom1db858a2012-03-11 22:44:45 -070080 UniquePtr<const DexFile> dex_file(DexFile::OpenFile(filename, filename, false));
Brian Carlstrom5b332c82012-02-01 15:02:31 -080081 if (dex_file.get() == NULL) {
82 return false;
83 }
84 checksum = dex_file->GetHeader().checksum_;
85 return true;
86 }
87 return false;
Brian Carlstrom78128a62011-09-15 17:21:19 -070088}
89
Brian Carlstrom16192862011-09-12 17:50:06 -070090const DexFile* DexFile::Open(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -080091 const std::string& location) {
jeffhao262bf462011-10-20 18:36:32 -070092 if (IsValidZipFilename(filename)) {
Brian Carlstroma004aa92012-02-08 18:05:09 -080093 return DexFile::OpenZip(filename, location);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070094 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -070095 if (!IsValidDexFilename(filename)) {
96 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
97 }
Brian Carlstroma004aa92012-02-08 18:05:09 -080098 return DexFile::OpenFile(filename, location, true);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070099}
100
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800101int DexFile::GetPermissions() const {
102 if (mem_map_.get() == NULL) {
103 return 0;
104 } else {
105 return mem_map_->GetProtect();
106 }
107}
108
Brian Carlstrom16192862011-09-12 17:50:06 -0700109const DexFile* DexFile::OpenFile(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -0800110 const std::string& location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800111 bool verify) {
Brian Carlstroma004aa92012-02-08 18:05:09 -0800112 CHECK(!location.empty()) << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700113 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700114 if (fd == -1) {
115 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
116 return NULL;
117 }
118 struct stat sbuf;
119 memset(&sbuf, 0, sizeof(sbuf));
120 if (fstat(fd, &sbuf) == -1) {
121 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
122 close(fd);
123 return NULL;
124 }
Ian Rogers7cfb93e2012-01-17 19:46:36 -0800125 if (S_ISDIR(sbuf.st_mode)) {
126 LOG(ERROR) << "attempt to mmap directory \"" << filename << "\"";
127 return NULL;
128 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700129 size_t length = sbuf.st_size;
Brian Carlstrom89521892011-12-07 22:05:07 -0800130 UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0));
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700131 if (map.get() == NULL) {
132 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700133 close(fd);
134 return NULL;
135 }
136 close(fd);
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800137
138 if (map->Size() < sizeof(DexFile::Header)) {
139 LOG(ERROR) << "Failed to open dex file '" << filename << "' that is too short to have a header";
140 return NULL;
141 }
142
143 const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
144
145 const DexFile* dex_file = OpenMemory(location, dex_header->checksum_, map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800146 if (dex_file == NULL) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800147 LOG(ERROR) << "Failed to open dex file '" << filename << "' from memory";
jeffhao54c1ceb2012-02-01 11:45:32 -0800148 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800149 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800150
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700151 if (verify && !DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800152 LOG(ERROR) << "Failed to verify dex file '" << filename << "'";
jeffhao54c1ceb2012-02-01 11:45:32 -0800153 return NULL;
154 }
155
jeffhaof6174e82012-01-31 16:14:17 -0800156 return dex_file;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700157}
158
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700159const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700160
Brian Carlstrom16192862011-09-12 17:50:06 -0700161const DexFile* DexFile::OpenZip(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -0800162 const std::string& location) {
Elliott Hughes90a33692011-08-30 13:27:07 -0700163 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
164 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700165 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700166 return NULL;
167 }
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800168 return DexFile::Open(*zip_archive.get(), location);
169}
170
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800171const DexFile* DexFile::OpenMemory(const std::string& location,
172 uint32_t location_checksum,
173 MemMap* mem_map) {
174 return OpenMemory(mem_map->Begin(),
175 mem_map->Size(),
176 location,
177 location_checksum,
178 mem_map);
179}
180
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800181const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
Brian Carlstroma004aa92012-02-08 18:05:09 -0800182 CHECK(!location.empty());
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800183 UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
Elliott Hughes90a33692011-08-30 13:27:07 -0700184 if (zip_entry.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800185 LOG(ERROR) << "Failed to find classes.dex within " << location;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700186 return NULL;
187 }
188
Brian Carlstrom89521892011-12-07 22:05:07 -0800189 uint32_t length = zip_entry->GetUncompressedLength();
Elliott Hughes850162c2012-01-12 18:46:43 -0800190 std::string name("classes.dex extracted in memory from ");
191 name += location;
192 UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE));
Brian Carlstrom89521892011-12-07 22:05:07 -0800193 if (map.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800194 LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
Brian Carlstrom89521892011-12-07 22:05:07 -0800195 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700196 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800197
198 // Extract classes.dex
199 bool success = zip_entry->ExtractToMemory(*map.get());
200 if (!success) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800201 LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
Brian Carlstrom89521892011-12-07 22:05:07 -0800202 return NULL;
203 }
204
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800205 const DexFile* dex_file = OpenMemory(location, zip_entry->GetCrc32(), map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800206 if (dex_file == NULL) {
207 LOG(ERROR) << "Failed to open dex file '" << location << "' from memory";
208 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800209 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800210
211 if (!DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
212 LOG(ERROR) << "Failed to verify dex file '" << location << "'";
213 return NULL;
214 }
215
jeffhaof6174e82012-01-31 16:14:17 -0800216 return dex_file;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700217}
218
Brian Carlstrom89521892011-12-07 22:05:07 -0800219const DexFile* DexFile::OpenMemory(const byte* base,
jeffhaof6174e82012-01-31 16:14:17 -0800220 size_t size,
Brian Carlstrom89521892011-12-07 22:05:07 -0800221 const std::string& location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800222 uint32_t location_checksum,
Brian Carlstrom89521892011-12-07 22:05:07 -0800223 MemMap* mem_map) {
224 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800225 UniquePtr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, 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
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700240class ScopedJniMonitorLock {
241 public:
242 ScopedJniMonitorLock(JNIEnv* env, jobject locked) : env_(env), locked_(locked){
243 env->MonitorEnter(locked_);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400244 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700245 ~ScopedJniMonitorLock() {
246 env_->MonitorExit(locked_);
247 }
248 private:
249 JNIEnv* const env_;
250 const jobject locked_;
251};
Jesse Wilson6bf19152011-09-29 13:12:33 -0400252
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700253jobject DexFile::GetDexObject(JNIEnv* env) const {
254 {
255 ScopedJniMonitorLock lock(env, WellKnownClasses::com_android_dex_Dex);
256 if (dex_object_ != NULL) {
257 return dex_object_;
258 }
259 }
Ian Rogers30fab402012-01-23 15:43:46 -0800260 void* address = const_cast<void*>(reinterpret_cast<const void*>(begin_));
jeffhaof6174e82012-01-31 16:14:17 -0800261 jobject byte_buffer = env->NewDirectByteBuffer(address, size_);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400262 if (byte_buffer == NULL) {
263 return NULL;
264 }
265
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700266 ScopedJniMonitorLock lock(env, WellKnownClasses::com_android_dex_Dex);
267 // Re-test to see if someone beat us to the creation when we had the lock released.
268 if (dex_object_ != NULL) {
269 return dex_object_;
270 }
Jesse Wilson6bf19152011-09-29 13:12:33 -0400271 jvalue args[1];
272 args[0].l = byte_buffer;
Elliott Hugheseac76672012-05-24 21:56:51 -0700273 jobject local = env->CallStaticObjectMethodA(WellKnownClasses::com_android_dex_Dex,
274 WellKnownClasses::com_android_dex_Dex_create,
275 args);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400276 if (local == NULL) {
277 return NULL;
278 }
279
280 dex_object_ = env->NewGlobalRef(local);
281 return dex_object_;
282}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700283
Brian Carlstromf615a612011-07-23 12:50:34 -0700284bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700285 InitMembers();
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800286 if (!CheckMagicAndVersion()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700287 return false;
288 }
289 InitIndex();
290 return true;
291}
292
Brian Carlstromf615a612011-07-23 12:50:34 -0700293void DexFile::InitMembers() {
Ian Rogers30fab402012-01-23 15:43:46 -0800294 const byte* b = begin_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700295 header_ = reinterpret_cast<const Header*>(b);
296 const Header* h = header_;
297 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
298 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
299 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
300 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
301 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
302 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
Brian Carlstrombd86bcc2013-03-10 20:26:16 -0700303 DCHECK_EQ(size_, header_->file_size_) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700304}
305
jeffhao10037c82012-01-23 15:06:23 -0800306bool DexFile::CheckMagicAndVersion() const {
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800307 CHECK(header_->magic_ != NULL) << GetLocation();
308 if (!IsMagicValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800309 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800310 << " " << header_->magic_[0]
311 << " " << header_->magic_[1]
312 << " " << header_->magic_[2]
313 << " " << header_->magic_[3];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700314 return false;
315 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800316 if (!IsVersionValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800317 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800318 << " " << header_->magic_[4]
319 << " " << header_->magic_[5]
320 << " " << header_->magic_[6]
321 << " " << header_->magic_[7];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700322 return false;
323 }
324 return true;
325}
326
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800327bool DexFile::IsMagicValid(const byte* magic) {
328 return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
329}
330
331bool DexFile::IsVersionValid(const byte* magic) {
332 const byte* version = &magic[sizeof(kDexMagic)];
333 return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
334}
335
Ian Rogersd81871c2011-10-03 13:57:23 -0700336uint32_t DexFile::GetVersion() const {
337 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
338 return atoi(version);
339}
340
Brian Carlstromf615a612011-07-23 12:50:34 -0700341void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800342 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700343 for (size_t i = 0; i < NumClassDefs(); ++i) {
344 const ClassDef& class_def = GetClassDef(i);
345 const char* descriptor = GetClassDescriptor(class_def);
Elliott Hughesa0e18062012-04-13 15:59:59 -0700346 index_.Put(descriptor, i);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700347 }
348}
349
Brian Carlstrome24fa612011-09-29 00:53:55 -0700350bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700351 Index::const_iterator it = index_.find(descriptor);
352 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700353 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700354 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700355 idx = it->second;
356 return true;
357}
358
359const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
360 uint32_t idx;
361 if (FindClassDefIndex(descriptor, idx)) {
362 return &GetClassDef(idx);
363 }
364 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700365}
366
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800367const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
368 const DexFile::StringId& name,
369 const DexFile::TypeId& type) const {
370 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
371 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
372 const uint32_t name_idx = GetIndexForStringId(name);
373 const uint16_t type_idx = GetIndexForTypeId(type);
374 uint32_t lo = 0;
375 uint32_t hi = NumFieldIds() - 1;
376 while (hi >= lo) {
377 uint32_t mid = (hi + lo) / 2;
378 const DexFile::FieldId& field = GetFieldId(mid);
379 if (class_idx > field.class_idx_) {
380 lo = mid + 1;
381 } else if (class_idx < field.class_idx_) {
382 hi = mid - 1;
383 } else {
384 if (name_idx > field.name_idx_) {
385 lo = mid + 1;
386 } else if (name_idx < field.name_idx_) {
387 hi = mid - 1;
388 } else {
389 if (type_idx > field.type_idx_) {
390 lo = mid + 1;
391 } else if (type_idx < field.type_idx_) {
392 hi = mid - 1;
393 } else {
394 return &field;
395 }
396 }
397 }
398 }
399 return NULL;
400}
401
402const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700403 const DexFile::StringId& name,
404 const DexFile::ProtoId& signature) const {
405 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800406 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700407 const uint32_t name_idx = GetIndexForStringId(name);
408 const uint16_t proto_idx = GetIndexForProtoId(signature);
409 uint32_t lo = 0;
410 uint32_t hi = NumMethodIds() - 1;
411 while (hi >= lo) {
412 uint32_t mid = (hi + lo) / 2;
413 const DexFile::MethodId& method = GetMethodId(mid);
414 if (class_idx > method.class_idx_) {
415 lo = mid + 1;
416 } else if (class_idx < method.class_idx_) {
417 hi = mid - 1;
418 } else {
419 if (name_idx > method.name_idx_) {
420 lo = mid + 1;
421 } else if (name_idx < method.name_idx_) {
422 hi = mid - 1;
423 } else {
424 if (proto_idx > method.proto_idx_) {
425 lo = mid + 1;
426 } else if (proto_idx < method.proto_idx_) {
427 hi = mid - 1;
428 } else {
429 return &method;
430 }
431 }
432 }
433 }
434 return NULL;
435}
436
437const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
438 uint32_t lo = 0;
439 uint32_t hi = NumStringIds() - 1;
440 while (hi >= lo) {
441 uint32_t mid = (hi + lo) / 2;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800442 uint32_t length;
Ian Rogers0571d352011-11-03 19:51:38 -0700443 const DexFile::StringId& str_id = GetStringId(mid);
444 const char* str = GetStringDataAndLength(str_id, &length);
445 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
446 if (compare > 0) {
447 lo = mid + 1;
448 } else if (compare < 0) {
449 hi = mid - 1;
450 } else {
451 return &str_id;
452 }
453 }
454 return NULL;
455}
456
457const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
458 uint32_t lo = 0;
459 uint32_t hi = NumTypeIds() - 1;
460 while (hi >= lo) {
461 uint32_t mid = (hi + lo) / 2;
462 const TypeId& type_id = GetTypeId(mid);
463 if (string_idx > type_id.descriptor_idx_) {
464 lo = mid + 1;
465 } else if (string_idx < type_id.descriptor_idx_) {
466 hi = mid - 1;
467 } else {
468 return &type_id;
469 }
470 }
471 return NULL;
472}
473
474const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800475 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700476 uint32_t lo = 0;
477 uint32_t hi = NumProtoIds() - 1;
478 while (hi >= lo) {
479 uint32_t mid = (hi + lo) / 2;
480 const DexFile::ProtoId& proto = GetProtoId(mid);
481 int compare = return_type_idx - proto.return_type_idx_;
482 if (compare == 0) {
483 DexFileParameterIterator it(*this, proto);
484 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800485 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
486 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700487 it.Next();
488 i++;
489 }
490 if (compare == 0) {
491 if (it.HasNext()) {
492 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800493 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700494 compare = 1;
495 }
496 }
497 }
498 if (compare > 0) {
499 lo = mid + 1;
500 } else if (compare < 0) {
501 hi = mid - 1;
502 } else {
503 return &proto;
504 }
505 }
506 return NULL;
507}
508
509// Given a signature place the type ids into the given vector
510bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
511 const std::string& signature) const {
512 if (signature[0] != '(') {
513 return false;
514 }
515 size_t offset = 1;
516 size_t end = signature.size();
517 bool process_return = false;
518 while (offset < end) {
519 char c = signature[offset];
520 offset++;
521 if (c == ')') {
522 process_return = true;
523 continue;
524 }
525 std::string descriptor;
526 descriptor += c;
527 while (c == '[') { // process array prefix
528 if (offset >= end) { // expect some descriptor following [
529 return false;
530 }
531 c = signature[offset];
532 offset++;
533 descriptor += c;
534 }
535 if (c == 'L') { // process type descriptors
536 do {
537 if (offset >= end) { // unexpected early termination of descriptor
538 return false;
539 }
540 c = signature[offset];
541 offset++;
542 descriptor += c;
543 } while (c != ';');
544 }
545 const DexFile::StringId* string_id = FindStringId(descriptor);
546 if (string_id == NULL) {
547 return false;
548 }
549 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
550 if (type_id == NULL) {
551 return false;
552 }
553 uint16_t type_idx = GetIndexForTypeId(*type_id);
554 if (!process_return) {
555 param_type_idxs->push_back(type_idx);
556 } else {
557 *return_type_idx = type_idx;
558 return offset == end; // return true if the signature had reached a sensible end
559 }
560 }
561 return false; // failed to correctly parse return type
562}
563
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700564// Materializes the method descriptor for a method prototype. Method
565// descriptors are not stored directly in the dex file. Instead, one
566// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700567std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700568 const ProtoId& proto_id = GetProtoId(proto_idx);
569 std::string descriptor;
570 descriptor.push_back('(');
571 const TypeList* type_list = GetProtoParameters(proto_id);
572 size_t parameter_length = 0;
573 if (type_list != NULL) {
574 // A non-zero number of arguments. Append the type names.
575 for (size_t i = 0; i < type_list->Size(); ++i) {
576 const TypeItem& type_item = type_list->GetTypeItem(i);
577 uint32_t type_idx = type_item.type_idx_;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800578 uint32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700579 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700580 parameter_length += type_length;
581 descriptor.append(name);
582 }
583 }
584 descriptor.push_back(')');
585 uint32_t return_type_idx = proto_id.return_type_idx_;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800586 uint32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700587 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700588 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700589 if (unicode_length != NULL) {
590 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
591 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700592 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700593}
594
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800595int32_t DexFile::GetLineNumFromPC(const mirror::AbstractMethod* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700596 // For native method, lineno should be -2 to indicate it is native. Note that
597 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700598 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700599 return -2;
600 }
601
TDYa127c8dc1012012-04-19 07:03:33 -0700602 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Elliott Hughescaf76542012-06-28 16:08:22 -0700603 DCHECK(code_item != NULL) << PrettyMethod(method) << " " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700604
605 // A method with no line number info should return -1
606 LineNumFromPcContext context(rel_pc, -1);
TDYa127c8dc1012012-04-19 07:03:33 -0700607 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800608 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700609 return context.line_num_;
610}
611
Ian Rogers0571d352011-11-03 19:51:38 -0700612int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
Elliott Hughesba8eee12012-01-24 20:25:24 -0800613 uint32_t address) {
Ian Rogers0571d352011-11-03 19:51:38 -0700614 // Note: Signed type is important for max and min.
615 int32_t min = 0;
616 int32_t max = tries_size - 1;
617
618 while (max >= min) {
619 int32_t mid = (min + max) / 2;
Elliott Hughes24edeb52012-06-18 15:29:46 -0700620 const TryItem* try_item = DexFile::GetTryItems(code_item, mid);
621 uint32_t start = try_item->start_addr_;
Ian Rogers0571d352011-11-03 19:51:38 -0700622 if (address < start) {
623 max = mid - 1;
624 } else {
Elliott Hughes24edeb52012-06-18 15:29:46 -0700625 uint32_t end = start + try_item->insn_count_;
Ian Rogers0571d352011-11-03 19:51:38 -0700626 if (address >= end) {
627 min = mid + 1;
628 } else { // We have a winner!
Elliott Hughes24edeb52012-06-18 15:29:46 -0700629 return (int32_t) try_item->handler_off_;
Ian Rogers0571d352011-11-03 19:51:38 -0700630 }
631 }
632 }
633 // No match.
634 return -1;
635}
636
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800637void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800638 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
639 void* context, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700640 uint32_t line = DecodeUnsignedLeb128(&stream);
641 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
642 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
643 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700644 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700645
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800646 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700647 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800648 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700649 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800650 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800651 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700652 local_in_reg[arg_reg].start_address_ = 0;
653 local_in_reg[arg_reg].is_live_ = true;
654 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700655 arg_reg++;
656 }
657
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800658 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700659 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700660 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700661 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800662 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700663 return;
664 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800665 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700666 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800667 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700668 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700669 local_in_reg[arg_reg].name_ = name;
670 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800671 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700672 local_in_reg[arg_reg].start_address_ = address;
673 local_in_reg[arg_reg].is_live_ = true;
674 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700675 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700676 case 'D':
677 case 'J':
678 arg_reg += 2;
679 break;
680 default:
681 arg_reg += 1;
682 break;
683 }
684 }
685
Ian Rogers0571d352011-11-03 19:51:38 -0700686 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800687 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700688 return;
689 }
690
691 for (;;) {
692 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700693 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700694 uint16_t name_idx;
695 uint16_t descriptor_idx;
696 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700697
Shih-wei Liao195487c2011-08-20 13:29:04 -0700698 switch (opcode) {
699 case DBG_END_SEQUENCE:
700 return;
701
702 case DBG_ADVANCE_PC:
703 address += DecodeUnsignedLeb128(&stream);
704 break;
705
706 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700707 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700708 break;
709
710 case DBG_START_LOCAL:
711 case DBG_START_LOCAL_EXTENDED:
712 reg = DecodeUnsignedLeb128(&stream);
713 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700714 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800715 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700716 return;
717 }
718
jeffhaof8728872011-10-28 19:11:13 -0700719 name_idx = DecodeUnsignedLeb128P1(&stream);
720 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
721 if (opcode == DBG_START_LOCAL_EXTENDED) {
722 signature_idx = DecodeUnsignedLeb128P1(&stream);
723 }
724
Shih-wei Liao195487c2011-08-20 13:29:04 -0700725 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700726 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800727 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700728
Ian Rogers0571d352011-11-03 19:51:38 -0700729 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
730 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700731 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700732 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700733 }
734 local_in_reg[reg].start_address_ = address;
735 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700737 break;
738
739 case DBG_END_LOCAL:
740 reg = DecodeUnsignedLeb128(&stream);
741 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700742 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800743 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700744 return;
745 }
746
Elliott Hughes30646832011-10-13 16:59:46 -0700747 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800748 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Elliott Hughes30646832011-10-13 16:59:46 -0700749 local_in_reg[reg].is_live_ = false;
750 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700751 break;
752
753 case DBG_RESTART_LOCAL:
754 reg = DecodeUnsignedLeb128(&stream);
755 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700756 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800757 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700758 return;
759 }
760
Elliott Hughes30646832011-10-13 16:59:46 -0700761 if (need_locals) {
762 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800763 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700764 return;
765 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700766
Elliott Hughes30646832011-10-13 16:59:46 -0700767 // If the register is live, the "restart" is superfluous,
768 // and we don't want to mess with the existing start address.
769 if (!local_in_reg[reg].is_live_) {
770 local_in_reg[reg].start_address_ = address;
771 local_in_reg[reg].is_live_ = true;
772 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700773 }
774 break;
775
776 case DBG_SET_PROLOGUE_END:
777 case DBG_SET_EPILOGUE_BEGIN:
778 case DBG_SET_FILE:
779 break;
780
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700781 default: {
782 int adjopcode = opcode - DBG_FIRST_SPECIAL;
783
Shih-wei Liao195487c2011-08-20 13:29:04 -0700784 address += adjopcode / DBG_LINE_RANGE;
785 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
786
Elliott Hughes2435a572012-02-17 16:07:41 -0800787 if (position_cb != NULL) {
788 if (position_cb(context, address, line)) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700789 // early exit
790 return;
791 }
792 }
793 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700794 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700795 }
796 }
797}
798
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800799void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800800 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
801 void* context) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700802 const byte* stream = GetDebugInfoStream(code_item);
Elliott Hughesee0fa762012-03-26 17:12:41 -0700803 UniquePtr<LocalInfo[]> local_in_reg(local_cb != NULL ? new LocalInfo[code_item->registers_size_] : NULL);
Ian Rogers0571d352011-11-03 19:51:38 -0700804 if (stream != NULL) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700805 DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]);
Ian Rogers0571d352011-11-03 19:51:38 -0700806 }
807 for (int reg = 0; reg < code_item->registers_size_; reg++) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700808 InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb);
Ian Rogers0571d352011-11-03 19:51:38 -0700809 }
810}
811
Elliott Hughes2435a572012-02-17 16:07:41 -0800812bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) {
813 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
Ian Rogers0571d352011-11-03 19:51:38 -0700814
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_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700840 if (last_idx_ != 0 && field_.field_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700841 LOG(WARNING) << "Duplicate field " << PrettyField(GetMemberIndex(), dex_file_)
842 << " in " << dex_file_.GetLocation();
843 }
Ian Rogers0571d352011-11-03 19:51:38 -0700844}
845
846void ClassDataItemIterator::ReadClassDataMethod() {
847 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
848 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
849 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700850 if (last_idx_ != 0 && method_.method_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700851 LOG(WARNING) << "Duplicate method " << PrettyMethod(GetMemberIndex(), dex_file_)
852 << " in " << dex_file_.GetLocation();
853 }
Ian Rogers0571d352011-11-03 19:51:38 -0700854}
855
856// Read a signed integer. "zwidth" is the zero-based byte count.
857static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
858 int32_t val = 0;
859 for (int i = zwidth; i >= 0; --i) {
860 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
861 }
862 val >>= (3 - zwidth) * 8;
863 return val;
864}
865
866// Read an unsigned integer. "zwidth" is the zero-based byte count,
867// "fill_on_right" indicates which side we want to zero-fill from.
868static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
869 uint32_t val = 0;
870 if (!fill_on_right) {
871 for (int i = zwidth; i >= 0; --i) {
872 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
873 }
874 val >>= (3 - zwidth) * 8;
875 } else {
876 for (int i = zwidth; i >= 0; --i) {
877 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
878 }
879 }
880 return val;
881}
882
883// Read a signed long. "zwidth" is the zero-based byte count.
884static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
885 int64_t val = 0;
886 for (int i = zwidth; i >= 0; --i) {
887 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
888 }
889 val >>= (7 - zwidth) * 8;
890 return val;
891}
892
893// Read an unsigned long. "zwidth" is the zero-based byte count,
894// "fill_on_right" indicates which side we want to zero-fill from.
895static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
896 uint64_t val = 0;
897 if (!fill_on_right) {
898 for (int i = zwidth; i >= 0; --i) {
899 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
900 }
901 val >>= (7 - zwidth) * 8;
902 } else {
903 for (int i = zwidth; i >= 0; --i) {
904 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
905 }
906 }
907 return val;
908}
909
910EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800911 mirror::DexCache* dex_cache,
912 mirror::ClassLoader* class_loader,
Ian Rogersca190662012-06-26 15:45:57 -0700913 ClassLinker* linker,
914 const DexFile::ClassDef& class_def)
Brian Carlstrom88f36542012-10-16 23:24:21 -0700915 : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker),
916 array_size_(), pos_(-1), type_(kByte) {
Ian Rogers0571d352011-11-03 19:51:38 -0700917 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
918 if (ptr_ == NULL) {
919 array_size_ = 0;
920 } else {
921 array_size_ = DecodeUnsignedLeb128(&ptr_);
922 }
923 if (array_size_ > 0) {
924 Next();
925 }
926}
927
928void EncodedStaticFieldValueIterator::Next() {
929 pos_++;
930 if (pos_ >= array_size_) {
931 return;
932 }
933 byte value_type = *ptr_++;
934 byte value_arg = value_type >> kEncodedValueArgShift;
935 size_t width = value_arg + 1; // assume and correct later
Brian Carlstrom88f36542012-10-16 23:24:21 -0700936 type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
Ian Rogers0571d352011-11-03 19:51:38 -0700937 switch (type_) {
938 case kBoolean:
939 jval_.i = (value_arg != 0) ? 1 : 0;
940 width = 0;
941 break;
942 case kByte:
943 jval_.i = ReadSignedInt(ptr_, value_arg);
944 CHECK(IsInt(8, jval_.i));
945 break;
946 case kShort:
947 jval_.i = ReadSignedInt(ptr_, value_arg);
948 CHECK(IsInt(16, jval_.i));
949 break;
950 case kChar:
951 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
952 CHECK(IsUint(16, jval_.i));
953 break;
954 case kInt:
955 jval_.i = ReadSignedInt(ptr_, value_arg);
956 break;
957 case kLong:
958 jval_.j = ReadSignedLong(ptr_, value_arg);
959 break;
960 case kFloat:
961 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
962 break;
963 case kDouble:
964 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
965 break;
966 case kString:
967 case kType:
Ian Rogers0571d352011-11-03 19:51:38 -0700968 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
969 break;
970 case kField:
Brian Carlstrom88f36542012-10-16 23:24:21 -0700971 case kMethod:
972 case kEnum:
Ian Rogers0571d352011-11-03 19:51:38 -0700973 case kArray:
974 case kAnnotation:
975 UNIMPLEMENTED(FATAL) << ": type " << type_;
976 break;
977 case kNull:
978 jval_.l = NULL;
979 width = 0;
980 break;
981 default:
982 LOG(FATAL) << "Unreached";
983 }
984 ptr_ += width;
985}
986
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800987void EncodedStaticFieldValueIterator::ReadValueToField(mirror::Field* field) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700988 switch (type_) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700989 case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); break;
990 case kByte: field->SetByte(field->GetDeclaringClass(), jval_.b); break;
991 case kShort: field->SetShort(field->GetDeclaringClass(), jval_.s); break;
992 case kChar: field->SetChar(field->GetDeclaringClass(), jval_.c); break;
993 case kInt: field->SetInt(field->GetDeclaringClass(), jval_.i); break;
994 case kLong: field->SetLong(field->GetDeclaringClass(), jval_.j); break;
995 case kFloat: field->SetFloat(field->GetDeclaringClass(), jval_.f); break;
996 case kDouble: field->SetDouble(field->GetDeclaringClass(), jval_.d); break;
997 case kNull: field->SetObject(field->GetDeclaringClass(), NULL); break;
Ian Rogers0571d352011-11-03 19:51:38 -0700998 case kString: {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800999 mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001000 field->SetObject(field->GetDeclaringClass(), resolved);
Ian Rogers0571d352011-11-03 19:51:38 -07001001 break;
1002 }
Brian Carlstrom88f36542012-10-16 23:24:21 -07001003 case kType: {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001004 mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_);
mikaelpeltierebf6aa82012-11-07 14:02:15 +01001005 field->SetObject(field->GetDeclaringClass(), resolved);
Brian Carlstrom88f36542012-10-16 23:24:21 -07001006 break;
1007 }
Ian Rogers0571d352011-11-03 19:51:38 -07001008 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
1009 }
1010}
1011
1012CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
1013 handler_.address_ = -1;
1014 int32_t offset = -1;
1015
1016 // Short-circuit the overwhelmingly common cases.
1017 switch (code_item.tries_size_) {
1018 case 0:
1019 break;
1020 case 1: {
1021 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1022 uint32_t start = tries->start_addr_;
1023 if (address >= start) {
1024 uint32_t end = start + tries->insn_count_;
1025 if (address < end) {
1026 offset = tries->handler_off_;
1027 }
1028 }
1029 break;
1030 }
1031 default:
1032 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1033 }
Logan Chien736df022012-04-27 16:25:57 +08001034 Init(code_item, offset);
1035}
1036
1037CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
1038 const DexFile::TryItem& try_item) {
1039 handler_.address_ = -1;
1040 Init(code_item, try_item.handler_off_);
1041}
1042
1043void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
1044 int32_t offset) {
Ian Rogers0571d352011-11-03 19:51:38 -07001045 if (offset >= 0) {
Logan Chien736df022012-04-27 16:25:57 +08001046 Init(DexFile::GetCatchHandlerData(code_item, offset));
Ian Rogers0571d352011-11-03 19:51:38 -07001047 } else {
1048 // Not found, initialize as empty
1049 current_data_ = NULL;
1050 remaining_count_ = -1;
1051 catch_all_ = false;
1052 DCHECK(!HasNext());
1053 }
1054}
1055
1056void CatchHandlerIterator::Init(const byte* handler_data) {
1057 current_data_ = handler_data;
1058 remaining_count_ = DecodeSignedLeb128(&current_data_);
1059
1060 // If remaining_count_ is non-positive, then it is the negative of
1061 // the number of catch types, and the catches are followed by a
1062 // catch-all handler.
1063 if (remaining_count_ <= 0) {
1064 catch_all_ = true;
1065 remaining_count_ = -remaining_count_;
1066 } else {
1067 catch_all_ = false;
1068 }
1069 Next();
1070}
1071
1072void CatchHandlerIterator::Next() {
1073 if (remaining_count_ > 0) {
1074 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1075 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1076 remaining_count_--;
1077 return;
1078 }
1079
1080 if (catch_all_) {
1081 handler_.type_idx_ = DexFile::kDexNoIndex16;
1082 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1083 catch_all_ = false;
1084 return;
1085 }
1086
1087 // no more handler
1088 remaining_count_ = -1;
1089}
1090
Carl Shapiro1fb86202011-06-27 17:43:13 -07001091} // namespace art