blob: b61babf7e5cc59c6a648c930fb56765f9e6e89a6 [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 Carlstromf615a612011-07-23 12:50:34 -070028DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070029
Brian Carlstromf615a612011-07-23 12:50:34 -070030DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070031 CHECK(addr != NULL);
32}
Brian Carlstromf615a612011-07-23 12:50:34 -070033DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070034 if (munmap(addr_, length_) == -1) {
35 PLOG(INFO) << "munmap failed";
36 }
37}
38
Brian Carlstromf615a612011-07-23 12:50:34 -070039DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
40DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070041
Brian Carlstromb0460ea2011-07-29 10:08:05 -070042DexFile* DexFile::OpenFile(const std::string& filename) {
43 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070044 if (fd == -1) {
45 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
46 return NULL;
47 }
48 struct stat sbuf;
49 memset(&sbuf, 0, sizeof(sbuf));
50 if (fstat(fd, &sbuf) == -1) {
51 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
52 close(fd);
53 return NULL;
54 }
55 size_t length = sbuf.st_size;
56 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
57 if (addr == MAP_FAILED) {
58 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
59 close(fd);
60 return NULL;
61 }
62 close(fd);
63 byte* dex_file = reinterpret_cast<byte*>(addr);
64 Closer* closer = new MmapCloser(addr, length);
65 return Open(dex_file, length, closer);
66}
67
Brian Carlstromb0460ea2011-07-29 10:08:05 -070068static const char* kClassesDex = "classes.dex";
69
70class LockedFd {
71 public:
72 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
73 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
74 if (fd == -1) {
75 PLOG(ERROR) << "Can't open file '" << name;
76 return NULL;
77 }
78 fchmod(fd, mode);
79
80 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
81 int result = flock(fd, LOCK_EX | LOCK_NB);
82 if (result == -1) {
83 LOG(WARNING) << "sleeping while locking file " << name;
84 result = flock(fd, LOCK_EX);
85 }
86 if (result == -1 ) {
87 close(fd);
88 PLOG(ERROR) << "Can't lock file '" << name;
89 return NULL;
90 }
91 return new LockedFd(fd);
92 }
93
94 int GetFd() const {
95 return fd_;
96 }
97
98 ~LockedFd() {
99 if (fd_ != -1) {
100 int result = flock(fd_, LOCK_UN);
101 if (result == -1) {
102 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
103 }
104 close(fd_);
105 }
106 }
107
108 private:
109 LockedFd(int fd) : fd_(fd) {}
110
111 int fd_;
112};
113
114class TmpFile {
115 public:
116 TmpFile(const std::string name) : name_(name) {}
117 ~TmpFile() {
118 unlink(name_.c_str());
119 }
120 private:
121 const std::string name_;
122};
123
124// Open classes.dex from within a .zip, .jar, .apk, ...
125DexFile* DexFile::OpenZip(const std::string& filename) {
126
127 // First, look for a ".dex" alongside the jar file. It will have
128 // the same name/path except for the extension.
129
130 // Example filename = dir/foo.jar
131 std::string adjacent_dex_filename(filename);
132 size_t found = adjacent_dex_filename.find_last_of(".");
133 if (found == std::string::npos) {
134 LOG(WARNING) << "No . in filename" << filename;
135 }
136 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
137 adjacent_dex_filename.end(),
138 ".dex");
139 // Example adjacent_dex_filename = dir/foo.dex
140 DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
141 if (adjacent_dex_file != NULL) {
142 // We don't verify anything in this case, because we aren't in
143 // the cache and typically the file is in the readonly /system
144 // area, so if something is wrong, there is nothing we can do.
145 return adjacent_dex_file;
146 }
147
148 char resolved[PATH_MAX];
149 char* absolute_path = realpath(filename.c_str(), resolved);
150 if (absolute_path == NULL) {
151 LOG(WARNING) << "Could not create absolute path for " << filename
152 << " when looking for classes.dex";
153 return NULL;
154 }
155 std::string cache_file(absolute_path+1); // skip leading slash
156 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
157 cache_file.push_back('@');
158 cache_file.append(kClassesDex);
159 // Example cache_file = parent@dir@foo.jar@classes.dex
160
161 const char* data_root = getenv("ANDROID_DATA");
162 if (data_root == NULL) {
163 data_root = "/data";
164 }
165
166 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
167 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
168
169 scoped_ptr<ZipArchive> zip_archive(ZipArchive::Open(filename));
170 if (zip_archive == NULL) {
171 LOG(WARNING) << "Could not open " << filename << " when looking for classes.dex";
172 return NULL;
173 }
174 scoped_ptr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
175 if (zip_entry == NULL) {
176 LOG(WARNING) << "Could not find classes.dex within " << filename;
177 return NULL;
178 }
179
180 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
181 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
182
183 while (true) {
184 DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
185 if (cached_dex_file != NULL) {
186 return cached_dex_file;
187 }
188
189 // Try to open the temporary cache file, grabbing an exclusive
190 // lock. If somebody else is working on it, we'll block here until
191 // they complete. Because we're waiting on an external resource,
192 // we go into native mode.
193 Thread* current_thread = Thread::Current();
194 Thread::State old = current_thread->GetState();
195 current_thread->SetState(Thread::kNative);
196 scoped_ptr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
197 current_thread->SetState(old);
198 if (fd == NULL) {
199 return NULL;
200 }
201
202 // Check to see if the fd we opened and locked matches the file in
203 // the filesystem. If they don't, then somebody else unlinked
204 // ours and created a new file, and we need to use that one
205 // instead. (If we caught them between the unlink and the create,
206 // we'll get an ENOENT from the file stat.)
207 struct stat fd_stat;
208 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
209 if (fd_stat_result == -1) {
210 PLOG(ERROR) << "Can't stat open file '" << cache_path_tmp << "'";
211 return NULL;
212 }
213 struct stat file_stat;
214 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
215 if (file_stat_result == -1 ||
216 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
217 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
218 usleep(250 * 1000); // if something is hosed, don't peg machine
219 continue;
220 }
221
222 // We have the correct file open and locked. Extract classes.dex
223 TmpFile tmp_file(cache_path_tmp);
224 bool success = zip_entry->Extract(fd->GetFd());
225 if (!success) {
226 return NULL;
227 }
228
229 // TODO restat and check length against zip_entry->GetUncompressedLength()?
230
231 // Compute checksum and compare to zip. If things look okay, rename from tmp.
232 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
233 if (lseek_result == -1) {
234 return NULL;
235 }
236 const size_t kBufSize = 32768;
237 scoped_ptr<uint8_t> buf(new uint8_t[kBufSize]);
238 if (buf == NULL) {
239 return NULL;
240 }
241 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
242 while (true) {
243 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
244 if (bytes_read == 0) {
245 break;
246 }
247 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
248 }
249 if (computed_crc != zip_entry->GetCrc32()) {
250 return NULL;
251 }
252 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
253 if (rename_result == -1) {
254 PLOG(ERROR) << "Can't install dex cache file '" << cache_path << "' from '" << cache_path_tmp;
255 unlink(cache_path.c_str());
256 }
257 }
258 // NOTREACHED
259}
260
Brian Carlstromf615a612011-07-23 12:50:34 -0700261DexFile* DexFile::OpenPtr(byte* ptr, size_t length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700262 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700263 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700264 return Open(ptr, length, closer);
265}
266
Brian Carlstromf615a612011-07-23 12:50:34 -0700267DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
268 Closer* closer) {
269 scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, closer));
270 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700271 return NULL;
272 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700273 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700274 }
275}
276
Brian Carlstromf615a612011-07-23 12:50:34 -0700277DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700278
Brian Carlstromf615a612011-07-23 12:50:34 -0700279bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700280 InitMembers();
281 if (!IsMagicValid()) {
282 return false;
283 }
284 InitIndex();
285 return true;
286}
287
Brian Carlstromf615a612011-07-23 12:50:34 -0700288void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700289 const byte* b = base_;
290 header_ = reinterpret_cast<const Header*>(b);
291 const Header* h = header_;
292 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
293 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
294 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
295 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
296 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
297 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
298}
299
Brian Carlstromf615a612011-07-23 12:50:34 -0700300bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700301 return CheckMagic(header_->magic_);
302}
303
Brian Carlstromf615a612011-07-23 12:50:34 -0700304bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700305 CHECK(magic != NULL);
306 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
307 LOG(WARNING) << "Unrecognized magic number:"
308 << " " << magic[0]
309 << " " << magic[1]
310 << " " << magic[2]
311 << " " << magic[3];
312 return false;
313 }
314 const byte* version = &magic[sizeof(kDexMagic)];
315 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
316 LOG(WARNING) << "Unrecognized version number:"
317 << " " << version[0]
318 << " " << version[1]
319 << " " << version[2]
320 << " " << version[3];
321 return false;
322 }
323 return true;
324}
325
Brian Carlstromf615a612011-07-23 12:50:34 -0700326void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700327 CHECK_EQ(index_.size(), 0U);
328 for (size_t i = 0; i < NumClassDefs(); ++i) {
329 const ClassDef& class_def = GetClassDef(i);
330 const char* descriptor = GetClassDescriptor(class_def);
331 index_[descriptor] = &class_def;
332 }
333}
334
Brian Carlstromf615a612011-07-23 12:50:34 -0700335const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700336 CHECK(descriptor != NULL);
337 Index::const_iterator it = index_.find(descriptor);
338 if (it == index_.end()) {
339 return NULL;
340 } else {
341 return it->second;
342 }
343}
344
345// Read a signed integer. "zwidth" is the zero-based byte count.
346static int32_t ReadSignedInt(const byte* ptr, int zwidth)
347{
348 int32_t val = 0;
349 for (int i = zwidth; i >= 0; --i) {
350 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
351 }
352 val >>= (3 - zwidth) * 8;
353 return val;
354}
355
356// Read an unsigned integer. "zwidth" is the zero-based byte count,
357// "fill_on_right" indicates which side we want to zero-fill from.
358static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
359 bool fill_on_right) {
360 uint32_t val = 0;
361 if (!fill_on_right) {
362 for (int i = zwidth; i >= 0; --i) {
363 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
364 }
365 val >>= (3 - zwidth) * 8;
366 } else {
367 for (int i = zwidth; i >= 0; --i) {
368 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
369 }
370 }
371 return val;
372}
373
374// Read a signed long. "zwidth" is the zero-based byte count.
375static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
376 int64_t val = 0;
377 for (int i = zwidth; i >= 0; --i) {
378 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
379 }
380 val >>= (7 - zwidth) * 8;
381 return val;
382}
383
384// Read an unsigned long. "zwidth" is the zero-based byte count,
385// "fill_on_right" indicates which side we want to zero-fill from.
386static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
387 bool fill_on_right) {
388 uint64_t val = 0;
389 if (!fill_on_right) {
390 for (int i = zwidth; i >= 0; --i) {
391 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
392 }
393 val >>= (7 - zwidth) * 8;
394 } else {
395 for (int i = zwidth; i >= 0; --i) {
396 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
397 }
398 }
399 return val;
400}
401
Brian Carlstromf615a612011-07-23 12:50:34 -0700402DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
403 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700404 const byte* ptr = *stream;
405 byte value_type = *ptr++;
406 byte value_arg = value_type >> kEncodedValueArgShift;
407 size_t width = value_arg + 1; // assume and correct later
408 int type = value_type & kEncodedValueTypeMask;
409 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700410 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700411 int32_t b = ReadSignedInt(ptr, value_arg);
412 CHECK(IsInt(8, b));
413 value->i = b;
414 break;
415 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700416 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700417 int32_t s = ReadSignedInt(ptr, value_arg);
418 CHECK(IsInt(16, s));
419 value->i = s;
420 break;
421 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700422 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700423 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
424 CHECK(IsUint(16, c));
425 value->i = c;
426 break;
427 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700428 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700429 value->i = ReadSignedInt(ptr, value_arg);
430 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700431 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700432 value->j = ReadSignedLong(ptr, value_arg);
433 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700434 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700435 value->i = ReadUnsignedInt(ptr, value_arg, true);
436 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700437 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700438 value->j = ReadUnsignedLong(ptr, value_arg, true);
439 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700440 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700441 value->i = (value_arg != 0);
442 width = 0;
443 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700444 case DexFile::kString:
445 case DexFile::kType:
446 case DexFile::kMethod:
447 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700448 value->i = ReadUnsignedInt(ptr, value_arg, false);
449 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700450 case DexFile::kField:
451 case DexFile::kArray:
452 case DexFile::kAnnotation:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700453 LOG(FATAL) << "Unimplemented";
454 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700455 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700456 value->i = 0;
457 width = 0;
458 break;
459 default:
460 LOG(FATAL) << "Unreached";
461 }
462 ptr += width;
463 *stream = ptr;
464 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700465}
466
Carl Shapiro1fb86202011-06-27 17:43:13 -0700467} // namespace art