blob: 23eae7cbe797606d0ff7727460fe1e8757169d18 [file] [log] [blame]
Brian Carlstrome24fa612011-09-29 00:53:55 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "oat_file.h"
4
5#include <sys/mman.h>
6
7#include "file.h"
8#include "os.h"
9#include "stl_util.h"
10
11namespace art {
12
Brian Carlstromb7bbba42011-10-13 14:58:47 -070013std::string OatFile::DexFileToOatFilename(const DexFile& dex_file) {
14 std::string location(dex_file.GetLocation());
15 CHECK(StringPiece(location).ends_with(".dex")
16 || StringPiece(location).ends_with(".zip")
17 || StringPiece(location).ends_with(".jar")
18 || StringPiece(location).ends_with(".apk"));
19 location.erase(location.size()-3);
20 location += "oat";
21 return location;
22}
23
Brian Carlstrome24fa612011-09-29 00:53:55 -070024OatFile* OatFile::Open(const std::string& filename,
25 const std::string& strip_location_prefix,
26 byte* requested_base) {
27 StringPiece location = filename;
28 if (!location.starts_with(strip_location_prefix)) {
29 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
30 return NULL;
31 }
32 location.remove_prefix(strip_location_prefix.size());
33
34 UniquePtr<OatFile> oat_file(new OatFile(location.ToString()));
35 bool success = oat_file->Read(filename, requested_base);
36 if (!success) {
37 return NULL;
38 }
39 return oat_file.release();
40}
41
42OatFile::OatFile(const std::string& filename) : location_(filename) {}
43
44OatFile::~OatFile() {
45 STLDeleteValues(&oat_dex_files_);
46}
47
48bool OatFile::Read(const std::string& filename, byte* requested_base) {
49 UniquePtr<File> file(OS::OpenFile(filename.c_str(), false));
50 if (file.get() == NULL) {
51 return false;
52 }
53
54 OatHeader oat_header;
55 bool success = file->ReadFully(&oat_header, sizeof(oat_header));
56 if (!success || !oat_header.IsValid()) {
57 LOG(WARNING) << "Invalid oat header " << filename;
58 return false;
59 }
60
61 UniquePtr<MemMap> map(MemMap::Map(requested_base,
62 file->Length(),
63 PROT_READ,
64 MAP_PRIVATE | ((requested_base != NULL) ? MAP_FIXED : 0),
65 file->Fd(),
66 0));
67 if (map.get() == NULL) {
68 LOG(WARNING) << "Failed to map oat file " << filename;
69 return false;
70 }
71 CHECK(requested_base == 0 || requested_base == map->GetAddress()) << map->GetAddress();
72 DCHECK_EQ(0, memcmp(&oat_header, map->GetAddress(), sizeof(OatHeader)));
73
74 off_t code_offset = oat_header.GetExecutableOffset();
75 if (code_offset < file->Length()) {
76 byte* code_address = map->GetAddress() + code_offset;
77 size_t code_length = file->Length() - code_offset;
78 if (mprotect(code_address, code_length, PROT_READ | PROT_EXEC) != 0) {
79 PLOG(ERROR) << "Failed to make oat code executable.";
80 return false;
81 }
82 } else {
83 // its possible to have no code if all the methods were abstract, native, etc
84 DCHECK_EQ(code_offset, RoundUp(file->Length(), kPageSize));
85 }
86
87 const byte* oat = map->GetAddress();
88 oat += sizeof(OatHeader);
89 CHECK_LT(oat, map->GetLimit());
90 for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
91 size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
92 oat += sizeof(dex_file_location_size);
93 CHECK_LT(oat, map->GetLimit());
94
95 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
96 oat += dex_file_location_size;
97 CHECK_LT(oat, map->GetLimit());
98
99 std::string dex_file_location(dex_file_location_data, dex_file_location_size);
100
101 uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
102 oat += sizeof(dex_file_checksum);
103 CHECK_LT(oat, map->GetLimit());
104
105 uint32_t classes_offset = *reinterpret_cast<const uint32_t*>(oat);
106 CHECK_GT(classes_offset, 0U);
107 CHECK_LT(classes_offset, static_cast<uint32_t>(file->Length()));
108 oat += sizeof(classes_offset);
109 CHECK_LT(oat, map->GetLimit());
110
111 uint32_t* classes_pointer = reinterpret_cast<uint32_t*>(map->GetAddress() + classes_offset);
112
113 oat_dex_files_[dex_file_location] = new OatDexFile(this,
114 dex_file_location,
115 dex_file_checksum,
116 classes_pointer);
117 }
118
119 mem_map_.reset(map.release());
120 return true;
121}
122
123const OatHeader& OatFile::GetOatHeader() const {
124 return *reinterpret_cast<const OatHeader*>(GetBase());
125}
126
127const byte* OatFile::GetBase() const {
128 CHECK(mem_map_->GetAddress() != NULL);
129 return mem_map_->GetAddress();
130}
131
132const byte* OatFile::GetLimit() const {
133 CHECK(mem_map_->GetLimit() != NULL);
134 return mem_map_->GetLimit();
135}
136
Brian Carlstromaded5f72011-10-07 17:15:04 -0700137const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_file_location) const {
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700138 Table::const_iterator it = oat_dex_files_.find(dex_file_location);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700139 if (it == oat_dex_files_.end()) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700140 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
141 return NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700142 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700143 return it->second;
144}
145
146std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const {
147 std::vector<const OatFile::OatDexFile*> result;
148 for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it ) {
149 result.push_back(it->second);
150 }
151 return result;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700152}
153
154OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
155 std::string dex_file_location,
156 uint32_t dex_file_checksum,
157 uint32_t* classes_pointer)
158 : oat_file_(oat_file),
159 dex_file_location_(dex_file_location),
160 dex_file_checksum_(dex_file_checksum),
161 classes_pointer_(classes_pointer) {}
162
163OatFile::OatDexFile::~OatDexFile() {}
164
Brian Carlstromaded5f72011-10-07 17:15:04 -0700165const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700166 uint32_t methods_offset = classes_pointer_[class_def_index];
167 const byte* methods_pointer = oat_file_->GetBase() + methods_offset;
168 CHECK_LT(methods_pointer, oat_file_->GetLimit());
Brian Carlstromaded5f72011-10-07 17:15:04 -0700169 return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700170}
171
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700172OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer)
Brian Carlstrome24fa612011-09-29 00:53:55 -0700173 : oat_file_(oat_file), methods_pointer_(methods_pointer) {}
174
175OatFile::OatClass::~OatClass() {}
176
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700177const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
178 const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index];
179 return OatMethod(
180 GetOatPointer<const void*>(oat_method_offsets.code_offset_),
181 oat_method_offsets.frame_size_in_bytes_,
182 oat_method_offsets.return_pc_offset_in_bytes_,
183 oat_method_offsets.core_spill_mask_,
184 oat_method_offsets.fp_spill_mask_,
185 GetOatPointer<const uint32_t*>(oat_method_offsets.mapping_table_offset_),
186 GetOatPointer<const uint16_t*>(oat_method_offsets.vmap_table_offset_),
187 GetOatPointer<const Method::InvokeStub*>(oat_method_offsets.invoke_stub_offset_));
188}
189
190OatFile::OatMethod::OatMethod(const void* code,
191 const size_t frame_size_in_bytes,
192 const size_t return_pc_offset_in_bytes,
193 const uint32_t core_spill_mask,
194 const uint32_t fp_spill_mask,
195 const uint32_t* mapping_table,
196 const uint16_t* vmap_table,
197 const Method::InvokeStub* invoke_stub) :
198 code_(code),
199 frame_size_in_bytes_(frame_size_in_bytes),
200 return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
201 core_spill_mask_(core_spill_mask),
202 fp_spill_mask_(fp_spill_mask),
203 mapping_table_(mapping_table),
204 vmap_table_(vmap_table),
205 invoke_stub_(invoke_stub) {}
206
207OatFile::OatMethod::~OatMethod() {}
208
Brian Carlstromaded5f72011-10-07 17:15:04 -0700209void OatFile::OatMethod::LinkMethod(Method* method) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700210 CHECK(method != NULL);
211 method->SetCode(code_);
212 method->SetFrameSizeInBytes(frame_size_in_bytes_);
213 method->SetReturnPcOffsetInBytes(return_pc_offset_in_bytes_);
214 method->SetCoreSpillMask(core_spill_mask_);
215 method->SetFpSpillMask(fp_spill_mask_);
216 method->SetMappingTable(mapping_table_);
217 method->SetVmapTable(vmap_table_);
218 method->SetInvokeStub(invoke_stub_);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700219}
220
221} // namespace art