blob: a11744d23230f39e2e8b67fb4f6647c086a8bad7 [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>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070012
Elliott Hughes90a33692011-08-30 13:27:07 -070013#include <map>
14
15#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070016#include "globals.h"
17#include "logging.h"
18#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070019#include "os.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070020#include "stringprintf.h"
21#include "thread.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070022#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070023#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070024
25namespace art {
26
Brian Carlstromf615a612011-07-23 12:50:34 -070027const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
28const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070029
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070030DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070031 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070032 for (size_t i = 0; i != class_path.size(); ++i) {
33 const DexFile* dex_file = class_path[i];
34 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
35 if (dex_class_def != NULL) {
36 return ClassPathEntry(dex_file, dex_class_def);
37 }
38 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070039 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070040 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
41 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070042}
43
Brian Carlstrom78128a62011-09-15 17:21:19 -070044void DexFile::OpenDexFiles(std::vector<const char*>& dex_filenames,
45 std::vector<const DexFile*>& dex_files,
46 const std::string& strip_location_prefix) {
47 for (size_t i = 0; i < dex_filenames.size(); i++) {
48 const char* dex_filename = dex_filenames[i];
49 const DexFile* dex_file = Open(dex_filename, strip_location_prefix);
50 if (dex_file == NULL) {
51 fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
52 exit(EXIT_FAILURE);
53 }
54 dex_files.push_back(dex_file);
55 }
56}
57
Brian Carlstrom16192862011-09-12 17:50:06 -070058const DexFile* DexFile::Open(const std::string& filename,
59 const std::string& strip_location_prefix) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070060 if (filename.size() < 4) {
Brian Carlstrom58ae9412011-10-04 00:56:06 -070061 LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'";
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070062 }
63 std::string suffix(filename.substr(filename.size() - 4));
64 if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
Brian Carlstrom16192862011-09-12 17:50:06 -070065 return DexFile::OpenZip(filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070066 } else {
Brian Carlstrom16192862011-09-12 17:50:06 -070067 return DexFile::OpenFile(filename, filename, strip_location_prefix);
Brian Carlstrom69b15fb2011-09-03 12:25:21 -070068 }
69}
70
jeffhaob4df5142011-09-19 20:25:32 -070071void DexFile::ChangePermissions(int prot) const {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070072 if (mprotect(mem_map_->GetAddress(), mem_map_->GetLength(), prot) != 0) {
jeffhaob4df5142011-09-19 20:25:32 -070073 PLOG(FATAL) << "Failed to change dex file permissions to " << prot;
74 }
75}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070076
Brian Carlstrom16192862011-09-12 17:50:06 -070077const DexFile* DexFile::OpenFile(const std::string& filename,
78 const std::string& original_location,
79 const std::string& strip_location_prefix) {
80 StringPiece location = original_location;
81 if (!location.starts_with(strip_location_prefix)) {
82 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
83 return NULL;
84 }
85 location.remove_prefix(strip_location_prefix.size());
Brian Carlstromb0460ea2011-07-29 10:08:05 -070086 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070087 if (fd == -1) {
88 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
89 return NULL;
90 }
91 struct stat sbuf;
92 memset(&sbuf, 0, sizeof(sbuf));
93 if (fstat(fd, &sbuf) == -1) {
94 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
95 close(fd);
96 return NULL;
97 }
98 size_t length = sbuf.st_size;
Brian Carlstrom33f741e2011-10-03 11:24:05 -070099 UniquePtr<MemMap> map(MemMap::Map(length, PROT_READ, MAP_PRIVATE, fd, 0));
100 if (map.get() == NULL) {
101 LOG(ERROR) << "mmap \"" << filename << "\" failed";
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700102 close(fd);
103 return NULL;
104 }
105 close(fd);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700106 byte* dex_file = map->GetAddress();
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700107 return OpenMemory(dex_file, length, location.ToString(), map.release());
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700108}
109
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700110const char* DexFile::kClassesDex = "classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700111
112class LockedFd {
113 public:
114 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
115 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
116 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700117 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700118 return NULL;
119 }
120 fchmod(fd, mode);
121
122 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
123 int result = flock(fd, LOCK_EX | LOCK_NB);
124 if (result == -1) {
125 LOG(WARNING) << "sleeping while locking file " << name;
126 result = flock(fd, LOCK_EX);
127 }
128 if (result == -1 ) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700129 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700130 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700131 return NULL;
132 }
133 return new LockedFd(fd);
134 }
135
136 int GetFd() const {
137 return fd_;
138 }
139
140 ~LockedFd() {
141 if (fd_ != -1) {
142 int result = flock(fd_, LOCK_UN);
143 if (result == -1) {
144 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
145 }
146 close(fd_);
147 }
148 }
149
150 private:
151 LockedFd(int fd) : fd_(fd) {}
152
153 int fd_;
154};
155
156class TmpFile {
157 public:
158 TmpFile(const std::string name) : name_(name) {}
159 ~TmpFile() {
160 unlink(name_.c_str());
161 }
162 private:
163 const std::string name_;
164};
165
166// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom16192862011-09-12 17:50:06 -0700167const DexFile* DexFile::OpenZip(const std::string& filename,
168 const std::string& strip_location_prefix) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700169
170 // First, look for a ".dex" alongside the jar file. It will have
171 // the same name/path except for the extension.
172
173 // Example filename = dir/foo.jar
174 std::string adjacent_dex_filename(filename);
175 size_t found = adjacent_dex_filename.find_last_of(".");
176 if (found == std::string::npos) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700177 LOG(ERROR) << "No . in filename" << filename;
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700178 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700179 }
180 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
181 adjacent_dex_filename.end(),
182 ".dex");
183 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700184 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700185 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename,
186 filename,
187 strip_location_prefix);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700188 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700189 // We don't verify anything in this case, because we aren't in
190 // the cache and typically the file is in the readonly /system
191 // area, so if something is wrong, there is nothing we can do.
192 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700193 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700194 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700195 }
196
197 char resolved[PATH_MAX];
198 char* absolute_path = realpath(filename.c_str(), resolved);
199 if (absolute_path == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700200 LOG(ERROR) << "Failed to create absolute path for " << filename
201 << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700202 return NULL;
203 }
204 std::string cache_file(absolute_path+1); // skip leading slash
205 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
206 cache_file.push_back('@');
207 cache_file.append(kClassesDex);
208 // Example cache_file = parent@dir@foo.jar@classes.dex
209
Brian Carlstroma9f19782011-10-13 00:14:47 -0700210 std::string art_cache = GetArtCacheOrDie();
211 std::string cache_path_tmp = art_cache + "/" + cache_file;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700212 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
213
Elliott Hughes90a33692011-08-30 13:27:07 -0700214 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
215 if (zip_archive.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700216 LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700217 return NULL;
218 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700219 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
220 if (zip_entry.get() == NULL) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700221 LOG(ERROR) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700222 return NULL;
223 }
224
225 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
226 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
227
228 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700229 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700230 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path,
231 filename,
232 strip_location_prefix);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700233 if (cached_dex_file != NULL) {
234 return cached_dex_file;
235 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700236 }
237
238 // Try to open the temporary cache file, grabbing an exclusive
239 // lock. If somebody else is working on it, we'll block here until
240 // they complete. Because we're waiting on an external resource,
241 // we go into native mode.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700242 // Note that self can be NULL if we're parsing the bootclasspath
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700243 // during JNI_CreateJavaVM.
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700244 Thread* self = Thread::Current();
245 UniquePtr<ScopedThreadStateChange> state_changer;
246 if (self != NULL) {
247 state_changer.reset(new ScopedThreadStateChange(self, Thread::kNative));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700248 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700249 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes8e4aac52011-09-26 17:03:36 -0700250 state_changer.reset(NULL);
Elliott Hughes90a33692011-08-30 13:27:07 -0700251 if (fd.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700252 return NULL;
253 }
254
255 // Check to see if the fd we opened and locked matches the file in
256 // the filesystem. If they don't, then somebody else unlinked
257 // ours and created a new file, and we need to use that one
258 // instead. (If we caught them between the unlink and the create,
259 // we'll get an ENOENT from the file stat.)
260 struct stat fd_stat;
261 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
262 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700263 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700264 return NULL;
265 }
266 struct stat file_stat;
267 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
268 if (file_stat_result == -1 ||
269 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
270 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
271 usleep(250 * 1000); // if something is hosed, don't peg machine
272 continue;
273 }
274
275 // We have the correct file open and locked. Extract classes.dex
276 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700277 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
278 if (file.get() == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700279 return NULL;
280 }
281 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700282 if (!success) {
283 return NULL;
284 }
285
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700286 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700287
288 // Compute checksum and compare to zip. If things look okay, rename from tmp.
289 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
290 if (lseek_result == -1) {
291 return NULL;
292 }
293 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700294 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
295 if (buf.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700296 return NULL;
297 }
298 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
299 while (true) {
300 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700301 if (bytes_read == -1) {
302 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
303 return NULL;
304 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700305 if (bytes_read == 0) {
306 break;
307 }
308 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
309 }
310 if (computed_crc != zip_entry->GetCrc32()) {
311 return NULL;
312 }
313 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
314 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700315 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700316 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700317 unlink(cache_path.c_str());
318 }
319 }
320 // NOTREACHED
321}
322
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700323const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length,
324 const std::string& location, MemMap* mem_map) {
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700325 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map));
Brian Carlstromf615a612011-07-23 12:50:34 -0700326 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700327 return NULL;
328 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700329 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700330 }
331}
332
Jesse Wilson6bf19152011-09-29 13:12:33 -0400333DexFile::~DexFile() {
Elliott Hughes8cef0b82011-10-11 19:24:00 -0700334 // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
335 // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
336 // re-attach, but cleaning up these global references is not obviously useful. It's not as if
337 // the global reference table is otherwise empty!
Jesse Wilson6bf19152011-09-29 13:12:33 -0400338}
339
340jobject DexFile::GetDexObject(JNIEnv* env) const {
341 MutexLock mu(dex_object_lock_);
342 if (dex_object_ != NULL) {
343 return dex_object_;
344 }
345
346 void* address = const_cast<void*>(reinterpret_cast<const void*>(base_));
347 jobject byte_buffer = env->NewDirectByteBuffer(address, length_);
348 if (byte_buffer == NULL) {
349 return NULL;
350 }
351
352 jclass c = env->FindClass("com/android/dex/Dex");
353 if (c == NULL) {
354 return NULL;
355 }
356
357 jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
358 if (mid == NULL) {
359 return NULL;
360 }
361
362 jvalue args[1];
363 args[0].l = byte_buffer;
364 jobject local = env->CallStaticObjectMethodA(c, mid, args);
365 if (local == NULL) {
366 return NULL;
367 }
368
369 dex_object_ = env->NewGlobalRef(local);
370 return dex_object_;
371}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700372
Brian Carlstromf615a612011-07-23 12:50:34 -0700373bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700374 InitMembers();
375 if (!IsMagicValid()) {
376 return false;
377 }
378 InitIndex();
379 return true;
380}
381
Brian Carlstromf615a612011-07-23 12:50:34 -0700382void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700383 const byte* b = base_;
384 header_ = reinterpret_cast<const Header*>(b);
385 const Header* h = header_;
386 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
387 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
388 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
389 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
390 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
391 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
392}
393
Brian Carlstromf615a612011-07-23 12:50:34 -0700394bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700395 return CheckMagic(header_->magic_);
396}
397
Brian Carlstromf615a612011-07-23 12:50:34 -0700398bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700399 CHECK(magic != NULL);
400 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700401 LOG(ERROR) << "Unrecognized magic number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700402 << " " << magic[0]
403 << " " << magic[1]
404 << " " << magic[2]
405 << " " << magic[3];
406 return false;
407 }
408 const byte* version = &magic[sizeof(kDexMagic)];
409 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700410 LOG(ERROR) << "Unrecognized version number:"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700411 << " " << version[0]
412 << " " << version[1]
413 << " " << version[2]
414 << " " << version[3];
415 return false;
416 }
417 return true;
418}
419
Brian Carlstromf615a612011-07-23 12:50:34 -0700420void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700421 CHECK_EQ(index_.size(), 0U);
422 for (size_t i = 0; i < NumClassDefs(); ++i) {
423 const ClassDef& class_def = GetClassDef(i);
424 const char* descriptor = GetClassDescriptor(class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700425 index_[descriptor] = i;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700426 }
427}
428
Brian Carlstrome24fa612011-09-29 00:53:55 -0700429bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700430 Index::const_iterator it = index_.find(descriptor);
431 if (it == index_.end()) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700432 return false;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700433 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700434 idx = it->second;
435 return true;
436}
437
438const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
439 uint32_t idx;
440 if (FindClassDefIndex(descriptor, idx)) {
441 return &GetClassDef(idx);
442 }
443 return NULL;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700444}
445
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700446// Materializes the method descriptor for a method prototype. Method
447// descriptors are not stored directly in the dex file. Instead, one
448// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700449std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
450 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700451 const ProtoId& proto_id = GetProtoId(proto_idx);
452 std::string descriptor;
453 descriptor.push_back('(');
454 const TypeList* type_list = GetProtoParameters(proto_id);
455 size_t parameter_length = 0;
456 if (type_list != NULL) {
457 // A non-zero number of arguments. Append the type names.
458 for (size_t i = 0; i < type_list->Size(); ++i) {
459 const TypeItem& type_item = type_list->GetTypeItem(i);
460 uint32_t type_idx = type_item.type_idx_;
461 int32_t type_length;
462 const char* name = dexStringByTypeIdx(type_idx, &type_length);
463 parameter_length += type_length;
464 descriptor.append(name);
465 }
466 }
467 descriptor.push_back(')');
468 uint32_t return_type_idx = proto_id.return_type_idx_;
469 int32_t return_type_length;
470 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
471 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700472 if (unicode_length != NULL) {
473 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
474 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700475 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700476}
477
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700478// Read a signed integer. "zwidth" is the zero-based byte count.
479static int32_t ReadSignedInt(const byte* ptr, int zwidth)
480{
481 int32_t val = 0;
482 for (int i = zwidth; i >= 0; --i) {
483 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
484 }
485 val >>= (3 - zwidth) * 8;
486 return val;
487}
488
489// Read an unsigned integer. "zwidth" is the zero-based byte count,
490// "fill_on_right" indicates which side we want to zero-fill from.
491static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
492 bool fill_on_right) {
493 uint32_t val = 0;
494 if (!fill_on_right) {
495 for (int i = zwidth; i >= 0; --i) {
496 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
497 }
498 val >>= (3 - zwidth) * 8;
499 } else {
500 for (int i = zwidth; i >= 0; --i) {
501 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
502 }
503 }
504 return val;
505}
506
507// Read a signed long. "zwidth" is the zero-based byte count.
508static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
509 int64_t val = 0;
510 for (int i = zwidth; i >= 0; --i) {
511 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
512 }
513 val >>= (7 - zwidth) * 8;
514 return val;
515}
516
517// Read an unsigned long. "zwidth" is the zero-based byte count,
518// "fill_on_right" indicates which side we want to zero-fill from.
519static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
520 bool fill_on_right) {
521 uint64_t val = 0;
522 if (!fill_on_right) {
523 for (int i = zwidth; i >= 0; --i) {
524 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
525 }
526 val >>= (7 - zwidth) * 8;
527 } else {
528 for (int i = zwidth; i >= 0; --i) {
529 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
530 }
531 }
532 return val;
533}
534
Brian Carlstromf615a612011-07-23 12:50:34 -0700535DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
536 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700537 const byte* ptr = *stream;
538 byte value_type = *ptr++;
539 byte value_arg = value_type >> kEncodedValueArgShift;
540 size_t width = value_arg + 1; // assume and correct later
541 int type = value_type & kEncodedValueTypeMask;
542 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700543 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700544 int32_t b = ReadSignedInt(ptr, value_arg);
545 CHECK(IsInt(8, b));
546 value->i = b;
547 break;
548 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700549 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700550 int32_t s = ReadSignedInt(ptr, value_arg);
551 CHECK(IsInt(16, s));
552 value->i = s;
553 break;
554 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700555 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700556 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
557 CHECK(IsUint(16, c));
558 value->i = c;
559 break;
560 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700561 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700562 value->i = ReadSignedInt(ptr, value_arg);
563 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700564 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700565 value->j = ReadSignedLong(ptr, value_arg);
566 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700567 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700568 value->i = ReadUnsignedInt(ptr, value_arg, true);
569 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700570 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700571 value->j = ReadUnsignedLong(ptr, value_arg, true);
572 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700573 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700574 value->i = (value_arg != 0);
575 width = 0;
576 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700577 case DexFile::kString:
578 case DexFile::kType:
579 case DexFile::kMethod:
580 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700581 value->i = ReadUnsignedInt(ptr, value_arg, false);
582 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700583 case DexFile::kField:
584 case DexFile::kArray:
585 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700586 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700587 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700588 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700589 value->i = 0;
590 width = 0;
591 break;
592 default:
593 LOG(FATAL) << "Unreached";
594 }
595 ptr += width;
596 *stream = ptr;
597 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700598}
599
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700600String* DexFile::dexArtStringById(int32_t idx) const {
601 if (idx == -1) {
602 return NULL;
603 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700604 return String::AllocFromModifiedUtf8(dexStringById(idx));
605}
606
607int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700608 // For native method, lineno should be -2 to indicate it is native. Note that
609 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700610 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700611 return -2;
612 }
613
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700614 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Shih-wei Liao195487c2011-08-20 13:29:04 -0700615 DCHECK(code_item != NULL);
616
617 // A method with no line number info should return -1
618 LineNumFromPcContext context(rel_pc, -1);
619 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
620 return context.line_num_;
621}
622
623void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
624 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
625 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
626 uint32_t line = DecodeUnsignedLeb128(&stream);
627 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
628 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
629 uint32_t address = 0;
Elliott Hughes30646832011-10-13 16:59:46 -0700630 bool need_locals = (local_cb != NULL);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700631
632 if (!method->IsStatic()) {
Elliott Hughes30646832011-10-13 16:59:46 -0700633 if (need_locals) {
634 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
635 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
636 local_in_reg[arg_reg].signature_ = NULL;
637 local_in_reg[arg_reg].start_address_ = 0;
638 local_in_reg[arg_reg].is_live_ = true;
639 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700640 arg_reg++;
641 }
642
Elliott Hughes30646832011-10-13 16:59:46 -0700643 ParameterIterator* it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
Shih-wei Liao195487c2011-08-20 13:29:04 -0700644 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
645 if (arg_reg >= code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700646 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700647 return;
648 }
Elliott Hughes30646832011-10-13 16:59:46 -0700649 int32_t id = DecodeUnsignedLeb128P1(&stream);
650 const char* descriptor_utf8 = it->GetDescriptor();
651 if (need_locals) {
652 String* descriptor = String::AllocFromModifiedUtf8(descriptor_utf8);
653 String* name = dexArtStringById(id);
654 local_in_reg[arg_reg].name_ = name;
655 local_in_reg[arg_reg].descriptor_ = descriptor;
656 local_in_reg[arg_reg].signature_ = NULL;
657 local_in_reg[arg_reg].start_address_ = address;
658 local_in_reg[arg_reg].is_live_ = true;
659 }
660 switch (*descriptor_utf8) {
Shih-wei Liao195487c2011-08-20 13:29:04 -0700661 case 'D':
662 case 'J':
663 arg_reg += 2;
664 break;
665 default:
666 arg_reg += 1;
667 break;
668 }
669 }
670
671 if (it->HasNext()) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700672 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700673 return;
674 }
675
676 for (;;) {
677 uint8_t opcode = *stream++;
678 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
679 uint16_t reg;
680
681
682 switch (opcode) {
683 case DBG_END_SEQUENCE:
684 return;
685
686 case DBG_ADVANCE_PC:
687 address += DecodeUnsignedLeb128(&stream);
688 break;
689
690 case DBG_ADVANCE_LINE:
691 line += DecodeUnsignedLeb128(&stream);
692 break;
693
694 case DBG_START_LOCAL:
695 case DBG_START_LOCAL_EXTENDED:
696 reg = DecodeUnsignedLeb128(&stream);
697 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700698 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700699 return;
700 }
701
702 // Emit what was previously there, if anything
Elliott Hughes30646832011-10-13 16:59:46 -0700703 if (need_locals) {
704 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
Shih-wei Liao195487c2011-08-20 13:29:04 -0700705
Elliott Hughes30646832011-10-13 16:59:46 -0700706 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
707 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
708 if (opcode == DBG_START_LOCAL_EXTENDED) {
709 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
710 } else {
711 local_in_reg[reg].signature_ = NULL;
712 }
713 local_in_reg[reg].start_address_ = address;
714 local_in_reg[reg].is_live_ = true;
Shih-wei Liao195487c2011-08-20 13:29:04 -0700715 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700716 break;
717
718 case DBG_END_LOCAL:
719 reg = DecodeUnsignedLeb128(&stream);
720 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700721 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700722 return;
723 }
724
Elliott Hughes30646832011-10-13 16:59:46 -0700725 if (need_locals) {
726 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
727 local_in_reg[reg].is_live_ = false;
728 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700729 break;
730
731 case DBG_RESTART_LOCAL:
732 reg = DecodeUnsignedLeb128(&stream);
733 if (reg > code_item->registers_size_) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700734 LOG(ERROR) << "invalid stream";
Shih-wei Liao195487c2011-08-20 13:29:04 -0700735 return;
736 }
737
Elliott Hughes30646832011-10-13 16:59:46 -0700738 if (need_locals) {
739 if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700740 LOG(ERROR) << "invalid stream";
Elliott Hughes30646832011-10-13 16:59:46 -0700741 return;
742 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700743
Elliott Hughes30646832011-10-13 16:59:46 -0700744 // If the register is live, the "restart" is superfluous,
745 // and we don't want to mess with the existing start address.
746 if (!local_in_reg[reg].is_live_) {
747 local_in_reg[reg].start_address_ = address;
748 local_in_reg[reg].is_live_ = true;
749 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700750 }
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