blob: 924953facc4e0f7bb3654e981a6c1aee8c1a65ca [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) {
62 LOG(WARNING) << "Ignoring short classpath entry '" << filename << "'";
63 return NULL;
64 }
65 std::string suffix(filename.substr(filename.size() - 4));
66 if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
Brian Carlstrom16192862011-09-12 17:50:06 -070067 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070068 } else {
Brian Carlstrom16192862011-09-12 17:50:06 -070069 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070070 }
71}
72
jeffhaob4df5142011-09-19 20:25:32 -070073void DexFile::ChangePermissions(int prot) const {
74 closer_->ChangePermissions(prot);
75}
76
Brian Carlstromf615a612011-07-23 12:50:34 -070077DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070078
Brian Carlstromf615a612011-07-23 12:50:34 -070079DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070080 CHECK(addr != NULL);
81}
Brian Carlstromf615a612011-07-23 12:50:34 -070082DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070083 if (munmap(addr_, length_) == -1) {
84 PLOG(INFO) << "munmap failed";
85 }
86}
jeffhaob4df5142011-09-19 20:25:32 -070087void DexFile::MmapCloser::ChangePermissions(int prot) {
88 if (mprotect(addr_, length_, prot) != 0) {
89 PLOG(FATAL) << "Failed to change dex file permissions to " << prot;
90 }
91}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070092
Brian Carlstromf615a612011-07-23 12:50:34 -070093DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
94DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
jeffhaob4df5142011-09-19 20:25:32 -070095void DexFile::PtrCloser::ChangePermissions(int prot) {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070096
Brian Carlstrom16192862011-09-12 17:50:06 -070097const DexFile* DexFile::OpenFile(const std::string& filename,
98 const std::string& original_location,
99 const std::string& strip_location_prefix) {
100 StringPiece location = original_location;
101 if (!location.starts_with(strip_location_prefix)) {
102 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
103 return NULL;
104 }
105 location.remove_prefix(strip_location_prefix.size());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700106 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700107 if (fd == -1) {
108 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
109 return NULL;
110 }
111 struct stat sbuf;
112 memset(&sbuf, 0, sizeof(sbuf));
113 if (fstat(fd, &sbuf) == -1) {
114 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
115 close(fd);
116 return NULL;
117 }
118 size_t length = sbuf.st_size;
jeffhaob4df5142011-09-19 20:25:32 -0700119 void* addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700120 if (addr == MAP_FAILED) {
121 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
122 close(fd);
123 return NULL;
124 }
125 close(fd);
126 byte* dex_file = reinterpret_cast<byte*>(addr);
127 Closer* closer = new MmapCloser(addr, length);
Brian Carlstrom16192862011-09-12 17:50:06 -0700128 return Open(dex_file, length, location.ToString(), closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700129}
130
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700131static const char* kClassesDex = "classes.dex";
132
133class LockedFd {
134 public:
135 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
136 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
137 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700138 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700139 return NULL;
140 }
141 fchmod(fd, mode);
142
143 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
144 int result = flock(fd, LOCK_EX | LOCK_NB);
145 if (result == -1) {
146 LOG(WARNING) << "sleeping while locking file " << name;
147 result = flock(fd, LOCK_EX);
148 }
149 if (result == -1 ) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700150 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700151 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700152 return NULL;
153 }
154 return new LockedFd(fd);
155 }
156
157 int GetFd() const {
158 return fd_;
159 }
160
161 ~LockedFd() {
162 if (fd_ != -1) {
163 int result = flock(fd_, LOCK_UN);
164 if (result == -1) {
165 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
166 }
167 close(fd_);
168 }
169 }
170
171 private:
172 LockedFd(int fd) : fd_(fd) {}
173
174 int fd_;
175};
176
177class TmpFile {
178 public:
179 TmpFile(const std::string name) : name_(name) {}
180 ~TmpFile() {
181 unlink(name_.c_str());
182 }
183 private:
184 const std::string name_;
185};
186
187// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700188const DexFile* DexFile::OpenZip(const std::string& filename,
189 const std::string& strip_location_prefix) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700190
191 // First, look for a ".dex" alongside the jar file. It will have
192 // the same name/path except for the extension.
193
194 // Example filename = dir/foo.jar
195 std::string adjacent_dex_filename(filename);
196 size_t found = adjacent_dex_filename.find_last_of(".");
197 if (found == std::string::npos) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700198 LOG(ERROR) << "No . in filename" << filename;
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700199 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700200 }
201 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
202 adjacent_dex_filename.end(),
203 ".dex");
204 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700205 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700206 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename,
207 filename,
208 strip_location_prefix);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700209 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700210 // We don't verify anything in this case, because we aren't in
211 // the cache and typically the file is in the readonly /system
212 // area, so if something is wrong, there is nothing we can do.
213 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700214 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700215 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700216 }
217
218 char resolved[PATH_MAX];
219 char* absolute_path = realpath(filename.c_str(), resolved);
220 if (absolute_path == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700221 LOG(ERROR) << "Failed to create absolute path for " << filename
222 << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700223 return NULL;
224 }
225 std::string cache_file(absolute_path+1); // skip leading slash
226 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
227 cache_file.push_back('@');
228 cache_file.append(kClassesDex);
229 // Example cache_file = parent@dir@foo.jar@classes.dex
230
231 const char* data_root = getenv("ANDROID_DATA");
232 if (data_root == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700233 if (OS::DirectoryExists("/data")) {
234 data_root = "/data";
235 } else {
236 data_root = "/tmp";
237 }
238 }
239 if (!OS::DirectoryExists(data_root)) {
240 LOG(ERROR) << "Failed to find ANDROID_DATA directory " << data_root;
241 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700242 }
243
Brian Carlstrom16192862011-09-12 17:50:06 -0700244 std::string art_cache = StringPrintf("%s/art-cache", data_root);
245
246 if (!OS::DirectoryExists(art_cache.c_str())) {
247 if (StringPiece(art_cache).starts_with("/tmp/")) {
248 int result = mkdir(art_cache.c_str(), 0700);
249 if (result != 0) {
Elliott Hughes380fac02011-09-16 16:01:07 -0700250 LOG(FATAL) << "Failed to create art-cache directory " << art_cache;
Brian Carlstrom16192862011-09-12 17:50:06 -0700251 return NULL;
252 }
253 } else {
Elliott Hughes380fac02011-09-16 16:01:07 -0700254 LOG(FATAL) << "Failed to find art-cache directory " << art_cache;
Brian Carlstrom16192862011-09-12 17:50:06 -0700255 return NULL;
256 }
257 }
258
259 std::string cache_path_tmp = StringPrintf("%s/%s", art_cache.c_str(), cache_file.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700260 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
261
Elliott Hughes90a33692011-08-30 13:27:07 -0700262 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
263 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700264 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700265 return NULL;
266 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700267 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
268 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700269 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700270 return NULL;
271 }
272
273 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
274 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
275
276 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700277 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700278 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path,
279 filename,
280 strip_location_prefix);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700281 if (cached_dex_file != NULL) {
282 return cached_dex_file;
283 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700284 }
285
286 // Try to open the temporary cache file, grabbing an exclusive
287 // lock. If somebody else is working on it, we'll block here until
288 // they complete. Because we're waiting on an external resource,
289 // we go into native mode.
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700290 // Note that current_thread can be NULL if we're parsing the bootclasspath
291 // during JNI_CreateJavaVM.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700292 Thread* current_thread = Thread::Current();
Elliott Hughesd92bec42011-09-02 17:04:36 -0700293 Thread::State old(Thread::kUnknown);
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700294 if (current_thread != NULL) {
Elliott Hughesad7c2a32011-08-31 11:58:10 -0700295 old = current_thread->SetState(Thread::kNative);
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700296 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700297 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700298 if (current_thread != NULL) {
299 current_thread->SetState(old);
300 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700301 if (fd.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700302 return NULL;
303 }
304
305 // Check to see if the fd we opened and locked matches the file in
306 // the filesystem. If they don't, then somebody else unlinked
307 // ours and created a new file, and we need to use that one
308 // instead. (If we caught them between the unlink and the create,
309 // we'll get an ENOENT from the file stat.)
310 struct stat fd_stat;
311 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
312 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700313 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700314 return NULL;
315 }
316 struct stat file_stat;
317 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
318 if (file_stat_result == -1 ||
319 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
320 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
321 usleep(250 * 1000); // if something is hosed, don't peg machine
322 continue;
323 }
324
325 // We have the correct file open and locked. Extract classes.dex
326 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700327 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
328 if (file.get() == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700329 return NULL;
330 }
331 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700332 if (!success) {
333 return NULL;
334 }
335
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700336 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700337
338 // Compute checksum and compare to zip. If things look okay, rename from tmp.
339 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
340 if (lseek_result == -1) {
341 return NULL;
342 }
343 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700344 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
345 if (buf.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700346 return NULL;
347 }
348 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
349 while (true) {
350 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700351 if (bytes_read == -1) {
352 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
353 return NULL;
354 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700355 if (bytes_read == 0) {
356 break;
357 }
358 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
359 }
360 if (computed_crc != zip_entry->GetCrc32()) {
361 return NULL;
362 }
363 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
364 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700365 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700366 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700367 unlink(cache_path.c_str());
368 }
369 }
370 // NOTREACHED
371}
372
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700373const DexFile* DexFile::OpenPtr(byte* ptr, size_t length, const std::string& location) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700374 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700375 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700376 return Open(ptr, length, location, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700377}
378
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700379const DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
380 const std::string& location, Closer* closer) {
Elliott Hughes90a33692011-08-30 13:27:07 -0700381 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, closer));
Brian Carlstromf615a612011-07-23 12:50:34 -0700382 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700383 return NULL;
384 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700385 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700386 }
387}
388
Brian Carlstromf615a612011-07-23 12:50:34 -0700389DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700390
Brian Carlstromf615a612011-07-23 12:50:34 -0700391bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700392 InitMembers();
393 if (!IsMagicValid()) {
394 return false;
395 }
396 InitIndex();
397 return true;
398}
399
Brian Carlstromf615a612011-07-23 12:50:34 -0700400void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700401 const byte* b = base_;
402 header_ = reinterpret_cast<const Header*>(b);
403 const Header* h = header_;
404 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
405 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
406 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
407 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
408 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
409 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
410}
411
Brian Carlstromf615a612011-07-23 12:50:34 -0700412bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700413 return CheckMagic(header_->magic_);
414}
415
Brian Carlstromf615a612011-07-23 12:50:34 -0700416bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700417 CHECK(magic != NULL);
418 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700419 LOG(ERROR) << "Unrecognized magic number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700420 << " " << magic[0]
421 << " " << magic[1]
422 << " " << magic[2]
423 << " " << magic[3];
424 return false;
425 }
426 const byte* version = &magic[sizeof(kDexMagic)];
427 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700428 LOG(ERROR) << "Unrecognized version number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700429 << " " << version[0]
430 << " " << version[1]
431 << " " << version[2]
432 << " " << version[3];
433 return false;
434 }
435 return true;
436}
437
Brian Carlstromf615a612011-07-23 12:50:34 -0700438void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700439 CHECK_EQ(index_.size(), 0U);
440 for (size_t i = 0; i < NumClassDefs(); ++i) {
441 const ClassDef& class_def = GetClassDef(i);
442 const char* descriptor = GetClassDescriptor(class_def);
443 index_[descriptor] = &class_def;
444 }
445}
446
Brian Carlstromf615a612011-07-23 12:50:34 -0700447const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700448 Index::const_iterator it = index_.find(descriptor);
449 if (it == index_.end()) {
450 return NULL;
451 } else {
452 return it->second;
453 }
454}
455
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700456// Materializes the method descriptor for a method prototype. Method
457// descriptors are not stored directly in the dex file. Instead, one
458// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700459std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
460 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700461 const ProtoId& proto_id = GetProtoId(proto_idx);
462 std::string descriptor;
463 descriptor.push_back('(');
464 const TypeList* type_list = GetProtoParameters(proto_id);
465 size_t parameter_length = 0;
466 if (type_list != NULL) {
467 // A non-zero number of arguments. Append the type names.
468 for (size_t i = 0; i < type_list->Size(); ++i) {
469 const TypeItem& type_item = type_list->GetTypeItem(i);
470 uint32_t type_idx = type_item.type_idx_;
471 int32_t type_length;
472 const char* name = dexStringByTypeIdx(type_idx, &type_length);
473 parameter_length += type_length;
474 descriptor.append(name);
475 }
476 }
477 descriptor.push_back(')');
478 uint32_t return_type_idx = proto_id.return_type_idx_;
479 int32_t return_type_length;
480 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
481 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700482 if (unicode_length != NULL) {
483 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
484 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700485 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700486}
487
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700488// Read a signed integer. "zwidth" is the zero-based byte count.
489static int32_t ReadSignedInt(const byte* ptr, int zwidth)
490{
491 int32_t val = 0;
492 for (int i = zwidth; i >= 0; --i) {
493 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
494 }
495 val >>= (3 - zwidth) * 8;
496 return val;
497}
498
499// Read an unsigned integer. "zwidth" is the zero-based byte count,
500// "fill_on_right" indicates which side we want to zero-fill from.
501static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
502 bool fill_on_right) {
503 uint32_t val = 0;
504 if (!fill_on_right) {
505 for (int i = zwidth; i >= 0; --i) {
506 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
507 }
508 val >>= (3 - zwidth) * 8;
509 } else {
510 for (int i = zwidth; i >= 0; --i) {
511 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
512 }
513 }
514 return val;
515}
516
517// Read a signed long. "zwidth" is the zero-based byte count.
518static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
519 int64_t val = 0;
520 for (int i = zwidth; i >= 0; --i) {
521 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
522 }
523 val >>= (7 - zwidth) * 8;
524 return val;
525}
526
527// Read an unsigned long. "zwidth" is the zero-based byte count,
528// "fill_on_right" indicates which side we want to zero-fill from.
529static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
530 bool fill_on_right) {
531 uint64_t val = 0;
532 if (!fill_on_right) {
533 for (int i = zwidth; i >= 0; --i) {
534 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
535 }
536 val >>= (7 - zwidth) * 8;
537 } else {
538 for (int i = zwidth; i >= 0; --i) {
539 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
540 }
541 }
542 return val;
543}
544
Brian Carlstromf615a612011-07-23 12:50:34 -0700545DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
546 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700547 const byte* ptr = *stream;
548 byte value_type = *ptr++;
549 byte value_arg = value_type >> kEncodedValueArgShift;
550 size_t width = value_arg + 1; // assume and correct later
551 int type = value_type & kEncodedValueTypeMask;
552 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700553 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700554 int32_t b = ReadSignedInt(ptr, value_arg);
555 CHECK(IsInt(8, b));
556 value->i = b;
557 break;
558 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700559 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700560 int32_t s = ReadSignedInt(ptr, value_arg);
561 CHECK(IsInt(16, s));
562 value->i = s;
563 break;
564 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700565 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700566 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
567 CHECK(IsUint(16, c));
568 value->i = c;
569 break;
570 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700571 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700572 value->i = ReadSignedInt(ptr, value_arg);
573 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700574 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700575 value->j = ReadSignedLong(ptr, value_arg);
576 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700577 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700578 value->i = ReadUnsignedInt(ptr, value_arg, true);
579 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700580 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700581 value->j = ReadUnsignedLong(ptr, value_arg, true);
582 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700583 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700584 value->i = (value_arg != 0);
585 width = 0;
586 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700587 case DexFile::kString:
588 case DexFile::kType:
589 case DexFile::kMethod:
590 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700591 value->i = ReadUnsignedInt(ptr, value_arg, false);
592 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700593 case DexFile::kField:
594 case DexFile::kArray:
595 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700596 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700597 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700598 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700599 value->i = 0;
600 width = 0;
601 break;
602 default:
603 LOG(FATAL) << "Unreached";
604 }
605 ptr += width;
606 *stream = ptr;
607 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700608}
609
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700610String* DexFile::dexArtStringById(int32_t idx) const {
611 if (idx == -1) {
612 return NULL;
613 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700614 return String::AllocFromModifiedUtf8(dexStringById(idx));
615}
616
617int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700618 // For native method, lineno should be -2 to indicate it is native. Note that
619 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700620 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700621 return -2;
622 }
623
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700624 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Shih-wei Liao195487c2011-08-20 13:29:04 -0700625 DCHECK(code_item != NULL);
626
627 // A method with no line number info should return -1
628 LineNumFromPcContext context(rel_pc, -1);
629 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
630 return context.line_num_;
631}
632
633void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
634 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
635 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
636 uint32_t line = DecodeUnsignedLeb128(&stream);
637 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
638 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
639 uint32_t address = 0;
640
641 if (!method->IsStatic()) {
642 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
643 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
644 local_in_reg[arg_reg].signature_ = NULL;
645 local_in_reg[arg_reg].start_address_ = 0;
646 local_in_reg[arg_reg].is_live_ = true;
647 arg_reg++;
648 }
649
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700650 ParameterIterator *it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
Shih-wei Liao195487c2011-08-20 13:29:04 -0700651 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
652 if (arg_reg >= code_item->registers_size_) {
653 LOG(FATAL) << "invalid stream";
654 return;
655 }
656
657 String* descriptor = String::AllocFromModifiedUtf8(it->GetDescriptor());
658 String* name = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
659
660 local_in_reg[arg_reg].name_ = name;
661 local_in_reg[arg_reg].descriptor_ = descriptor;
662 local_in_reg[arg_reg].signature_ = NULL;
663 local_in_reg[arg_reg].start_address_ = address;
664 local_in_reg[arg_reg].is_live_ = true;
665 switch (descriptor->CharAt(0)) {
666 case 'D':
667 case 'J':
668 arg_reg += 2;
669 break;
670 default:
671 arg_reg += 1;
672 break;
673 }
674 }
675
676 if (it->HasNext()) {
677 LOG(FATAL) << "invalid stream";
678 return;
679 }
680
681 for (;;) {
682 uint8_t opcode = *stream++;
683 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
684 uint16_t reg;
685
686
687 switch (opcode) {
688 case DBG_END_SEQUENCE:
689 return;
690
691 case DBG_ADVANCE_PC:
692 address += DecodeUnsignedLeb128(&stream);
693 break;
694
695 case DBG_ADVANCE_LINE:
696 line += DecodeUnsignedLeb128(&stream);
697 break;
698
699 case DBG_START_LOCAL:
700 case DBG_START_LOCAL_EXTENDED:
701 reg = DecodeUnsignedLeb128(&stream);
702 if (reg > code_item->registers_size_) {
703 LOG(FATAL) << "invalid stream";
704 return;
705 }
706
707 // Emit what was previously there, if anything
708 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
709
710 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
711 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
712 if (opcode == DBG_START_LOCAL_EXTENDED) {
713 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
714 } else {
715 local_in_reg[reg].signature_ = NULL;
716 }
717 local_in_reg[reg].start_address_ = address;
718 local_in_reg[reg].is_live_ = true;
719 break;
720
721 case DBG_END_LOCAL:
722 reg = DecodeUnsignedLeb128(&stream);
723 if (reg > code_item->registers_size_) {
724 LOG(FATAL) << "invalid stream";
725 return;
726 }
727
728 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
729 local_in_reg[reg].is_live_ = false;
730 break;
731
732 case DBG_RESTART_LOCAL:
733 reg = DecodeUnsignedLeb128(&stream);
734 if (reg > code_item->registers_size_) {
735 LOG(FATAL) << "invalid stream";
736 return;
737 }
738
739 if (local_in_reg[reg].name_ == NULL
740 || local_in_reg[reg].descriptor_ == NULL) {
741 LOG(FATAL) << "invalid stream";
742 return;
743 }
744
745 // If the register is live, the "restart" is superfluous,
746 // and we don't want to mess with the existing start address.
747 if (!local_in_reg[reg].is_live_) {
748 local_in_reg[reg].start_address_ = address;
749 local_in_reg[reg].is_live_ = true;
750 }
751 break;
752
753 case DBG_SET_PROLOGUE_END:
754 case DBG_SET_EPILOGUE_BEGIN:
755 case DBG_SET_FILE:
756 break;
757
758 default:
759 address += adjopcode / DBG_LINE_RANGE;
760 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
761
762 if (posCb != NULL) {
763 if (posCb(cnxt, address, line)) {
764 // early exit
765 return;
766 }
767 }
768 break;
769 }
770 }
771}
772
Carl Shapiro1fb86202011-06-27 17:43:13 -0700773} // namespace art