blob: fde6f014fd79ccb821b55f86b72903080c01261a [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 Carlstromb0460ea2011-07-29 10:08:05 -07006#include <stdio.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07007#include <string.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -07008#include <sys/file.h>
Brian Carlstrom7e49dca2011-07-22 18:07:34 -07009#include <sys/mman.h>
10#include <sys/stat.h>
11#include <sys/types.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 Carlstromf615a612011-07-23 12:50:34 -070044DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070045
Brian Carlstromf615a612011-07-23 12:50:34 -070046DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070047 CHECK(addr != NULL);
48}
Brian Carlstromf615a612011-07-23 12:50:34 -070049DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070050 if (munmap(addr_, length_) == -1) {
51 PLOG(INFO) << "munmap failed";
52 }
53}
54
Brian Carlstromf615a612011-07-23 12:50:34 -070055DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
56DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070057
Brian Carlstrom9f30b382011-08-28 22:41:38 -070058const DexFile* DexFile::OpenFile(const std::string& filename) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -070059 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070060 if (fd == -1) {
61 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
62 return NULL;
63 }
64 struct stat sbuf;
65 memset(&sbuf, 0, sizeof(sbuf));
66 if (fstat(fd, &sbuf) == -1) {
67 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
68 close(fd);
69 return NULL;
70 }
71 size_t length = sbuf.st_size;
72 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
73 if (addr == MAP_FAILED) {
74 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
75 close(fd);
76 return NULL;
77 }
78 close(fd);
79 byte* dex_file = reinterpret_cast<byte*>(addr);
80 Closer* closer = new MmapCloser(addr, length);
Brian Carlstroma663ea52011-08-19 23:33:41 -070081 return Open(dex_file, length, filename, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070082}
83
Brian Carlstromb0460ea2011-07-29 10:08:05 -070084static const char* kClassesDex = "classes.dex";
85
86class LockedFd {
87 public:
88 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
89 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
90 if (fd == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -070091 PLOG(ERROR) << "Can't open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -070092 return NULL;
93 }
94 fchmod(fd, mode);
95
96 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
97 int result = flock(fd, LOCK_EX | LOCK_NB);
98 if (result == -1) {
99 LOG(WARNING) << "sleeping while locking file " << name;
100 result = flock(fd, LOCK_EX);
101 }
102 if (result == -1 ) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700103 PLOG(ERROR) << "Can't lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700104 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700105 return NULL;
106 }
107 return new LockedFd(fd);
108 }
109
110 int GetFd() const {
111 return fd_;
112 }
113
114 ~LockedFd() {
115 if (fd_ != -1) {
116 int result = flock(fd_, LOCK_UN);
117 if (result == -1) {
118 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
119 }
120 close(fd_);
121 }
122 }
123
124 private:
125 LockedFd(int fd) : fd_(fd) {}
126
127 int fd_;
128};
129
130class TmpFile {
131 public:
132 TmpFile(const std::string name) : name_(name) {}
133 ~TmpFile() {
134 unlink(name_.c_str());
135 }
136 private:
137 const std::string name_;
138};
139
140// Open classes.dex from within a .zip, .jar, .apk, ...
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700141const DexFile* DexFile::OpenZip(const std::string& filename) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700142
143 // First, look for a ".dex" alongside the jar file. It will have
144 // the same name/path except for the extension.
145
146 // Example filename = dir/foo.jar
147 std::string adjacent_dex_filename(filename);
148 size_t found = adjacent_dex_filename.find_last_of(".");
149 if (found == std::string::npos) {
150 LOG(WARNING) << "No . in filename" << filename;
151 }
152 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
153 adjacent_dex_filename.end(),
154 ".dex");
155 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700156 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700157 const DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700158 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700159 // We don't verify anything in this case, because we aren't in
160 // the cache and typically the file is in the readonly /system
161 // area, so if something is wrong, there is nothing we can do.
162 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700163 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700164 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700165 }
166
167 char resolved[PATH_MAX];
168 char* absolute_path = realpath(filename.c_str(), resolved);
169 if (absolute_path == NULL) {
170 LOG(WARNING) << "Could not create absolute path for " << filename
171 << " when looking for classes.dex";
172 return NULL;
173 }
174 std::string cache_file(absolute_path+1); // skip leading slash
175 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
176 cache_file.push_back('@');
177 cache_file.append(kClassesDex);
178 // Example cache_file = parent@dir@foo.jar@classes.dex
179
180 const char* data_root = getenv("ANDROID_DATA");
181 if (data_root == NULL) {
182 data_root = "/data";
183 }
184
185 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
186 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
187
Elliott Hughes90a33692011-08-30 13:27:07 -0700188 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename));
189 if (zip_archive.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700190 LOG(WARNING) << "Could not open " << filename << " when looking for classes.dex";
191 return NULL;
192 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700193 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
194 if (zip_entry.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700195 LOG(WARNING) << "Could not find classes.dex within " << filename;
196 return NULL;
197 }
198
199 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
200 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
201
202 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700203 if (OS::FileExists(cache_path.c_str())) {
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700204 const DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700205 if (cached_dex_file != NULL) {
206 return cached_dex_file;
207 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700208 }
209
210 // Try to open the temporary cache file, grabbing an exclusive
211 // lock. If somebody else is working on it, we'll block here until
212 // they complete. Because we're waiting on an external resource,
213 // we go into native mode.
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700214 // Note that current_thread can be NULL if we're parsing the bootclasspath
215 // during JNI_CreateJavaVM.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700216 Thread* current_thread = Thread::Current();
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700217 Thread::State old;
218 if (current_thread != NULL) {
219 old = current_thread->GetState();
220 current_thread->SetState(Thread::kNative);
221 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700222 UniquePtr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700223 if (current_thread != NULL) {
224 current_thread->SetState(old);
225 }
Elliott Hughes90a33692011-08-30 13:27:07 -0700226 if (fd.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700227 return NULL;
228 }
229
230 // Check to see if the fd we opened and locked matches the file in
231 // the filesystem. If they don't, then somebody else unlinked
232 // ours and created a new file, and we need to use that one
233 // instead. (If we caught them between the unlink and the create,
234 // we'll get an ENOENT from the file stat.)
235 struct stat fd_stat;
236 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
237 if (fd_stat_result == -1) {
238 PLOG(ERROR) << "Can't stat open file '" << cache_path_tmp << "'";
239 return NULL;
240 }
241 struct stat file_stat;
242 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
243 if (file_stat_result == -1 ||
244 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
245 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
246 usleep(250 * 1000); // if something is hosed, don't peg machine
247 continue;
248 }
249
250 // We have the correct file open and locked. Extract classes.dex
251 TmpFile tmp_file(cache_path_tmp);
Elliott Hughes90a33692011-08-30 13:27:07 -0700252 UniquePtr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
253 if (file.get() == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700254 return NULL;
255 }
256 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700257 if (!success) {
258 return NULL;
259 }
260
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700261 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700262
263 // Compute checksum and compare to zip. If things look okay, rename from tmp.
264 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
265 if (lseek_result == -1) {
266 return NULL;
267 }
268 const size_t kBufSize = 32768;
Elliott Hughes90a33692011-08-30 13:27:07 -0700269 UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]);
270 if (buf.get() == NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700271 return NULL;
272 }
273 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
274 while (true) {
275 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700276 if (bytes_read == -1) {
277 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
278 return NULL;
279 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700280 if (bytes_read == 0) {
281 break;
282 }
283 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
284 }
285 if (computed_crc != zip_entry->GetCrc32()) {
286 return NULL;
287 }
288 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
289 if (rename_result == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700290 PLOG(ERROR) << "Can't install dex cache file '" << cache_path << "'"
291 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700292 unlink(cache_path.c_str());
293 }
294 }
295 // NOTREACHED
296}
297
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700298const DexFile* DexFile::OpenPtr(byte* ptr, size_t length, const std::string& location) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700299 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700300 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700301 return Open(ptr, length, location, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700302}
303
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700304const DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
305 const std::string& location, Closer* closer) {
Elliott Hughes90a33692011-08-30 13:27:07 -0700306 UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, closer));
Brian Carlstromf615a612011-07-23 12:50:34 -0700307 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700308 return NULL;
309 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700310 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700311 }
312}
313
Brian Carlstromf615a612011-07-23 12:50:34 -0700314DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700315
Brian Carlstromf615a612011-07-23 12:50:34 -0700316bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700317 InitMembers();
318 if (!IsMagicValid()) {
319 return false;
320 }
321 InitIndex();
322 return true;
323}
324
Brian Carlstromf615a612011-07-23 12:50:34 -0700325void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700326 const byte* b = base_;
327 header_ = reinterpret_cast<const Header*>(b);
328 const Header* h = header_;
329 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
330 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
331 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
332 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
333 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
334 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
335}
336
Brian Carlstromf615a612011-07-23 12:50:34 -0700337bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700338 return CheckMagic(header_->magic_);
339}
340
Brian Carlstromf615a612011-07-23 12:50:34 -0700341bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700342 CHECK(magic != NULL);
343 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
344 LOG(WARNING) << "Unrecognized magic number:"
345 << " " << magic[0]
346 << " " << magic[1]
347 << " " << magic[2]
348 << " " << magic[3];
349 return false;
350 }
351 const byte* version = &magic[sizeof(kDexMagic)];
352 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
353 LOG(WARNING) << "Unrecognized version number:"
354 << " " << version[0]
355 << " " << version[1]
356 << " " << version[2]
357 << " " << version[3];
358 return false;
359 }
360 return true;
361}
362
Brian Carlstromf615a612011-07-23 12:50:34 -0700363void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700364 CHECK_EQ(index_.size(), 0U);
365 for (size_t i = 0; i < NumClassDefs(); ++i) {
366 const ClassDef& class_def = GetClassDef(i);
367 const char* descriptor = GetClassDescriptor(class_def);
368 index_[descriptor] = &class_def;
369 }
370}
371
Brian Carlstromf615a612011-07-23 12:50:34 -0700372const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700373 CHECK(descriptor != NULL);
374 Index::const_iterator it = index_.find(descriptor);
375 if (it == index_.end()) {
376 return NULL;
377 } else {
378 return it->second;
379 }
380}
381
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700382// Materializes the method descriptor for a method prototype. Method
383// descriptors are not stored directly in the dex file. Instead, one
384// must assemble the descriptor from references in the prototype.
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700385std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
386 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700387 const ProtoId& proto_id = GetProtoId(proto_idx);
388 std::string descriptor;
389 descriptor.push_back('(');
390 const TypeList* type_list = GetProtoParameters(proto_id);
391 size_t parameter_length = 0;
392 if (type_list != NULL) {
393 // A non-zero number of arguments. Append the type names.
394 for (size_t i = 0; i < type_list->Size(); ++i) {
395 const TypeItem& type_item = type_list->GetTypeItem(i);
396 uint32_t type_idx = type_item.type_idx_;
397 int32_t type_length;
398 const char* name = dexStringByTypeIdx(type_idx, &type_length);
399 parameter_length += type_length;
400 descriptor.append(name);
401 }
402 }
403 descriptor.push_back(')');
404 uint32_t return_type_idx = proto_id.return_type_idx_;
405 int32_t return_type_length;
406 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
407 descriptor.append(name);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700408 if (unicode_length != NULL) {
409 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
410 }
Elliott Hughes0c424cb2011-08-26 10:16:25 -0700411 return descriptor;
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700412}
413
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700414// Read a signed integer. "zwidth" is the zero-based byte count.
415static int32_t ReadSignedInt(const byte* ptr, int zwidth)
416{
417 int32_t val = 0;
418 for (int i = zwidth; i >= 0; --i) {
419 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
420 }
421 val >>= (3 - zwidth) * 8;
422 return val;
423}
424
425// Read an unsigned integer. "zwidth" is the zero-based byte count,
426// "fill_on_right" indicates which side we want to zero-fill from.
427static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
428 bool fill_on_right) {
429 uint32_t val = 0;
430 if (!fill_on_right) {
431 for (int i = zwidth; i >= 0; --i) {
432 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
433 }
434 val >>= (3 - zwidth) * 8;
435 } else {
436 for (int i = zwidth; i >= 0; --i) {
437 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
438 }
439 }
440 return val;
441}
442
443// Read a signed long. "zwidth" is the zero-based byte count.
444static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
445 int64_t val = 0;
446 for (int i = zwidth; i >= 0; --i) {
447 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
448 }
449 val >>= (7 - zwidth) * 8;
450 return val;
451}
452
453// Read an unsigned long. "zwidth" is the zero-based byte count,
454// "fill_on_right" indicates which side we want to zero-fill from.
455static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
456 bool fill_on_right) {
457 uint64_t val = 0;
458 if (!fill_on_right) {
459 for (int i = zwidth; i >= 0; --i) {
460 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
461 }
462 val >>= (7 - zwidth) * 8;
463 } else {
464 for (int i = zwidth; i >= 0; --i) {
465 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
466 }
467 }
468 return val;
469}
470
Brian Carlstromf615a612011-07-23 12:50:34 -0700471DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
472 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700473 const byte* ptr = *stream;
474 byte value_type = *ptr++;
475 byte value_arg = value_type >> kEncodedValueArgShift;
476 size_t width = value_arg + 1; // assume and correct later
477 int type = value_type & kEncodedValueTypeMask;
478 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700479 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700480 int32_t b = ReadSignedInt(ptr, value_arg);
481 CHECK(IsInt(8, b));
482 value->i = b;
483 break;
484 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700485 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700486 int32_t s = ReadSignedInt(ptr, value_arg);
487 CHECK(IsInt(16, s));
488 value->i = s;
489 break;
490 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700491 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700492 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
493 CHECK(IsUint(16, c));
494 value->i = c;
495 break;
496 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700497 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700498 value->i = ReadSignedInt(ptr, value_arg);
499 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700500 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700501 value->j = ReadSignedLong(ptr, value_arg);
502 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700503 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700504 value->i = ReadUnsignedInt(ptr, value_arg, true);
505 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700506 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700507 value->j = ReadUnsignedLong(ptr, value_arg, true);
508 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700509 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700510 value->i = (value_arg != 0);
511 width = 0;
512 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700513 case DexFile::kString:
514 case DexFile::kType:
515 case DexFile::kMethod:
516 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700517 value->i = ReadUnsignedInt(ptr, value_arg, false);
518 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700519 case DexFile::kField:
520 case DexFile::kArray:
521 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700522 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700523 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700524 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700525 value->i = 0;
526 width = 0;
527 break;
528 default:
529 LOG(FATAL) << "Unreached";
530 }
531 ptr += width;
532 *stream = ptr;
533 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700534}
535
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700536String* DexFile::dexArtStringById(int32_t idx) const {
537 if (idx == -1) {
538 return NULL;
539 }
Shih-wei Liao195487c2011-08-20 13:29:04 -0700540 return String::AllocFromModifiedUtf8(dexStringById(idx));
541}
542
543int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700544 // For native method, lineno should be -2 to indicate it is native. Note that
545 // "line number == -2" is how libcore tells from StackTraceElement.
546 if (method->code_off_ == 0) {
547 return -2;
548 }
549
Shih-wei Liao195487c2011-08-20 13:29:04 -0700550 const CodeItem* code_item = GetCodeItem(method->code_off_);
551 DCHECK(code_item != NULL);
552
553 // A method with no line number info should return -1
554 LineNumFromPcContext context(rel_pc, -1);
555 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
556 return context.line_num_;
557}
558
559void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
560 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
561 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
562 uint32_t line = DecodeUnsignedLeb128(&stream);
563 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
564 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
565 uint32_t address = 0;
566
567 if (!method->IsStatic()) {
568 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
569 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
570 local_in_reg[arg_reg].signature_ = NULL;
571 local_in_reg[arg_reg].start_address_ = 0;
572 local_in_reg[arg_reg].is_live_ = true;
573 arg_reg++;
574 }
575
576 ParameterIterator *it = GetParameterIterator(GetProtoId(method->proto_idx_));
577 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
578 if (arg_reg >= code_item->registers_size_) {
579 LOG(FATAL) << "invalid stream";
580 return;
581 }
582
583 String* descriptor = String::AllocFromModifiedUtf8(it->GetDescriptor());
584 String* name = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
585
586 local_in_reg[arg_reg].name_ = name;
587 local_in_reg[arg_reg].descriptor_ = descriptor;
588 local_in_reg[arg_reg].signature_ = NULL;
589 local_in_reg[arg_reg].start_address_ = address;
590 local_in_reg[arg_reg].is_live_ = true;
591 switch (descriptor->CharAt(0)) {
592 case 'D':
593 case 'J':
594 arg_reg += 2;
595 break;
596 default:
597 arg_reg += 1;
598 break;
599 }
600 }
601
602 if (it->HasNext()) {
603 LOG(FATAL) << "invalid stream";
604 return;
605 }
606
607 for (;;) {
608 uint8_t opcode = *stream++;
609 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
610 uint16_t reg;
611
612
613 switch (opcode) {
614 case DBG_END_SEQUENCE:
615 return;
616
617 case DBG_ADVANCE_PC:
618 address += DecodeUnsignedLeb128(&stream);
619 break;
620
621 case DBG_ADVANCE_LINE:
622 line += DecodeUnsignedLeb128(&stream);
623 break;
624
625 case DBG_START_LOCAL:
626 case DBG_START_LOCAL_EXTENDED:
627 reg = DecodeUnsignedLeb128(&stream);
628 if (reg > code_item->registers_size_) {
629 LOG(FATAL) << "invalid stream";
630 return;
631 }
632
633 // Emit what was previously there, if anything
634 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
635
636 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
637 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
638 if (opcode == DBG_START_LOCAL_EXTENDED) {
639 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
640 } else {
641 local_in_reg[reg].signature_ = NULL;
642 }
643 local_in_reg[reg].start_address_ = address;
644 local_in_reg[reg].is_live_ = true;
645 break;
646
647 case DBG_END_LOCAL:
648 reg = DecodeUnsignedLeb128(&stream);
649 if (reg > code_item->registers_size_) {
650 LOG(FATAL) << "invalid stream";
651 return;
652 }
653
654 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
655 local_in_reg[reg].is_live_ = false;
656 break;
657
658 case DBG_RESTART_LOCAL:
659 reg = DecodeUnsignedLeb128(&stream);
660 if (reg > code_item->registers_size_) {
661 LOG(FATAL) << "invalid stream";
662 return;
663 }
664
665 if (local_in_reg[reg].name_ == NULL
666 || local_in_reg[reg].descriptor_ == NULL) {
667 LOG(FATAL) << "invalid stream";
668 return;
669 }
670
671 // If the register is live, the "restart" is superfluous,
672 // and we don't want to mess with the existing start address.
673 if (!local_in_reg[reg].is_live_) {
674 local_in_reg[reg].start_address_ = address;
675 local_in_reg[reg].is_live_ = true;
676 }
677 break;
678
679 case DBG_SET_PROLOGUE_END:
680 case DBG_SET_EPILOGUE_BEGIN:
681 case DBG_SET_FILE:
682 break;
683
684 default:
685 address += adjopcode / DBG_LINE_RANGE;
686 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
687
688 if (posCb != NULL) {
689 if (posCb(cnxt, address, line)) {
690 // early exit
691 return;
692 }
693 }
694 break;
695 }
696 }
697}
698
Carl Shapiro1fb86202011-06-27 17:43:13 -0700699} // namespace art