blob: 11ddcd585b0c661c28abb3c982c5bdef1ab48b40 [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 Rogersdbbc99d2013-04-18 16:51:54 -0700612int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) {
Ian Rogers0571d352011-11-03 19:51:38 -0700613 // Note: Signed type is important for max and min.
614 int32_t min = 0;
Ian Rogersdbbc99d2013-04-18 16:51:54 -0700615 int32_t max = code_item.tries_size_ - 1;
Ian Rogers0571d352011-11-03 19:51:38 -0700616
Ian Rogersdbbc99d2013-04-18 16:51:54 -0700617 while (min <= max) {
618 int32_t mid = min + ((max - min) / 2);
619
620 const art::DexFile::TryItem* ti = GetTryItems(code_item, mid);
621 uint32_t start = ti->start_addr_;
622 uint32_t end = start + ti->insn_count_;
623
Ian Rogers0571d352011-11-03 19:51:38 -0700624 if (address < start) {
625 max = mid - 1;
Ian Rogersdbbc99d2013-04-18 16:51:54 -0700626 } else if (address >= end) {
627 min = mid + 1;
628 } else { // We have a winner!
629 return mid;
Ian Rogers0571d352011-11-03 19:51:38 -0700630 }
631 }
632 // No match.
633 return -1;
634}
635
Ian Rogersdbbc99d2013-04-18 16:51:54 -0700636int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, uint32_t address) {
637 int32_t try_item = FindTryItem(code_item, address);
638 if (try_item == -1) {
639 return -1;
640 } else {
641 return DexFile::GetTryItems(code_item, try_item)->handler_off_;
642 }
643}
644
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800645void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800646 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
647 void* context, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700648 uint32_t line = DecodeUnsignedLeb128(&stream);
649 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
650 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
651 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700652 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700653
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800654 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700655 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800656 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700657 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800658 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800659 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700660 local_in_reg[arg_reg].start_address_ = 0;
661 local_in_reg[arg_reg].is_live_ = true;
662 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700663 arg_reg++;
664 }
665
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800666 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700667 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700668 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700669 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800670 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700671 return;
672 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800673 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700674 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800675 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700676 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700677 local_in_reg[arg_reg].name_ = name;
678 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800679 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700680 local_in_reg[arg_reg].start_address_ = address;
681 local_in_reg[arg_reg].is_live_ = true;
682 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700683 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700684 case 'D':
685 case 'J':
686 arg_reg += 2;
687 break;
688 default:
689 arg_reg += 1;
690 break;
691 }
692 }
693
Ian Rogers0571d352011-11-03 19:51:38 -0700694 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800695 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700696 return;
697 }
698
699 for (;;) {
700 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700701 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700702 uint16_t name_idx;
703 uint16_t descriptor_idx;
704 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700705
Shih-wei Liao195487c2011-08-20 13:29:04 -0700706 switch (opcode) {
707 case DBG_END_SEQUENCE:
708 return;
709
710 case DBG_ADVANCE_PC:
711 address += DecodeUnsignedLeb128(&stream);
712 break;
713
714 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700715 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700716 break;
717
718 case DBG_START_LOCAL:
719 case DBG_START_LOCAL_EXTENDED:
720 reg = DecodeUnsignedLeb128(&stream);
721 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700722 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800723 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700724 return;
725 }
726
jeffhaof8728872011-10-28 19:11:13 -0700727 name_idx = DecodeUnsignedLeb128P1(&stream);
728 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
729 if (opcode == DBG_START_LOCAL_EXTENDED) {
730 signature_idx = DecodeUnsignedLeb128P1(&stream);
731 }
732
Shih-wei Liao195487c2011-08-20 13:29:04 -0700733 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700734 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800735 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736
Ian Rogers0571d352011-11-03 19:51:38 -0700737 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
738 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700739 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700740 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700741 }
742 local_in_reg[reg].start_address_ = address;
743 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700744 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700745 break;
746
747 case DBG_END_LOCAL:
748 reg = DecodeUnsignedLeb128(&stream);
749 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700750 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800751 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700752 return;
753 }
754
Elliott Hughes30646832011-10-13 16:59:46 -0700755 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800756 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Elliott Hughes30646832011-10-13 16:59:46 -0700757 local_in_reg[reg].is_live_ = false;
758 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700759 break;
760
761 case DBG_RESTART_LOCAL:
762 reg = DecodeUnsignedLeb128(&stream);
763 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700764 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800765 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700766 return;
767 }
768
Elliott Hughes30646832011-10-13 16:59:46 -0700769 if (need_locals) {
770 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800771 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700772 return;
773 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700774
Elliott Hughes30646832011-10-13 16:59:46 -0700775 // If the register is live, the "restart" is superfluous,
776 // and we don't want to mess with the existing start address.
777 if (!local_in_reg[reg].is_live_) {
778 local_in_reg[reg].start_address_ = address;
779 local_in_reg[reg].is_live_ = true;
780 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700781 }
782 break;
783
784 case DBG_SET_PROLOGUE_END:
785 case DBG_SET_EPILOGUE_BEGIN:
786 case DBG_SET_FILE:
787 break;
788
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700789 default: {
790 int adjopcode = opcode - DBG_FIRST_SPECIAL;
791
Shih-wei Liao195487c2011-08-20 13:29:04 -0700792 address += adjopcode / DBG_LINE_RANGE;
793 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
794
Elliott Hughes2435a572012-02-17 16:07:41 -0800795 if (position_cb != NULL) {
796 if (position_cb(context, address, line)) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700797 // early exit
798 return;
799 }
800 }
801 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700802 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700803 }
804 }
805}
806
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800807void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800808 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
809 void* context) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700810 const byte* stream = GetDebugInfoStream(code_item);
Elliott Hughesee0fa762012-03-26 17:12:41 -0700811 UniquePtr<LocalInfo[]> local_in_reg(local_cb != NULL ? new LocalInfo[code_item->registers_size_] : NULL);
Ian Rogers0571d352011-11-03 19:51:38 -0700812 if (stream != NULL) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700813 DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]);
Ian Rogers0571d352011-11-03 19:51:38 -0700814 }
815 for (int reg = 0; reg < code_item->registers_size_; reg++) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700816 InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb);
Ian Rogers0571d352011-11-03 19:51:38 -0700817 }
818}
819
Elliott Hughes2435a572012-02-17 16:07:41 -0800820bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) {
821 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
Ian Rogers0571d352011-11-03 19:51:38 -0700822
823 // We know that this callback will be called in
824 // ascending address order, so keep going until we find
825 // a match or we've just gone past it.
826 if (address > context->address_) {
827 // The line number from the previous positions callback
828 // wil be the final result.
829 return true;
830 } else {
831 context->line_num_ = line_num;
832 return address == context->address_;
833 }
834}
835
836// Decodes the header section from the class data bytes.
837void ClassDataItemIterator::ReadClassDataHeader() {
838 CHECK(ptr_pos_ != NULL);
839 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
840 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
841 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
842 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
843}
844
845void ClassDataItemIterator::ReadClassDataField() {
846 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
847 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700848 if (last_idx_ != 0 && field_.field_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700849 LOG(WARNING) << "Duplicate field " << PrettyField(GetMemberIndex(), dex_file_)
850 << " in " << dex_file_.GetLocation();
851 }
Ian Rogers0571d352011-11-03 19:51:38 -0700852}
853
854void ClassDataItemIterator::ReadClassDataMethod() {
855 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
856 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
857 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700858 if (last_idx_ != 0 && method_.method_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700859 LOG(WARNING) << "Duplicate method " << PrettyMethod(GetMemberIndex(), dex_file_)
860 << " in " << dex_file_.GetLocation();
861 }
Ian Rogers0571d352011-11-03 19:51:38 -0700862}
863
864// Read a signed integer. "zwidth" is the zero-based byte count.
865static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
866 int32_t val = 0;
867 for (int i = zwidth; i >= 0; --i) {
868 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
869 }
870 val >>= (3 - zwidth) * 8;
871 return val;
872}
873
874// Read an unsigned integer. "zwidth" is the zero-based byte count,
875// "fill_on_right" indicates which side we want to zero-fill from.
876static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
877 uint32_t val = 0;
878 if (!fill_on_right) {
879 for (int i = zwidth; i >= 0; --i) {
880 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
881 }
882 val >>= (3 - zwidth) * 8;
883 } else {
884 for (int i = zwidth; i >= 0; --i) {
885 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
886 }
887 }
888 return val;
889}
890
891// Read a signed long. "zwidth" is the zero-based byte count.
892static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
893 int64_t val = 0;
894 for (int i = zwidth; i >= 0; --i) {
895 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
896 }
897 val >>= (7 - zwidth) * 8;
898 return val;
899}
900
901// Read an unsigned long. "zwidth" is the zero-based byte count,
902// "fill_on_right" indicates which side we want to zero-fill from.
903static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
904 uint64_t val = 0;
905 if (!fill_on_right) {
906 for (int i = zwidth; i >= 0; --i) {
907 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
908 }
909 val >>= (7 - zwidth) * 8;
910 } else {
911 for (int i = zwidth; i >= 0; --i) {
912 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
913 }
914 }
915 return val;
916}
917
918EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800919 mirror::DexCache* dex_cache,
920 mirror::ClassLoader* class_loader,
Ian Rogersca190662012-06-26 15:45:57 -0700921 ClassLinker* linker,
922 const DexFile::ClassDef& class_def)
Brian Carlstrom88f36542012-10-16 23:24:21 -0700923 : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker),
924 array_size_(), pos_(-1), type_(kByte) {
Ian Rogers0571d352011-11-03 19:51:38 -0700925 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
926 if (ptr_ == NULL) {
927 array_size_ = 0;
928 } else {
929 array_size_ = DecodeUnsignedLeb128(&ptr_);
930 }
931 if (array_size_ > 0) {
932 Next();
933 }
934}
935
936void EncodedStaticFieldValueIterator::Next() {
937 pos_++;
938 if (pos_ >= array_size_) {
939 return;
940 }
941 byte value_type = *ptr_++;
942 byte value_arg = value_type >> kEncodedValueArgShift;
943 size_t width = value_arg + 1; // assume and correct later
Brian Carlstrom88f36542012-10-16 23:24:21 -0700944 type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
Ian Rogers0571d352011-11-03 19:51:38 -0700945 switch (type_) {
946 case kBoolean:
947 jval_.i = (value_arg != 0) ? 1 : 0;
948 width = 0;
949 break;
950 case kByte:
951 jval_.i = ReadSignedInt(ptr_, value_arg);
952 CHECK(IsInt(8, jval_.i));
953 break;
954 case kShort:
955 jval_.i = ReadSignedInt(ptr_, value_arg);
956 CHECK(IsInt(16, jval_.i));
957 break;
958 case kChar:
959 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
960 CHECK(IsUint(16, jval_.i));
961 break;
962 case kInt:
963 jval_.i = ReadSignedInt(ptr_, value_arg);
964 break;
965 case kLong:
966 jval_.j = ReadSignedLong(ptr_, value_arg);
967 break;
968 case kFloat:
969 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
970 break;
971 case kDouble:
972 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
973 break;
974 case kString:
975 case kType:
Ian Rogers0571d352011-11-03 19:51:38 -0700976 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
977 break;
978 case kField:
Brian Carlstrom88f36542012-10-16 23:24:21 -0700979 case kMethod:
980 case kEnum:
Ian Rogers0571d352011-11-03 19:51:38 -0700981 case kArray:
982 case kAnnotation:
983 UNIMPLEMENTED(FATAL) << ": type " << type_;
984 break;
985 case kNull:
986 jval_.l = NULL;
987 width = 0;
988 break;
989 default:
990 LOG(FATAL) << "Unreached";
991 }
992 ptr_ += width;
993}
994
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800995void EncodedStaticFieldValueIterator::ReadValueToField(mirror::Field* field) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700996 switch (type_) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700997 case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); break;
998 case kByte: field->SetByte(field->GetDeclaringClass(), jval_.b); break;
999 case kShort: field->SetShort(field->GetDeclaringClass(), jval_.s); break;
1000 case kChar: field->SetChar(field->GetDeclaringClass(), jval_.c); break;
1001 case kInt: field->SetInt(field->GetDeclaringClass(), jval_.i); break;
1002 case kLong: field->SetLong(field->GetDeclaringClass(), jval_.j); break;
1003 case kFloat: field->SetFloat(field->GetDeclaringClass(), jval_.f); break;
1004 case kDouble: field->SetDouble(field->GetDeclaringClass(), jval_.d); break;
1005 case kNull: field->SetObject(field->GetDeclaringClass(), NULL); break;
Ian Rogers0571d352011-11-03 19:51:38 -07001006 case kString: {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001007 mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001008 field->SetObject(field->GetDeclaringClass(), resolved);
Ian Rogers0571d352011-11-03 19:51:38 -07001009 break;
1010 }
Brian Carlstrom88f36542012-10-16 23:24:21 -07001011 case kType: {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001012 mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_);
mikaelpeltierebf6aa82012-11-07 14:02:15 +01001013 field->SetObject(field->GetDeclaringClass(), resolved);
Brian Carlstrom88f36542012-10-16 23:24:21 -07001014 break;
1015 }
Ian Rogers0571d352011-11-03 19:51:38 -07001016 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
1017 }
1018}
1019
1020CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
1021 handler_.address_ = -1;
1022 int32_t offset = -1;
1023
1024 // Short-circuit the overwhelmingly common cases.
1025 switch (code_item.tries_size_) {
1026 case 0:
1027 break;
1028 case 1: {
1029 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1030 uint32_t start = tries->start_addr_;
1031 if (address >= start) {
1032 uint32_t end = start + tries->insn_count_;
1033 if (address < end) {
1034 offset = tries->handler_off_;
1035 }
1036 }
1037 break;
1038 }
1039 default:
Ian Rogersdbbc99d2013-04-18 16:51:54 -07001040 offset = DexFile::FindCatchHandlerOffset(code_item, address);
Ian Rogers0571d352011-11-03 19:51:38 -07001041 }
Logan Chien736df022012-04-27 16:25:57 +08001042 Init(code_item, offset);
1043}
1044
1045CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
1046 const DexFile::TryItem& try_item) {
1047 handler_.address_ = -1;
1048 Init(code_item, try_item.handler_off_);
1049}
1050
1051void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
1052 int32_t offset) {
Ian Rogers0571d352011-11-03 19:51:38 -07001053 if (offset >= 0) {
Logan Chien736df022012-04-27 16:25:57 +08001054 Init(DexFile::GetCatchHandlerData(code_item, offset));
Ian Rogers0571d352011-11-03 19:51:38 -07001055 } else {
1056 // Not found, initialize as empty
1057 current_data_ = NULL;
1058 remaining_count_ = -1;
1059 catch_all_ = false;
1060 DCHECK(!HasNext());
1061 }
1062}
1063
1064void CatchHandlerIterator::Init(const byte* handler_data) {
1065 current_data_ = handler_data;
1066 remaining_count_ = DecodeSignedLeb128(&current_data_);
1067
1068 // If remaining_count_ is non-positive, then it is the negative of
1069 // the number of catch types, and the catches are followed by a
1070 // catch-all handler.
1071 if (remaining_count_ <= 0) {
1072 catch_all_ = true;
1073 remaining_count_ = -remaining_count_;
1074 } else {
1075 catch_all_ = false;
1076 }
1077 Next();
1078}
1079
1080void CatchHandlerIterator::Next() {
1081 if (remaining_count_ > 0) {
1082 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1083 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1084 remaining_count_--;
1085 return;
1086 }
1087
1088 if (catch_all_) {
1089 handler_.type_idx_ = DexFile::kDexNoIndex16;
1090 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1091 catch_all_ = false;
1092 return;
1093 }
1094
1095 // no more handler
1096 remaining_count_ = -1;
1097}
1098
Carl Shapiro1fb86202011-06-27 17:43:13 -07001099} // namespace art