blob: a5ac01bd9d90234457bd46d7a9d08ca5954d0036 [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>
6#include <string.h>
7#include <sys/mman.h>
8#include <sys/stat.h>
9#include <sys/types.h>
10#include <map>
11
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070012#include "globals.h"
13#include "logging.h"
14#include "object.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070015#include "scoped_ptr.h"
16#include "utils.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070017
18namespace art {
19
Brian Carlstromf615a612011-07-23 12:50:34 -070020const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
21const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070022
Brian Carlstromf615a612011-07-23 12:50:34 -070023DexFile::Closer::~Closer() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070024
Brian Carlstromf615a612011-07-23 12:50:34 -070025DexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026 CHECK(addr != NULL);
27}
Brian Carlstromf615a612011-07-23 12:50:34 -070028DexFile::MmapCloser::~MmapCloser() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070029 if (munmap(addr_, length_) == -1) {
30 PLOG(INFO) << "munmap failed";
31 }
32}
33
Brian Carlstromf615a612011-07-23 12:50:34 -070034DexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
35DexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070036
Brian Carlstromf615a612011-07-23 12:50:34 -070037DexFile* DexFile::OpenFile(const char* filename) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070038 CHECK(filename != NULL);
39 int fd = open(filename, O_RDONLY); // TODO: scoped_fd
40 if (fd == -1) {
41 PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
42 return NULL;
43 }
44 struct stat sbuf;
45 memset(&sbuf, 0, sizeof(sbuf));
46 if (fstat(fd, &sbuf) == -1) {
47 PLOG(ERROR) << "fstat \"" << filename << "\" failed";
48 close(fd);
49 return NULL;
50 }
51 size_t length = sbuf.st_size;
52 void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
53 if (addr == MAP_FAILED) {
54 PLOG(ERROR) << "mmap \"" << filename << "\" failed";
55 close(fd);
56 return NULL;
57 }
58 close(fd);
59 byte* dex_file = reinterpret_cast<byte*>(addr);
60 Closer* closer = new MmapCloser(addr, length);
61 return Open(dex_file, length, closer);
62}
63
Brian Carlstromf615a612011-07-23 12:50:34 -070064DexFile* DexFile::OpenPtr(byte* ptr, size_t length) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070065 CHECK(ptr != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -070066 DexFile::Closer* closer = new PtrCloser(ptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070067 return Open(ptr, length, closer);
68}
69
Brian Carlstromf615a612011-07-23 12:50:34 -070070DexFile* DexFile::Open(const byte* dex_bytes, size_t length,
71 Closer* closer) {
72 scoped_ptr<DexFile> dex_file(new DexFile(dex_bytes, length, closer));
73 if (!dex_file->Init()) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070074 return NULL;
75 } else {
Brian Carlstromf615a612011-07-23 12:50:34 -070076 return dex_file.release();
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070077 }
78}
79
Brian Carlstromf615a612011-07-23 12:50:34 -070080DexFile::~DexFile() {}
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070081
Brian Carlstromf615a612011-07-23 12:50:34 -070082bool DexFile::Init() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070083 InitMembers();
84 if (!IsMagicValid()) {
85 return false;
86 }
87 InitIndex();
88 return true;
89}
90
Brian Carlstromf615a612011-07-23 12:50:34 -070091void DexFile::InitMembers() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070092 const byte* b = base_;
93 header_ = reinterpret_cast<const Header*>(b);
94 const Header* h = header_;
95 string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
96 type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
97 field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
98 method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
99 proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
100 class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
101}
102
Brian Carlstromf615a612011-07-23 12:50:34 -0700103bool DexFile::IsMagicValid() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700104 return CheckMagic(header_->magic_);
105}
106
Brian Carlstromf615a612011-07-23 12:50:34 -0700107bool DexFile::CheckMagic(const byte* magic) {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700108 CHECK(magic != NULL);
109 if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
110 LOG(WARNING) << "Unrecognized magic number:"
111 << " " << magic[0]
112 << " " << magic[1]
113 << " " << magic[2]
114 << " " << magic[3];
115 return false;
116 }
117 const byte* version = &magic[sizeof(kDexMagic)];
118 if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
119 LOG(WARNING) << "Unrecognized version number:"
120 << " " << version[0]
121 << " " << version[1]
122 << " " << version[2]
123 << " " << version[3];
124 return false;
125 }
126 return true;
127}
128
Brian Carlstromf615a612011-07-23 12:50:34 -0700129void DexFile::InitIndex() {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700130 CHECK_EQ(index_.size(), 0U);
131 for (size_t i = 0; i < NumClassDefs(); ++i) {
132 const ClassDef& class_def = GetClassDef(i);
133 const char* descriptor = GetClassDescriptor(class_def);
134 index_[descriptor] = &class_def;
135 }
136}
137
Brian Carlstromf615a612011-07-23 12:50:34 -0700138const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700139 CHECK(descriptor != NULL);
140 Index::const_iterator it = index_.find(descriptor);
141 if (it == index_.end()) {
142 return NULL;
143 } else {
144 return it->second;
145 }
146}
147
148// Read a signed integer. "zwidth" is the zero-based byte count.
149static int32_t ReadSignedInt(const byte* ptr, int zwidth)
150{
151 int32_t val = 0;
152 for (int i = zwidth; i >= 0; --i) {
153 val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
154 }
155 val >>= (3 - zwidth) * 8;
156 return val;
157}
158
159// Read an unsigned integer. "zwidth" is the zero-based byte count,
160// "fill_on_right" indicates which side we want to zero-fill from.
161static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
162 bool fill_on_right) {
163 uint32_t val = 0;
164 if (!fill_on_right) {
165 for (int i = zwidth; i >= 0; --i) {
166 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
167 }
168 val >>= (3 - zwidth) * 8;
169 } else {
170 for (int i = zwidth; i >= 0; --i) {
171 val = (val >> 8) | (((uint32_t)*ptr++) << 24);
172 }
173 }
174 return val;
175}
176
177// Read a signed long. "zwidth" is the zero-based byte count.
178static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
179 int64_t val = 0;
180 for (int i = zwidth; i >= 0; --i) {
181 val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
182 }
183 val >>= (7 - zwidth) * 8;
184 return val;
185}
186
187// Read an unsigned long. "zwidth" is the zero-based byte count,
188// "fill_on_right" indicates which side we want to zero-fill from.
189static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
190 bool fill_on_right) {
191 uint64_t val = 0;
192 if (!fill_on_right) {
193 for (int i = zwidth; i >= 0; --i) {
194 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
195 }
196 val >>= (7 - zwidth) * 8;
197 } else {
198 for (int i = zwidth; i >= 0; --i) {
199 val = (val >> 8) | (((uint64_t)*ptr++) << 56);
200 }
201 }
202 return val;
203}
204
Brian Carlstromf615a612011-07-23 12:50:34 -0700205DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
206 JValue* value) const {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700207 const byte* ptr = *stream;
208 byte value_type = *ptr++;
209 byte value_arg = value_type >> kEncodedValueArgShift;
210 size_t width = value_arg + 1; // assume and correct later
211 int type = value_type & kEncodedValueTypeMask;
212 switch (type) {
Brian Carlstromf615a612011-07-23 12:50:34 -0700213 case DexFile::kByte: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700214 int32_t b = ReadSignedInt(ptr, value_arg);
215 CHECK(IsInt(8, b));
216 value->i = b;
217 break;
218 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700219 case DexFile::kShort: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700220 int32_t s = ReadSignedInt(ptr, value_arg);
221 CHECK(IsInt(16, s));
222 value->i = s;
223 break;
224 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700225 case DexFile::kChar: {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700226 uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
227 CHECK(IsUint(16, c));
228 value->i = c;
229 break;
230 }
Brian Carlstromf615a612011-07-23 12:50:34 -0700231 case DexFile::kInt:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700232 value->i = ReadSignedInt(ptr, value_arg);
233 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700234 case DexFile::kLong:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700235 value->j = ReadSignedLong(ptr, value_arg);
236 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700237 case DexFile::kFloat:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700238 value->i = ReadUnsignedInt(ptr, value_arg, true);
239 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700240 case DexFile::kDouble:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700241 value->j = ReadUnsignedLong(ptr, value_arg, true);
242 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700243 case DexFile::kBoolean:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700244 value->i = (value_arg != 0);
245 width = 0;
246 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700247 case DexFile::kString:
248 case DexFile::kType:
249 case DexFile::kMethod:
250 case DexFile::kEnum:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700251 value->i = ReadUnsignedInt(ptr, value_arg, false);
252 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700253 case DexFile::kField:
254 case DexFile::kArray:
255 case DexFile::kAnnotation:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700256 LOG(FATAL) << "Unimplemented";
257 break;
Brian Carlstromf615a612011-07-23 12:50:34 -0700258 case DexFile::kNull:
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700259 value->i = 0;
260 width = 0;
261 break;
262 default:
263 LOG(FATAL) << "Unreached";
264 }
265 ptr += width;
266 *stream = ptr;
267 return static_cast<ValueType>(type);
Carl Shapiro1fb86202011-06-27 17:43:13 -0700268}
269
Carl Shapiro1fb86202011-06-27 17:43:13 -0700270} // namespace art