blob: 35e98db020920fe1fc47ecac6210fc718bad1488 [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 Carlstrom7e49dca2011-07-22 18:07:34 -070017#include "scoped_ptr.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070018#include "stringprintf.h"
19#include "thread.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070020#include "utils.h"
Brian Carlstromb0460ea2011-07-29 10:08:05 -070021#include "zip_archive.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070022
23namespace art {
24
Brian Carlstromf615a612011-07-23 12:50:34 -070025const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
26const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070027
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070028DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor,
29 ClassPath& class_path) {
30 for (size_t i = 0; i != class_path.size(); ++i) {
31 const DexFile* dex_file = class_path[i];
32 const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
33 if (dex_class_def != NULL) {
34 return ClassPathEntry(dex_file, dex_class_def);
35 }
36 }
37 return ClassPathEntry(NULL, NULL);
38}
39
Brian Carlstromf615a612011-07-23 12:50:34 -070040DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070041
Brian Carlstromf615a612011-07-23 12:50:34 -070042DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070043 CHECK(addr != NULL);
44}
Brian Carlstromf615a612011-07-23 12:50:34 -070045DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070046 if (munmap(addr_, length_) == -1) {
47 PLOG(INFO) << "munmap failed";
48 }
49}
50
Brian Carlstromf615a612011-07-23 12:50:34 -070051DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
52DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070053
Brian Carlstromb0460ea2011-07-29 10:08:05 -070054DexFile* DexFile::OpenFile(const std::string& filename) {
55 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070056 if (fd == -1) {
57 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
58 return NULL;
59 }
60 struct stat sbuf;
61 memset(&sbuf, 0, sizeof(sbuf));
62 if (fstat(fd, &sbuf) == -1) {
63 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
64 close(fd);
65 return NULL;
66 }
67 size_t length = sbuf.st_size;
68 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
69 if (addr == MAP_FAILED) {
70 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
71 close(fd);
72 return NULL;
73 }
74 close(fd);
75 byte* dex_file = reinterpret_cast<byte*>(addr);
76 Closer* closer = new MmapCloser(addr, length);
77 return Open(dex_file, length, closer);
78}
79
Brian Carlstromb0460ea2011-07-29 10:08:05 -070080static const char* kClassesDex = "classes.dex";
81
82class LockedFd {
83 public:
84 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
85 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
86 if (fd == -1) {
87 PLOG(ERROR) << "Can't open file '" << name;
88 return NULL;
89 }
90 fchmod(fd, mode);
91
92 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
93 int result = flock(fd, LOCK_EX | LOCK_NB);
94 if (result == -1) {
95 LOG(WARNING) << "sleeping while locking file " << name;
96 result = flock(fd, LOCK_EX);
97 }
98 if (result == -1 ) {
99 close(fd);
100 PLOG(ERROR) << "Can't lock file '" << name;
101 return NULL;
102 }
103 return new LockedFd(fd);
104 }
105
106 int GetFd() const {
107 return fd_;
108 }
109
110 ~LockedFd() {
111 if (fd_ != -1) {
112 int result = flock(fd_, LOCK_UN);
113 if (result == -1) {
114 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
115 }
116 close(fd_);
117 }
118 }
119
120 private:
121 LockedFd(int fd) : fd_(fd) {}
122
123 int fd_;
124};
125
126class TmpFile {
127 public:
128 TmpFile(const std::string name) : name_(name) {}
129 ~TmpFile() {
130 unlink(name_.c_str());
131 }
132 private:
133 const std::string name_;
134};
135
136// Open classes.dex from within a .zip, .jar, .apk, ...
137DexFile* DexFile::OpenZip(const std::string& filename) {
138
139 // First, look for a ".dex" alongside the jar file. It will have
140 // the same name/path except for the extension.
141
142 // Example filename = dir/foo.jar
143 std::string adjacent_dex_filename(filename);
144 size_t found = adjacent_dex_filename.find_last_of(".");
145 if (found == std::string::npos) {
146 LOG(WARNING) << "No . in filename" << filename;
147 }
148 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
149 adjacent_dex_filename.end(),
150 ".dex");
151 // Example adjacent_dex_filename = dir/foo.dex
152 DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
153 if (adjacent_dex_file != NULL) {
154 // We don't verify anything in this case, because we aren't in
155 // the cache and typically the file is in the readonly /system
156 // area, so if something is wrong, there is nothing we can do.
157 return adjacent_dex_file;
158 }
159
160 char resolved[PATH_MAX];
161 char* absolute_path = realpath(filename.c_str(), resolved);
162 if (absolute_path == NULL) {
163 LOG(WARNING) << "Could not create absolute path for " << filename
164 << " when looking for classes.dex";
165 return NULL;
166 }
167 std::string cache_file(absolute_path+1); // skip leading slash
168 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
169 cache_file.push_back('@');
170 cache_file.append(kClassesDex);
171 // Example cache_file = parent@dir@foo.jar@classes.dex
172
173 const char* data_root = getenv("ANDROID_DATA");
174 if (data_root == NULL) {
175 data_root = "/data";
176 }
177
178 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
179 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
180
181 scoped_ptr<ZipArchive> zip_archive(ZipArchive::Open(filename));
182 if (zip_archive == NULL) {
183 LOG(WARNING) << "Could not open " << filename << " when looking for classes.dex";
184 return NULL;
185 }
186 scoped_ptr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
187 if (zip_entry == NULL) {
188 LOG(WARNING) << "Could not find classes.dex within " << filename;
189 return NULL;
190 }
191
192 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
193 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
194
195 while (true) {
196 DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
197 if (cached_dex_file != NULL) {
198 return cached_dex_file;
199 }
200
201 // Try to open the temporary cache file, grabbing an exclusive
202 // lock. If somebody else is working on it, we'll block here until
203 // they complete. Because we're waiting on an external resource,
204 // we go into native mode.
205 Thread* current_thread = Thread::Current();
206 Thread::State old = current_thread->GetState();
207 current_thread->SetState(Thread::kNative);
208 scoped_ptr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
209 current_thread->SetState(old);
210 if (fd == NULL) {
211 return NULL;
212 }
213
214 // Check to see if the fd we opened and locked matches the file in
215 // the filesystem. If they don't, then somebody else unlinked
216 // ours and created a new file, and we need to use that one
217 // instead. (If we caught them between the unlink and the create,
218 // we'll get an ENOENT from the file stat.)
219 struct stat fd_stat;
220 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
221 if (fd_stat_result == -1) {
222 PLOG(ERROR) << "Can't stat open file '" << cache_path_tmp << "'";
223 return NULL;
224 }
225 struct stat file_stat;
226 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
227 if (file_stat_result == -1 ||
228 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
229 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
230 usleep(250 * 1000); // if something is hosed, don't peg machine
231 continue;
232 }
233
234 // We have the correct file open and locked. Extract classes.dex
235 TmpFile tmp_file(cache_path_tmp);
236 bool success = zip_entry->Extract(fd->GetFd());
237 if (!success) {
238 return NULL;
239 }
240
241 // TODO restat and check length against zip_entry->GetUncompressedLength()?
242
243 // Compute checksum and compare to zip. If things look okay, rename from tmp.
244 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
245 if (lseek_result == -1) {
246 return NULL;
247 }
248 const size_t kBufSize = 32768;
249 scoped_ptr<uint8_t> buf(new uint8_t[kBufSize]);
250 if (buf == NULL) {
251 return NULL;
252 }
253 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
254 while (true) {
255 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
256 if (bytes_read == 0) {
257 break;
258 }
259 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
260 }
261 if (computed_crc != zip_entry->GetCrc32()) {
262 return NULL;
263 }
264 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
265 if (rename_result == -1) {
266 PLOG(ERROR) << "Can't install dex cache file '" << cache_path << "' from '" << cache_path_tmp;
267 unlink(cache_path.c_str());
268 }
269 }
270 // NOTREACHED
271}
272
Brian Carlstromf615a612011-07-23 12:50:34 -0700273DexFile* DexFile::OpenPtr(byte* ptr, size_t length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700274 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700275 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700276 return Open(ptr, length, closer);
277}
278
Brian Carlstromf615a612011-07-23 12:50:34 -0700279DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
280 Closer* closer) {
281 scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, closer));
282 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700283 return NULL;
284 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700285 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700286 }
287}
288
Brian Carlstromf615a612011-07-23 12:50:34 -0700289DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700290
Brian Carlstromf615a612011-07-23 12:50:34 -0700291bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700292 InitMembers();
293 if (!IsMagicValid()) {
294 return false;
295 }
296 InitIndex();
297 return true;
298}
299
Brian Carlstromf615a612011-07-23 12:50:34 -0700300void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700301 const byte* b = base_;
302 header_ = reinterpret_cast<const Header*>(b);
303 const Header* h = header_;
304 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
305 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
306 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
307 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
308 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
309 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
310}
311
Brian Carlstromf615a612011-07-23 12:50:34 -0700312bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700313 return CheckMagic(header_->magic_);
314}
315
Brian Carlstromf615a612011-07-23 12:50:34 -0700316bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700317 CHECK(magic != NULL);
318 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
319 LOG(WARNING) << "Unrecognized magic number:"
320 << " " << magic[0]
321 << " " << magic[1]
322 << " " << magic[2]
323 << " " << magic[3];
324 return false;
325 }
326 const byte* version = &magic[sizeof(kDexMagic)];
327 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
328 LOG(WARNING) << "Unrecognized version number:"
329 << " " << version[0]
330 << " " << version[1]
331 << " " << version[2]
332 << " " << version[3];
333 return false;
334 }
335 return true;
336}
337
Brian Carlstromf615a612011-07-23 12:50:34 -0700338void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700339 CHECK_EQ(index_.size(), 0U);
340 for (size_t i = 0; i < NumClassDefs(); ++i) {
341 const ClassDef& class_def = GetClassDef(i);
342 const char* descriptor = GetClassDescriptor(class_def);
343 index_[descriptor] = &class_def;
344 }
345}
346
Brian Carlstromf615a612011-07-23 12:50:34 -0700347const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700348 CHECK(descriptor != NULL);
349 Index::const_iterator it = index_.find(descriptor);
350 if (it == index_.end()) {
351 return NULL;
352 } else {
353 return it->second;
354 }
355}
356
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700357// Materializes the method descriptor for a method prototype. Method
358// descriptors are not stored directly in the dex file. Instead, one
359// must assemble the descriptor from references in the prototype.
360char* DexFile::CreateMethodDescriptor(uint32_t proto_idx,
361 int32_t* unicode_length) const {
362 CHECK(unicode_length != NULL);
363 const ProtoId& proto_id = GetProtoId(proto_idx);
364 std::string descriptor;
365 descriptor.push_back('(');
366 const TypeList* type_list = GetProtoParameters(proto_id);
367 size_t parameter_length = 0;
368 if (type_list != NULL) {
369 // A non-zero number of arguments. Append the type names.
370 for (size_t i = 0; i < type_list->Size(); ++i) {
371 const TypeItem& type_item = type_list->GetTypeItem(i);
372 uint32_t type_idx = type_item.type_idx_;
373 int32_t type_length;
374 const char* name = dexStringByTypeIdx(type_idx, &type_length);
375 parameter_length += type_length;
376 descriptor.append(name);
377 }
378 }
379 descriptor.push_back(')');
380 uint32_t return_type_idx = proto_id.return_type_idx_;
381 int32_t return_type_length;
382 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
383 descriptor.append(name);
384 // TODO: should this just return a std::string?
385 scoped_ptr<char> c_string(new char[descriptor.size() + 1]);
386 strcpy(c_string.get(), descriptor.c_str());
387 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
388 return c_string.release();
389}
390
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700391// Read a signed integer. "zwidth" is the zero-based byte count.
392static int32_t ReadSignedInt(const byte* ptr, int zwidth)
393{
394 int32_t val = 0;
395 for (int i = zwidth; i >= 0; --i) {
396 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
397 }
398 val >>= (3 - zwidth) * 8;
399 return val;
400}
401
402// Read an unsigned integer. "zwidth" is the zero-based byte count,
403// "fill_on_right" indicates which side we want to zero-fill from.
404static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
405 bool fill_on_right) {
406 uint32_t val = 0;
407 if (!fill_on_right) {
408 for (int i = zwidth; i >= 0; --i) {
409 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
410 }
411 val >>= (3 - zwidth) * 8;
412 } else {
413 for (int i = zwidth; i >= 0; --i) {
414 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
415 }
416 }
417 return val;
418}
419
420// Read a signed long. "zwidth" is the zero-based byte count.
421static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
422 int64_t val = 0;
423 for (int i = zwidth; i >= 0; --i) {
424 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
425 }
426 val >>= (7 - zwidth) * 8;
427 return val;
428}
429
430// Read an unsigned long. "zwidth" is the zero-based byte count,
431// "fill_on_right" indicates which side we want to zero-fill from.
432static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
433 bool fill_on_right) {
434 uint64_t val = 0;
435 if (!fill_on_right) {
436 for (int i = zwidth; i >= 0; --i) {
437 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
438 }
439 val >>= (7 - zwidth) * 8;
440 } else {
441 for (int i = zwidth; i >= 0; --i) {
442 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
443 }
444 }
445 return val;
446}
447
Brian Carlstromf615a612011-07-23 12:50:34 -0700448DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
449 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700450 const byte* ptr = *stream;
451 byte value_type = *ptr++;
452 byte value_arg = value_type >> kEncodedValueArgShift;
453 size_t width = value_arg + 1; // assume and correct later
454 int type = value_type & kEncodedValueTypeMask;
455 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700456 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700457 int32_t b = ReadSignedInt(ptr, value_arg);
458 CHECK(IsInt(8, b));
459 value->i = b;
460 break;
461 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700462 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700463 int32_t s = ReadSignedInt(ptr, value_arg);
464 CHECK(IsInt(16, s));
465 value->i = s;
466 break;
467 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700468 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700469 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
470 CHECK(IsUint(16, c));
471 value->i = c;
472 break;
473 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700474 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700475 value->i = ReadSignedInt(ptr, value_arg);
476 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700477 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700478 value->j = ReadSignedLong(ptr, value_arg);
479 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700480 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700481 value->i = ReadUnsignedInt(ptr, value_arg, true);
482 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700483 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700484 value->j = ReadUnsignedLong(ptr, value_arg, true);
485 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700486 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700487 value->i = (value_arg != 0);
488 width = 0;
489 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700490 case DexFile::kString:
491 case DexFile::kType:
492 case DexFile::kMethod:
493 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700494 value->i = ReadUnsignedInt(ptr, value_arg, false);
495 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700496 case DexFile::kField:
497 case DexFile::kArray:
498 case DexFile::kAnnotation:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700499 LOG(FATAL) << "Unimplemented";
500 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700501 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700502 value->i = 0;
503 width = 0;
504 break;
505 default:
506 LOG(FATAL) << "Unreached";
507 }
508 ptr += width;
509 *stream = ptr;
510 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700511}
512
Carl Shapiro1fb86202011-06-27 17:43:13 -0700513} // namespace art