blob: b92760bb27ce393bcbc25a67fd058f0f5d5e22ea [file] [log] [blame]
Carl Shapiro1fb86202011-06-27 17:43:13 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "dex_file.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07004
5#include <fcntl.h>
Brian Carlstrom1f870082011-08-23 16:02:11 -07006#include <limits.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -07007#include <stdio.h>
Ian Rogersd81871c2011-10-03 13:57:23 -07008#include <stdlib.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07009#include <string.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070010#include <sys/file.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070011#include <sys/mman.h>
12#include <sys/stat.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070013
Elliott Hughes90a33692011-08-30 13:27:07 -070014#include <map>
15
16#include "UniquePtr.h"
Ian Rogers0571d352011-11-03 19:51:38 -070017#include "class_linker.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070018#include "globals.h"
Ian Rogers0571d352011-11-03 19:51:38 -070019#include "leb128.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "logging.h"
21#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070022#include "os.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070023#include "stringprintf.h"
24#include "thread.h"
Ian Rogers0571d352011-11-03 19:51:38 -070025#include "utf.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070027#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070028
29namespace art {
30
Brian Carlstromf615a612011-07-23 12:50:34 -070031const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
32const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070033
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070034DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070035 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070036 for (size_t i = 0; i != class_path.size(); ++i) {
37 const DexFile* dex_file = class_path[i];
38 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
39 if (dex_class_def != NULL) {
40 return ClassPathEntry(dex_file, dex_class_def);
41 }
42 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070043 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070044 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
45 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070046}
47
Brian Carlstromae826982011-11-09 01:33:42 -080048void DexFile::OpenDexFiles(const std::vector<const char*>& dex_filenames,
Brian Carlstrom78128a62011-09-15 17:21:19 -070049 std::vector<const DexFile*>& dex_files,
50 const std::string& strip_location_prefix) {
51 for (size_t i = 0; i < dex_filenames.size(); i++) {
52 const char* dex_filename = dex_filenames[i];
53 const DexFile* dex_file = Open(dex_filename, strip_location_prefix);
54 if (dex_file == NULL) {
55 fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
56 exit(EXIT_FAILURE);
57 }
58 dex_files.push_back(dex_file);
59 }
60}
61
Brian Carlstrom16192862011-09-12 17:50:06 -070062const DexFile* DexFile::Open(const std::string& filename,
63 const std::string& strip_location_prefix) {
jeffhao262bf462011-10-20 18:36:32 -070064 if (IsValidZipFilename(filename)) {
Brian Carlstrom16192862011-09-12 17:50:06 -070065 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070066 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -070067 if (!IsValidDexFilename(filename)) {
68 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
69 }
70 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070071}
72
jeffhaob4df5142011-09-19 20:25:32 -070073void DexFile::ChangePermissions(int prot) const {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070074 if (mprotect(mem_map_->GetAddress(), mem_map_->GetLength(), prot) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -080075 PLOG(FATAL) << "Failed to change dex file permissions to " << prot << " for " << GetLocation();
jeffhaob4df5142011-09-19 20:25:32 -070076 }
77}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070078
Brian Carlstrom16192862011-09-12 17:50:06 -070079const DexFile* DexFile::OpenFile(const std::string& filename,
80 const std::string& original_location,
81 const std::string& strip_location_prefix) {
82 StringPiece location = original_location;
83 if (!location.starts_with(strip_location_prefix)) {
84 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
85 return NULL;
86 }
87 location.remove_prefix(strip_location_prefix.size());
Brian Carlstromb0460ea2011-07-29 10:08:05 -070088 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070089 if (fd == -1) {
90 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
91 return NULL;
92 }
93 struct stat sbuf;
94 memset(&sbuf, 0, sizeof(sbuf));
95 if (fstat(fd, &sbuf) == -1) {
96 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
97 close(fd);
98 return NULL;
99 }
100 size_t length = sbuf.st_size;
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700101 UniquePtr<MemMap> map(MemMap::Map(length, PROT_READ, MAP_PRIVATE, fd, 0));
102 if (map.get() == NULL) {
103 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700104 close(fd);
105 return NULL;
106 }
107 close(fd);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700108 byte* dex_file = map->GetAddress();
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700109 return OpenMemory(dex_file, length, location.ToString(), map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700110}
111
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700112const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700113
114class LockedFd {
115 public:
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700116 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700117 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
118 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700119 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700120 return NULL;
121 }
122 fchmod(fd, mode);
123
124 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
125 int result = flock(fd, LOCK_EX | LOCK_NB);
126 if (result == -1) {
127 LOG(WARNING) << "sleeping while locking file " << name;
128 result = flock(fd, LOCK_EX);
129 }
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700130 if (result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700131 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700132 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700133 return NULL;
134 }
135 return new LockedFd(fd);
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700136 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700137
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700138 int GetFd() const {
139 return fd_;
140 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700141
142 ~LockedFd() {
143 if (fd_ != -1) {
144 int result = flock(fd_, LOCK_UN);
145 if (result == -1) {
146 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
147 }
148 close(fd_);
149 }
150 }
151
152 private:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700153 explicit LockedFd(int fd) : fd_(fd) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700154
155 int fd_;
156};
157
158class TmpFile {
159 public:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700160 explicit TmpFile(const std::string& name) : name_(name) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700161 ~TmpFile() {
162 unlink(name_.c_str());
163 }
164 private:
165 const std::string name_;
166};
167
168// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700169const DexFile* DexFile::OpenZip(const std::string& filename,
170 const std::string& strip_location_prefix) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700171 // First, look for a ".dex" alongside the jar file. It will have
172 // the same name/path except for the extension.
173
174 // Example filename = dir/foo.jar
175 std::string adjacent_dex_filename(filename);
176 size_t found = adjacent_dex_filename.find_last_of(".");
177 if (found == std::string::npos) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700178 LOG(ERROR) << "No . in filename" << filename;
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700179 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700180 }
181 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
182 adjacent_dex_filename.end(),
183 ".dex");
184 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700185 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700186 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename,
187 filename,
188 strip_location_prefix);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700189 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700190 // We don't verify anything in this case, because we aren't in
191 // the cache and typically the file is in the readonly /system
192 // area, so if something is wrong, there is nothing we can do.
193 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700194 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700195 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700196 }
197
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700198 UniquePtr<char[]> resolved(new char[PATH_MAX]);
199 char* absolute_path = realpath(filename.c_str(), resolved.get());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700200 if (absolute_path == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700201 LOG(ERROR) << "Failed to create absolute path for " << filename
202 << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700203 return NULL;
204 }
jeffhao262bf462011-10-20 18:36:32 -0700205 std::string cache_path_tmp(GetArtCacheFilenameOrDie(absolute_path));
206 cache_path_tmp.push_back('@');
207 cache_path_tmp.append(kClassesDex);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700208 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
209
Elliott Hughes90a33692011-08-30 13:27:07 -0700210 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
211 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700212 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700213 return NULL;
214 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700215 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
216 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700217 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700218 return NULL;
219 }
220
221 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
222 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
223
Brian Carlstrom996a72b2011-12-12 10:32:52 -0800224 bool created = false;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700225 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700226 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700227 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path,
228 filename,
229 strip_location_prefix);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700230 if (cached_dex_file != NULL) {
231 return cached_dex_file;
232 }
Brian Carlstrom996a72b2011-12-12 10:32:52 -0800233 if (created) {
234 // We created the dex file with the correct checksum,
235 // there must be something wrong with the file itself.
236 return NULL;
237 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700238 }
239
240 // Try to open the temporary cache file, grabbing an exclusive
241 // lock. If somebody else is working on it, we'll block here until
242 // they complete. Because we're waiting on an external resource,
243 // we go into native mode.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700244 // Note that self can be NULL if we're parsing the bootclasspath
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700245 // during JNI_CreateJavaVM.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700246 Thread* self = Thread::Current();
247 UniquePtr<ScopedThreadStateChange> state_changer;
248 if (self != NULL) {
249 state_changer.reset(new ScopedThreadStateChange(self, Thread::kNative));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700250 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700251 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700252 state_changer.reset(NULL);
Elliott Hughes90a33692011-08-30 13:27:07 -0700253 if (fd.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700254 PLOG(ERROR) << "Failed to lock file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700255 return NULL;
256 }
257
258 // Check to see if the fd we opened and locked matches the file in
259 // the filesystem. If they don't, then somebody else unlinked
260 // ours and created a new file, and we need to use that one
261 // instead. (If we caught them between the unlink and the create,
262 // we'll get an ENOENT from the file stat.)
263 struct stat fd_stat;
264 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
265 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700266 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700267 return NULL;
268 }
269 struct stat file_stat;
270 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
271 if (file_stat_result == -1 ||
272 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
273 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
274 usleep(250 * 1000); // if something is hosed, don't peg machine
275 continue;
276 }
277
278 // We have the correct file open and locked. Extract classes.dex
279 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700280 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
281 if (file.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700282 LOG(ERROR) << "Failed to create file for '" << cache_path_tmp << "'";
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700283 return NULL;
284 }
285 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700286 if (!success) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700287 LOG(ERROR) << "Failed to extract classes.dex to '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700288 return NULL;
289 }
290
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700291 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700292
293 // Compute checksum and compare to zip. If things look okay, rename from tmp.
294 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
295 if (lseek_result == -1) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700296 PLOG(ERROR) << "Failed to seek to start of '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700297 return NULL;
298 }
299 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700300 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
301 if (buf.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700302 LOG(ERROR) << "Failed to allocate buffer to checksum '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700303 return NULL;
304 }
305 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
306 while (true) {
307 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700308 if (bytes_read == -1) {
309 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
310 return NULL;
311 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700312 if (bytes_read == 0) {
313 break;
314 }
315 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
316 }
317 if (computed_crc != zip_entry->GetCrc32()) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700318 LOG(ERROR) << "Failed to validate checksum for '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700319 return NULL;
320 }
321 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
322 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700323 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700324 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700325 unlink(cache_path.c_str());
Brian Carlstrom996a72b2011-12-12 10:32:52 -0800326 } else {
327 created = true;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700328 }
329 }
330 // NOTREACHED
331}
332
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700333const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length,
334 const std::string& location, MemMap* mem_map) {
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700335 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700336 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700337 return NULL;
338 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700339 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700340 }
341}
342
Jesse Wilson6bf19152011-09-29 13:12:33 -0400343DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700344 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
345 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
346 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
347 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400348}
349
350jobject DexFile::GetDexObject(JNIEnv* env) const {
351 MutexLock mu(dex_object_lock_);
352 if (dex_object_ != NULL) {
353 return dex_object_;
354 }
355
356 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
357 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
358 if (byte_buffer == NULL) {
359 return NULL;
360 }
361
362 jclass c = env->FindClass("com/android/dex/Dex");
363 if (c == NULL) {
364 return NULL;
365 }
366
367 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
368 if (mid == NULL) {
369 return NULL;
370 }
371
372 jvalue args[1];
373 args[0].l = byte_buffer;
374 jobject local = env->CallStaticObjectMethodA(c, mid, args);
375 if (local == NULL) {
376 return NULL;
377 }
378
379 dex_object_ = env->NewGlobalRef(local);
380 return dex_object_;
381}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700382
Brian Carlstromf615a612011-07-23 12:50:34 -0700383bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700384 InitMembers();
385 if (!IsMagicValid()) {
386 return false;
387 }
388 InitIndex();
389 return true;
390}
391
Brian Carlstromf615a612011-07-23 12:50:34 -0700392void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700393 const byte* b = base_;
394 header_ = reinterpret_cast<const Header*>(b);
395 const Header* h = header_;
396 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
397 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
398 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
399 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
400 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
401 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
402}
403
Brian Carlstromf615a612011-07-23 12:50:34 -0700404bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700405 return CheckMagic(header_->magic_);
406}
407
Brian Carlstromf615a612011-07-23 12:50:34 -0700408bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800409 CHECK(magic != NULL) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700410 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800411 LOG(ERROR) << "Unrecognized magic number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700412 << " " << magic[0]
413 << " " << magic[1]
414 << " " << magic[2]
415 << " " << magic[3];
416 return false;
417 }
418 const byte* version = &magic[sizeof(kDexMagic)];
419 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800420 LOG(ERROR) << "Unrecognized version number in " << GetLocation() << ":"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700421 << " " << version[0]
422 << " " << version[1]
423 << " " << version[2]
424 << " " << version[3];
425 return false;
426 }
427 return true;
428}
429
Ian Rogersd81871c2011-10-03 13:57:23 -0700430uint32_t DexFile::GetVersion() const {
431 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
432 return atoi(version);
433}
434
Ian Rogers0571d352011-11-03 19:51:38 -0700435int32_t DexFile::GetStringLength(const StringId& string_id) const {
436 const byte* ptr = base_ + string_id.string_data_off_;
437 return DecodeUnsignedLeb128(&ptr);
438}
439
440// Returns a pointer to the UTF-8 string data referred to by the given string_id.
441const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800442 CHECK(length != NULL) << GetLocation();
Ian Rogers0571d352011-11-03 19:51:38 -0700443 const byte* ptr = base_ + string_id.string_data_off_;
444 *length = DecodeUnsignedLeb128(&ptr);
445 return reinterpret_cast<const char*>(ptr);
446}
447
Brian Carlstromf615a612011-07-23 12:50:34 -0700448void DexFile::InitIndex() {
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800449 CHECK_EQ(index_.size(), 0U) << GetLocation();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700450 for (size_t i = 0; i < NumClassDefs(); ++i) {
451 const ClassDef& class_def = GetClassDef(i);
452 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700453 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700454 }
455}
456
Brian Carlstrome24fa612011-09-29 00:53:55 -0700457bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700458 Index::const_iterator it = index_.find(descriptor);
459 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700460 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700461 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700462 idx = it->second;
463 return true;
464}
465
466const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
467 uint32_t idx;
468 if (FindClassDefIndex(descriptor, idx)) {
469 return &GetClassDef(idx);
470 }
471 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700472}
473
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800474const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
475 const DexFile::StringId& name,
476 const DexFile::TypeId& type) const {
477 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
478 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
479 const uint32_t name_idx = GetIndexForStringId(name);
480 const uint16_t type_idx = GetIndexForTypeId(type);
481 uint32_t lo = 0;
482 uint32_t hi = NumFieldIds() - 1;
483 while (hi >= lo) {
484 uint32_t mid = (hi + lo) / 2;
485 const DexFile::FieldId& field = GetFieldId(mid);
486 if (class_idx > field.class_idx_) {
487 lo = mid + 1;
488 } else if (class_idx < field.class_idx_) {
489 hi = mid - 1;
490 } else {
491 if (name_idx > field.name_idx_) {
492 lo = mid + 1;
493 } else if (name_idx < field.name_idx_) {
494 hi = mid - 1;
495 } else {
496 if (type_idx > field.type_idx_) {
497 lo = mid + 1;
498 } else if (type_idx < field.type_idx_) {
499 hi = mid - 1;
500 } else {
501 return &field;
502 }
503 }
504 }
505 }
506 return NULL;
507}
508
509const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
Ian Rogers0571d352011-11-03 19:51:38 -0700510 const DexFile::StringId& name,
511 const DexFile::ProtoId& signature) const {
512 // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800513 const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
Ian Rogers0571d352011-11-03 19:51:38 -0700514 const uint32_t name_idx = GetIndexForStringId(name);
515 const uint16_t proto_idx = GetIndexForProtoId(signature);
516 uint32_t lo = 0;
517 uint32_t hi = NumMethodIds() - 1;
518 while (hi >= lo) {
519 uint32_t mid = (hi + lo) / 2;
520 const DexFile::MethodId& method = GetMethodId(mid);
521 if (class_idx > method.class_idx_) {
522 lo = mid + 1;
523 } else if (class_idx < method.class_idx_) {
524 hi = mid - 1;
525 } else {
526 if (name_idx > method.name_idx_) {
527 lo = mid + 1;
528 } else if (name_idx < method.name_idx_) {
529 hi = mid - 1;
530 } else {
531 if (proto_idx > method.proto_idx_) {
532 lo = mid + 1;
533 } else if (proto_idx < method.proto_idx_) {
534 hi = mid - 1;
535 } else {
536 return &method;
537 }
538 }
539 }
540 }
541 return NULL;
542}
543
544const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
545 uint32_t lo = 0;
546 uint32_t hi = NumStringIds() - 1;
547 while (hi >= lo) {
548 uint32_t mid = (hi + lo) / 2;
549 int32_t length;
550 const DexFile::StringId& str_id = GetStringId(mid);
551 const char* str = GetStringDataAndLength(str_id, &length);
552 int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
553 if (compare > 0) {
554 lo = mid + 1;
555 } else if (compare < 0) {
556 hi = mid - 1;
557 } else {
558 return &str_id;
559 }
560 }
561 return NULL;
562}
563
564const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
565 uint32_t lo = 0;
566 uint32_t hi = NumTypeIds() - 1;
567 while (hi >= lo) {
568 uint32_t mid = (hi + lo) / 2;
569 const TypeId& type_id = GetTypeId(mid);
570 if (string_idx > type_id.descriptor_idx_) {
571 lo = mid + 1;
572 } else if (string_idx < type_id.descriptor_idx_) {
573 hi = mid - 1;
574 } else {
575 return &type_id;
576 }
577 }
578 return NULL;
579}
580
581const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800582 const std::vector<uint16_t>& signature_type_idxs) const {
Ian Rogers0571d352011-11-03 19:51:38 -0700583 uint32_t lo = 0;
584 uint32_t hi = NumProtoIds() - 1;
585 while (hi >= lo) {
586 uint32_t mid = (hi + lo) / 2;
587 const DexFile::ProtoId& proto = GetProtoId(mid);
588 int compare = return_type_idx - proto.return_type_idx_;
589 if (compare == 0) {
590 DexFileParameterIterator it(*this, proto);
591 size_t i = 0;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800592 while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) {
593 compare = signature_type_idxs[i] - it.GetTypeIdx();
Ian Rogers0571d352011-11-03 19:51:38 -0700594 it.Next();
595 i++;
596 }
597 if (compare == 0) {
598 if (it.HasNext()) {
599 compare = -1;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800600 } else if (i < signature_type_idxs.size()) {
Ian Rogers0571d352011-11-03 19:51:38 -0700601 compare = 1;
602 }
603 }
604 }
605 if (compare > 0) {
606 lo = mid + 1;
607 } else if (compare < 0) {
608 hi = mid - 1;
609 } else {
610 return &proto;
611 }
612 }
613 return NULL;
614}
615
616// Given a signature place the type ids into the given vector
617bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
618 const std::string& signature) const {
619 if (signature[0] != '(') {
620 return false;
621 }
622 size_t offset = 1;
623 size_t end = signature.size();
624 bool process_return = false;
625 while (offset < end) {
626 char c = signature[offset];
627 offset++;
628 if (c == ')') {
629 process_return = true;
630 continue;
631 }
632 std::string descriptor;
633 descriptor += c;
634 while (c == '[') { // process array prefix
635 if (offset >= end) { // expect some descriptor following [
636 return false;
637 }
638 c = signature[offset];
639 offset++;
640 descriptor += c;
641 }
642 if (c == 'L') { // process type descriptors
643 do {
644 if (offset >= end) { // unexpected early termination of descriptor
645 return false;
646 }
647 c = signature[offset];
648 offset++;
649 descriptor += c;
650 } while (c != ';');
651 }
652 const DexFile::StringId* string_id = FindStringId(descriptor);
653 if (string_id == NULL) {
654 return false;
655 }
656 const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
657 if (type_id == NULL) {
658 return false;
659 }
660 uint16_t type_idx = GetIndexForTypeId(*type_id);
661 if (!process_return) {
662 param_type_idxs->push_back(type_idx);
663 } else {
664 *return_type_idx = type_idx;
665 return offset == end; // return true if the signature had reached a sensible end
666 }
667 }
668 return false; // failed to correctly parse return type
669}
670
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700671// Materializes the method descriptor for a method prototype. Method
672// descriptors are not stored directly in the dex file. Instead, one
673// must assemble the descriptor from references in the prototype.
Ian Rogers0571d352011-11-03 19:51:38 -0700674std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700675 const ProtoId& proto_id = GetProtoId(proto_idx);
676 std::string descriptor;
677 descriptor.push_back('(');
678 const TypeList* type_list = GetProtoParameters(proto_id);
679 size_t parameter_length = 0;
680 if (type_list != NULL) {
681 // A non-zero number of arguments. Append the type names.
682 for (size_t i = 0; i < type_list->Size(); ++i) {
683 const TypeItem& type_item = type_list->GetTypeItem(i);
684 uint32_t type_idx = type_item.type_idx_;
685 int32_t type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700686 const char* name = StringByTypeIdx(type_idx, &type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700687 parameter_length += type_length;
688 descriptor.append(name);
689 }
690 }
691 descriptor.push_back(')');
692 uint32_t return_type_idx = proto_id.return_type_idx_;
693 int32_t return_type_length;
Ian Rogers0571d352011-11-03 19:51:38 -0700694 const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700695 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700696 if (unicode_length != NULL) {
697 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
698 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700699 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700700}
701
Carl Shapiro1fb86202011-06-27 17:43:13 -0700702
Shih-wei Liao195487c2011-08-20 13:29:04 -0700703int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700704 // For native method, lineno should be -2 to indicate it is native. Note that
705 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700706 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700707 return -2;
708 }
709
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700710 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Brian Carlstrom61e513c2011-12-09 15:30:06 -0800711 DCHECK(code_item != NULL) << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700712
713 // A method with no line number info should return -1
714 LineNumFromPcContext context(rel_pc, -1);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800715 DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
716 NULL, &context);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700717 return context.line_num_;
718}
719
Ian Rogers0571d352011-11-03 19:51:38 -0700720int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
721 uint32_t address){
722 // Note: Signed type is important for max and min.
723 int32_t min = 0;
724 int32_t max = tries_size - 1;
725
726 while (max >= min) {
727 int32_t mid = (min + max) / 2;
728 const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
729 uint32_t start = pTry->start_addr_;
730 if (address < start) {
731 max = mid - 1;
732 } else {
733 uint32_t end = start + pTry->insn_count_;
734 if (address >= end) {
735 min = mid + 1;
736 } else { // We have a winner!
737 return (int32_t) pTry->handler_off_;
738 }
739 }
740 }
741 // No match.
742 return -1;
743}
744
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800745void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700746 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
747 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700748 uint32_t line = DecodeUnsignedLeb128(&stream);
749 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
750 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
751 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700752 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700753
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800754 if (!is_static) {
Elliott Hughes30646832011-10-13 16:59:46 -0700755 if (need_locals) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800756 const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700757 local_in_reg[arg_reg].name_ = "this";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800758 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800759 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700760 local_in_reg[arg_reg].start_address_ = 0;
761 local_in_reg[arg_reg].is_live_ = true;
762 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700763 arg_reg++;
764 }
765
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800766 DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
Ian Rogers0571d352011-11-03 19:51:38 -0700767 for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700768 if (arg_reg >= code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700769 LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800770 << " >= " << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700771 return;
772 }
Elliott Hughes392b1242011-11-30 13:55:50 -0800773 uint32_t id = DecodeUnsignedLeb128P1(&stream);
Ian Rogers0571d352011-11-03 19:51:38 -0700774 const char* descriptor = it.GetDescriptor();
Elliott Hughes392b1242011-11-30 13:55:50 -0800775 if (need_locals && id != kDexNoIndex) {
Ian Rogers0571d352011-11-03 19:51:38 -0700776 const char* name = StringDataByIdx(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700777 local_in_reg[arg_reg].name_ = name;
778 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes392b1242011-11-30 13:55:50 -0800779 local_in_reg[arg_reg].signature_ = NULL;
Elliott Hughes30646832011-10-13 16:59:46 -0700780 local_in_reg[arg_reg].start_address_ = address;
781 local_in_reg[arg_reg].is_live_ = true;
782 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700783 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700784 case 'D':
785 case 'J':
786 arg_reg += 2;
787 break;
788 default:
789 arg_reg += 1;
790 break;
791 }
792 }
793
Ian Rogers0571d352011-11-03 19:51:38 -0700794 if (it.HasNext()) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800795 LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700796 return;
797 }
798
799 for (;;) {
800 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700801 uint16_t reg;
jeffhaof8728872011-10-28 19:11:13 -0700802 uint16_t name_idx;
803 uint16_t descriptor_idx;
804 uint16_t signature_idx = 0;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700805
Shih-wei Liao195487c2011-08-20 13:29:04 -0700806 switch (opcode) {
807 case DBG_END_SEQUENCE:
808 return;
809
810 case DBG_ADVANCE_PC:
811 address += DecodeUnsignedLeb128(&stream);
812 break;
813
814 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700815 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700816 break;
817
818 case DBG_START_LOCAL:
819 case DBG_START_LOCAL_EXTENDED:
820 reg = DecodeUnsignedLeb128(&stream);
821 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700822 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800823 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700824 return;
825 }
826
jeffhaof8728872011-10-28 19:11:13 -0700827 name_idx = DecodeUnsignedLeb128P1(&stream);
828 descriptor_idx = DecodeUnsignedLeb128P1(&stream);
829 if (opcode == DBG_START_LOCAL_EXTENDED) {
830 signature_idx = DecodeUnsignedLeb128P1(&stream);
831 }
832
Shih-wei Liao195487c2011-08-20 13:29:04 -0700833 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700834 if (need_locals) {
835 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700836
Ian Rogers0571d352011-11-03 19:51:38 -0700837 local_in_reg[reg].name_ = StringDataByIdx(name_idx);
838 local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700839 if (opcode == DBG_START_LOCAL_EXTENDED) {
Ian Rogers0571d352011-11-03 19:51:38 -0700840 local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
Elliott Hughes30646832011-10-13 16:59:46 -0700841 }
842 local_in_reg[reg].start_address_ = address;
843 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700844 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700845 break;
846
847 case DBG_END_LOCAL:
848 reg = DecodeUnsignedLeb128(&stream);
849 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700850 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800851 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700852 return;
853 }
854
Elliott Hughes30646832011-10-13 16:59:46 -0700855 if (need_locals) {
856 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
857 local_in_reg[reg].is_live_ = false;
858 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700859 break;
860
861 case DBG_RESTART_LOCAL:
862 reg = DecodeUnsignedLeb128(&stream);
863 if (reg > code_item->registers_size_) {
jeffhaof8728872011-10-28 19:11:13 -0700864 LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800865 << code_item->registers_size_ << ") in " << GetLocation();
Shih-wei Liao195487c2011-08-20 13:29:04 -0700866 return;
867 }
868
Elliott Hughes30646832011-10-13 16:59:46 -0700869 if (need_locals) {
870 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstrom2aab9472011-12-12 15:21:43 -0800871 LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
Elliott Hughes30646832011-10-13 16:59:46 -0700872 return;
873 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700874
Elliott Hughes30646832011-10-13 16:59:46 -0700875 // If the register is live, the "restart" is superfluous,
876 // and we don't want to mess with the existing start address.
877 if (!local_in_reg[reg].is_live_) {
878 local_in_reg[reg].start_address_ = address;
879 local_in_reg[reg].is_live_ = true;
880 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700881 }
882 break;
883
884 case DBG_SET_PROLOGUE_END:
885 case DBG_SET_EPILOGUE_BEGIN:
886 case DBG_SET_FILE:
887 break;
888
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700889 default: {
890 int adjopcode = opcode - DBG_FIRST_SPECIAL;
891
Shih-wei Liao195487c2011-08-20 13:29:04 -0700892 address += adjopcode / DBG_LINE_RANGE;
893 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
894
895 if (posCb != NULL) {
896 if (posCb(cnxt, address, line)) {
897 // early exit
898 return;
899 }
900 }
901 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700902 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700903 }
904 }
905}
906
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800907void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
Ian Rogers0571d352011-11-03 19:51:38 -0700908 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
909 void* cnxt) const {
910 const byte* stream = GetDebugInfoStream(code_item);
911 LocalInfo local_in_reg[code_item->registers_size_];
912
913 if (stream != NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800914 DecodeDebugInfo0(code_item, is_static, method_idx, posCb, local_cb, cnxt, stream, local_in_reg);
Ian Rogers0571d352011-11-03 19:51:38 -0700915 }
916 for (int reg = 0; reg < code_item->registers_size_; reg++) {
917 InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
918 }
919}
920
921bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
922 LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
923
924 // We know that this callback will be called in
925 // ascending address order, so keep going until we find
926 // a match or we've just gone past it.
927 if (address > context->address_) {
928 // The line number from the previous positions callback
929 // wil be the final result.
930 return true;
931 } else {
932 context->line_num_ = line_num;
933 return address == context->address_;
934 }
935}
936
937// Decodes the header section from the class data bytes.
938void ClassDataItemIterator::ReadClassDataHeader() {
939 CHECK(ptr_pos_ != NULL);
940 header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
941 header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
942 header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
943 header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
944}
945
946void ClassDataItemIterator::ReadClassDataField() {
947 field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
948 field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
949}
950
951void ClassDataItemIterator::ReadClassDataMethod() {
952 method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
953 method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
954 method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
955}
956
957// Read a signed integer. "zwidth" is the zero-based byte count.
958static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
959 int32_t val = 0;
960 for (int i = zwidth; i >= 0; --i) {
961 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
962 }
963 val >>= (3 - zwidth) * 8;
964 return val;
965}
966
967// Read an unsigned integer. "zwidth" is the zero-based byte count,
968// "fill_on_right" indicates which side we want to zero-fill from.
969static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
970 uint32_t val = 0;
971 if (!fill_on_right) {
972 for (int i = zwidth; i >= 0; --i) {
973 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
974 }
975 val >>= (3 - zwidth) * 8;
976 } else {
977 for (int i = zwidth; i >= 0; --i) {
978 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
979 }
980 }
981 return val;
982}
983
984// Read a signed long. "zwidth" is the zero-based byte count.
985static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
986 int64_t val = 0;
987 for (int i = zwidth; i >= 0; --i) {
988 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
989 }
990 val >>= (7 - zwidth) * 8;
991 return val;
992}
993
994// Read an unsigned long. "zwidth" is the zero-based byte count,
995// "fill_on_right" indicates which side we want to zero-fill from.
996static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
997 uint64_t val = 0;
998 if (!fill_on_right) {
999 for (int i = zwidth; i >= 0; --i) {
1000 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
1001 }
1002 val >>= (7 - zwidth) * 8;
1003 } else {
1004 for (int i = zwidth; i >= 0; --i) {
1005 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
1006 }
1007 }
1008 return val;
1009}
1010
1011EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
1012 DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
1013 dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
1014 ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
1015 if (ptr_ == NULL) {
1016 array_size_ = 0;
1017 } else {
1018 array_size_ = DecodeUnsignedLeb128(&ptr_);
1019 }
1020 if (array_size_ > 0) {
1021 Next();
1022 }
1023}
1024
1025void EncodedStaticFieldValueIterator::Next() {
1026 pos_++;
1027 if (pos_ >= array_size_) {
1028 return;
1029 }
1030 byte value_type = *ptr_++;
1031 byte value_arg = value_type >> kEncodedValueArgShift;
1032 size_t width = value_arg + 1; // assume and correct later
1033 type_ = value_type & kEncodedValueTypeMask;
1034 switch (type_) {
1035 case kBoolean:
1036 jval_.i = (value_arg != 0) ? 1 : 0;
1037 width = 0;
1038 break;
1039 case kByte:
1040 jval_.i = ReadSignedInt(ptr_, value_arg);
1041 CHECK(IsInt(8, jval_.i));
1042 break;
1043 case kShort:
1044 jval_.i = ReadSignedInt(ptr_, value_arg);
1045 CHECK(IsInt(16, jval_.i));
1046 break;
1047 case kChar:
1048 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
1049 CHECK(IsUint(16, jval_.i));
1050 break;
1051 case kInt:
1052 jval_.i = ReadSignedInt(ptr_, value_arg);
1053 break;
1054 case kLong:
1055 jval_.j = ReadSignedLong(ptr_, value_arg);
1056 break;
1057 case kFloat:
1058 jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
1059 break;
1060 case kDouble:
1061 jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
1062 break;
1063 case kString:
1064 case kType:
1065 case kMethod:
1066 case kEnum:
1067 jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
1068 break;
1069 case kField:
1070 case kArray:
1071 case kAnnotation:
1072 UNIMPLEMENTED(FATAL) << ": type " << type_;
1073 break;
1074 case kNull:
1075 jval_.l = NULL;
1076 width = 0;
1077 break;
1078 default:
1079 LOG(FATAL) << "Unreached";
1080 }
1081 ptr_ += width;
1082}
1083
1084void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
1085 switch (type_) {
1086 case kBoolean: field->SetBoolean(NULL, jval_.z); break;
1087 case kByte: field->SetByte(NULL, jval_.b); break;
1088 case kShort: field->SetShort(NULL, jval_.s); break;
1089 case kChar: field->SetChar(NULL, jval_.c); break;
1090 case kInt: field->SetInt(NULL, jval_.i); break;
1091 case kLong: field->SetLong(NULL, jval_.j); break;
1092 case kFloat: field->SetFloat(NULL, jval_.f); break;
1093 case kDouble: field->SetDouble(NULL, jval_.d); break;
1094 case kNull: field->SetObject(NULL, NULL); break;
1095 case kString: {
1096 String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
1097 field->SetObject(NULL, resolved);
1098 break;
1099 }
1100 default: UNIMPLEMENTED(FATAL) << ": type " << type_;
1101 }
1102}
1103
1104CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
1105 handler_.address_ = -1;
1106 int32_t offset = -1;
1107
1108 // Short-circuit the overwhelmingly common cases.
1109 switch (code_item.tries_size_) {
1110 case 0:
1111 break;
1112 case 1: {
1113 const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1114 uint32_t start = tries->start_addr_;
1115 if (address >= start) {
1116 uint32_t end = start + tries->insn_count_;
1117 if (address < end) {
1118 offset = tries->handler_off_;
1119 }
1120 }
1121 break;
1122 }
1123 default:
1124 offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
1125 }
1126 if (offset >= 0) {
1127 const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
1128 Init(handler_data);
1129 } else {
1130 // Not found, initialize as empty
1131 current_data_ = NULL;
1132 remaining_count_ = -1;
1133 catch_all_ = false;
1134 DCHECK(!HasNext());
1135 }
1136}
1137
1138void CatchHandlerIterator::Init(const byte* handler_data) {
1139 current_data_ = handler_data;
1140 remaining_count_ = DecodeSignedLeb128(&current_data_);
1141
1142 // If remaining_count_ is non-positive, then it is the negative of
1143 // the number of catch types, and the catches are followed by a
1144 // catch-all handler.
1145 if (remaining_count_ <= 0) {
1146 catch_all_ = true;
1147 remaining_count_ = -remaining_count_;
1148 } else {
1149 catch_all_ = false;
1150 }
1151 Next();
1152}
1153
1154void CatchHandlerIterator::Next() {
1155 if (remaining_count_ > 0) {
1156 handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1157 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1158 remaining_count_--;
1159 return;
1160 }
1161
1162 if (catch_all_) {
1163 handler_.type_idx_ = DexFile::kDexNoIndex16;
1164 handler_.address_ = DecodeUnsignedLeb128(&current_data_);
1165 catch_all_ = false;
1166 return;
1167 }
1168
1169 // no more handler
1170 remaining_count_ = -1;
1171}
1172
Carl Shapiro1fb86202011-06-27 17:43:13 -07001173} // namespace art