blob: 55493e84a95316fbfdc4dbee4a76ee69a58f779e [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
Brian Carlstromaded5f72011-10-07 17:15:04 -0700133const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_file_location) const {
Brian Carlstrom58ae9412011-10-04 00:56:06 -0700134 Table::const_iterator it = oat_dex_files_.find(dex_file_location);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700135 if (it == oat_dex_files_.end()) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700136 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
137 return NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700138 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700139 return it->second;
140}
141
142std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const {
143 std::vector<const OatFile::OatDexFile*> result;
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700144 for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700145 result.push_back(it->second);
146 }
147 return result;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700148}
149
150OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
151 std::string dex_file_location,
152 uint32_t dex_file_checksum,
153 uint32_t* classes_pointer)
154 : oat_file_(oat_file),
155 dex_file_location_(dex_file_location),
156 dex_file_checksum_(dex_file_checksum),
157 classes_pointer_(classes_pointer) {}
158
159OatFile::OatDexFile::~OatDexFile() {}
160
Brian Carlstromaded5f72011-10-07 17:15:04 -0700161const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700162 uint32_t methods_offset = classes_pointer_[class_def_index];
163 const byte* methods_pointer = oat_file_->GetBase() + methods_offset;
164 CHECK_LT(methods_pointer, oat_file_->GetLimit());
Brian Carlstromaded5f72011-10-07 17:15:04 -0700165 return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700166}
167
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700168OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer)
Brian Carlstrome24fa612011-09-29 00:53:55 -0700169 : oat_file_(oat_file), methods_pointer_(methods_pointer) {}
170
171OatFile::OatClass::~OatClass() {}
172
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700173const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
174 const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index];
175 return OatMethod(
Brian Carlstromae826982011-11-09 01:33:42 -0800176 oat_file_->GetBase(),
177 oat_method_offsets.code_offset_,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700178 oat_method_offsets.frame_size_in_bytes_,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700179 oat_method_offsets.core_spill_mask_,
180 oat_method_offsets.fp_spill_mask_,
Brian Carlstromae826982011-11-09 01:33:42 -0800181 oat_method_offsets.mapping_table_offset_,
182 oat_method_offsets.vmap_table_offset_,
183 oat_method_offsets.invoke_stub_offset_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700184}
185
Brian Carlstromae826982011-11-09 01:33:42 -0800186OatFile::OatMethod::OatMethod(const byte* base,
187 const uint32_t code_offset,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700188 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700189 const uint32_t core_spill_mask,
190 const uint32_t fp_spill_mask,
Brian Carlstromae826982011-11-09 01:33:42 -0800191 const uint32_t mapping_table_offset,
192 const uint32_t vmap_table_offset,
193 const uint32_t invoke_stub_offset)
194 : base_(base),
195 code_offset_(code_offset),
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700196 frame_size_in_bytes_(frame_size_in_bytes),
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700197 core_spill_mask_(core_spill_mask),
198 fp_spill_mask_(fp_spill_mask),
Brian Carlstromae826982011-11-09 01:33:42 -0800199 mapping_table_offset_(mapping_table_offset),
200 vmap_table_offset_(vmap_table_offset),
201 invoke_stub_offset_(invoke_stub_offset) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700202
203#ifndef NDEBUG
Brian Carlstromae826982011-11-09 01:33:42 -0800204 if (mapping_table_offset_ != 0) { // implies non-native, non-stub code
205 if (vmap_table_offset_ == 0) {
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700206 DCHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_)));
207 } else {
Brian Carlstromae826982011-11-09 01:33:42 -0800208 const uint16_t* vmap_table_ = reinterpret_cast<const uint16_t*>(base_ + vmap_table_offset_);
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700209 DCHECK_EQ(vmap_table_[0], static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_)));
210 }
211 } else {
Brian Carlstromae826982011-11-09 01:33:42 -0800212 DCHECK(vmap_table_offset_ == 0);
Brian Carlstrom0dd7dda2011-10-25 15:47:53 -0700213 }
214#endif
215}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700216
217OatFile::OatMethod::~OatMethod() {}
218
Brian Carlstromae826982011-11-09 01:33:42 -0800219void OatFile::OatMethod::LinkMethodPointers(Method* method) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700220 CHECK(method != NULL);
Brian Carlstromae826982011-11-09 01:33:42 -0800221 method->SetCode(GetCode());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700222 method->SetFrameSizeInBytes(frame_size_in_bytes_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700223 method->SetCoreSpillMask(core_spill_mask_);
224 method->SetFpSpillMask(fp_spill_mask_);
Brian Carlstromae826982011-11-09 01:33:42 -0800225 method->SetMappingTable(GetMappingTable());
226 method->SetVmapTable(GetVmapTable());
227 method->SetInvokeStub(GetInvokeStub());
228}
229
230void OatFile::OatMethod::LinkMethodOffsets(Method* method) const {
231 CHECK(method != NULL);
232 method->SetOatCodeOffset(GetCodeOffset());
233 method->SetFrameSizeInBytes(GetFrameSizeInBytes());
234 method->SetCoreSpillMask(GetCoreSpillMask());
235 method->SetFpSpillMask(GetFpSpillMask());
236 method->SetOatMappingTableOffset(GetMappingTableOffset());
237 method->SetOatVmapTableOffset(GetVmapTableOffset());
238 method->SetOatInvokeStubOffset(GetInvokeStubOffset());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700239}
240
241} // namespace art