blob: 16fd407e53456061db110d9c4842b9465f0c0e5a [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
Elliott Hughes90a33692011-08-30 13:27:07 -070028#include <map>
29
30#include "UniquePtr.h"
Ian Rogers0571d352011-11-03 19:51:38 -070031#include "class_linker.h"
jeffhao10037c82012-01-23 15:06:23 -080032#include "dex_file_verifier.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070033#include "globals.h"
Ian Rogers0571d352011-11-03 19:51:38 -070034#include "leb128.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070035#include "logging.h"
36#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070037#include "os.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070038#include "stringprintf.h"
39#include "thread.h"
Ian Rogers0571d352011-11-03 19:51:38 -070040#include "utf.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070041#include "utils.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)) {
77 UniquePtr<const DexFile> dex_file(DexFile::OpenFile(filename, "", false));
78 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,
88 const std::string& strip_location_prefix) {
jeffhao262bf462011-10-20 18:36:32 -070089 if (IsValidZipFilename(filename)) {
Brian Carlstrom16192862011-09-12 17:50:06 -070090 return DexFile::OpenZip(filename, strip_location_prefix);
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 Carlstrom5b332c82012-02-01 15:02:31 -080095 return DexFile::OpenFile(filename, strip_location_prefix, true);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070096}
97
jeffhaob4df5142011-09-19 20:25:32 -070098void DexFile::ChangePermissions(int prot) const {
Ian Rogers30fab402012-01-23 15:43:46 -080099 if (mprotect(mem_map_->Begin(), mem_map_->Size(), prot) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800100 PLOG(FATAL) << "Failed to change dex file permissions to " << prot << " for " << GetLocation();
jeffhaob4df5142011-09-19 20:25:32 -0700101 }
102}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700103
Brian Carlstrom89521892011-12-07 22:05:07 -0800104const std::string StripLocationPrefix(const std::string& original_location,
105 const std::string& strip_location_prefix) {
106 StringPiece location = original_location;
107 if (!location.starts_with(strip_location_prefix)) {
108 LOG(ERROR) << location << " does not start with " << strip_location_prefix;
109 return "";
110 }
111 location.remove_prefix(strip_location_prefix.size());
112 return location.ToString();
113}
114
Brian Carlstrom16192862011-09-12 17:50:06 -0700115const DexFile* DexFile::OpenFile(const std::string& filename,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800116 const std::string& strip_location_prefix,
117 bool verify) {
118 std::string location(StripLocationPrefix(filename, strip_location_prefix));
Brian Carlstrom89521892011-12-07 22:05:07 -0800119 if (location.empty()) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700120 return NULL;
121 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800122
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700123 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700124 if (fd == -1) {
125 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
126 return NULL;
127 }
128 struct stat sbuf;
129 memset(&sbuf, 0, sizeof(sbuf));
130 if (fstat(fd, &sbuf) == -1) {
131 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
132 close(fd);
133 return NULL;
134 }
Ian Rogers7cfb93e2012-01-17 19:46:36 -0800135 if (S_ISDIR(sbuf.st_mode)) {
136 LOG(ERROR) << "attempt to mmap directory \"" << filename << "\"";
137 return NULL;
138 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700139 size_t length = sbuf.st_size;
Brian Carlstrom89521892011-12-07 22:05:07 -0800140 UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0));
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700141 if (map.get() == NULL) {
142 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700143 close(fd);
144 return NULL;
145 }
146 close(fd);
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800147
148 if (map->Size() < sizeof(DexFile::Header)) {
149 LOG(ERROR) << "Failed to open dex file '" << filename << "' that is too short to have a header";
150 return NULL;
151 }
152
153 const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
154
155 const DexFile* dex_file = OpenMemory(location, dex_header->checksum_, map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800156 if (dex_file == NULL) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800157 LOG(ERROR) << "Failed to open dex file '" << filename << "' from memory";
jeffhao54c1ceb2012-02-01 11:45:32 -0800158 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800159 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800160
161 if (!DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800162 LOG(ERROR) << "Failed to verify dex file '" << filename << "'";
jeffhao54c1ceb2012-02-01 11:45:32 -0800163 return NULL;
164 }
165
jeffhaof6174e82012-01-31 16:14:17 -0800166 return dex_file;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700167}
168
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700169const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700170
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700171// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700172const DexFile* DexFile::OpenZip(const std::string& filename,
173 const std::string& strip_location_prefix) {
Brian Carlstrom89521892011-12-07 22:05:07 -0800174 std::string location(StripLocationPrefix(filename, strip_location_prefix));
175 if (location.empty()) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700176 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700177 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700178
Elliott Hughes90a33692011-08-30 13:27:07 -0700179 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
180 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700181 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700182 return NULL;
183 }
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800184 return DexFile::Open(*zip_archive.get(), location);
185}
186
187const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
188 UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
Elliott Hughes90a33692011-08-30 13:27:07 -0700189 if (zip_entry.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800190 LOG(ERROR) << "Failed to find classes.dex within " << location;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700191 return NULL;
192 }
193
Brian Carlstrom89521892011-12-07 22:05:07 -0800194 uint32_t length = zip_entry->GetUncompressedLength();
Elliott Hughes850162c2012-01-12 18:46:43 -0800195 std::string name("classes.dex extracted in memory from ");
196 name += location;
197 UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE));
Brian Carlstrom89521892011-12-07 22:05:07 -0800198 if (map.get() == NULL) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800199 LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
Brian Carlstrom89521892011-12-07 22:05:07 -0800200 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700201 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800202
203 // Extract classes.dex
204 bool success = zip_entry->ExtractToMemory(*map.get());
205 if (!success) {
Brian Carlstroma6cc8932012-01-04 14:44:07 -0800206 LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
Brian Carlstrom89521892011-12-07 22:05:07 -0800207 return NULL;
208 }
209
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800210 const DexFile* dex_file = OpenMemory(location, zip_entry->GetCrc32(), map.release());
jeffhao54c1ceb2012-02-01 11:45:32 -0800211 if (dex_file == NULL) {
212 LOG(ERROR) << "Failed to open dex file '" << location << "' from memory";
213 return NULL;
jeffhaof6174e82012-01-31 16:14:17 -0800214 }
jeffhao54c1ceb2012-02-01 11:45:32 -0800215
216 if (!DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) {
217 LOG(ERROR) << "Failed to verify dex file '" << location << "'";
218 return NULL;
219 }
220
jeffhaof6174e82012-01-31 16:14:17 -0800221 return dex_file;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700222}
223
Brian Carlstrom89521892011-12-07 22:05:07 -0800224const DexFile* DexFile::OpenMemory(const byte* base,
jeffhaof6174e82012-01-31 16:14:17 -0800225 size_t size,
Brian Carlstrom89521892011-12-07 22:05:07 -0800226 const std::string& location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800227 uint32_t location_checksum,
Brian Carlstrom89521892011-12-07 22:05:07 -0800228 MemMap* mem_map) {
229 CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800230 UniquePtr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700231 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700232 return NULL;
233 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700234 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700235 }
236}
237
Jesse Wilson6bf19152011-09-29 13:12:33 -0400238DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700239 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
240 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
241 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
242 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400243}
244
245jobject DexFile::GetDexObject(JNIEnv* env) const {
246 MutexLock mu(dex_object_lock_);
247 if (dex_object_ != NULL) {
248 return dex_object_;
249 }
250
Ian Rogers30fab402012-01-23 15:43:46 -0800251 void* address = const_cast<void*>(reinterpret_cast<const void*>(begin_));
jeffhaof6174e82012-01-31 16:14:17 -0800252 jobject byte_buffer = env->NewDirectByteBuffer(address, size_);
Jesse Wilson6bf19152011-09-29 13:12:33 -0400253 if (byte_buffer == NULL) {
254 return NULL;
255 }
256
257 jclass c = env->FindClass("com/android/dex/Dex");
258 if (c == NULL) {
259 return NULL;
260 }
261
262 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
263 if (mid == NULL) {
264 return NULL;
265 }
266
267 jvalue args[1];
268 args[0].l = byte_buffer;
269 jobject local = env->CallStaticObjectMethodA(c, mid, args);
270 if (local == NULL) {
271 return NULL;
272 }
273
274 dex_object_ = env->NewGlobalRef(local);
275 return dex_object_;
276}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700277
Brian Carlstromf615a612011-07-23 12:50:34 -0700278bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700279 InitMembers();
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800280 if (!CheckMagicAndVersion()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700281 return false;
282 }
283 InitIndex();
284 return true;
285}
286
Brian Carlstromf615a612011-07-23 12:50:34 -0700287void DexFile::InitMembers() {
Ian Rogers30fab402012-01-23 15:43:46 -0800288 const byte* b = begin_;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700289 header_ = reinterpret_cast<const Header*>(b);
290 const Header* h = header_;
291 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
292 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
293 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
294 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
295 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
296 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
jeffhaof6174e82012-01-31 16:14:17 -0800297 DCHECK_EQ(size_, header_->file_size_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700298}
299
jeffhao10037c82012-01-23 15:06:23 -0800300bool DexFile::CheckMagicAndVersion() const {
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800301 CHECK(header_->magic_ != NULL) << GetLocation();
302 if (!IsMagicValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800303 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800304 << " " << header_->magic_[0]
305 << " " << header_->magic_[1]
306 << " " << header_->magic_[2]
307 << " " << header_->magic_[3];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700308 return false;
309 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800310 if (!IsVersionValid(header_->magic_)) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800311 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800312 << " " << header_->magic_[4]
313 << " " << header_->magic_[5]
314 << " " << header_->magic_[6]
315 << " " << header_->magic_[7];
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700316 return false;
317 }
318 return true;
319}
320
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800321bool DexFile::IsMagicValid(const byte* magic) {
322 return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
323}
324
325bool DexFile::IsVersionValid(const byte* magic) {
326 const byte* version = &magic[sizeof(kDexMagic)];
327 return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
328}
329
Ian Rogersd81871c2011-10-03 13:57:23 -0700330uint32_t DexFile::GetVersion() const {
331 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
332 return atoi(version);
333}
334
Ian Rogers0571d352011-11-03 19:51:38 -0700335int32_t DexFile::GetStringLength(const StringId& string_id) const {
Ian Rogers30fab402012-01-23 15:43:46 -0800336 const byte* ptr = begin_ + string_id.string_data_off_;
Ian Rogers0571d352011-11-03 19:51:38 -0700337 return DecodeUnsignedLeb128(&ptr);
338}
339
340// Returns a pointer to the UTF-8 string data referred to by the given string_id.
341const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800342 CHECK(length != NULL) << GetLocation();
Ian Rogers30fab402012-01-23 15:43:46 -0800343 const byte* ptr = begin_ + string_id.string_data_off_;
Ian Rogers0571d352011-11-03 19:51:38 -0700344 *length = DecodeUnsignedLeb128(&ptr);
345 return reinterpret_cast<const char*>(ptr);
346}
347
Brian Carlstromf615a612011-07-23 12:50:34 -0700348void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800349 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700350 for (size_t i = 0; i < NumClassDefs(); ++i) {
351 const ClassDef& class_def = GetClassDef(i);
352 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700353 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700354 }
355}
356
Brian Carlstrome24fa612011-09-29 00:53:55 -0700357bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700358 Index::const_iterator it = index_.find(descriptor);
359 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700360 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700361 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700362 idx = it->second;
363 return true;
364}
365
366const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
367 uint32_t idx;
368 if (FindClassDefIndex(descriptor, idx)) {
369 return &GetClassDef(idx);
370 }
371 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700372}
373
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800374const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
375 const DexFile::StringId& name,
376 const DexFile::TypeId& type) const {
377 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
378 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
379 const uint32_t name_idx = GetIndexForStringId(name);
380 const uint16_t type_idx = GetIndexForTypeId(type);
381 uint32_t lo = 0;
382 uint32_t hi = NumFieldIds() - 1;
383 while (hi >= lo) {
384 uint32_t mid = (hi + lo) / 2;
385 const DexFile::FieldId& field = GetFieldId(mid);
386 if (class_idx > field.class_idx_) {
387 lo = mid + 1;
388 } else if (class_idx < field.class_idx_) {
389 hi = mid - 1;
390 } else {
391 if (name_idx > field.name_idx_) {
392 lo = mid + 1;
393 } else if (name_idx < field.name_idx_) {
394 hi = mid - 1;
395 } else {
396 if (type_idx > field.type_idx_) {
397 lo = mid + 1;
398 } else if (type_idx < field.type_idx_) {
399 hi = mid - 1;
400 } else {
401 return &field;
402 }
403 }
404 }
405 }
406 return NULL;
407}
408
409const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700410 const DexFile::StringId& name,
411 const DexFile::ProtoId& signature) const {
412 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800413 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700414 const uint32_t name_idx = GetIndexForStringId(name);
415 const uint16_t proto_idx = GetIndexForProtoId(signature);
416 uint32_t lo = 0;
417 uint32_t hi = NumMethodIds() - 1;
418 while (hi >= lo) {
419 uint32_t mid = (hi + lo) / 2;
420 const DexFile::MethodId& method = GetMethodId(mid);
421 if (class_idx > method.class_idx_) {
422 lo = mid + 1;
423 } else if (class_idx < method.class_idx_) {
424 hi = mid - 1;
425 } else {
426 if (name_idx > method.name_idx_) {
427 lo = mid + 1;
428 } else if (name_idx < method.name_idx_) {
429 hi = mid - 1;
430 } else {
431 if (proto_idx > method.proto_idx_) {
432 lo = mid + 1;
433 } else if (proto_idx < method.proto_idx_) {
434 hi = mid - 1;
435 } else {
436 return &method;
437 }
438 }
439 }
440 }
441 return NULL;
442}
443
444const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
445 uint32_t lo = 0;
446 uint32_t hi = NumStringIds() - 1;
447 while (hi >= lo) {
448 uint32_t mid = (hi + lo) / 2;
449 int32_t length;
450 const DexFile::StringId& str_id = GetStringId(mid);
451 const char* str = GetStringDataAndLength(str_id, &length);
452 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
453 if (compare > 0) {
454 lo = mid + 1;
455 } else if (compare < 0) {
456 hi = mid - 1;
457 } else {
458 return &str_id;
459 }
460 }
461 return NULL;
462}
463
464const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
465 uint32_t lo = 0;
466 uint32_t hi = NumTypeIds() - 1;
467 while (hi >= lo) {
468 uint32_t mid = (hi + lo) / 2;
469 const TypeId& type_id = GetTypeId(mid);
470 if (string_idx > type_id.descriptor_idx_) {
471 lo = mid + 1;
472 } else if (string_idx < type_id.descriptor_idx_) {
473 hi = mid - 1;
474 } else {
475 return &type_id;
476 }
477 }
478 return NULL;
479}
480
481const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800482 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700483 uint32_t lo = 0;
484 uint32_t hi = NumProtoIds() - 1;
485 while (hi >= lo) {
486 uint32_t mid = (hi + lo) / 2;
487 const DexFile::ProtoId& proto = GetProtoId(mid);
488 int compare = return_type_idx - proto.return_type_idx_;
489 if (compare == 0) {
490 DexFileParameterIterator it(*this, proto);
491 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800492 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
493 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700494 it.Next();
495 i++;
496 }
497 if (compare == 0) {
498 if (it.HasNext()) {
499 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800500 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700501 compare = 1;
502 }
503 }
504 }
505 if (compare > 0) {
506 lo = mid + 1;
507 } else if (compare < 0) {
508 hi = mid - 1;
509 } else {
510 return &proto;
511 }
512 }
513 return NULL;
514}
515
516// Given a signature place the type ids into the given vector
517bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
518 const std::string& signature) const {
519 if (signature[0] != '(') {
520 return false;
521 }
522 size_t offset = 1;
523 size_t end = signature.size();
524 bool process_return = false;
525 while (offset < end) {
526 char c = signature[offset];
527 offset++;
528 if (c == ')') {
529 process_return = true;
530 continue;
531 }
532 std::string descriptor;
533 descriptor += c;
534 while (c == '[') { // process array prefix
535 if (offset >= end) { // expect some descriptor following [
536 return false;
537 }
538 c = signature[offset];
539 offset++;
540 descriptor += c;
541 }
542 if (c == 'L') { // process type descriptors
543 do {
544 if (offset >= end) { // unexpected early termination of descriptor
545 return false;
546 }
547 c = signature[offset];
548 offset++;
549 descriptor += c;
550 } while (c != ';');
551 }
552 const DexFile::StringId* string_id = FindStringId(descriptor);
553 if (string_id == NULL) {
554 return false;
555 }
556 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
557 if (type_id == NULL) {
558 return false;
559 }
560 uint16_t type_idx = GetIndexForTypeId(*type_id);
561 if (!process_return) {
562 param_type_idxs->push_back(type_idx);
563 } else {
564 *return_type_idx = type_idx;
565 return offset == end; // return true if the signature had reached a sensible end
566 }
567 }
568 return false; // failed to correctly parse return type
569}
570
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700571// Materializes the method descriptor for a method prototype. Method
572// descriptors are not stored directly in the dex file. Instead, one
573// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700574std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700575 const ProtoId& proto_id = GetProtoId(proto_idx);
576 std::string descriptor;
577 descriptor.push_back('(');
578 const TypeList* type_list = GetProtoParameters(proto_id);
579 size_t parameter_length = 0;
580 if (type_list != NULL) {
581 // A non-zero number of arguments. Append the type names.
582 for (size_t i = 0; i < type_list->Size(); ++i) {
583 const TypeItem& type_item = type_list->GetTypeItem(i);
584 uint32_t type_idx = type_item.type_idx_;
585 int32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700586 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700587 parameter_length += type_length;
588 descriptor.append(name);
589 }
590 }
591 descriptor.push_back(')');
592 uint32_t return_type_idx = proto_id.return_type_idx_;
593 int32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700594 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700595 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700596 if (unicode_length != NULL) {
597 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
598 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700599 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700600}
601
Carl Shapiro1fb86202011-06-27 17:43:13 -0700602
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800603int32_t DexFile::GetLineNumFromPC(const Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700604 // For native method, lineno should be -2 to indicate it is native. Note that
605 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700606 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700607 return -2;
608 }
609
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700610 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800611 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700612
613 // A method with no line number info should return -1
614 LineNumFromPcContext context(rel_pc, -1);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800615 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
616 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700617 return context.line_num_;
618}
619
Ian Rogers0571d352011-11-03 19:51:38 -0700620int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
Elliott Hughesba8eee12012-01-24 20:25:24 -0800621 uint32_t address) {
Ian Rogers0571d352011-11-03 19:51:38 -0700622 // Note: Signed type is important for max and min.
623 int32_t min = 0;
624 int32_t max = tries_size - 1;
625
626 while (max >= min) {
627 int32_t mid = (min + max) / 2;
628 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
629 uint32_t start = pTry->start_addr_;
630 if (address < start) {
631 max = mid - 1;
632 } else {
633 uint32_t end = start + pTry->insn_count_;
634 if (address >= end) {
635 min = mid + 1;
636 } else { // We have a winner!
637 return (int32_t) pTry->handler_off_;
638 }
639 }
640 }
641 // No match.
642 return -1;
643}
644
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800645void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700646 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
647 void* cnxt, 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) {
735 InvokeLocalCbIfLive(cnxt, 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) {
756 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
757 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
795 if (posCb != NULL) {
796 if (posCb(cnxt, address, line)) {
797 // 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,
Ian Rogers0571d352011-11-03 19:51:38 -0700808 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
809 void* cnxt) const {
810 const byte* stream = GetDebugInfoStream(code_item);
811 LocalInfo local_in_reg[code_item->registers_size_];
812
813 if (stream != NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800814 DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
Ian Rogers0571d352011-11-03 19:51:38 -0700815 }
816 for (int reg = 0; reg < code_item->registers_size_; reg++) {
817 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
818 }
819}
820
821bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800822 LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(cnxt);
Ian Rogers0571d352011-11-03 19:51:38 -0700823
824 // We know that this callback will be called in
825 // ascending address order, so keep going until we find
826 // a match or we've just gone past it.
827 if (address > context->address_) {
828 // The line number from the previous positions callback
829 // wil be the final result.
830 return true;
831 } else {
832 context->line_num_ = line_num;
833 return address == context->address_;
834 }
835}
836
837// Decodes the header section from the class data bytes.
838void ClassDataItemIterator::ReadClassDataHeader() {
839 CHECK(ptr_pos_ != NULL);
840 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
841 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
842 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
843 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
844}
845
846void ClassDataItemIterator::ReadClassDataField() {
847 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
848 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
849}
850
851void ClassDataItemIterator::ReadClassDataMethod() {
852 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
853 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
854 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
855}
856
857// Read a signed integer. "zwidth" is the zero-based byte count.
858static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
859 int32_t val = 0;
860 for (int i = zwidth; i >= 0; --i) {
861 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
862 }
863 val >>= (3 - zwidth) * 8;
864 return val;
865}
866
867// Read an unsigned integer. "zwidth" is the zero-based byte count,
868// "fill_on_right" indicates which side we want to zero-fill from.
869static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
870 uint32_t val = 0;
871 if (!fill_on_right) {
872 for (int i = zwidth; i >= 0; --i) {
873 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
874 }
875 val >>= (3 - zwidth) * 8;
876 } else {
877 for (int i = zwidth; i >= 0; --i) {
878 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
879 }
880 }
881 return val;
882}
883
884// Read a signed long. "zwidth" is the zero-based byte count.
885static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
886 int64_t val = 0;
887 for (int i = zwidth; i >= 0; --i) {
888 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
889 }
890 val >>= (7 - zwidth) * 8;
891 return val;
892}
893
894// Read an unsigned long. "zwidth" is the zero-based byte count,
895// "fill_on_right" indicates which side we want to zero-fill from.
896static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
897 uint64_t val = 0;
898 if (!fill_on_right) {
899 for (int i = zwidth; i >= 0; --i) {
900 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
901 }
902 val >>= (7 - zwidth) * 8;
903 } else {
904 for (int i = zwidth; i >= 0; --i) {
905 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
906 }
907 }
908 return val;
909}
910
911EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
912 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
913 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
914 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
915 if (ptr_ == NULL) {
916 array_size_ = 0;
917 } else {
918 array_size_ = DecodeUnsignedLeb128(&ptr_);
919 }
920 if (array_size_ > 0) {
921 Next();
922 }
923}
924
925void EncodedStaticFieldValueIterator::Next() {
926 pos_++;
927 if (pos_ >= array_size_) {
928 return;
929 }
930 byte value_type = *ptr_++;
931 byte value_arg = value_type >> kEncodedValueArgShift;
932 size_t width = value_arg + 1; // assume and correct later
933 type_ = value_type & kEncodedValueTypeMask;
934 switch (type_) {
935 case kBoolean:
936 jval_.i = (value_arg != 0) ? 1 : 0;
937 width = 0;
938 break;
939 case kByte:
940 jval_.i = ReadSignedInt(ptr_, value_arg);
941 CHECK(IsInt(8, jval_.i));
942 break;
943 case kShort:
944 jval_.i = ReadSignedInt(ptr_, value_arg);
945 CHECK(IsInt(16, jval_.i));
946 break;
947 case kChar:
948 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
949 CHECK(IsUint(16, jval_.i));
950 break;
951 case kInt:
952 jval_.i = ReadSignedInt(ptr_, value_arg);
953 break;
954 case kLong:
955 jval_.j = ReadSignedLong(ptr_, value_arg);
956 break;
957 case kFloat:
958 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
959 break;
960 case kDouble:
961 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
962 break;
963 case kString:
964 case kType:
965 case kMethod:
966 case kEnum:
967 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
968 break;
969 case kField:
970 case kArray:
971 case kAnnotation:
972 UNIMPLEMENTED(FATAL) << ": type " << type_;
973 break;
974 case kNull:
975 jval_.l = NULL;
976 width = 0;
977 break;
978 default:
979 LOG(FATAL) << "Unreached";
980 }
981 ptr_ += width;
982}
983
984void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
985 switch (type_) {
986 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
987 case kByte: field->SetByte(NULL, jval_.b); break;
988 case kShort: field->SetShort(NULL, jval_.s); break;
989 case kChar: field->SetChar(NULL, jval_.c); break;
990 case kInt: field->SetInt(NULL, jval_.i); break;
991 case kLong: field->SetLong(NULL, jval_.j); break;
992 case kFloat: field->SetFloat(NULL, jval_.f); break;
993 case kDouble: field->SetDouble(NULL, jval_.d); break;
994 case kNull: field->SetObject(NULL, NULL); break;
995 case kString: {
996 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
997 field->SetObject(NULL, resolved);
998 break;
999 }
1000 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
1001 }
1002}
1003
1004CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
1005 handler_.address_ = -1;
1006 int32_t offset = -1;
1007
1008 // Short-circuit the overwhelmingly common cases.
1009 switch (code_item.tries_size_) {
1010 case 0:
1011 break;
1012 case 1: {
1013 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1014 uint32_t start = tries->start_addr_;
1015 if (address >= start) {
1016 uint32_t end = start + tries->insn_count_;
1017 if (address < end) {
1018 offset = tries->handler_off_;
1019 }
1020 }
1021 break;
1022 }
1023 default:
1024 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1025 }
1026 if (offset >= 0) {
1027 const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
1028 Init(handler_data);
1029 } else {
1030 // Not found, initialize as empty
1031 current_data_ = NULL;
1032 remaining_count_ = -1;
1033 catch_all_ = false;
1034 DCHECK(!HasNext());
1035 }
1036}
1037
1038void CatchHandlerIterator::Init(const byte* handler_data) {
1039 current_data_ = handler_data;
1040 remaining_count_ = DecodeSignedLeb128(&current_data_);
1041
1042 // If remaining_count_ is non-positive, then it is the negative of
1043 // the number of catch types, and the catches are followed by a
1044 // catch-all handler.
1045 if (remaining_count_ <= 0) {
1046 catch_all_ = true;
1047 remaining_count_ = -remaining_count_;
1048 } else {
1049 catch_all_ = false;
1050 }
1051 Next();
1052}
1053
1054void CatchHandlerIterator::Next() {
1055 if (remaining_count_ > 0) {
1056 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1057 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1058 remaining_count_--;
1059 return;
1060 }
1061
1062 if (catch_all_) {
1063 handler_.type_idx_ = DexFile::kDexNoIndex16;
1064 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1065 catch_all_ = false;
1066 return;
1067 }
1068
1069 // no more handler
1070 remaining_count_ = -1;
1071}
1072
Carl Shapiro1fb86202011-06-27 17:43:13 -07001073} // namespace art