blob: f7dec88c1cc84b0c6fe5ff6fb564ba13a4f18f0d [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 <map>
7#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
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070014#include "globals.h"
15#include "logging.h"
16#include "object.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070017#include "os.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070018#include "scoped_ptr.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070019#include "stringprintf.h"
20#include "thread.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070021#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070022#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070023
24namespace art {
25
Brian Carlstromf615a612011-07-23 12:50:34 -070026const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
27const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070028
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070029DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070030 const ClassPath& class_path) {
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070031 for (size_t i = 0; i != class_path.size(); ++i) {
32 const DexFile* dex_file = class_path[i];
33 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
34 if (dex_class_def != NULL) {
35 return ClassPathEntry(dex_file, dex_class_def);
36 }
37 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070038 // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
Brian Carlstrom7e93b502011-08-04 14:16:22 -070039 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
40 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070041}
42
Brian Carlstromf615a612011-07-23 12:50:34 -070043DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070044
Brian Carlstromf615a612011-07-23 12:50:34 -070045DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070046 CHECK(addr != NULL);
47}
Brian Carlstromf615a612011-07-23 12:50:34 -070048DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070049 if (munmap(addr_, length_) == -1) {
50 PLOG(INFO) << "munmap failed";
51 }
52}
53
Brian Carlstromf615a612011-07-23 12:50:34 -070054DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
55DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070056
Brian Carlstromb0460ea2011-07-29 10:08:05 -070057DexFile* DexFile::OpenFile(const std::string& filename) {
58 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070059 if (fd == -1) {
60 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
61 return NULL;
62 }
63 struct stat sbuf;
64 memset(&sbuf, 0, sizeof(sbuf));
65 if (fstat(fd, &sbuf) == -1) {
66 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
67 close(fd);
68 return NULL;
69 }
70 size_t length = sbuf.st_size;
71 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
72 if (addr == MAP_FAILED) {
73 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
74 close(fd);
75 return NULL;
76 }
77 close(fd);
78 byte* dex_file = reinterpret_cast<byte*>(addr);
79 Closer* closer = new MmapCloser(addr, length);
Brian Carlstroma663ea52011-08-19 23:33:41 -070080 return Open(dex_file, length, filename, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070081}
82
Brian Carlstromb0460ea2011-07-29 10:08:05 -070083static const char* kClassesDex = "classes.dex";
84
85class LockedFd {
86 public:
87 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
88 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
89 if (fd == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -070090 PLOG(ERROR) << "Can't open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -070091 return NULL;
92 }
93 fchmod(fd, mode);
94
95 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
96 int result = flock(fd, LOCK_EX | LOCK_NB);
97 if (result == -1) {
98 LOG(WARNING) << "sleeping while locking file " << name;
99 result = flock(fd, LOCK_EX);
100 }
101 if (result == -1 ) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700102 PLOG(ERROR) << "Can't lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700103 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700104 return NULL;
105 }
106 return new LockedFd(fd);
107 }
108
109 int GetFd() const {
110 return fd_;
111 }
112
113 ~LockedFd() {
114 if (fd_ != -1) {
115 int result = flock(fd_, LOCK_UN);
116 if (result == -1) {
117 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
118 }
119 close(fd_);
120 }
121 }
122
123 private:
124 LockedFd(int fd) : fd_(fd) {}
125
126 int fd_;
127};
128
129class TmpFile {
130 public:
131 TmpFile(const std::string name) : name_(name) {}
132 ~TmpFile() {
133 unlink(name_.c_str());
134 }
135 private:
136 const std::string name_;
137};
138
139// Open classes.dex from within a .zip, .jar, .apk, ...
140DexFile* DexFile::OpenZip(const std::string& filename) {
141
142 // First, look for a ".dex" alongside the jar file. It will have
143 // the same name/path except for the extension.
144
145 // Example filename = dir/foo.jar
146 std::string adjacent_dex_filename(filename);
147 size_t found = adjacent_dex_filename.find_last_of(".");
148 if (found == std::string::npos) {
149 LOG(WARNING) << "No . in filename" << filename;
150 }
151 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
152 adjacent_dex_filename.end(),
153 ".dex");
154 // Example adjacent_dex_filename = dir/foo.dex
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700155 if (OS::FileExists(adjacent_dex_filename.c_str())) {
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700156 DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
157 if (adjacent_dex_file != NULL) {
Brian Carlstrom4e777d42011-08-15 13:53:52 -0700158 // We don't verify anything in this case, because we aren't in
159 // the cache and typically the file is in the readonly /system
160 // area, so if something is wrong, there is nothing we can do.
161 return adjacent_dex_file;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700162 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700163 return NULL;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700164 }
165
166 char resolved[PATH_MAX];
167 char* absolute_path = realpath(filename.c_str(), resolved);
168 if (absolute_path == NULL) {
169 LOG(WARNING) << "Could not create absolute path for " << filename
170 << " when looking for classes.dex";
171 return NULL;
172 }
173 std::string cache_file(absolute_path+1); // skip leading slash
174 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
175 cache_file.push_back('@');
176 cache_file.append(kClassesDex);
177 // Example cache_file = parent@dir@foo.jar@classes.dex
178
179 const char* data_root = getenv("ANDROID_DATA");
180 if (data_root == NULL) {
181 data_root = "/data";
182 }
183
184 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
185 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
186
187 scoped_ptr<ZipArchive> zip_archive(ZipArchive::Open(filename));
188 if (zip_archive == NULL) {
189 LOG(WARNING) << "Could not open " << filename << " when looking for classes.dex";
190 return NULL;
191 }
192 scoped_ptr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
193 if (zip_entry == NULL) {
194 LOG(WARNING) << "Could not find classes.dex within " << filename;
195 return NULL;
196 }
197
198 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
199 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
200
201 while (true) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700202 if (OS::FileExists(cache_path.c_str())) {
203 DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
204 if (cached_dex_file != NULL) {
205 return cached_dex_file;
206 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700207 }
208
209 // Try to open the temporary cache file, grabbing an exclusive
210 // lock. If somebody else is working on it, we'll block here until
211 // they complete. Because we're waiting on an external resource,
212 // we go into native mode.
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700213 // Note that current_thread can be NULL if we're parsing the bootclasspath
214 // during JNI_CreateJavaVM.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700215 Thread* current_thread = Thread::Current();
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700216 Thread::State old;
217 if (current_thread != NULL) {
218 old = current_thread->GetState();
219 current_thread->SetState(Thread::kNative);
220 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700221 scoped_ptr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700222 if (current_thread != NULL) {
223 current_thread->SetState(old);
224 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700225 if (fd == NULL) {
226 return NULL;
227 }
228
229 // Check to see if the fd we opened and locked matches the file in
230 // the filesystem. If they don't, then somebody else unlinked
231 // ours and created a new file, and we need to use that one
232 // instead. (If we caught them between the unlink and the create,
233 // we'll get an ENOENT from the file stat.)
234 struct stat fd_stat;
235 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
236 if (fd_stat_result == -1) {
237 PLOG(ERROR) << "Can't stat open file '" << cache_path_tmp << "'";
238 return NULL;
239 }
240 struct stat file_stat;
241 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
242 if (file_stat_result == -1 ||
243 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
244 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
245 usleep(250 * 1000); // if something is hosed, don't peg machine
246 continue;
247 }
248
249 // We have the correct file open and locked. Extract classes.dex
250 TmpFile tmp_file(cache_path_tmp);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700251 scoped_ptr<File> file(OS::FileFromFd(cache_path_tmp.c_str(), fd->GetFd()));
252 if (file == NULL) {
253 return NULL;
254 }
255 bool success = zip_entry->Extract(*file);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700256 if (!success) {
257 return NULL;
258 }
259
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700260 // TODO: restat and check length against zip_entry->GetUncompressedLength()?
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700261
262 // Compute checksum and compare to zip. If things look okay, rename from tmp.
263 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
264 if (lseek_result == -1) {
265 return NULL;
266 }
267 const size_t kBufSize = 32768;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700268 scoped_array<uint8_t> buf(new uint8_t[kBufSize]);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700269 if (buf == NULL) {
270 return NULL;
271 }
272 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
273 while (true) {
274 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700275 if (bytes_read == -1) {
276 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
277 return NULL;
278 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700279 if (bytes_read == 0) {
280 break;
281 }
282 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
283 }
284 if (computed_crc != zip_entry->GetCrc32()) {
285 return NULL;
286 }
287 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
288 if (rename_result == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700289 PLOG(ERROR) << "Can't install dex cache file '" << cache_path << "'"
290 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700291 unlink(cache_path.c_str());
292 }
293 }
294 // NOTREACHED
295}
296
Brian Carlstroma663ea52011-08-19 23:33:41 -0700297DexFile* DexFile::OpenPtr(byte* ptr, size_t length, const std::string& location) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700298 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700299 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700300 return Open(ptr, length, location, closer);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700301}
302
Brian Carlstromf615a612011-07-23 12:50:34 -0700303DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
Brian Carlstroma663ea52011-08-19 23:33:41 -0700304 const std::string& location, Closer* closer) {
305 scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, location, closer));
Brian Carlstromf615a612011-07-23 12:50:34 -0700306 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700307 return NULL;
308 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700309 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700310 }
311}
312
Brian Carlstromf615a612011-07-23 12:50:34 -0700313DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700314
Brian Carlstromf615a612011-07-23 12:50:34 -0700315bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700316 InitMembers();
317 if (!IsMagicValid()) {
318 return false;
319 }
320 InitIndex();
321 return true;
322}
323
Brian Carlstromf615a612011-07-23 12:50:34 -0700324void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700325 const byte* b = base_;
326 header_ = reinterpret_cast<const Header*>(b);
327 const Header* h = header_;
328 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
329 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
330 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
331 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
332 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
333 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
334}
335
Brian Carlstromf615a612011-07-23 12:50:34 -0700336bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700337 return CheckMagic(header_->magic_);
338}
339
Brian Carlstromf615a612011-07-23 12:50:34 -0700340bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700341 CHECK(magic != NULL);
342 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
343 LOG(WARNING) << "Unrecognized magic number:"
344 << " " << magic[0]
345 << " " << magic[1]
346 << " " << magic[2]
347 << " " << magic[3];
348 return false;
349 }
350 const byte* version = &magic[sizeof(kDexMagic)];
351 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
352 LOG(WARNING) << "Unrecognized version number:"
353 << " " << version[0]
354 << " " << version[1]
355 << " " << version[2]
356 << " " << version[3];
357 return false;
358 }
359 return true;
360}
361
Brian Carlstromf615a612011-07-23 12:50:34 -0700362void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700363 CHECK_EQ(index_.size(), 0U);
364 for (size_t i = 0; i < NumClassDefs(); ++i) {
365 const ClassDef& class_def = GetClassDef(i);
366 const char* descriptor = GetClassDescriptor(class_def);
367 index_[descriptor] = &class_def;
368 }
369}
370
Brian Carlstromf615a612011-07-23 12:50:34 -0700371const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700372 CHECK(descriptor != NULL);
373 Index::const_iterator it = index_.find(descriptor);
374 if (it == index_.end()) {
375 return NULL;
376 } else {
377 return it->second;
378 }
379}
380
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700381// Materializes the method descriptor for a method prototype. Method
382// descriptors are not stored directly in the dex file. Instead, one
383// must assemble the descriptor from references in the prototype.
384char* DexFile::CreateMethodDescriptor(uint32_t proto_idx,
385 int32_t* unicode_length) const {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700386 const ProtoId& proto_id = GetProtoId(proto_idx);
387 std::string descriptor;
388 descriptor.push_back('(');
389 const TypeList* type_list = GetProtoParameters(proto_id);
390 size_t parameter_length = 0;
391 if (type_list != NULL) {
392 // A non-zero number of arguments. Append the type names.
393 for (size_t i = 0; i < type_list->Size(); ++i) {
394 const TypeItem& type_item = type_list->GetTypeItem(i);
395 uint32_t type_idx = type_item.type_idx_;
396 int32_t type_length;
397 const char* name = dexStringByTypeIdx(type_idx, &type_length);
398 parameter_length += type_length;
399 descriptor.append(name);
400 }
401 }
402 descriptor.push_back(')');
403 uint32_t return_type_idx = proto_id.return_type_idx_;
404 int32_t return_type_length;
405 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
406 descriptor.append(name);
407 // TODO: should this just return a std::string?
408 scoped_ptr<char> c_string(new char[descriptor.size() + 1]);
409 strcpy(c_string.get(), descriptor.c_str());
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700410 if (unicode_length != NULL) {
411 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
412 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700413 return c_string.release();
414}
415
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700416// Read a signed integer. "zwidth" is the zero-based byte count.
417static int32_t ReadSignedInt(const byte* ptr, int zwidth)
418{
419 int32_t val = 0;
420 for (int i = zwidth; i >= 0; --i) {
421 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
422 }
423 val >>= (3 - zwidth) * 8;
424 return val;
425}
426
427// Read an unsigned integer. "zwidth" is the zero-based byte count,
428// "fill_on_right" indicates which side we want to zero-fill from.
429static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
430 bool fill_on_right) {
431 uint32_t val = 0;
432 if (!fill_on_right) {
433 for (int i = zwidth; i >= 0; --i) {
434 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
435 }
436 val >>= (3 - zwidth) * 8;
437 } else {
438 for (int i = zwidth; i >= 0; --i) {
439 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
440 }
441 }
442 return val;
443}
444
445// Read a signed long. "zwidth" is the zero-based byte count.
446static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
447 int64_t val = 0;
448 for (int i = zwidth; i >= 0; --i) {
449 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
450 }
451 val >>= (7 - zwidth) * 8;
452 return val;
453}
454
455// Read an unsigned long. "zwidth" is the zero-based byte count,
456// "fill_on_right" indicates which side we want to zero-fill from.
457static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
458 bool fill_on_right) {
459 uint64_t val = 0;
460 if (!fill_on_right) {
461 for (int i = zwidth; i >= 0; --i) {
462 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
463 }
464 val >>= (7 - zwidth) * 8;
465 } else {
466 for (int i = zwidth; i >= 0; --i) {
467 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
468 }
469 }
470 return val;
471}
472
Brian Carlstromf615a612011-07-23 12:50:34 -0700473DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
474 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700475 const byte* ptr = *stream;
476 byte value_type = *ptr++;
477 byte value_arg = value_type >> kEncodedValueArgShift;
478 size_t width = value_arg + 1; // assume and correct later
479 int type = value_type & kEncodedValueTypeMask;
480 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700481 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700482 int32_t b = ReadSignedInt(ptr, value_arg);
483 CHECK(IsInt(8, b));
484 value->i = b;
485 break;
486 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700487 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700488 int32_t s = ReadSignedInt(ptr, value_arg);
489 CHECK(IsInt(16, s));
490 value->i = s;
491 break;
492 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700493 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700494 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
495 CHECK(IsUint(16, c));
496 value->i = c;
497 break;
498 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700499 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700500 value->i = ReadSignedInt(ptr, value_arg);
501 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700502 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700503 value->j = ReadSignedLong(ptr, value_arg);
504 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700505 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700506 value->i = ReadUnsignedInt(ptr, value_arg, true);
507 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700508 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700509 value->j = ReadUnsignedLong(ptr, value_arg, true);
510 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700511 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700512 value->i = (value_arg != 0);
513 width = 0;
514 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700515 case DexFile::kString:
516 case DexFile::kType:
517 case DexFile::kMethod:
518 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700519 value->i = ReadUnsignedInt(ptr, value_arg, false);
520 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700521 case DexFile::kField:
522 case DexFile::kArray:
523 case DexFile::kAnnotation:
Elliott Hughes53b61312011-08-12 18:28:20 -0700524 UNIMPLEMENTED(FATAL) << ": type " << type;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700525 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700526 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700527 value->i = 0;
528 width = 0;
529 break;
530 default:
531 LOG(FATAL) << "Unreached";
532 }
533 ptr += width;
534 *stream = ptr;
535 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700536}
537
Shih-wei Liao195487c2011-08-20 13:29:04 -0700538String* DexFile::dexArtStringById(uint32_t idx) const {
539 return String::AllocFromModifiedUtf8(dexStringById(idx));
540}
541
542int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
543 const CodeItem* code_item = GetCodeItem(method->code_off_);
544 DCHECK(code_item != NULL);
545
546 // A method with no line number info should return -1
547 LineNumFromPcContext context(rel_pc, -1);
548 dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
549 return context.line_num_;
550}
551
552void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
553 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
554 void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
555 uint32_t line = DecodeUnsignedLeb128(&stream);
556 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
557 uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
558 uint32_t address = 0;
559
560 if (!method->IsStatic()) {
561 local_in_reg[arg_reg].name_ = String::AllocFromModifiedUtf8("this");
562 local_in_reg[arg_reg].descriptor_ = method->GetDeclaringClass()->GetDescriptor();
563 local_in_reg[arg_reg].signature_ = NULL;
564 local_in_reg[arg_reg].start_address_ = 0;
565 local_in_reg[arg_reg].is_live_ = true;
566 arg_reg++;
567 }
568
569 ParameterIterator *it = GetParameterIterator(GetProtoId(method->proto_idx_));
570 for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
571 if (arg_reg >= code_item->registers_size_) {
572 LOG(FATAL) << "invalid stream";
573 return;
574 }
575
576 String* descriptor = String::AllocFromModifiedUtf8(it->GetDescriptor());
577 String* name = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
578
579 local_in_reg[arg_reg].name_ = name;
580 local_in_reg[arg_reg].descriptor_ = descriptor;
581 local_in_reg[arg_reg].signature_ = NULL;
582 local_in_reg[arg_reg].start_address_ = address;
583 local_in_reg[arg_reg].is_live_ = true;
584 switch (descriptor->CharAt(0)) {
585 case 'D':
586 case 'J':
587 arg_reg += 2;
588 break;
589 default:
590 arg_reg += 1;
591 break;
592 }
593 }
594
595 if (it->HasNext()) {
596 LOG(FATAL) << "invalid stream";
597 return;
598 }
599
600 for (;;) {
601 uint8_t opcode = *stream++;
602 uint8_t adjopcode = opcode - DBG_FIRST_SPECIAL;
603 uint16_t reg;
604
605
606 switch (opcode) {
607 case DBG_END_SEQUENCE:
608 return;
609
610 case DBG_ADVANCE_PC:
611 address += DecodeUnsignedLeb128(&stream);
612 break;
613
614 case DBG_ADVANCE_LINE:
615 line += DecodeUnsignedLeb128(&stream);
616 break;
617
618 case DBG_START_LOCAL:
619 case DBG_START_LOCAL_EXTENDED:
620 reg = DecodeUnsignedLeb128(&stream);
621 if (reg > code_item->registers_size_) {
622 LOG(FATAL) << "invalid stream";
623 return;
624 }
625
626 // Emit what was previously there, if anything
627 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
628
629 local_in_reg[reg].name_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
630 local_in_reg[reg].descriptor_ = dexArtStringByTypeIdx(DecodeUnsignedLeb128P1(&stream));
631 if (opcode == DBG_START_LOCAL_EXTENDED) {
632 local_in_reg[reg].signature_ = dexArtStringById(DecodeUnsignedLeb128P1(&stream));
633 } else {
634 local_in_reg[reg].signature_ = NULL;
635 }
636 local_in_reg[reg].start_address_ = address;
637 local_in_reg[reg].is_live_ = true;
638 break;
639
640 case DBG_END_LOCAL:
641 reg = DecodeUnsignedLeb128(&stream);
642 if (reg > code_item->registers_size_) {
643 LOG(FATAL) << "invalid stream";
644 return;
645 }
646
647 InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
648 local_in_reg[reg].is_live_ = false;
649 break;
650
651 case DBG_RESTART_LOCAL:
652 reg = DecodeUnsignedLeb128(&stream);
653 if (reg > code_item->registers_size_) {
654 LOG(FATAL) << "invalid stream";
655 return;
656 }
657
658 if (local_in_reg[reg].name_ == NULL
659 || local_in_reg[reg].descriptor_ == NULL) {
660 LOG(FATAL) << "invalid stream";
661 return;
662 }
663
664 // If the register is live, the "restart" is superfluous,
665 // and we don't want to mess with the existing start address.
666 if (!local_in_reg[reg].is_live_) {
667 local_in_reg[reg].start_address_ = address;
668 local_in_reg[reg].is_live_ = true;
669 }
670 break;
671
672 case DBG_SET_PROLOGUE_END:
673 case DBG_SET_EPILOGUE_BEGIN:
674 case DBG_SET_FILE:
675 break;
676
677 default:
678 address += adjopcode / DBG_LINE_RANGE;
679 line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
680
681 if (posCb != NULL) {
682 if (posCb(cnxt, address, line)) {
683 // early exit
684 return;
685 }
686 }
687 break;
688 }
689 }
690}
691
Carl Shapiro1fb86202011-06-27 17:43:13 -0700692} // namespace art