blob: 0645a651930d3ada1216ab94c61ebfa5ec7bc963 [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 }
Brian Carlstrom7e93b502011-08-04 14:16:22 -070037 // TODO remove reinterpret_cast when issue with -std=gnu++0x host issue resolved
38 return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL),
39 reinterpret_cast<const DexFile::ClassDef*>(NULL));
Brian Carlstrom74eb46a2011-08-02 20:10:14 -070040}
41
Brian Carlstromf615a612011-07-23 12:50:34 -070042DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070043
Brian Carlstromf615a612011-07-23 12:50:34 -070044DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070045 CHECK(addr != NULL);
46}
Brian Carlstromf615a612011-07-23 12:50:34 -070047DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070048 if (munmap(addr_, length_) == -1) {
49 PLOG(INFO) << "munmap failed";
50 }
51}
52
Brian Carlstromf615a612011-07-23 12:50:34 -070053DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
54DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070055
Brian Carlstromb0460ea2011-07-29 10:08:05 -070056DexFile* DexFile::OpenFile(const std::string& filename) {
57 int fd = open(filename.c_str(), O_RDONLY); // TODO: scoped_fd
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070058 if (fd == -1) {
59 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
60 return NULL;
61 }
62 struct stat sbuf;
63 memset(&sbuf, 0, sizeof(sbuf));
64 if (fstat(fd, &sbuf) == -1) {
65 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
66 close(fd);
67 return NULL;
68 }
69 size_t length = sbuf.st_size;
70 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
71 if (addr == MAP_FAILED) {
72 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
73 close(fd);
74 return NULL;
75 }
76 close(fd);
77 byte* dex_file = reinterpret_cast<byte*>(addr);
78 Closer* closer = new MmapCloser(addr, length);
79 return Open(dex_file, length, closer);
80}
81
Brian Carlstromb0460ea2011-07-29 10:08:05 -070082static const char* kClassesDex = "classes.dex";
83
84class LockedFd {
85 public:
86 static LockedFd* CreateAndLock(std::string& name, mode_t mode) {
87 int fd = open(name.c_str(), O_CREAT | O_RDWR, mode);
88 if (fd == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -070089 PLOG(ERROR) << "Can't open file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -070090 return NULL;
91 }
92 fchmod(fd, mode);
93
94 LOG(INFO) << "locking file " << name << " (fd=" << fd << ")";
95 int result = flock(fd, LOCK_EX | LOCK_NB);
96 if (result == -1) {
97 LOG(WARNING) << "sleeping while locking file " << name;
98 result = flock(fd, LOCK_EX);
99 }
100 if (result == -1 ) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700101 PLOG(ERROR) << "Can't lock file '" << name << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700102 close(fd);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700103 return NULL;
104 }
105 return new LockedFd(fd);
106 }
107
108 int GetFd() const {
109 return fd_;
110 }
111
112 ~LockedFd() {
113 if (fd_ != -1) {
114 int result = flock(fd_, LOCK_UN);
115 if (result == -1) {
116 PLOG(WARNING) << "flock(" << fd_ << ", LOCK_UN) failed";
117 }
118 close(fd_);
119 }
120 }
121
122 private:
123 LockedFd(int fd) : fd_(fd) {}
124
125 int fd_;
126};
127
128class TmpFile {
129 public:
130 TmpFile(const std::string name) : name_(name) {}
131 ~TmpFile() {
132 unlink(name_.c_str());
133 }
134 private:
135 const std::string name_;
136};
137
138// Open classes.dex from within a .zip, .jar, .apk, ...
139DexFile* DexFile::OpenZip(const std::string& filename) {
140
141 // First, look for a ".dex" alongside the jar file. It will have
142 // the same name/path except for the extension.
143
144 // Example filename = dir/foo.jar
145 std::string adjacent_dex_filename(filename);
146 size_t found = adjacent_dex_filename.find_last_of(".");
147 if (found == std::string::npos) {
148 LOG(WARNING) << "No . in filename" << filename;
149 }
150 adjacent_dex_filename.replace(adjacent_dex_filename.begin() + found,
151 adjacent_dex_filename.end(),
152 ".dex");
153 // Example adjacent_dex_filename = dir/foo.dex
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700154 struct stat sb;
155 if (stat(adjacent_dex_filename.c_str(), &sb) == 0) {
156 DexFile* adjacent_dex_file = DexFile::OpenFile(adjacent_dex_filename);
157 if (adjacent_dex_file != NULL) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -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 Carlstromb0460ea2011-07-29 10:08:05 -0700163 }
164
165 char resolved[PATH_MAX];
166 char* absolute_path = realpath(filename.c_str(), resolved);
167 if (absolute_path == NULL) {
168 LOG(WARNING) << "Could not create absolute path for " << filename
169 << " when looking for classes.dex";
170 return NULL;
171 }
172 std::string cache_file(absolute_path+1); // skip leading slash
173 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
174 cache_file.push_back('@');
175 cache_file.append(kClassesDex);
176 // Example cache_file = parent@dir@foo.jar@classes.dex
177
178 const char* data_root = getenv("ANDROID_DATA");
179 if (data_root == NULL) {
180 data_root = "/data";
181 }
182
183 std::string cache_path_tmp = StringPrintf("%s/art-cache/%s", data_root, cache_file.c_str());
184 // Example cache_path_tmp = /data/art-cache/parent@dir@foo.jar@classes.dex
185
186 scoped_ptr<ZipArchive> zip_archive(ZipArchive::Open(filename));
187 if (zip_archive == NULL) {
188 LOG(WARNING) << "Could not open " << filename << " when looking for classes.dex";
189 return NULL;
190 }
191 scoped_ptr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
192 if (zip_entry == NULL) {
193 LOG(WARNING) << "Could not find classes.dex within " << filename;
194 return NULL;
195 }
196
197 std::string cache_path = StringPrintf("%s.%08x", cache_path_tmp.c_str(), zip_entry->GetCrc32());
198 // Example cache_path = /data/art-cache/parent@dir@foo.jar@classes.dex.1a2b3c4d
199
200 while (true) {
201 DexFile* cached_dex_file = DexFile::OpenFile(cache_path);
202 if (cached_dex_file != NULL) {
203 return cached_dex_file;
204 }
205
206 // Try to open the temporary cache file, grabbing an exclusive
207 // lock. If somebody else is working on it, we'll block here until
208 // they complete. Because we're waiting on an external resource,
209 // we go into native mode.
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700210 // Note that current_thread can be NULL if we're parsing the bootclasspath
211 // during JNI_CreateJavaVM.
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700212 Thread* current_thread = Thread::Current();
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700213 Thread::State old;
214 if (current_thread != NULL) {
215 old = current_thread->GetState();
216 current_thread->SetState(Thread::kNative);
217 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700218 scoped_ptr<LockedFd> fd(LockedFd::CreateAndLock(cache_path_tmp, 0644));
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700219 if (current_thread != NULL) {
220 current_thread->SetState(old);
221 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700222 if (fd == NULL) {
223 return NULL;
224 }
225
226 // Check to see if the fd we opened and locked matches the file in
227 // the filesystem. If they don't, then somebody else unlinked
228 // ours and created a new file, and we need to use that one
229 // instead. (If we caught them between the unlink and the create,
230 // we'll get an ENOENT from the file stat.)
231 struct stat fd_stat;
232 int fd_stat_result = fstat(fd->GetFd(), &fd_stat);
233 if (fd_stat_result == -1) {
234 PLOG(ERROR) << "Can't stat open file '" << cache_path_tmp << "'";
235 return NULL;
236 }
237 struct stat file_stat;
238 int file_stat_result = stat(cache_path_tmp.c_str(), &file_stat);
239 if (file_stat_result == -1 ||
240 fd_stat.st_dev != file_stat.st_dev || fd_stat.st_ino != file_stat.st_ino) {
241 LOG(WARNING) << "our open cache file is stale; sleeping and retrying";
242 usleep(250 * 1000); // if something is hosed, don't peg machine
243 continue;
244 }
245
246 // We have the correct file open and locked. Extract classes.dex
247 TmpFile tmp_file(cache_path_tmp);
248 bool success = zip_entry->Extract(fd->GetFd());
249 if (!success) {
250 return NULL;
251 }
252
253 // TODO restat and check length against zip_entry->GetUncompressedLength()?
254
255 // Compute checksum and compare to zip. If things look okay, rename from tmp.
256 off_t lseek_result = lseek(fd->GetFd(), 0, SEEK_SET);
257 if (lseek_result == -1) {
258 return NULL;
259 }
260 const size_t kBufSize = 32768;
Elliott Hughese0fc0ef2011-08-12 17:39:17 -0700261 scoped_array<uint8_t> buf(new uint8_t[kBufSize]);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700262 if (buf == NULL) {
263 return NULL;
264 }
265 uint32_t computed_crc = crc32(0L, Z_NULL, 0);
266 while (true) {
267 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd->GetFd(), buf.get(), kBufSize));
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700268 if (bytes_read == -1) {
269 PLOG(ERROR) << "Problem computing CRC of '" << cache_path_tmp << "'";
270 return NULL;
271 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700272 if (bytes_read == 0) {
273 break;
274 }
275 computed_crc = crc32(computed_crc, buf.get(), bytes_read);
276 }
277 if (computed_crc != zip_entry->GetCrc32()) {
278 return NULL;
279 }
280 int rename_result = rename(cache_path_tmp.c_str(), cache_path.c_str());
281 if (rename_result == -1) {
Brian Carlstrom0024d6c2011-08-09 08:26:12 -0700282 PLOG(ERROR) << "Can't install dex cache file '" << cache_path << "'"
283 << " from '" << cache_path_tmp << "'";
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700284 unlink(cache_path.c_str());
285 }
286 }
287 // NOTREACHED
288}
289
Brian Carlstromf615a612011-07-23 12:50:34 -0700290DexFile* DexFile::OpenPtr(byte* ptr, size_t length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700291 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -0700292 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700293 return Open(ptr, length, closer);
294}
295
Brian Carlstromf615a612011-07-23 12:50:34 -0700296DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
297 Closer* closer) {
298 scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, closer));
299 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700300 return NULL;
301 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -0700302 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700303 }
304}
305
Brian Carlstromf615a612011-07-23 12:50:34 -0700306DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700307
Brian Carlstromf615a612011-07-23 12:50:34 -0700308bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700309 InitMembers();
310 if (!IsMagicValid()) {
311 return false;
312 }
313 InitIndex();
314 return true;
315}
316
Brian Carlstromf615a612011-07-23 12:50:34 -0700317void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700318 const byte* b = base_;
319 header_ = reinterpret_cast<const Header*>(b);
320 const Header* h = header_;
321 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
322 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
323 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
324 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
325 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
326 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
327}
328
Brian Carlstromf615a612011-07-23 12:50:34 -0700329bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700330 return CheckMagic(header_->magic_);
331}
332
Brian Carlstromf615a612011-07-23 12:50:34 -0700333bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700334 CHECK(magic != NULL);
335 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
336 LOG(WARNING) << "Unrecognized magic number:"
337 << " " << magic[0]
338 << " " << magic[1]
339 << " " << magic[2]
340 << " " << magic[3];
341 return false;
342 }
343 const byte* version = &magic[sizeof(kDexMagic)];
344 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
345 LOG(WARNING) << "Unrecognized version number:"
346 << " " << version[0]
347 << " " << version[1]
348 << " " << version[2]
349 << " " << version[3];
350 return false;
351 }
352 return true;
353}
354
Brian Carlstromf615a612011-07-23 12:50:34 -0700355void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700356 CHECK_EQ(index_.size(), 0U);
357 for (size_t i = 0; i < NumClassDefs(); ++i) {
358 const ClassDef& class_def = GetClassDef(i);
359 const char* descriptor = GetClassDescriptor(class_def);
360 index_[descriptor] = &class_def;
361 }
362}
363
Brian Carlstromf615a612011-07-23 12:50:34 -0700364const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700365 CHECK(descriptor != NULL);
366 Index::const_iterator it = index_.find(descriptor);
367 if (it == index_.end()) {
368 return NULL;
369 } else {
370 return it->second;
371 }
372}
373
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700374// Materializes the method descriptor for a method prototype. Method
375// descriptors are not stored directly in the dex file. Instead, one
376// must assemble the descriptor from references in the prototype.
377char* DexFile::CreateMethodDescriptor(uint32_t proto_idx,
378 int32_t* unicode_length) const {
379 CHECK(unicode_length != NULL);
380 const ProtoId& proto_id = GetProtoId(proto_idx);
381 std::string descriptor;
382 descriptor.push_back('(');
383 const TypeList* type_list = GetProtoParameters(proto_id);
384 size_t parameter_length = 0;
385 if (type_list != NULL) {
386 // A non-zero number of arguments. Append the type names.
387 for (size_t i = 0; i < type_list->Size(); ++i) {
388 const TypeItem& type_item = type_list->GetTypeItem(i);
389 uint32_t type_idx = type_item.type_idx_;
390 int32_t type_length;
391 const char* name = dexStringByTypeIdx(type_idx, &type_length);
392 parameter_length += type_length;
393 descriptor.append(name);
394 }
395 }
396 descriptor.push_back(')');
397 uint32_t return_type_idx = proto_id.return_type_idx_;
398 int32_t return_type_length;
399 const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
400 descriptor.append(name);
401 // TODO: should this just return a std::string?
402 scoped_ptr<char> c_string(new char[descriptor.size() + 1]);
403 strcpy(c_string.get(), descriptor.c_str());
404 *unicode_length = parameter_length + return_type_length + 2; // 2 for ( and )
405 return c_string.release();
406}
407
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700408// Read a signed integer. "zwidth" is the zero-based byte count.
409static int32_t ReadSignedInt(const byte* ptr, int zwidth)
410{
411 int32_t val = 0;
412 for (int i = zwidth; i >= 0; --i) {
413 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
414 }
415 val >>= (3 - zwidth) * 8;
416 return val;
417}
418
419// Read an unsigned integer. "zwidth" is the zero-based byte count,
420// "fill_on_right" indicates which side we want to zero-fill from.
421static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
422 bool fill_on_right) {
423 uint32_t val = 0;
424 if (!fill_on_right) {
425 for (int i = zwidth; i >= 0; --i) {
426 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
427 }
428 val >>= (3 - zwidth) * 8;
429 } else {
430 for (int i = zwidth; i >= 0; --i) {
431 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
432 }
433 }
434 return val;
435}
436
437// Read a signed long. "zwidth" is the zero-based byte count.
438static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
439 int64_t val = 0;
440 for (int i = zwidth; i >= 0; --i) {
441 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
442 }
443 val >>= (7 - zwidth) * 8;
444 return val;
445}
446
447// Read an unsigned long. "zwidth" is the zero-based byte count,
448// "fill_on_right" indicates which side we want to zero-fill from.
449static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
450 bool fill_on_right) {
451 uint64_t val = 0;
452 if (!fill_on_right) {
453 for (int i = zwidth; i >= 0; --i) {
454 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
455 }
456 val >>= (7 - zwidth) * 8;
457 } else {
458 for (int i = zwidth; i >= 0; --i) {
459 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
460 }
461 }
462 return val;
463}
464
Brian Carlstromf615a612011-07-23 12:50:34 -0700465DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
466 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700467 const byte* ptr = *stream;
468 byte value_type = *ptr++;
469 byte value_arg = value_type >> kEncodedValueArgShift;
470 size_t width = value_arg + 1; // assume and correct later
471 int type = value_type & kEncodedValueTypeMask;
472 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700473 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700474 int32_t b = ReadSignedInt(ptr, value_arg);
475 CHECK(IsInt(8, b));
476 value->i = b;
477 break;
478 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700479 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700480 int32_t s = ReadSignedInt(ptr, value_arg);
481 CHECK(IsInt(16, s));
482 value->i = s;
483 break;
484 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700485 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700486 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
487 CHECK(IsUint(16, c));
488 value->i = c;
489 break;
490 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700491 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700492 value->i = ReadSignedInt(ptr, value_arg);
493 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700494 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700495 value->j = ReadSignedLong(ptr, value_arg);
496 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700497 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700498 value->i = ReadUnsignedInt(ptr, value_arg, true);
499 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700500 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700501 value->j = ReadUnsignedLong(ptr, value_arg, true);
502 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700503 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700504 value->i = (value_arg != 0);
505 width = 0;
506 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700507 case DexFile::kString:
508 case DexFile::kType:
509 case DexFile::kMethod:
510 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700511 value->i = ReadUnsignedInt(ptr, value_arg, false);
512 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700513 case DexFile::kField:
514 case DexFile::kArray:
515 case DexFile::kAnnotation:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700516 LOG(FATAL) << "Unimplemented";
517 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700518 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700519 value->i = 0;
520 width = 0;
521 break;
522 default:
523 LOG(FATAL) << "Unreached";
524 }
525 ptr += width;
526 *stream = ptr;
527 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700528}
529
Carl Shapiro1fb86202011-06-27 17:43:13 -0700530} // namespace art