blob: 474d74213d43a902143aec1bd72e37c5dc304fcb [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>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07008#include <string.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -07009#include <sys/file.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070010#include <sys/mman.h>
11#include <sys/stat.h>
12#include <sys/types.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) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070061 if (filename.size() < 4) {
Brian Carlstrom58ae9412011-10-04 00:56:06 -070062 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070063 }
64 std::string suffix(filename.substr(filename.size() - 4));
65 if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
Brian Carlstrom16192862011-09-12 17:50:06 -070066 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070067 } else {
Brian Carlstrom16192862011-09-12 17:50:06 -070068 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070069 }
70}
71
jeffhaob4df5142011-09-19 20:25:32 -070072void DexFile::ChangePermissions(int prot) const {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070073 if (mprotect(mem_map_->GetAddress(), mem_map_->GetLength(), prot) != 0) {
jeffhaob4df5142011-09-19 20:25:32 -070074 PLOG(FATAL) << "Failed to change dex file permissions to " << prot;
75 }
76}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070077
Brian Carlstrom16192862011-09-12 17:50:06 -070078const DexFile* DexFile::OpenFile(const std::string& filename,
79 const std::string& original_location,
80 const std::string& strip_location_prefix) {
81 StringPiece location = original_location;
82 if (!location.starts_with(strip_location_prefix)) {
83 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
84 return NULL;
85 }
86 location.remove_prefix(strip_location_prefix.size());
Brian Carlstromb0460ea2011-07-29 10:08:05 -070087 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070088 if (fd == -1) {
89 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
90 return NULL;
91 }
92 struct stat sbuf;
93 memset(&sbuf, 0, sizeof(sbuf));
94 if (fstat(fd, &sbuf) == -1) {
95 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
96 close(fd);
97 return NULL;
98 }
99 size_t length = sbuf.st_size;
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700100 UniquePtr<MemMap> map(MemMap::Map(length, PROT_READ, MAP_PRIVATE, fd, 0));
101 if (map.get() == NULL) {
102 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700103 close(fd);
104 return NULL;
105 }
106 close(fd);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700107 byte* dex_file = map->GetAddress();
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700108 return OpenMemory(dex_file, length, location.ToString(), map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700109}
110
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700111static const char* kClassesDex = "classes.dex";
112
113class LockedFd {
114 public:
115 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
116 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
117 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700118 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700119 return NULL;
120 }
121 fchmod(fd, mode);
122
123 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
124 int result = flock(fd, LOCK_EX | LOCK_NB);
125 if (result == -1) {
126 LOG(WARNING) << "sleeping while locking file " << name;
127 result = flock(fd, LOCK_EX);
128 }
129 if (result == -1 ) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700130 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700131 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700132 return NULL;
133 }
134 return new LockedFd(fd);
135 }
136
137 int GetFd() const {
138 return fd_;
139 }
140
141 ~LockedFd() {
142 if (fd_ != -1) {
143 int result = flock(fd_, LOCK_UN);
144 if (result == -1) {
145 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
146 }
147 close(fd_);
148 }
149 }
150
151 private:
152 LockedFd(int fd) : fd_(fd) {}
153
154 int fd_;
155};
156
157class TmpFile {
158 public:
159 TmpFile(const std::string name) : name_(name) {}
160 ~TmpFile() {
161 unlink(name_.c_str());
162 }
163 private:
164 const std::string name_;
165};
166
167// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700168const DexFile* DexFile::OpenZip(const std::string& filename,
169 const std::string& strip_location_prefix) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700170
171 // 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
198 char resolved[PATH_MAX];
199 char* absolute_path = realpath(filename.c_str(), resolved);
200 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 }
205 std::string cache_file(absolute_path+1); // skip leading slash
206 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
207 cache_file.push_back('@');
208 cache_file.append(kClassesDex);
209 // Example cache_file = parent@dir@foo.jar@classes.dex
210
211 const char* data_root = getenv("ANDROID_DATA");
212 if (data_root == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700213 if (OS::DirectoryExists("/data")) {
214 data_root = "/data";
215 } else {
216 data_root = "/tmp";
217 }
218 }
219 if (!OS::DirectoryExists(data_root)) {
220 LOG(ERROR) << "Failed to find ANDROID_DATA directory " << data_root;
221 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700222 }
223
Brian Carlstrom16192862011-09-12 17:50:06 -0700224 std::string art_cache = StringPrintf("%s/art-cache", data_root);
225
226 if (!OS::DirectoryExists(art_cache.c_str())) {
227 if (StringPiece(art_cache).starts_with("/tmp/")) {
228 int result = mkdir(art_cache.c_str(), 0700);
229 if (result != 0) {
Elliott Hughes380fac02011-09-16 16:01:07 -0700230 LOG(FATAL) << "Failed to create art-cache directory " << art_cache;
Brian Carlstrom16192862011-09-12 17:50:06 -0700231 return NULL;
232 }
233 } else {
Elliott Hughes380fac02011-09-16 16:01:07 -0700234 LOG(FATAL) << "Failed to find art-cache directory " << art_cache;
Brian Carlstrom16192862011-09-12 17:50:06 -0700235 return NULL;
236 }
237 }
238
239 std::string cache_path_tmp = StringPrintf("%s/%s", art_cache.c_str(), cache_file.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700240 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
241
Elliott Hughes90a33692011-08-30 13:27:07 -0700242 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
243 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700244 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700245 return NULL;
246 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700247 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
248 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700249 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700250 return NULL;
251 }
252
253 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
254 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
255
256 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700257 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700258 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path,
259 filename,
260 strip_location_prefix);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700261 if (cached_dex_file != NULL) {
262 return cached_dex_file;
263 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700264 }
265
266 // Try to open the temporary cache file, grabbing an exclusive
267 // lock. If somebody else is working on it, we'll block here until
268 // they complete. Because we're waiting on an external resource,
269 // we go into native mode.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700270 // Note that self can be NULL if we're parsing the bootclasspath
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700271 // during JNI_CreateJavaVM.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700272 Thread* self = Thread::Current();
273 UniquePtr<ScopedThreadStateChange> state_changer;
274 if (self != NULL) {
275 state_changer.reset(new ScopedThreadStateChange(self, Thread::kNative));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700276 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700277 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700278 state_changer.reset(NULL);
Elliott Hughes90a33692011-08-30 13:27:07 -0700279 if (fd.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700280 return NULL;
281 }
282
283 // Check to see if the fd we opened and locked matches the file in
284 // the filesystem. If they don't, then somebody else unlinked
285 // ours and created a new file, and we need to use that one
286 // instead. (If we caught them between the unlink and the create,
287 // we'll get an ENOENT from the file stat.)
288 struct stat fd_stat;
289 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
290 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700291 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700292 return NULL;
293 }
294 struct stat file_stat;
295 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
296 if (file_stat_result == -1 ||
297 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
298 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
299 usleep(250 * 1000); // if something is hosed, don't peg machine
300 continue;
301 }
302
303 // We have the correct file open and locked. Extract classes.dex
304 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700305 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
306 if (file.get() == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700307 return NULL;
308 }
309 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700310 if (!success) {
311 return NULL;
312 }
313
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700314 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700315
316 // Compute checksum and compare to zip. If things look okay, rename from tmp.
317 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
318 if (lseek_result == -1) {
319 return NULL;
320 }
321 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700322 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
323 if (buf.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700324 return NULL;
325 }
326 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
327 while (true) {
328 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700329 if (bytes_read == -1) {
330 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
331 return NULL;
332 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700333 if (bytes_read == 0) {
334 break;
335 }
336 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
337 }
338 if (computed_crc != zip_entry->GetCrc32()) {
339 return NULL;
340 }
341 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
342 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700343 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700344 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700345 unlink(cache_path.c_str());
346 }
347 }
348 // NOTREACHED
349}
350
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700351const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length,
352 const std::string& location, MemMap* mem_map) {
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700353 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700354 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700355 return NULL;
356 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700357 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700358 }
359}
360
Jesse Wilson6bf19152011-09-29 13:12:33 -0400361DexFile::~DexFile() {
362 if (dex_object_ != NULL) {
363 UNIMPLEMENTED(WARNING) << "leaked a global reference to an com.android.dex.Dex instance";
364 }
365}
366
367jobject DexFile::GetDexObject(JNIEnv* env) const {
368 MutexLock mu(dex_object_lock_);
369 if (dex_object_ != NULL) {
370 return dex_object_;
371 }
372
373 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
374 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
375 if (byte_buffer == NULL) {
376 return NULL;
377 }
378
379 jclass c = env->FindClass("com/android/dex/Dex");
380 if (c == NULL) {
381 return NULL;
382 }
383
384 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
385 if (mid == NULL) {
386 return NULL;
387 }
388
389 jvalue args[1];
390 args[0].l = byte_buffer;
391 jobject local = env->CallStaticObjectMethodA(c, mid, args);
392 if (local == NULL) {
393 return NULL;
394 }
395
396 dex_object_ = env->NewGlobalRef(local);
397 return dex_object_;
398}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700399
Brian Carlstromf615a612011-07-23 12:50:34 -0700400bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700401 InitMembers();
402 if (!IsMagicValid()) {
403 return false;
404 }
405 InitIndex();
406 return true;
407}
408
Brian Carlstromf615a612011-07-23 12:50:34 -0700409void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700410 const byte* b = base_;
411 header_ = reinterpret_cast<const Header*>(b);
412 const Header* h = header_;
413 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
414 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
415 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
416 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
417 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
418 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
419}
420
Brian Carlstromf615a612011-07-23 12:50:34 -0700421bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700422 return CheckMagic(header_->magic_);
423}
424
Brian Carlstromf615a612011-07-23 12:50:34 -0700425bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700426 CHECK(magic != NULL);
427 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700428 LOG(ERROR) << "Unrecognized magic number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700429 << " " << magic[0]
430 << " " << magic[1]
431 << " " << magic[2]
432 << " " << magic[3];
433 return false;
434 }
435 const byte* version = &magic[sizeof(kDexMagic)];
436 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700437 LOG(ERROR) << "Unrecognized version number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700438 << " " << version[0]
439 << " " << version[1]
440 << " " << version[2]
441 << " " << version[3];
442 return false;
443 }
444 return true;
445}
446
Brian Carlstromf615a612011-07-23 12:50:34 -0700447void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700448 CHECK_EQ(index_.size(), 0U);
449 for (size_t i = 0; i < NumClassDefs(); ++i) {
450 const ClassDef& class_def = GetClassDef(i);
451 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700452 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700453 }
454}
455
Brian Carlstrome24fa612011-09-29 00:53:55 -0700456bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700457 Index::const_iterator it = index_.find(descriptor);
458 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700459 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700460 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700461 idx = it->second;
462 return true;
463}
464
465const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
466 uint32_t idx;
467 if (FindClassDefIndex(descriptor, idx)) {
468 return &GetClassDef(idx);
469 }
470 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700471}
472
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700473// Materializes the method descriptor for a method prototype. Method
474// descriptors are not stored directly in the dex file. Instead, one
475// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700476std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
477 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700478 const ProtoId& proto_id = GetProtoId(proto_idx);
479 std::string descriptor;
480 descriptor.push_back('(');
481 const TypeList* type_list = GetProtoParameters(proto_id);
482 size_t parameter_length = 0;
483 if (type_list != NULL) {
484 // A non-zero number of arguments. Append the type names.
485 for (size_t i = 0; i < type_list->Size(); ++i) {
486 const TypeItem& type_item = type_list->GetTypeItem(i);
487 uint32_t type_idx = type_item.type_idx_;
488 int32_t type_length;
489 const char* name = dexStringByTypeIdx(type_idx, &type_length);
490 parameter_length += type_length;
491 descriptor.append(name);
492 }
493 }
494 descriptor.push_back(')');
495 uint32_t return_type_idx = proto_id.return_type_idx_;
496 int32_t return_type_length;
497 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
498 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700499 if (unicode_length != NULL) {
500 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
501 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700502 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700503}
504
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700505// Read a signed integer. "zwidth" is the zero-based byte count.
506static int32_t ReadSignedInt(const byte* ptr, int zwidth)
507{
508 int32_t val = 0;
509 for (int i = zwidth; i >= 0; --i) {
510 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
511 }
512 val >>= (3 - zwidth) * 8;
513 return val;
514}
515
516// Read an unsigned integer. "zwidth" is the zero-based byte count,
517// "fill_on_right" indicates which side we want to zero-fill from.
518static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
519 bool fill_on_right) {
520 uint32_t val = 0;
521 if (!fill_on_right) {
522 for (int i = zwidth; i >= 0; --i) {
523 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
524 }
525 val >>= (3 - zwidth) * 8;
526 } else {
527 for (int i = zwidth; i >= 0; --i) {
528 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
529 }
530 }
531 return val;
532}
533
534// Read a signed long. "zwidth" is the zero-based byte count.
535static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
536 int64_t val = 0;
537 for (int i = zwidth; i >= 0; --i) {
538 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
539 }
540 val >>= (7 - zwidth) * 8;
541 return val;
542}
543
544// Read an unsigned long. "zwidth" is the zero-based byte count,
545// "fill_on_right" indicates which side we want to zero-fill from.
546static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
547 bool fill_on_right) {
548 uint64_t val = 0;
549 if (!fill_on_right) {
550 for (int i = zwidth; i >= 0; --i) {
551 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
552 }
553 val >>= (7 - zwidth) * 8;
554 } else {
555 for (int i = zwidth; i >= 0; --i) {
556 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
557 }
558 }
559 return val;
560}
561
Brian Carlstromf615a612011-07-23 12:50:34 -0700562DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
563 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700564 const byte* ptr = *stream;
565 byte value_type = *ptr++;
566 byte value_arg = value_type >> kEncodedValueArgShift;
567 size_t width = value_arg + 1; // assume and correct later
568 int type = value_type & kEncodedValueTypeMask;
569 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700570 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700571 int32_t b = ReadSignedInt(ptr, value_arg);
572 CHECK(IsInt(8, b));
573 value->i = b;
574 break;
575 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700576 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700577 int32_t s = ReadSignedInt(ptr, value_arg);
578 CHECK(IsInt(16, s));
579 value->i = s;
580 break;
581 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700582 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700583 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
584 CHECK(IsUint(16, c));
585 value->i = c;
586 break;
587 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700588 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700589 value->i = ReadSignedInt(ptr, value_arg);
590 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700591 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700592 value->j = ReadSignedLong(ptr, value_arg);
593 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700594 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700595 value->i = ReadUnsignedInt(ptr, value_arg, true);
596 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700597 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700598 value->j = ReadUnsignedLong(ptr, value_arg, true);
599 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700600 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700601 value->i = (value_arg != 0);
602 width = 0;
603 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700604 case DexFile::kString:
605 case DexFile::kType:
606 case DexFile::kMethod:
607 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700608 value->i = ReadUnsignedInt(ptr, value_arg, false);
609 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700610 case DexFile::kField:
611 case DexFile::kArray:
612 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700613 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700614 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700615 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700616 value->i = 0;
617 width = 0;
618 break;
619 default:
620 LOG(FATAL) << "Unreached";
621 }
622 ptr += width;
623 *stream = ptr;
624 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700625}
626
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700627String* DexFile::dexArtStringById(int32_t idx) const {
628 if (idx == -1) {
629 return NULL;
630 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700631 return String::AllocFromModifiedUtf8(dexStringById(idx));
632}
633
634int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700635 // For native method, lineno should be -2 to indicate it is native. Note that
636 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700637 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700638 return -2;
639 }
640
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700641 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Shih-wei Liao195487c2011-08-20 13:29:04 -0700642 DCHECK(code_item != NULL);
643
644 // A method with no line number info should return -1
645 LineNumFromPcContext context(rel_pc, -1);
646 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
647 return context.line_num_;
648}
649
650void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
651 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
652 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
653 uint32_t line = DecodeUnsignedLeb128(&stream);
654 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
655 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
656 uint32_t address = 0;
657
658 if (!method->IsStatic()) {
659 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
660 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
661 local_in_reg[arg_reg].signature_ = NULL;
662 local_in_reg[arg_reg].start_address_ = 0;
663 local_in_reg[arg_reg].is_live_ = true;
664 arg_reg++;
665 }
666
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700667 ParameterIterator *it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
Shih-wei Liao195487c2011-08-20 13:29:04 -0700668 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
669 if (arg_reg >= code_item->registers_size_) {
670 LOG(FATAL) << "invalid stream";
671 return;
672 }
673
674 String* descriptor = String::AllocFromModifiedUtf8(it->GetDescriptor());
675 String* name = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
676
677 local_in_reg[arg_reg].name_ = name;
678 local_in_reg[arg_reg].descriptor_ = descriptor;
679 local_in_reg[arg_reg].signature_ = NULL;
680 local_in_reg[arg_reg].start_address_ = address;
681 local_in_reg[arg_reg].is_live_ = true;
682 switch (descriptor->CharAt(0)) {
683 case 'D':
684 case 'J':
685 arg_reg += 2;
686 break;
687 default:
688 arg_reg += 1;
689 break;
690 }
691 }
692
693 if (it->HasNext()) {
694 LOG(FATAL) << "invalid stream";
695 return;
696 }
697
698 for (;;) {
699 uint8_t opcode = *stream++;
700 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
701 uint16_t reg;
702
703
704 switch (opcode) {
705 case DBG_END_SEQUENCE:
706 return;
707
708 case DBG_ADVANCE_PC:
709 address += DecodeUnsignedLeb128(&stream);
710 break;
711
712 case DBG_ADVANCE_LINE:
713 line += DecodeUnsignedLeb128(&stream);
714 break;
715
716 case DBG_START_LOCAL:
717 case DBG_START_LOCAL_EXTENDED:
718 reg = DecodeUnsignedLeb128(&stream);
719 if (reg > code_item->registers_size_) {
720 LOG(FATAL) << "invalid stream";
721 return;
722 }
723
724 // Emit what was previously there, if anything
725 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
726
727 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
728 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
729 if (opcode == DBG_START_LOCAL_EXTENDED) {
730 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
731 } else {
732 local_in_reg[reg].signature_ = NULL;
733 }
734 local_in_reg[reg].start_address_ = address;
735 local_in_reg[reg].is_live_ = true;
736 break;
737
738 case DBG_END_LOCAL:
739 reg = DecodeUnsignedLeb128(&stream);
740 if (reg > code_item->registers_size_) {
741 LOG(FATAL) << "invalid stream";
742 return;
743 }
744
745 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
746 local_in_reg[reg].is_live_ = false;
747 break;
748
749 case DBG_RESTART_LOCAL:
750 reg = DecodeUnsignedLeb128(&stream);
751 if (reg > code_item->registers_size_) {
752 LOG(FATAL) << "invalid stream";
753 return;
754 }
755
756 if (local_in_reg[reg].name_ == NULL
757 || local_in_reg[reg].descriptor_ == NULL) {
758 LOG(FATAL) << "invalid stream";
759 return;
760 }
761
762 // If the register is live, the "restart" is superfluous,
763 // and we don't want to mess with the existing start address.
764 if (!local_in_reg[reg].is_live_) {
765 local_in_reg[reg].start_address_ = address;
766 local_in_reg[reg].is_live_ = true;
767 }
768 break;
769
770 case DBG_SET_PROLOGUE_END:
771 case DBG_SET_EPILOGUE_BEGIN:
772 case DBG_SET_FILE:
773 break;
774
775 default:
776 address += adjopcode / DBG_LINE_RANGE;
777 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
778
779 if (posCb != NULL) {
780 if (posCb(cnxt, address, line)) {
781 // early exit
782 return;
783 }
784 }
785 break;
786 }
787 }
788}
789
Carl Shapiro1fb86202011-06-27 17:43:13 -0700790} // namespace art