blob: b98229136294b6a827b4fcdb1af6f838de70d8b3 [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 Carlstrom69b15fb2011-09-03 12:25:21 -070045const DexFile* DexFile::Open(const std::string& filename) {
46 if (filename.size() < 4) {
47 LOG(WARNING) << "Ignoring short classpath entry '" << filename << "'";
48 return NULL;
49 }
50 std::string suffix(filename.substr(filename.size() - 4));
51 if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") {
52 return DexFile::OpenZip(filename);
53 } else {
54 return DexFile::OpenFile(filename);
55 }
56}
57
Brian Carlstromf615a612011-07-23 12:50:34 -070058DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070059
Brian Carlstromf615a612011-07-23 12:50:34 -070060DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070061 CHECK(addr != NULL);
62}
Brian Carlstromf615a612011-07-23 12:50:34 -070063DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070064 if (munmap(addr_, length_) == -1) {
65 PLOG(INFO) << "munmap failed";
66 }
67}
68
Brian Carlstromf615a612011-07-23 12:50:34 -070069DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
70DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070071
Brian Carlstrom9f30b382011-08-28 22:41:38 -070072const DexFile* DexFile::OpenFile(const std::string& filename) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -070073 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070074 if (fd == -1) {
75 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
76 return NULL;
77 }
78 struct stat sbuf;
79 memset(&sbuf, 0, sizeof(sbuf));
80 if (fstat(fd, &sbuf) == -1) {
81 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
82 close(fd);
83 return NULL;
84 }
85 size_t length = sbuf.st_size;
86 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
87 if (addr == MAP_FAILED) {
88 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
89 close(fd);
90 return NULL;
91 }
92 close(fd);
93 byte* dex_file = reinterpret_cast<byte*>(addr);
94 Closer* closer = new MmapCloser(addr, length);
Brian Carlstroma663ea52011-08-19 23:33:41 -070095 return Open(dex_file, length, filename, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070096}
97
Brian Carlstromb0460ea2011-07-29 10:08:05 -070098static const char* kClassesDex = "classes.dex";
99
100class LockedFd {
101 public:
102 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
103 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
104 if (fd == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700105 PLOG(ERROR) << "Failed to open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700106 return NULL;
107 }
108 fchmod(fd, mode);
109
110 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
111 int result = flock(fd, LOCK_EX | LOCK_NB);
112 if (result == -1) {
113 LOG(WARNING) << "sleeping while locking file " << name;
114 result = flock(fd, LOCK_EX);
115 }
116 if (result == -1 ) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700117 PLOG(ERROR) << "Failed to lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700118 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700119 return NULL;
120 }
121 return new LockedFd(fd);
122 }
123
124 int GetFd() const {
125 return fd_;
126 }
127
128 ~LockedFd() {
129 if (fd_ != -1) {
130 int result = flock(fd_, LOCK_UN);
131 if (result == -1) {
132 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
133 }
134 close(fd_);
135 }
136 }
137
138 private:
139 LockedFd(int fd) : fd_(fd) {}
140
141 int fd_;
142};
143
144class TmpFile {
145 public:
146 TmpFile(const std::string name) : name_(name) {}
147 ~TmpFile() {
148 unlink(name_.c_str());
149 }
150 private:
151 const std::string name_;
152};
153
154// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700155const DexFile* DexFile::OpenZip(const std::string& filename) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700156
157 // First, look for a ".dex" alongside the jar file. It will have
158 // the same name/path except for the extension.
159
160 // Example filename = dir/foo.jar
161 std::string adjacent_dex_filename(filename);
162 size_t found = adjacent_dex_filename.find_last_of(".");
163 if (found == std::string::npos) {
164 LOG(WARNING) << "No . in filename" << filename;
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700165 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700166 }
167 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
168 adjacent_dex_filename.end(),
169 ".dex");
170 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700171 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700172 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700173 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700174 // We don't verify anything in this case, because we aren't in
175 // the cache and typically the file is in the readonly /system
176 // area, so if something is wrong, there is nothing we can do.
177 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700178 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700179 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700180 }
181
182 char resolved[PATH_MAX];
183 char* absolute_path = realpath(filename.c_str(), resolved);
184 if (absolute_path == NULL) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700185 LOG(WARNING) << "Failed to create absolute path for " << filename
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700186 << " when looking for classes.dex";
187 return NULL;
188 }
189 std::string cache_file(absolute_path+1); // skip leading slash
190 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
191 cache_file.push_back('@');
192 cache_file.append(kClassesDex);
193 // Example cache_file = parent@dir@foo.jar@classes.dex
194
195 const char* data_root = getenv("ANDROID_DATA");
196 if (data_root == NULL) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700197 data_root = "/data";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700198 }
199
200 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
201 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
202
Elliott Hughes90a33692011-08-30 13:27:07 -0700203 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
204 if (zip_archive.get() == NULL) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700205 LOG(WARNING) << "Failed to open " << filename << " when looking for classes.dex";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700206 return NULL;
207 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700208 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
209 if (zip_entry.get() == NULL) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700210 LOG(WARNING) << "Failed to find classes.dex within " << filename;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700211 return NULL;
212 }
213
214 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
215 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
216
217 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700218 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700219 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700220 if (cached_dex_file != NULL) {
221 return cached_dex_file;
222 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700223 }
224
225 // Try to open the temporary cache file, grabbing an exclusive
226 // lock. If somebody else is working on it, we'll block here until
227 // they complete. Because we're waiting on an external resource,
228 // we go into native mode.
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700229 // Note that current_thread can be NULL if we're parsing the bootclasspath
230 // during JNI_CreateJavaVM.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700231 Thread* current_thread = Thread::Current();
Elliott Hughesd92bec42011-09-02 17:04:36 -0700232 Thread::State old(Thread::kUnknown);
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700233 if (current_thread != NULL) {
Elliott Hughesad7c2a32011-08-31 11:58:10 -0700234 old = current_thread->SetState(Thread::kNative);
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700235 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700236 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700237 if (current_thread != NULL) {
238 current_thread->SetState(old);
239 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700240 if (fd.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700241 return NULL;
242 }
243
244 // Check to see if the fd we opened and locked matches the file in
245 // the filesystem. If they don't, then somebody else unlinked
246 // ours and created a new file, and we need to use that one
247 // instead. (If we caught them between the unlink and the create,
248 // we'll get an ENOENT from the file stat.)
249 struct stat fd_stat;
250 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
251 if (fd_stat_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700252 PLOG(ERROR) << "Failed to stat open file '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700253 return NULL;
254 }
255 struct stat file_stat;
256 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
257 if (file_stat_result == -1 ||
258 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
259 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
260 usleep(250 * 1000); // if something is hosed, don't peg machine
261 continue;
262 }
263
264 // We have the correct file open and locked. Extract classes.dex
265 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700266 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
267 if (file.get() == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700268 return NULL;
269 }
270 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700271 if (!success) {
272 return NULL;
273 }
274
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700275 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700276
277 // Compute checksum and compare to zip. If things look okay, rename from tmp.
278 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
279 if (lseek_result == -1) {
280 return NULL;
281 }
282 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700283 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
284 if (buf.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700285 return NULL;
286 }
287 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
288 while (true) {
289 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700290 if (bytes_read == -1) {
291 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
292 return NULL;
293 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700294 if (bytes_read == 0) {
295 break;
296 }
297 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
298 }
299 if (computed_crc != zip_entry->GetCrc32()) {
300 return NULL;
301 }
302 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
303 if (rename_result == -1) {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700304 PLOG(ERROR) << "Failed to install dex cache file '" << cache_path << "'"
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700305 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700306 unlink(cache_path.c_str());
307 }
308 }
309 // NOTREACHED
310}
311
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700312const DexFile* DexFile::OpenPtr(byte* ptr, size_t length, const std::string& location) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700313 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700314 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700315 return Open(ptr, length, location, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700316}
317
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700318const DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
319 const std::string& location, Closer* closer) {
Elliott Hughes90a33692011-08-30 13:27:07 -0700320 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, closer));
Brian Carlstromf615a612011-07-23 12:50:34 -0700321 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700322 return NULL;
323 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700324 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700325 }
326}
327
Brian Carlstromf615a612011-07-23 12:50:34 -0700328DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329
Brian Carlstromf615a612011-07-23 12:50:34 -0700330bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700331 InitMembers();
332 if (!IsMagicValid()) {
333 return false;
334 }
335 InitIndex();
336 return true;
337}
338
Brian Carlstromf615a612011-07-23 12:50:34 -0700339void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700340 const byte* b = base_;
341 header_ = reinterpret_cast<const Header*>(b);
342 const Header* h = header_;
343 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
344 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
345 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
346 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
347 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
348 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
349}
350
Brian Carlstromf615a612011-07-23 12:50:34 -0700351bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700352 return CheckMagic(header_->magic_);
353}
354
Brian Carlstromf615a612011-07-23 12:50:34 -0700355bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700356 CHECK(magic != NULL);
357 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
358 LOG(WARNING) << "Unrecognized magic number:"
359 << " " << magic[0]
360 << " " << magic[1]
361 << " " << magic[2]
362 << " " << magic[3];
363 return false;
364 }
365 const byte* version = &magic[sizeof(kDexMagic)];
366 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
367 LOG(WARNING) << "Unrecognized version number:"
368 << " " << version[0]
369 << " " << version[1]
370 << " " << version[2]
371 << " " << version[3];
372 return false;
373 }
374 return true;
375}
376
Brian Carlstromf615a612011-07-23 12:50:34 -0700377void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700378 CHECK_EQ(index_.size(), 0U);
379 for (size_t i = 0; i < NumClassDefs(); ++i) {
380 const ClassDef& class_def = GetClassDef(i);
381 const char* descriptor = GetClassDescriptor(class_def);
382 index_[descriptor] = &class_def;
383 }
384}
385
Brian Carlstromf615a612011-07-23 12:50:34 -0700386const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700387 CHECK(descriptor != NULL);
388 Index::const_iterator it = index_.find(descriptor);
389 if (it == index_.end()) {
390 return NULL;
391 } else {
392 return it->second;
393 }
394}
395
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700396// Materializes the method descriptor for a method prototype. Method
397// descriptors are not stored directly in the dex file. Instead, one
398// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700399std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
400 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700401 const ProtoId& proto_id = GetProtoId(proto_idx);
402 std::string descriptor;
403 descriptor.push_back('(');
404 const TypeList* type_list = GetProtoParameters(proto_id);
405 size_t parameter_length = 0;
406 if (type_list != NULL) {
407 // A non-zero number of arguments. Append the type names.
408 for (size_t i = 0; i < type_list->Size(); ++i) {
409 const TypeItem& type_item = type_list->GetTypeItem(i);
410 uint32_t type_idx = type_item.type_idx_;
411 int32_t type_length;
412 const char* name = dexStringByTypeIdx(type_idx, &type_length);
413 parameter_length += type_length;
414 descriptor.append(name);
415 }
416 }
417 descriptor.push_back(')');
418 uint32_t return_type_idx = proto_id.return_type_idx_;
419 int32_t return_type_length;
420 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
421 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700422 if (unicode_length != NULL) {
423 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
424 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700425 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700426}
427
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700428// Read a signed integer. "zwidth" is the zero-based byte count.
429static int32_t ReadSignedInt(const byte* ptr, int zwidth)
430{
431 int32_t val = 0;
432 for (int i = zwidth; i >= 0; --i) {
433 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
434 }
435 val >>= (3 - zwidth) * 8;
436 return val;
437}
438
439// Read an unsigned integer. "zwidth" is the zero-based byte count,
440// "fill_on_right" indicates which side we want to zero-fill from.
441static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
442 bool fill_on_right) {
443 uint32_t val = 0;
444 if (!fill_on_right) {
445 for (int i = zwidth; i >= 0; --i) {
446 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
447 }
448 val >>= (3 - zwidth) * 8;
449 } else {
450 for (int i = zwidth; i >= 0; --i) {
451 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
452 }
453 }
454 return val;
455}
456
457// Read a signed long. "zwidth" is the zero-based byte count.
458static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
459 int64_t val = 0;
460 for (int i = zwidth; i >= 0; --i) {
461 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
462 }
463 val >>= (7 - zwidth) * 8;
464 return val;
465}
466
467// Read an unsigned long. "zwidth" is the zero-based byte count,
468// "fill_on_right" indicates which side we want to zero-fill from.
469static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
470 bool fill_on_right) {
471 uint64_t val = 0;
472 if (!fill_on_right) {
473 for (int i = zwidth; i >= 0; --i) {
474 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
475 }
476 val >>= (7 - zwidth) * 8;
477 } else {
478 for (int i = zwidth; i >= 0; --i) {
479 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
480 }
481 }
482 return val;
483}
484
Brian Carlstromf615a612011-07-23 12:50:34 -0700485DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
486 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700487 const byte* ptr = *stream;
488 byte value_type = *ptr++;
489 byte value_arg = value_type >> kEncodedValueArgShift;
490 size_t width = value_arg + 1; // assume and correct later
491 int type = value_type & kEncodedValueTypeMask;
492 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700493 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700494 int32_t b = ReadSignedInt(ptr, value_arg);
495 CHECK(IsInt(8, b));
496 value->i = b;
497 break;
498 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700499 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700500 int32_t s = ReadSignedInt(ptr, value_arg);
501 CHECK(IsInt(16, s));
502 value->i = s;
503 break;
504 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700505 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700506 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
507 CHECK(IsUint(16, c));
508 value->i = c;
509 break;
510 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700511 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700512 value->i = ReadSignedInt(ptr, value_arg);
513 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700514 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700515 value->j = ReadSignedLong(ptr, value_arg);
516 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700517 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700518 value->i = ReadUnsignedInt(ptr, value_arg, true);
519 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700520 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700521 value->j = ReadUnsignedLong(ptr, value_arg, true);
522 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700523 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700524 value->i = (value_arg != 0);
525 width = 0;
526 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700527 case DexFile::kString:
528 case DexFile::kType:
529 case DexFile::kMethod:
530 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700531 value->i = ReadUnsignedInt(ptr, value_arg, false);
532 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700533 case DexFile::kField:
534 case DexFile::kArray:
535 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700536 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700537 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700538 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700539 value->i = 0;
540 width = 0;
541 break;
542 default:
543 LOG(FATAL) << "Unreached";
544 }
545 ptr += width;
546 *stream = ptr;
547 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700548}
549
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700550String* DexFile::dexArtStringById(int32_t idx) const {
551 if (idx == -1) {
552 return NULL;
553 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700554 return String::AllocFromModifiedUtf8(dexStringById(idx));
555}
556
557int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700558 // For native method, lineno should be -2 to indicate it is native. Note that
559 // "line number == -2" is how libcore tells from StackTraceElement.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700560 if (method->GetCodeItemOffset() == 0) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700561 return -2;
562 }
563
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700564 const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
Shih-wei Liao195487c2011-08-20 13:29:04 -0700565 DCHECK(code_item != NULL);
566
567 // A method with no line number info should return -1
568 LineNumFromPcContext context(rel_pc, -1);
569 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
570 return context.line_num_;
571}
572
573void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
574 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
575 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
576 uint32_t line = DecodeUnsignedLeb128(&stream);
577 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
578 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
579 uint32_t address = 0;
580
581 if (!method->IsStatic()) {
582 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
583 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
584 local_in_reg[arg_reg].signature_ = NULL;
585 local_in_reg[arg_reg].start_address_ = 0;
586 local_in_reg[arg_reg].is_live_ = true;
587 arg_reg++;
588 }
589
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700590 ParameterIterator *it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
Shih-wei Liao195487c2011-08-20 13:29:04 -0700591 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
592 if (arg_reg >= code_item->registers_size_) {
593 LOG(FATAL) << "invalid stream";
594 return;
595 }
596
597 String* descriptor = String::AllocFromModifiedUtf8(it->GetDescriptor());
598 String* name = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
599
600 local_in_reg[arg_reg].name_ = name;
601 local_in_reg[arg_reg].descriptor_ = descriptor;
602 local_in_reg[arg_reg].signature_ = NULL;
603 local_in_reg[arg_reg].start_address_ = address;
604 local_in_reg[arg_reg].is_live_ = true;
605 switch (descriptor->CharAt(0)) {
606 case 'D':
607 case 'J':
608 arg_reg += 2;
609 break;
610 default:
611 arg_reg += 1;
612 break;
613 }
614 }
615
616 if (it->HasNext()) {
617 LOG(FATAL) << "invalid stream";
618 return;
619 }
620
621 for (;;) {
622 uint8_t opcode = *stream++;
623 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
624 uint16_t reg;
625
626
627 switch (opcode) {
628 case DBG_END_SEQUENCE:
629 return;
630
631 case DBG_ADVANCE_PC:
632 address += DecodeUnsignedLeb128(&stream);
633 break;
634
635 case DBG_ADVANCE_LINE:
636 line += DecodeUnsignedLeb128(&stream);
637 break;
638
639 case DBG_START_LOCAL:
640 case DBG_START_LOCAL_EXTENDED:
641 reg = DecodeUnsignedLeb128(&stream);
642 if (reg > code_item->registers_size_) {
643 LOG(FATAL) << "invalid stream";
644 return;
645 }
646
647 // Emit what was previously there, if anything
648 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
649
650 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
651 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
652 if (opcode == DBG_START_LOCAL_EXTENDED) {
653 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
654 } else {
655 local_in_reg[reg].signature_ = NULL;
656 }
657 local_in_reg[reg].start_address_ = address;
658 local_in_reg[reg].is_live_ = true;
659 break;
660
661 case DBG_END_LOCAL:
662 reg = DecodeUnsignedLeb128(&stream);
663 if (reg > code_item->registers_size_) {
664 LOG(FATAL) << "invalid stream";
665 return;
666 }
667
668 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
669 local_in_reg[reg].is_live_ = false;
670 break;
671
672 case DBG_RESTART_LOCAL:
673 reg = DecodeUnsignedLeb128(&stream);
674 if (reg > code_item->registers_size_) {
675 LOG(FATAL) << "invalid stream";
676 return;
677 }
678
679 if (local_in_reg[reg].name_ == NULL
680 || local_in_reg[reg].descriptor_ == NULL) {
681 LOG(FATAL) << "invalid stream";
682 return;
683 }
684
685 // If the register is live, the "restart" is superfluous,
686 // and we don't want to mess with the existing start address.
687 if (!local_in_reg[reg].is_live_) {
688 local_in_reg[reg].start_address_ = address;
689 local_in_reg[reg].is_live_ = true;
690 }
691 break;
692
693 case DBG_SET_PROLOGUE_END:
694 case DBG_SET_EPILOGUE_BEGIN:
695 case DBG_SET_FILE:
696 break;
697
698 default:
699 address += adjopcode / DBG_LINE_RANGE;
700 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
701
702 if (posCb != NULL) {
703 if (posCb(cnxt, address, line)) {
704 // early exit
705 return;
706 }
707 }
708 break;
709 }
710 }
711}
712
Carl Shapiro1fb86202011-06-27 17:43:13 -0700713} // namespace art