blob: 4804864d766a467e36fe8bcd2168ba2c55c4b8b0 [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
jeffhao262bf462011-10-20 18:36:32 -070013std::string OatFile::DexFilenameToOatFilename(const std::string& location) {
jeffhao262bf462011-10-20 18:36:32 -070014 CHECK(IsValidDexFilename(location) || IsValidZipFilename(location));
15 std::string oat_location = location.substr(0, location.size()-3);
16 oat_location += "oat";
17 return oat_location;
Brian Carlstromb7bbba42011-10-13 14:58:47 -070018}
19
Brian Carlstrome24fa612011-09-29 00:53:55 -070020OatFile* OatFile::Open(const std::string& filename,
21 const std::string& strip_location_prefix,
22 byte* requested_base) {
23 StringPiece location = filename;
24 if (!location.starts_with(strip_location_prefix)) {
25 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
26 return NULL;
27 }
28 location.remove_prefix(strip_location_prefix.size());
29
30 UniquePtr<OatFile> oat_file(new OatFile(location.ToString()));
31 bool success = oat_file->Read(filename, requested_base);
32 if (!success) {
33 return NULL;
34 }
35 return oat_file.release();
36}
37
38OatFile::OatFile(const std::string& filename) : location_(filename) {}
39
40OatFile::~OatFile() {
41 STLDeleteValues(&oat_dex_files_);
42}
43
44bool OatFile::Read(const std::string& filename, byte* requested_base) {
45 UniquePtr<File> file(OS::OpenFile(filename.c_str(), false));
46 if (file.get() == NULL) {
47 return false;
48 }
49
50 OatHeader oat_header;
51 bool success = file->ReadFully(&oat_header, sizeof(oat_header));
52 if (!success || !oat_header.IsValid()) {
53 LOG(WARNING) << "Invalid oat header " << filename;
54 return false;
55 }
56
57 UniquePtr<MemMap> map(MemMap::Map(requested_base,
58 file->Length(),
59 PROT_READ,
60 MAP_PRIVATE | ((requested_base != NULL) ? MAP_FIXED : 0),
61 file->Fd(),
62 0));
63 if (map.get() == NULL) {
64 LOG(WARNING) << "Failed to map oat file " << filename;
65 return false;
66 }
67 CHECK(requested_base == 0 || requested_base == map->GetAddress()) << map->GetAddress();
68 DCHECK_EQ(0, memcmp(&oat_header, map->GetAddress(), sizeof(OatHeader)));
69
70 off_t code_offset = oat_header.GetExecutableOffset();
71 if (code_offset < file->Length()) {
72 byte* code_address = map->GetAddress() + code_offset;
73 size_t code_length = file->Length() - code_offset;
74 if (mprotect(code_address, code_length, PROT_READ | PROT_EXEC) != 0) {
75 PLOG(ERROR) << "Failed to make oat code executable.";
76 return false;
77 }
78 } else {
79 // its possible to have no code if all the methods were abstract, native, etc
80 DCHECK_EQ(code_offset, RoundUp(file->Length(), kPageSize));
81 }
82
83 const byte* oat = map->GetAddress();
84 oat += sizeof(OatHeader);
85 CHECK_LT(oat, map->GetLimit());
86 for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
87 size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
88 oat += sizeof(dex_file_location_size);
89 CHECK_LT(oat, map->GetLimit());
90
91 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
92 oat += dex_file_location_size;
93 CHECK_LT(oat, map->GetLimit());
94
95 std::string dex_file_location(dex_file_location_data, dex_file_location_size);
96
97 uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
98 oat += sizeof(dex_file_checksum);
99 CHECK_LT(oat, map->GetLimit());
100
101 uint32_t classes_offset = *reinterpret_cast<const uint32_t*>(oat);
102 CHECK_GT(classes_offset, 0U);
103 CHECK_LT(classes_offset, static_cast<uint32_t>(file->Length()));
104 oat += sizeof(classes_offset);
105 CHECK_LT(oat, map->GetLimit());
106
107 uint32_t* classes_pointer = reinterpret_cast<uint32_t*>(map->GetAddress() + classes_offset);
108
109 oat_dex_files_[dex_file_location] = new OatDexFile(this,
110 dex_file_location,
111 dex_file_checksum,
112 classes_pointer);
113 }
114
115 mem_map_.reset(map.release());
116 return true;
117}
118
119const OatHeader& OatFile::GetOatHeader() const {
120 return *reinterpret_cast<const OatHeader*>(GetBase());
121}
122
123const byte* OatFile::GetBase() const {
124 CHECK(mem_map_->GetAddress() != NULL);
125 return mem_map_->GetAddress();
126}
127
128const byte* OatFile::GetLimit() const {
129 CHECK(mem_map_->GetLimit() != NULL);
130 return mem_map_->GetLimit();
131}
132
Ian Rogers7fe2c692011-12-06 16:35:59 -0800133const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_file_location,
134 bool warn_if_not_found) const {
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700135 Table::const_iterator it = oat_dex_files_.find(dex_file_location);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700136 if (it == oat_dex_files_.end()) {
Ian Rogers7fe2c692011-12-06 16:35:59 -0800137 if (warn_if_not_found) {
138 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
139 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700140 return NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700141 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700142 return it->second;
143}
144
145std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const {
146 std::vector<const OatFile::OatDexFile*> result;
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700147 for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700148 result.push_back(it->second);
149 }
150 return result;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700151}
152
153OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
154 std::string dex_file_location,
155 uint32_t dex_file_checksum,
156 uint32_t* classes_pointer)
157 : oat_file_(oat_file),
158 dex_file_location_(dex_file_location),
159 dex_file_checksum_(dex_file_checksum),
160 classes_pointer_(classes_pointer) {}
161
162OatFile::OatDexFile::~OatDexFile() {}
163
Brian Carlstromaded5f72011-10-07 17:15:04 -0700164const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700165 uint32_t methods_offset = classes_pointer_[class_def_index];
166 const byte* methods_pointer = oat_file_->GetBase() + methods_offset;
167 CHECK_LT(methods_pointer, oat_file_->GetLimit());
Brian Carlstromaded5f72011-10-07 17:15:04 -0700168 return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700169}
170
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700171OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer)
Brian Carlstrome24fa612011-09-29 00:53:55 -0700172 : oat_file_(oat_file), methods_pointer_(methods_pointer) {}
173
174OatFile::OatClass::~OatClass() {}
175
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700176const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
177 const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index];
178 return OatMethod(
Brian Carlstromae826982011-11-09 01:33:42 -0800179 oat_file_->GetBase(),
180 oat_method_offsets.code_offset_,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700181 oat_method_offsets.frame_size_in_bytes_,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700182 oat_method_offsets.core_spill_mask_,
183 oat_method_offsets.fp_spill_mask_,
Brian Carlstromae826982011-11-09 01:33:42 -0800184 oat_method_offsets.mapping_table_offset_,
185 oat_method_offsets.vmap_table_offset_,
186 oat_method_offsets.invoke_stub_offset_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700187}
188
Brian Carlstromae826982011-11-09 01:33:42 -0800189OatFile::OatMethod::OatMethod(const byte* base,
190 const uint32_t code_offset,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700191 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700192 const uint32_t core_spill_mask,
193 const uint32_t fp_spill_mask,
Brian Carlstromae826982011-11-09 01:33:42 -0800194 const uint32_t mapping_table_offset,
195 const uint32_t vmap_table_offset,
196 const uint32_t invoke_stub_offset)
197 : base_(base),
198 code_offset_(code_offset),
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700199 frame_size_in_bytes_(frame_size_in_bytes),
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700200 core_spill_mask_(core_spill_mask),
201 fp_spill_mask_(fp_spill_mask),
Brian Carlstromae826982011-11-09 01:33:42 -0800202 mapping_table_offset_(mapping_table_offset),
203 vmap_table_offset_(vmap_table_offset),
204 invoke_stub_offset_(invoke_stub_offset) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700205
206#ifndef NDEBUG
Brian Carlstromae826982011-11-09 01:33:42 -0800207 if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
208 if (vmap_table_offset_ == 0) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700209 DCHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_)));
210 } else {
Brian Carlstromae826982011-11-09 01:33:42 -0800211 const uint16_t* vmap_table_ = reinterpret_cast<const uint16_t*>(base_ + vmap_table_offset_);
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700212 DCHECK_EQ(vmap_table_[0], static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_)));
213 }
214 } else {
Brian Carlstromae826982011-11-09 01:33:42 -0800215 DCHECK(vmap_table_offset_ == 0);
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700216 }
217#endif
218}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700219
220OatFile::OatMethod::~OatMethod() {}
221
Brian Carlstromae826982011-11-09 01:33:42 -0800222void OatFile::OatMethod::LinkMethodPointers(Method* method) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700223 CHECK(method != NULL);
Brian Carlstromae826982011-11-09 01:33:42 -0800224 method->SetCode(GetCode());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700225 method->SetFrameSizeInBytes(frame_size_in_bytes_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700226 method->SetCoreSpillMask(core_spill_mask_);
227 method->SetFpSpillMask(fp_spill_mask_);
Brian Carlstromae826982011-11-09 01:33:42 -0800228 method->SetMappingTable(GetMappingTable());
229 method->SetVmapTable(GetVmapTable());
230 method->SetInvokeStub(GetInvokeStub());
231}
232
233void OatFile::OatMethod::LinkMethodOffsets(Method* method) const {
234 CHECK(method != NULL);
235 method->SetOatCodeOffset(GetCodeOffset());
236 method->SetFrameSizeInBytes(GetFrameSizeInBytes());
237 method->SetCoreSpillMask(GetCoreSpillMask());
238 method->SetFpSpillMask(GetFpSpillMask());
239 method->SetOatMappingTableOffset(GetMappingTableOffset());
240 method->SetOatVmapTableOffset(GetVmapTableOffset());
241 method->SetOatInvokeStubOffset(GetInvokeStubOffset());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700242}
243
244} // namespace art