blob: c9e2f6285f30c0eb3cdf7689b2446201a79412f7 [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"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "globals.h"
18#include "logging.h"
19#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070020#include "os.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070021#include "stringprintf.h"
22#include "thread.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070023#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070024#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070025
26namespace art {
27
Brian Carlstromf615a612011-07-23 12:50:34 -070028const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
29const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070030
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070031DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070032 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070033 for (size_t i = 0; i != class_path.size(); ++i) {
34 const DexFile* dex_file = class_path[i];
35 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
36 if (dex_class_def != NULL) {
37 return ClassPathEntry(dex_file, dex_class_def);
38 }
39 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070040 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070041 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
42 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070043}
44
Brian Carlstrom78128a62011-09-15 17:21:19 -070045void DexFile::OpenDexFiles(std::vector<const char*>& dex_filenames,
46 std::vector<const DexFile*>& dex_files,
47 const std::string& strip_location_prefix) {
48 for (size_t i = 0; i < dex_filenames.size(); i++) {
49 const char* dex_filename = dex_filenames[i];
50 const DexFile* dex_file = Open(dex_filename, strip_location_prefix);
51 if (dex_file == NULL) {
52 fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
53 exit(EXIT_FAILURE);
54 }
55 dex_files.push_back(dex_file);
56 }
57}
58
Brian Carlstrom16192862011-09-12 17:50:06 -070059const DexFile* DexFile::Open(const std::string& filename,
60 const std::string& strip_location_prefix) {
jeffhao262bf462011-10-20 18:36:32 -070061 if (IsValidZipFilename(filename)) {
Brian Carlstrom16192862011-09-12 17:50:06 -070062 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070063 }
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -070064 if (!IsValidDexFilename(filename)) {
65 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
66 }
67 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070068}
69
jeffhaob4df5142011-09-19 20:25:32 -070070void DexFile::ChangePermissions(int prot) const {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070071 if (mprotect(mem_map_->GetAddress(), mem_map_->GetLength(), prot) != 0) {
jeffhaob4df5142011-09-19 20:25:32 -070072 PLOG(FATAL) << "Failed to change dex file permissions to " << prot;
73 }
74}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070075
Brian Carlstrom16192862011-09-12 17:50:06 -070076const DexFile* DexFile::OpenFile(const std::string& filename,
77 const std::string& original_location,
78 const std::string& strip_location_prefix) {
79 StringPiece location = original_location;
80 if (!location.starts_with(strip_location_prefix)) {
81 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
82 return NULL;
83 }
84 location.remove_prefix(strip_location_prefix.size());
Brian Carlstromb0460ea2011-07-29 10:08:05 -070085 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070086 if (fd == -1) {
87 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
88 return NULL;
89 }
90 struct stat sbuf;
91 memset(&sbuf, 0, sizeof(sbuf));
92 if (fstat(fd, &sbuf) == -1) {
93 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
94 close(fd);
95 return NULL;
96 }
97 size_t length = sbuf.st_size;
Brian Carlstrom33f741e2011-10-03 11:24:05 -070098 UniquePtr<MemMap> map(MemMap::Map(length, PROT_READ, MAP_PRIVATE, fd, 0));
99 if (map.get() == NULL) {
100 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700101 close(fd);
102 return NULL;
103 }
104 close(fd);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700105 byte* dex_file = map->GetAddress();
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700106 return OpenMemory(dex_file, length, location.ToString(), map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700107}
108
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700109const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700110
111class LockedFd {
112 public:
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700113 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700114 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
115 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700116 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700117 return NULL;
118 }
119 fchmod(fd, mode);
120
121 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
122 int result = flock(fd, LOCK_EX | LOCK_NB);
123 if (result == -1) {
124 LOG(WARNING) << "sleeping while locking file " << name;
125 result = flock(fd, LOCK_EX);
126 }
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700127 if (result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700128 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700129 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700130 return NULL;
131 }
132 return new LockedFd(fd);
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700133 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700134
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700135 int GetFd() const {
136 return fd_;
137 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700138
139 ~LockedFd() {
140 if (fd_ != -1) {
141 int result = flock(fd_, LOCK_UN);
142 if (result == -1) {
143 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
144 }
145 close(fd_);
146 }
147 }
148
149 private:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700150 explicit LockedFd(int fd) : fd_(fd) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700151
152 int fd_;
153};
154
155class TmpFile {
156 public:
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700157 explicit TmpFile(const std::string& name) : name_(name) {}
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700158 ~TmpFile() {
159 unlink(name_.c_str());
160 }
161 private:
162 const std::string name_;
163};
164
165// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700166const DexFile* DexFile::OpenZip(const std::string& filename,
167 const std::string& strip_location_prefix) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700168 // First, look for a ".dex" alongside the jar file. It will have
169 // the same name/path except for the extension.
170
171 // Example filename = dir/foo.jar
172 std::string adjacent_dex_filename(filename);
173 size_t found = adjacent_dex_filename.find_last_of(".");
174 if (found == std::string::npos) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700175 LOG(ERROR) << "No . in filename" << filename;
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700176 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700177 }
178 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
179 adjacent_dex_filename.end(),
180 ".dex");
181 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700182 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700183 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename,
184 filename,
185 strip_location_prefix);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700186 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700187 // We don't verify anything in this case, because we aren't in
188 // the cache and typically the file is in the readonly /system
189 // area, so if something is wrong, there is nothing we can do.
190 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700191 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700192 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700193 }
194
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700195 UniquePtr<char[]> resolved(new char[PATH_MAX]);
196 char* absolute_path = realpath(filename.c_str(), resolved.get());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700197 if (absolute_path == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700198 LOG(ERROR) << "Failed to create absolute path for " << filename
199 << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700200 return NULL;
201 }
jeffhao262bf462011-10-20 18:36:32 -0700202 std::string cache_path_tmp(GetArtCacheFilenameOrDie(absolute_path));
203 cache_path_tmp.push_back('@');
204 cache_path_tmp.append(kClassesDex);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700205 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
206
Elliott Hughes90a33692011-08-30 13:27:07 -0700207 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
208 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700209 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700210 return NULL;
211 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700212 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
213 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700214 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700215 return NULL;
216 }
217
218 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
219 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
220
221 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700222 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700223 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path,
224 filename,
225 strip_location_prefix);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700226 if (cached_dex_file != NULL) {
227 return cached_dex_file;
228 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700229 }
230
231 // Try to open the temporary cache file, grabbing an exclusive
232 // lock. If somebody else is working on it, we'll block here until
233 // they complete. Because we're waiting on an external resource,
234 // we go into native mode.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700235 // Note that self can be NULL if we're parsing the bootclasspath
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700236 // during JNI_CreateJavaVM.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700237 Thread* self = Thread::Current();
238 UniquePtr<ScopedThreadStateChange> state_changer;
239 if (self != NULL) {
240 state_changer.reset(new ScopedThreadStateChange(self, Thread::kNative));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700241 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700242 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700243 state_changer.reset(NULL);
Elliott Hughes90a33692011-08-30 13:27:07 -0700244 if (fd.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700245 PLOG(ERROR) << "Failed to lock file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700246 return NULL;
247 }
248
249 // Check to see if the fd we opened and locked matches the file in
250 // the filesystem. If they don't, then somebody else unlinked
251 // ours and created a new file, and we need to use that one
252 // instead. (If we caught them between the unlink and the create,
253 // we'll get an ENOENT from the file stat.)
254 struct stat fd_stat;
255 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
256 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700257 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700258 return NULL;
259 }
260 struct stat file_stat;
261 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
262 if (file_stat_result == -1 ||
263 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
264 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
265 usleep(250 * 1000); // if something is hosed, don't peg machine
266 continue;
267 }
268
269 // We have the correct file open and locked. Extract classes.dex
270 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700271 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
272 if (file.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700273 LOG(ERROR) << "Failed to create file for '" << cache_path_tmp << "'";
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700274 return NULL;
275 }
276 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700277 if (!success) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700278 LOG(ERROR) << "Failed to extract classes.dex to '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700279 return NULL;
280 }
281
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700282 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700283
284 // Compute checksum and compare to zip. If things look okay, rename from tmp.
285 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
286 if (lseek_result == -1) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700287 PLOG(ERROR) << "Failed to seek to start of '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700288 return NULL;
289 }
290 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700291 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
292 if (buf.get() == NULL) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700293 LOG(ERROR) << "Failed to allocate buffer to checksum '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700294 return NULL;
295 }
296 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
297 while (true) {
298 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700299 if (bytes_read == -1) {
300 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
301 return NULL;
302 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700303 if (bytes_read == 0) {
304 break;
305 }
306 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
307 }
308 if (computed_crc != zip_entry->GetCrc32()) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700309 LOG(ERROR) << "Failed to validate checksum for '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700310 return NULL;
311 }
312 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
313 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700314 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700315 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700316 unlink(cache_path.c_str());
317 }
318 }
319 // NOTREACHED
320}
321
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700322const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length,
323 const std::string& location, MemMap* mem_map) {
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700324 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700325 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700326 return NULL;
327 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700328 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329 }
330}
331
Jesse Wilson6bf19152011-09-29 13:12:33 -0400332DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700333 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
334 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
335 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
336 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400337}
338
339jobject DexFile::GetDexObject(JNIEnv* env) const {
340 MutexLock mu(dex_object_lock_);
341 if (dex_object_ != NULL) {
342 return dex_object_;
343 }
344
345 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
346 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
347 if (byte_buffer == NULL) {
348 return NULL;
349 }
350
351 jclass c = env->FindClass("com/android/dex/Dex");
352 if (c == NULL) {
353 return NULL;
354 }
355
356 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
357 if (mid == NULL) {
358 return NULL;
359 }
360
361 jvalue args[1];
362 args[0].l = byte_buffer;
363 jobject local = env->CallStaticObjectMethodA(c, mid, args);
364 if (local == NULL) {
365 return NULL;
366 }
367
368 dex_object_ = env->NewGlobalRef(local);
369 return dex_object_;
370}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700371
Brian Carlstromf615a612011-07-23 12:50:34 -0700372bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700373 InitMembers();
374 if (!IsMagicValid()) {
375 return false;
376 }
377 InitIndex();
378 return true;
379}
380
Brian Carlstromf615a612011-07-23 12:50:34 -0700381void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700382 const byte* b = base_;
383 header_ = reinterpret_cast<const Header*>(b);
384 const Header* h = header_;
385 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
386 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
387 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
388 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
389 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
390 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
391}
392
Brian Carlstromf615a612011-07-23 12:50:34 -0700393bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700394 return CheckMagic(header_->magic_);
395}
396
Brian Carlstromf615a612011-07-23 12:50:34 -0700397bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700398 CHECK(magic != NULL);
399 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700400 LOG(ERROR) << "Unrecognized magic number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700401 << " " << magic[0]
402 << " " << magic[1]
403 << " " << magic[2]
404 << " " << magic[3];
405 return false;
406 }
407 const byte* version = &magic[sizeof(kDexMagic)];
408 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700409 LOG(ERROR) << "Unrecognized version number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700410 << " " << version[0]
411 << " " << version[1]
412 << " " << version[2]
413 << " " << version[3];
414 return false;
415 }
416 return true;
417}
418
Ian Rogersd81871c2011-10-03 13:57:23 -0700419uint32_t DexFile::GetVersion() const {
420 const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
421 return atoi(version);
422}
423
Brian Carlstromf615a612011-07-23 12:50:34 -0700424void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700425 CHECK_EQ(index_.size(), 0U);
426 for (size_t i = 0; i < NumClassDefs(); ++i) {
427 const ClassDef& class_def = GetClassDef(i);
428 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700429 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700430 }
431}
432
Brian Carlstrome24fa612011-09-29 00:53:55 -0700433bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700434 Index::const_iterator it = index_.find(descriptor);
435 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700436 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700437 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700438 idx = it->second;
439 return true;
440}
441
442const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
443 uint32_t idx;
444 if (FindClassDefIndex(descriptor, idx)) {
445 return &GetClassDef(idx);
446 }
447 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700448}
449
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700450// Materializes the method descriptor for a method prototype. Method
451// descriptors are not stored directly in the dex file. Instead, one
452// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700453std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
454 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700455 const ProtoId& proto_id = GetProtoId(proto_idx);
456 std::string descriptor;
457 descriptor.push_back('(');
458 const TypeList* type_list = GetProtoParameters(proto_id);
459 size_t parameter_length = 0;
460 if (type_list != NULL) {
461 // A non-zero number of arguments. Append the type names.
462 for (size_t i = 0; i < type_list->Size(); ++i) {
463 const TypeItem& type_item = type_list->GetTypeItem(i);
464 uint32_t type_idx = type_item.type_idx_;
465 int32_t type_length;
466 const char* name = dexStringByTypeIdx(type_idx, &type_length);
467 parameter_length += type_length;
468 descriptor.append(name);
469 }
470 }
471 descriptor.push_back(')');
472 uint32_t return_type_idx = proto_id.return_type_idx_;
473 int32_t return_type_length;
474 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
475 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700476 if (unicode_length != NULL) {
477 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
478 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700479 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700480}
481
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700482// Read a signed integer. "zwidth" is the zero-based byte count.
483static int32_t ReadSignedInt(const byte* ptr, int zwidth)
484{
485 int32_t val = 0;
486 for (int i = zwidth; i >= 0; --i) {
487 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
488 }
489 val >>= (3 - zwidth) * 8;
490 return val;
491}
492
493// Read an unsigned integer. "zwidth" is the zero-based byte count,
494// "fill_on_right" indicates which side we want to zero-fill from.
495static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
496 bool fill_on_right) {
497 uint32_t val = 0;
498 if (!fill_on_right) {
499 for (int i = zwidth; i >= 0; --i) {
500 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
501 }
502 val >>= (3 - zwidth) * 8;
503 } else {
504 for (int i = zwidth; i >= 0; --i) {
505 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
506 }
507 }
508 return val;
509}
510
511// Read a signed long. "zwidth" is the zero-based byte count.
512static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
513 int64_t val = 0;
514 for (int i = zwidth; i >= 0; --i) {
515 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
516 }
517 val >>= (7 - zwidth) * 8;
518 return val;
519}
520
521// Read an unsigned long. "zwidth" is the zero-based byte count,
522// "fill_on_right" indicates which side we want to zero-fill from.
523static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
524 bool fill_on_right) {
525 uint64_t val = 0;
526 if (!fill_on_right) {
527 for (int i = zwidth; i >= 0; --i) {
528 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
529 }
530 val >>= (7 - zwidth) * 8;
531 } else {
532 for (int i = zwidth; i >= 0; --i) {
533 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
534 }
535 }
536 return val;
537}
538
Brian Carlstromf615a612011-07-23 12:50:34 -0700539DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
540 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700541 const byte* ptr = *stream;
542 byte value_type = *ptr++;
543 byte value_arg = value_type >> kEncodedValueArgShift;
544 size_t width = value_arg + 1; // assume and correct later
545 int type = value_type & kEncodedValueTypeMask;
546 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700547 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700548 int32_t b = ReadSignedInt(ptr, value_arg);
549 CHECK(IsInt(8, b));
550 value->i = b;
551 break;
552 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700553 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700554 int32_t s = ReadSignedInt(ptr, value_arg);
555 CHECK(IsInt(16, s));
556 value->i = s;
557 break;
558 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700559 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700560 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
561 CHECK(IsUint(16, c));
562 value->i = c;
563 break;
564 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700565 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700566 value->i = ReadSignedInt(ptr, value_arg);
567 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700568 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700569 value->j = ReadSignedLong(ptr, value_arg);
570 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700571 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700572 value->i = ReadUnsignedInt(ptr, value_arg, true);
573 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700574 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700575 value->j = ReadUnsignedLong(ptr, value_arg, true);
576 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700577 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700578 value->i = (value_arg != 0);
579 width = 0;
580 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700581 case DexFile::kString:
582 case DexFile::kType:
583 case DexFile::kMethod:
584 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700585 value->i = ReadUnsignedInt(ptr, value_arg, false);
586 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700587 case DexFile::kField:
588 case DexFile::kArray:
589 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700590 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700591 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700592 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700593 value->i = 0;
594 width = 0;
595 break;
596 default:
597 LOG(FATAL) << "Unreached";
598 }
599 ptr += width;
600 *stream = ptr;
601 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700602}
603
Shih-wei Liao195487c2011-08-20 13:29:04 -0700604int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700605 // For native method, lineno should be -2 to indicate it is native. Note that
606 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700607 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700608 return -2;
609 }
610
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700611 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Shih-wei Liao195487c2011-08-20 13:29:04 -0700612 DCHECK(code_item != NULL);
613
614 // A method with no line number info should return -1
615 LineNumFromPcContext context(rel_pc, -1);
616 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
617 return context.line_num_;
618}
619
620void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
621 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
622 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
623 uint32_t line = DecodeUnsignedLeb128(&stream);
624 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
625 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
626 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700627 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700628
629 if (!method->IsStatic()) {
Elliott Hughes30646832011-10-13 16:59:46 -0700630 if (need_locals) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700631 std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8();
632 const ClassDef* class_def = FindClassDef(descriptor);
633 CHECK(class_def != NULL) << descriptor;
634 local_in_reg[arg_reg].name_ = "this";
635 local_in_reg[arg_reg].descriptor_ = GetClassDescriptor(*class_def);
Elliott Hughes30646832011-10-13 16:59:46 -0700636 local_in_reg[arg_reg].start_address_ = 0;
637 local_in_reg[arg_reg].is_live_ = true;
638 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700639 arg_reg++;
640 }
641
Elliott Hughes30646832011-10-13 16:59:46 -0700642 ParameterIterator* it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
Shih-wei Liao195487c2011-08-20 13:29:04 -0700643 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
644 if (arg_reg >= code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700645 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700646 return;
647 }
Elliott Hughes30646832011-10-13 16:59:46 -0700648 int32_t id = DecodeUnsignedLeb128P1(&stream);
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700649 const char* descriptor = it->GetDescriptor();
Elliott Hughes30646832011-10-13 16:59:46 -0700650 if (need_locals) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700651 const char* name = dexStringById(id);
Elliott Hughes30646832011-10-13 16:59:46 -0700652 local_in_reg[arg_reg].name_ = name;
653 local_in_reg[arg_reg].descriptor_ = descriptor;
Elliott Hughes30646832011-10-13 16:59:46 -0700654 local_in_reg[arg_reg].start_address_ = address;
655 local_in_reg[arg_reg].is_live_ = true;
656 }
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700657 switch (*descriptor) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700658 case 'D':
659 case 'J':
660 arg_reg += 2;
661 break;
662 default:
663 arg_reg += 1;
664 break;
665 }
666 }
667
668 if (it->HasNext()) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700669 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700670 return;
671 }
672
673 for (;;) {
674 uint8_t opcode = *stream++;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700675 uint16_t reg;
676
Shih-wei Liao195487c2011-08-20 13:29:04 -0700677 switch (opcode) {
678 case DBG_END_SEQUENCE:
679 return;
680
681 case DBG_ADVANCE_PC:
682 address += DecodeUnsignedLeb128(&stream);
683 break;
684
685 case DBG_ADVANCE_LINE:
Shih-wei Liao8a05d272011-10-15 18:45:43 -0700686 line += DecodeSignedLeb128(&stream);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700687 break;
688
689 case DBG_START_LOCAL:
690 case DBG_START_LOCAL_EXTENDED:
691 reg = DecodeUnsignedLeb128(&stream);
692 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700693 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700694 return;
695 }
696
697 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700698 if (need_locals) {
699 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700700
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700701 local_in_reg[reg].name_ = dexStringById(DecodeUnsignedLeb128P1(&stream));
702 local_in_reg[reg].descriptor_ = dexStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
Elliott Hughes30646832011-10-13 16:59:46 -0700703 if (opcode == DBG_START_LOCAL_EXTENDED) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700704 local_in_reg[reg].signature_ = dexStringById(DecodeUnsignedLeb128P1(&stream));
Elliott Hughes30646832011-10-13 16:59:46 -0700705 }
706 local_in_reg[reg].start_address_ = address;
707 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700708 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700709 break;
710
711 case DBG_END_LOCAL:
712 reg = DecodeUnsignedLeb128(&stream);
713 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700714 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700715 return;
716 }
717
Elliott Hughes30646832011-10-13 16:59:46 -0700718 if (need_locals) {
719 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
720 local_in_reg[reg].is_live_ = false;
721 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700722 break;
723
724 case DBG_RESTART_LOCAL:
725 reg = DecodeUnsignedLeb128(&stream);
726 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700727 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700728 return;
729 }
730
Elliott Hughes30646832011-10-13 16:59:46 -0700731 if (need_locals) {
732 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700733 LOG(ERROR) << "invalid stream";
Elliott Hughes30646832011-10-13 16:59:46 -0700734 return;
735 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700736
Elliott Hughes30646832011-10-13 16:59:46 -0700737 // If the register is live, the "restart" is superfluous,
738 // and we don't want to mess with the existing start address.
739 if (!local_in_reg[reg].is_live_) {
740 local_in_reg[reg].start_address_ = address;
741 local_in_reg[reg].is_live_ = true;
742 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700743 }
744 break;
745
746 case DBG_SET_PROLOGUE_END:
747 case DBG_SET_EPILOGUE_BEGIN:
748 case DBG_SET_FILE:
749 break;
750
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700751 default: {
752 int adjopcode = opcode - DBG_FIRST_SPECIAL;
753
Shih-wei Liao195487c2011-08-20 13:29:04 -0700754 address += adjopcode / DBG_LINE_RANGE;
755 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
756
757 if (posCb != NULL) {
758 if (posCb(cnxt, address, line)) {
759 // early exit
760 return;
761 }
762 }
763 break;
Shih-wei Liao8e1b4ff2011-10-15 15:43:51 -0700764 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700765 }
766 }
767}
768
Carl Shapiro1fb86202011-06-27 17:43:13 -0700769} // namespace art