blob: 3ba671e23e982eb1e4cb7abea9ecd61492981436 [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/mman.h>
26#include <sys/stat.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070027
Ian Rogers0571d352011-11-03 19:51:38 -070028#include "class_linker.h"
jeffhao10037c82012-01-23 15:06:23 -080029#include "dex_file_verifier.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070030#include "globals.h"
Ian Rogers0571d352011-11-03 19:51:38 -070031#include "leb128.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070032#include "logging.h"
33#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070034#include "os.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070035#include "safe_map.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070036#include "stringprintf.h"
37#include "thread.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070038#include "UniquePtr.h"
Ian Rogers0571d352011-11-03 19:51:38 -070039#include "utf.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070040#include "utils.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070041#include "well_known_classes.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070042#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070043
44namespace art {
45
Brian Carlstromf615a612011-07-23 12:50:34 -070046const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
47const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070048
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070049DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070050 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070051 for (size_t i = 0; i != class_path.size(); ++i) {
52 const DexFile* dex_file = class_path[i];
53 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
54 if (dex_class_def != NULL) {
55 return ClassPathEntry(dex_file, dex_class_def);
56 }
57 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070058 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070059 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
60 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070061}
62
Brian Carlstrom5b332c82012-02-01 15:02:31 -080063bool DexFile::GetChecksum(const std::string& filename, uint32_t& checksum) {
64 if (IsValidZipFilename(filename)) {
65 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
66 if (zip_archive.get() == NULL) {
67 return false;
Brian Carlstrom78128a62011-09-15 17:21:19 -070068 }
Brian Carlstrom5b332c82012-02-01 15:02:31 -080069 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
70 if (zip_entry.get() == NULL) {
71 return false;
72 }
73 checksum = zip_entry->GetCrc32();
74 return true;
Brian Carlstrom78128a62011-09-15 17:21:19 -070075 }
Brian Carlstrom5b332c82012-02-01 15:02:31 -080076 if (IsValidDexFilename(filename)) {
Brian Carlstrom1db858a2012-03-11 22:44:45 -070077 UniquePtr<const DexFile> dex_file(DexFile::OpenFile(filename, filename, false));
Brian Carlstrom5b332c82012-02-01 15:02:31 -080078 if (dex_file.get() == NULL) {
79 return false;
80 }
81 checksum = dex_file->GetHeader().checksum_;
82 return true;
83 }
84 return false;
Brian Carlstrom78128a62011-09-15 17:21:19 -070085}
86
Brian Carlstrom16192862011-09-12 17:50:06 -070087const DexFile* DexFile::Open(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -080088 const std::string& location) {
jeffhao262bf462011-10-20 18:36:32 -070089 if (IsValidZipFilename(filename)) {
Brian Carlstroma004aa92012-02-08 18:05:09 -080090 return DexFile::OpenZip(filename, location);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070091 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -070092 if (!IsValidDexFilename(filename)) {
93 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
94 }
Brian Carlstroma004aa92012-02-08 18:05:09 -080095 return DexFile::OpenFile(filename, location, true);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070096}
97
jeffhaob4df5142011-09-19 20:25:32 -070098void DexFile::ChangePermissions(int prot) const {
Logan Chiend88fa262012-06-06 15:23:32 +080099 mem_map_->Protect(prot);
jeffhaob4df5142011-09-19 20:25:32 -0700100}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700101
Brian Carlstrom16192862011-09-12 17:50:06 -0700102const DexFile* DexFile::OpenFile(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -0800103 const std::string& location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800104 bool verify) {
Brian Carlstroma004aa92012-02-08 18:05:09 -0800105 CHECK(!location.empty()) << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700106 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700107 if (fd == -1) {
108 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
109 return NULL;
110 }
111 struct stat sbuf;
112 memset(&sbuf, 0, sizeof(sbuf));
113 if (fstat(fd, &sbuf) == -1) {
114 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
115 close(fd);
116 return NULL;
117 }
Ian Rogers7cfb93e2012-01-17 19:46:36 -0800118 if (S_ISDIR(sbuf.st_mode)) {
119 LOG(ERROR) << "attempt to mmap directory \"" << filename << "\"";
120 return NULL;
121 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700122 size_t length = sbuf.st_size;
Brian Carlstrom89521892011-12-07 22:05:07 -0800123 UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0));
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700124 if (map.get() == NULL) {
125 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700126 close(fd);
127 return NULL;
128 }
129 close(fd);
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800130
131 if (map->Size() < sizeof(DexFile::Header)) {
132 LOG(ERROR) << "Failed to open dex file '" << filename << "' that is too short to have a header";
133 return NULL;
134 }
135
136 const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
137
138 const DexFile* dex_file = OpenMemory(location, dex_header->checksum_, map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800139 if (dex_file == NULL) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800140 LOG(ERROR) << "Failed to open dex file '" << filename << "' from memory";
jeffhao54c1ceb2012-02-01 11:45:32 -0800141 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800142 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800143
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700144 if (verify && !DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800145 LOG(ERROR) << "Failed to verify dex file '" << filename << "'";
jeffhao54c1ceb2012-02-01 11:45:32 -0800146 return NULL;
147 }
148
jeffhaof6174e82012-01-31 16:14:17 -0800149 return dex_file;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700150}
151
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700152const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700153
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700154// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700155const DexFile* DexFile::OpenZip(const std::string& filename,
Brian Carlstroma004aa92012-02-08 18:05:09 -0800156 const std::string& location) {
Elliott Hughes90a33692011-08-30 13:27:07 -0700157 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
158 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700159 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700160 return NULL;
161 }
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800162 return DexFile::Open(*zip_archive.get(), location);
163}
164
165const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
Brian Carlstroma004aa92012-02-08 18:05:09 -0800166 CHECK(!location.empty());
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800167 UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
Elliott Hughes90a33692011-08-30 13:27:07 -0700168 if (zip_entry.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800169 LOG(ERROR) << "Failed to find classes.dex within " << location;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700170 return NULL;
171 }
172
Brian Carlstrom89521892011-12-07 22:05:07 -0800173 uint32_t length = zip_entry->GetUncompressedLength();
Elliott Hughes850162c2012-01-12 18:46:43 -0800174 std::string name("classes.dex extracted in memory from ");
175 name += location;
176 UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE));
Brian Carlstrom89521892011-12-07 22:05:07 -0800177 if (map.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800178 LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
Brian Carlstrom89521892011-12-07 22:05:07 -0800179 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700180 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800181
182 // Extract classes.dex
183 bool success = zip_entry->ExtractToMemory(*map.get());
184 if (!success) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800185 LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
Brian Carlstrom89521892011-12-07 22:05:07 -0800186 return NULL;
187 }
188
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800189 const DexFile* dex_file = OpenMemory(location, zip_entry->GetCrc32(), map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800190 if (dex_file == NULL) {
191 LOG(ERROR) << "Failed to open dex file '" << location << "' from memory";
192 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800193 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800194
195 if (!DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
196 LOG(ERROR) << "Failed to verify dex file '" << location << "'";
197 return NULL;
198 }
199
jeffhaof6174e82012-01-31 16:14:17 -0800200 return dex_file;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700201}
202
Brian Carlstrom89521892011-12-07 22:05:07 -0800203const DexFile* DexFile::OpenMemory(const byte* base,
jeffhaof6174e82012-01-31 16:14:17 -0800204 size_t size,
Brian Carlstrom89521892011-12-07 22:05:07 -0800205 const std::string& location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800206 uint32_t location_checksum,
Brian Carlstrom89521892011-12-07 22:05:07 -0800207 MemMap* mem_map) {
208 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800209 UniquePtr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700210 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700211 return NULL;
212 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700213 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700214 }
215}
216
Jesse Wilson6bf19152011-09-29 13:12:33 -0400217DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700218 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
219 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
220 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
221 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400222}
223
224jobject DexFile::GetDexObject(JNIEnv* env) const {
225 MutexLock mu(dex_object_lock_);
226 if (dex_object_ != NULL) {
227 return dex_object_;
228 }
229
Ian Rogers30fab402012-01-23 15:43:46 -0800230 void* address = const_cast<void*>(reinterpret_cast<const void*>(begin_));
jeffhaof6174e82012-01-31 16:14:17 -0800231 jobject byte_buffer = env->NewDirectByteBuffer(address, size_);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400232 if (byte_buffer == NULL) {
233 return NULL;
234 }
235
Jesse Wilson6bf19152011-09-29 13:12:33 -0400236 jvalue args[1];
237 args[0].l = byte_buffer;
Elliott Hugheseac76672012-05-24 21:56:51 -0700238 jobject local = env->CallStaticObjectMethodA(WellKnownClasses::com_android_dex_Dex,
239 WellKnownClasses::com_android_dex_Dex_create,
240 args);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400241 if (local == NULL) {
242 return NULL;
243 }
244
245 dex_object_ = env->NewGlobalRef(local);
246 return dex_object_;
247}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700248
Brian Carlstromf615a612011-07-23 12:50:34 -0700249bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700250 InitMembers();
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800251 if (!CheckMagicAndVersion()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700252 return false;
253 }
254 InitIndex();
255 return true;
256}
257
Brian Carlstromf615a612011-07-23 12:50:34 -0700258void DexFile::InitMembers() {
Ian Rogers30fab402012-01-23 15:43:46 -0800259 const byte* b = begin_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700260 header_ = reinterpret_cast<const Header*>(b);
261 const Header* h = header_;
262 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
263 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
264 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
265 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
266 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
267 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
jeffhaof6174e82012-01-31 16:14:17 -0800268 DCHECK_EQ(size_, header_->file_size_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700269}
270
jeffhao10037c82012-01-23 15:06:23 -0800271bool DexFile::CheckMagicAndVersion() const {
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800272 CHECK(header_->magic_ != NULL) << GetLocation();
273 if (!IsMagicValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800274 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800275 << " " << header_->magic_[0]
276 << " " << header_->magic_[1]
277 << " " << header_->magic_[2]
278 << " " << header_->magic_[3];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700279 return false;
280 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800281 if (!IsVersionValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800282 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800283 << " " << header_->magic_[4]
284 << " " << header_->magic_[5]
285 << " " << header_->magic_[6]
286 << " " << header_->magic_[7];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700287 return false;
288 }
289 return true;
290}
291
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800292bool DexFile::IsMagicValid(const byte* magic) {
293 return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
294}
295
296bool DexFile::IsVersionValid(const byte* magic) {
297 const byte* version = &magic[sizeof(kDexMagic)];
298 return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
299}
300
Ian Rogersd81871c2011-10-03 13:57:23 -0700301uint32_t DexFile::GetVersion() const {
302 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
303 return atoi(version);
304}
305
Ian Rogers0571d352011-11-03 19:51:38 -0700306int32_t DexFile::GetStringLength(const StringId& string_id) const {
Ian Rogers30fab402012-01-23 15:43:46 -0800307 const byte* ptr = begin_ + string_id.string_data_off_;
Ian Rogers0571d352011-11-03 19:51:38 -0700308 return DecodeUnsignedLeb128(&ptr);
309}
310
311// Returns a pointer to the UTF-8 string data referred to by the given string_id.
Elliott Hughes45651fd2012-02-21 15:48:20 -0800312const char* DexFile::GetStringDataAndLength(const StringId& string_id, uint32_t* length) const {
Ian Rogers7b0c5b42012-02-16 15:29:07 -0800313 DCHECK(length != NULL) << GetLocation();
Ian Rogers30fab402012-01-23 15:43:46 -0800314 const byte* ptr = begin_ + string_id.string_data_off_;
Ian Rogers0571d352011-11-03 19:51:38 -0700315 *length = DecodeUnsignedLeb128(&ptr);
316 return reinterpret_cast<const char*>(ptr);
317}
318
Brian Carlstromf615a612011-07-23 12:50:34 -0700319void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800320 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700321 for (size_t i = 0; i < NumClassDefs(); ++i) {
322 const ClassDef& class_def = GetClassDef(i);
323 const char* descriptor = GetClassDescriptor(class_def);
Elliott Hughesa0e18062012-04-13 15:59:59 -0700324 index_.Put(descriptor, i);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700325 }
326}
327
Brian Carlstrome24fa612011-09-29 00:53:55 -0700328bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329 Index::const_iterator it = index_.find(descriptor);
330 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700331 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700332 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700333 idx = it->second;
334 return true;
335}
336
337const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
338 uint32_t idx;
339 if (FindClassDefIndex(descriptor, idx)) {
340 return &GetClassDef(idx);
341 }
342 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700343}
344
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800345const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
346 const DexFile::StringId& name,
347 const DexFile::TypeId& type) const {
348 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
349 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
350 const uint32_t name_idx = GetIndexForStringId(name);
351 const uint16_t type_idx = GetIndexForTypeId(type);
352 uint32_t lo = 0;
353 uint32_t hi = NumFieldIds() - 1;
354 while (hi >= lo) {
355 uint32_t mid = (hi + lo) / 2;
356 const DexFile::FieldId& field = GetFieldId(mid);
357 if (class_idx > field.class_idx_) {
358 lo = mid + 1;
359 } else if (class_idx < field.class_idx_) {
360 hi = mid - 1;
361 } else {
362 if (name_idx > field.name_idx_) {
363 lo = mid + 1;
364 } else if (name_idx < field.name_idx_) {
365 hi = mid - 1;
366 } else {
367 if (type_idx > field.type_idx_) {
368 lo = mid + 1;
369 } else if (type_idx < field.type_idx_) {
370 hi = mid - 1;
371 } else {
372 return &field;
373 }
374 }
375 }
376 }
377 return NULL;
378}
379
380const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700381 const DexFile::StringId& name,
382 const DexFile::ProtoId& signature) const {
383 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800384 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700385 const uint32_t name_idx = GetIndexForStringId(name);
386 const uint16_t proto_idx = GetIndexForProtoId(signature);
387 uint32_t lo = 0;
388 uint32_t hi = NumMethodIds() - 1;
389 while (hi >= lo) {
390 uint32_t mid = (hi + lo) / 2;
391 const DexFile::MethodId& method = GetMethodId(mid);
392 if (class_idx > method.class_idx_) {
393 lo = mid + 1;
394 } else if (class_idx < method.class_idx_) {
395 hi = mid - 1;
396 } else {
397 if (name_idx > method.name_idx_) {
398 lo = mid + 1;
399 } else if (name_idx < method.name_idx_) {
400 hi = mid - 1;
401 } else {
402 if (proto_idx > method.proto_idx_) {
403 lo = mid + 1;
404 } else if (proto_idx < method.proto_idx_) {
405 hi = mid - 1;
406 } else {
407 return &method;
408 }
409 }
410 }
411 }
412 return NULL;
413}
414
415const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
416 uint32_t lo = 0;
417 uint32_t hi = NumStringIds() - 1;
418 while (hi >= lo) {
419 uint32_t mid = (hi + lo) / 2;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800420 uint32_t length;
Ian Rogers0571d352011-11-03 19:51:38 -0700421 const DexFile::StringId& str_id = GetStringId(mid);
422 const char* str = GetStringDataAndLength(str_id, &length);
423 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
424 if (compare > 0) {
425 lo = mid + 1;
426 } else if (compare < 0) {
427 hi = mid - 1;
428 } else {
429 return &str_id;
430 }
431 }
432 return NULL;
433}
434
435const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
436 uint32_t lo = 0;
437 uint32_t hi = NumTypeIds() - 1;
438 while (hi >= lo) {
439 uint32_t mid = (hi + lo) / 2;
440 const TypeId& type_id = GetTypeId(mid);
441 if (string_idx > type_id.descriptor_idx_) {
442 lo = mid + 1;
443 } else if (string_idx < type_id.descriptor_idx_) {
444 hi = mid - 1;
445 } else {
446 return &type_id;
447 }
448 }
449 return NULL;
450}
451
452const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800453 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700454 uint32_t lo = 0;
455 uint32_t hi = NumProtoIds() - 1;
456 while (hi >= lo) {
457 uint32_t mid = (hi + lo) / 2;
458 const DexFile::ProtoId& proto = GetProtoId(mid);
459 int compare = return_type_idx - proto.return_type_idx_;
460 if (compare == 0) {
461 DexFileParameterIterator it(*this, proto);
462 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800463 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
464 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700465 it.Next();
466 i++;
467 }
468 if (compare == 0) {
469 if (it.HasNext()) {
470 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800471 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700472 compare = 1;
473 }
474 }
475 }
476 if (compare > 0) {
477 lo = mid + 1;
478 } else if (compare < 0) {
479 hi = mid - 1;
480 } else {
481 return &proto;
482 }
483 }
484 return NULL;
485}
486
487// Given a signature place the type ids into the given vector
488bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
489 const std::string& signature) const {
490 if (signature[0] != '(') {
491 return false;
492 }
493 size_t offset = 1;
494 size_t end = signature.size();
495 bool process_return = false;
496 while (offset < end) {
497 char c = signature[offset];
498 offset++;
499 if (c == ')') {
500 process_return = true;
501 continue;
502 }
503 std::string descriptor;
504 descriptor += c;
505 while (c == '[') { // process array prefix
506 if (offset >= end) { // expect some descriptor following [
507 return false;
508 }
509 c = signature[offset];
510 offset++;
511 descriptor += c;
512 }
513 if (c == 'L') { // process type descriptors
514 do {
515 if (offset >= end) { // unexpected early termination of descriptor
516 return false;
517 }
518 c = signature[offset];
519 offset++;
520 descriptor += c;
521 } while (c != ';');
522 }
523 const DexFile::StringId* string_id = FindStringId(descriptor);
524 if (string_id == NULL) {
525 return false;
526 }
527 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
528 if (type_id == NULL) {
529 return false;
530 }
531 uint16_t type_idx = GetIndexForTypeId(*type_id);
532 if (!process_return) {
533 param_type_idxs->push_back(type_idx);
534 } else {
535 *return_type_idx = type_idx;
536 return offset == end; // return true if the signature had reached a sensible end
537 }
538 }
539 return false; // failed to correctly parse return type
540}
541
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700542// Materializes the method descriptor for a method prototype. Method
543// descriptors are not stored directly in the dex file. Instead, one
544// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700545std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700546 const ProtoId& proto_id = GetProtoId(proto_idx);
547 std::string descriptor;
548 descriptor.push_back('(');
549 const TypeList* type_list = GetProtoParameters(proto_id);
550 size_t parameter_length = 0;
551 if (type_list != NULL) {
552 // A non-zero number of arguments. Append the type names.
553 for (size_t i = 0; i < type_list->Size(); ++i) {
554 const TypeItem& type_item = type_list->GetTypeItem(i);
555 uint32_t type_idx = type_item.type_idx_;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800556 uint32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700557 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700558 parameter_length += type_length;
559 descriptor.append(name);
560 }
561 }
562 descriptor.push_back(')');
563 uint32_t return_type_idx = proto_id.return_type_idx_;
Elliott Hughes45651fd2012-02-21 15:48:20 -0800564 uint32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700565 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700566 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700567 if (unicode_length != NULL) {
568 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
569 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700570 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700571}
572
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800573int32_t DexFile::GetLineNumFromPC(const Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700574 // For native method, lineno should be -2 to indicate it is native. Note that
575 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700576 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700577 return -2;
578 }
579
TDYa127c8dc1012012-04-19 07:03:33 -0700580 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800581 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700582
583 // A method with no line number info should return -1
584 LineNumFromPcContext context(rel_pc, -1);
TDYa127c8dc1012012-04-19 07:03:33 -0700585 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800586 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700587 return context.line_num_;
588}
589
Ian Rogers0571d352011-11-03 19:51:38 -0700590int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
Elliott Hughesba8eee12012-01-24 20:25:24 -0800591 uint32_t address) {
Ian Rogers0571d352011-11-03 19:51:38 -0700592 // Note: Signed type is important for max and min.
593 int32_t min = 0;
594 int32_t max = tries_size - 1;
595
596 while (max >= min) {
597 int32_t mid = (min + max) / 2;
598 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
599 uint32_t start = pTry->start_addr_;
600 if (address < start) {
601 max = mid - 1;
602 } else {
603 uint32_t end = start + pTry->insn_count_;
604 if (address >= end) {
605 min = mid + 1;
606 } else { // We have a winner!
607 return (int32_t) pTry->handler_off_;
608 }
609 }
610 }
611 // No match.
612 return -1;
613}
614
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800615void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800616 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
617 void* context, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700618 uint32_t line = DecodeUnsignedLeb128(&stream);
619 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
620 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
621 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700622 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700623
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800624 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700625 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800626 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700627 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800628 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800629 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700630 local_in_reg[arg_reg].start_address_ = 0;
631 local_in_reg[arg_reg].is_live_ = true;
632 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700633 arg_reg++;
634 }
635
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800636 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700637 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700638 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700639 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800640 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700641 return;
642 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800643 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700644 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800645 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700646 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700647 local_in_reg[arg_reg].name_ = name;
648 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800649 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700650 local_in_reg[arg_reg].start_address_ = address;
651 local_in_reg[arg_reg].is_live_ = true;
652 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700653 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700654 case 'D':
655 case 'J':
656 arg_reg += 2;
657 break;
658 default:
659 arg_reg += 1;
660 break;
661 }
662 }
663
Ian Rogers0571d352011-11-03 19:51:38 -0700664 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800665 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700666 return;
667 }
668
669 for (;;) {
670 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700671 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700672 uint16_t name_idx;
673 uint16_t descriptor_idx;
674 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700675
Shih-wei Liao195487c2011-08-20 13:29:04 -0700676 switch (opcode) {
677 case DBG_END_SEQUENCE:
678 return;
679
680 case DBG_ADVANCE_PC:
681 address += DecodeUnsignedLeb128(&stream);
682 break;
683
684 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700685 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700686 break;
687
688 case DBG_START_LOCAL:
689 case DBG_START_LOCAL_EXTENDED:
690 reg = DecodeUnsignedLeb128(&stream);
691 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700692 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800693 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700694 return;
695 }
696
jeffhaof8728872011-10-28 19:11:13 -0700697 name_idx = DecodeUnsignedLeb128P1(&stream);
698 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
699 if (opcode == DBG_START_LOCAL_EXTENDED) {
700 signature_idx = DecodeUnsignedLeb128P1(&stream);
701 }
702
Shih-wei Liao195487c2011-08-20 13:29:04 -0700703 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700704 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800705 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700706
Ian Rogers0571d352011-11-03 19:51:38 -0700707 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
708 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700709 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700710 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700711 }
712 local_in_reg[reg].start_address_ = address;
713 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700714 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700715 break;
716
717 case DBG_END_LOCAL:
718 reg = DecodeUnsignedLeb128(&stream);
719 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700720 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800721 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700722 return;
723 }
724
Elliott Hughes30646832011-10-13 16:59:46 -0700725 if (need_locals) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800726 InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
Elliott Hughes30646832011-10-13 16:59:46 -0700727 local_in_reg[reg].is_live_ = false;
728 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700729 break;
730
731 case DBG_RESTART_LOCAL:
732 reg = DecodeUnsignedLeb128(&stream);
733 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700734 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800735 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736 return;
737 }
738
Elliott Hughes30646832011-10-13 16:59:46 -0700739 if (need_locals) {
740 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800741 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700742 return;
743 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700744
Elliott Hughes30646832011-10-13 16:59:46 -0700745 // If the register is live, the "restart" is superfluous,
746 // and we don't want to mess with the existing start address.
747 if (!local_in_reg[reg].is_live_) {
748 local_in_reg[reg].start_address_ = address;
749 local_in_reg[reg].is_live_ = true;
750 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700751 }
752 break;
753
754 case DBG_SET_PROLOGUE_END:
755 case DBG_SET_EPILOGUE_BEGIN:
756 case DBG_SET_FILE:
757 break;
758
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700759 default: {
760 int adjopcode = opcode - DBG_FIRST_SPECIAL;
761
Shih-wei Liao195487c2011-08-20 13:29:04 -0700762 address += adjopcode / DBG_LINE_RANGE;
763 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
764
Elliott Hughes2435a572012-02-17 16:07:41 -0800765 if (position_cb != NULL) {
766 if (position_cb(context, address, line)) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700767 // early exit
768 return;
769 }
770 }
771 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700772 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700773 }
774 }
775}
776
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800777void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Elliott Hughes2435a572012-02-17 16:07:41 -0800778 DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
779 void* context) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700780 const byte* stream = GetDebugInfoStream(code_item);
Elliott Hughesee0fa762012-03-26 17:12:41 -0700781 UniquePtr<LocalInfo[]> local_in_reg(local_cb != NULL ? new LocalInfo[code_item->registers_size_] : NULL);
Ian Rogers0571d352011-11-03 19:51:38 -0700782 if (stream != NULL) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700783 DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]);
Ian Rogers0571d352011-11-03 19:51:38 -0700784 }
785 for (int reg = 0; reg < code_item->registers_size_; reg++) {
Elliott Hughesee0fa762012-03-26 17:12:41 -0700786 InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb);
Ian Rogers0571d352011-11-03 19:51:38 -0700787 }
788}
789
Elliott Hughes2435a572012-02-17 16:07:41 -0800790bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) {
791 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
Ian Rogers0571d352011-11-03 19:51:38 -0700792
793 // We know that this callback will be called in
794 // ascending address order, so keep going until we find
795 // a match or we've just gone past it.
796 if (address > context->address_) {
797 // The line number from the previous positions callback
798 // wil be the final result.
799 return true;
800 } else {
801 context->line_num_ = line_num;
802 return address == context->address_;
803 }
804}
805
806// Decodes the header section from the class data bytes.
807void ClassDataItemIterator::ReadClassDataHeader() {
808 CHECK(ptr_pos_ != NULL);
809 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
810 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
811 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
812 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
813}
814
815void ClassDataItemIterator::ReadClassDataField() {
816 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
817 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700818 if (last_idx_ != 0 && field_.field_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700819 LOG(WARNING) << "Duplicate field " << PrettyField(GetMemberIndex(), dex_file_)
820 << " in " << dex_file_.GetLocation();
821 }
Ian Rogers0571d352011-11-03 19:51:38 -0700822}
823
824void ClassDataItemIterator::ReadClassDataMethod() {
825 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
826 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
827 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
Brian Carlstrom68adbe42012-05-11 17:18:08 -0700828 if (last_idx_ != 0 && method_.method_idx_delta_ == 0) {
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700829 LOG(WARNING) << "Duplicate method " << PrettyMethod(GetMemberIndex(), dex_file_)
830 << " in " << dex_file_.GetLocation();
831 }
Ian Rogers0571d352011-11-03 19:51:38 -0700832}
833
834// Read a signed integer. "zwidth" is the zero-based byte count.
835static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
836 int32_t val = 0;
837 for (int i = zwidth; i >= 0; --i) {
838 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
839 }
840 val >>= (3 - zwidth) * 8;
841 return val;
842}
843
844// Read an unsigned integer. "zwidth" is the zero-based byte count,
845// "fill_on_right" indicates which side we want to zero-fill from.
846static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
847 uint32_t val = 0;
848 if (!fill_on_right) {
849 for (int i = zwidth; i >= 0; --i) {
850 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
851 }
852 val >>= (3 - zwidth) * 8;
853 } else {
854 for (int i = zwidth; i >= 0; --i) {
855 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
856 }
857 }
858 return val;
859}
860
861// Read a signed long. "zwidth" is the zero-based byte count.
862static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
863 int64_t val = 0;
864 for (int i = zwidth; i >= 0; --i) {
865 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
866 }
867 val >>= (7 - zwidth) * 8;
868 return val;
869}
870
871// Read an unsigned long. "zwidth" is the zero-based byte count,
872// "fill_on_right" indicates which side we want to zero-fill from.
873static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
874 uint64_t val = 0;
875 if (!fill_on_right) {
876 for (int i = zwidth; i >= 0; --i) {
877 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
878 }
879 val >>= (7 - zwidth) * 8;
880 } else {
881 for (int i = zwidth; i >= 0; --i) {
882 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
883 }
884 }
885 return val;
886}
887
888EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
889 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
890 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
891 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
892 if (ptr_ == NULL) {
893 array_size_ = 0;
894 } else {
895 array_size_ = DecodeUnsignedLeb128(&ptr_);
896 }
897 if (array_size_ > 0) {
898 Next();
899 }
900}
901
902void EncodedStaticFieldValueIterator::Next() {
903 pos_++;
904 if (pos_ >= array_size_) {
905 return;
906 }
907 byte value_type = *ptr_++;
908 byte value_arg = value_type >> kEncodedValueArgShift;
909 size_t width = value_arg + 1; // assume and correct later
910 type_ = value_type & kEncodedValueTypeMask;
911 switch (type_) {
912 case kBoolean:
913 jval_.i = (value_arg != 0) ? 1 : 0;
914 width = 0;
915 break;
916 case kByte:
917 jval_.i = ReadSignedInt(ptr_, value_arg);
918 CHECK(IsInt(8, jval_.i));
919 break;
920 case kShort:
921 jval_.i = ReadSignedInt(ptr_, value_arg);
922 CHECK(IsInt(16, jval_.i));
923 break;
924 case kChar:
925 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
926 CHECK(IsUint(16, jval_.i));
927 break;
928 case kInt:
929 jval_.i = ReadSignedInt(ptr_, value_arg);
930 break;
931 case kLong:
932 jval_.j = ReadSignedLong(ptr_, value_arg);
933 break;
934 case kFloat:
935 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
936 break;
937 case kDouble:
938 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
939 break;
940 case kString:
941 case kType:
942 case kMethod:
943 case kEnum:
944 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
945 break;
946 case kField:
947 case kArray:
948 case kAnnotation:
949 UNIMPLEMENTED(FATAL) << ": type " << type_;
950 break;
951 case kNull:
952 jval_.l = NULL;
953 width = 0;
954 break;
955 default:
956 LOG(FATAL) << "Unreached";
957 }
958 ptr_ += width;
959}
960
961void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
962 switch (type_) {
963 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
964 case kByte: field->SetByte(NULL, jval_.b); break;
965 case kShort: field->SetShort(NULL, jval_.s); break;
966 case kChar: field->SetChar(NULL, jval_.c); break;
967 case kInt: field->SetInt(NULL, jval_.i); break;
968 case kLong: field->SetLong(NULL, jval_.j); break;
969 case kFloat: field->SetFloat(NULL, jval_.f); break;
970 case kDouble: field->SetDouble(NULL, jval_.d); break;
971 case kNull: field->SetObject(NULL, NULL); break;
972 case kString: {
973 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
974 field->SetObject(NULL, resolved);
975 break;
976 }
977 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
978 }
979}
980
981CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
982 handler_.address_ = -1;
983 int32_t offset = -1;
984
985 // Short-circuit the overwhelmingly common cases.
986 switch (code_item.tries_size_) {
987 case 0:
988 break;
989 case 1: {
990 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
991 uint32_t start = tries->start_addr_;
992 if (address >= start) {
993 uint32_t end = start + tries->insn_count_;
994 if (address < end) {
995 offset = tries->handler_off_;
996 }
997 }
998 break;
999 }
1000 default:
1001 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1002 }
Logan Chien736df022012-04-27 16:25:57 +08001003 Init(code_item, offset);
1004}
1005
1006CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
1007 const DexFile::TryItem& try_item) {
1008 handler_.address_ = -1;
1009 Init(code_item, try_item.handler_off_);
1010}
1011
1012void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
1013 int32_t offset) {
Ian Rogers0571d352011-11-03 19:51:38 -07001014 if (offset >= 0) {
Logan Chien736df022012-04-27 16:25:57 +08001015 Init(DexFile::GetCatchHandlerData(code_item, offset));
Ian Rogers0571d352011-11-03 19:51:38 -07001016 } else {
1017 // Not found, initialize as empty
1018 current_data_ = NULL;
1019 remaining_count_ = -1;
1020 catch_all_ = false;
1021 DCHECK(!HasNext());
1022 }
1023}
1024
1025void CatchHandlerIterator::Init(const byte* handler_data) {
1026 current_data_ = handler_data;
1027 remaining_count_ = DecodeSignedLeb128(&current_data_);
1028
1029 // If remaining_count_ is non-positive, then it is the negative of
1030 // the number of catch types, and the catches are followed by a
1031 // catch-all handler.
1032 if (remaining_count_ <= 0) {
1033 catch_all_ = true;
1034 remaining_count_ = -remaining_count_;
1035 } else {
1036 catch_all_ = false;
1037 }
1038 Next();
1039}
1040
1041void CatchHandlerIterator::Next() {
1042 if (remaining_count_ > 0) {
1043 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1044 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1045 remaining_count_--;
1046 return;
1047 }
1048
1049 if (catch_all_) {
1050 handler_.type_idx_ = DexFile::kDexNoIndex16;
1051 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1052 catch_all_ = false;
1053 return;
1054 }
1055
1056 // no more handler
1057 remaining_count_ = -1;
1058}
1059
Carl Shapiro1fb86202011-06-27 17:43:13 -07001060} // namespace art