blob: 3dcde8e2f925488662b8b4ef44a043cc7ac2629c [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) {
14 LOG(INFO) << "dexfilenametooatfilename " << location;
15 CHECK(IsValidDexFilename(location) || IsValidZipFilename(location));
16 std::string oat_location = location.substr(0, location.size()-3);
17 oat_location += "oat";
18 return oat_location;
Brian Carlstromb7bbba42011-10-13 14:58:47 -070019}
20
Brian Carlstrome24fa612011-09-29 00:53:55 -070021OatFile* OatFile::Open(const std::string& filename,
22 const std::string& strip_location_prefix,
23 byte* requested_base) {
24 StringPiece location = filename;
25 if (!location.starts_with(strip_location_prefix)) {
26 LOG(ERROR) << filename << " does not start with " << strip_location_prefix;
27 return NULL;
28 }
29 location.remove_prefix(strip_location_prefix.size());
30
31 UniquePtr<OatFile> oat_file(new OatFile(location.ToString()));
32 bool success = oat_file->Read(filename, requested_base);
33 if (!success) {
34 return NULL;
35 }
36 return oat_file.release();
37}
38
39OatFile::OatFile(const std::string& filename) : location_(filename) {}
40
41OatFile::~OatFile() {
42 STLDeleteValues(&oat_dex_files_);
43}
44
45bool OatFile::Read(const std::string& filename, byte* requested_base) {
46 UniquePtr<File> file(OS::OpenFile(filename.c_str(), false));
47 if (file.get() == NULL) {
48 return false;
49 }
50
51 OatHeader oat_header;
52 bool success = file->ReadFully(&oat_header, sizeof(oat_header));
53 if (!success || !oat_header.IsValid()) {
54 LOG(WARNING) << "Invalid oat header " << filename;
55 return false;
56 }
57
58 UniquePtr<MemMap> map(MemMap::Map(requested_base,
59 file->Length(),
60 PROT_READ,
61 MAP_PRIVATE | ((requested_base != NULL) ? MAP_FIXED : 0),
62 file->Fd(),
63 0));
64 if (map.get() == NULL) {
65 LOG(WARNING) << "Failed to map oat file " << filename;
66 return false;
67 }
68 CHECK(requested_base == 0 || requested_base == map->GetAddress()) << map->GetAddress();
69 DCHECK_EQ(0, memcmp(&oat_header, map->GetAddress(), sizeof(OatHeader)));
70
71 off_t code_offset = oat_header.GetExecutableOffset();
72 if (code_offset < file->Length()) {
73 byte* code_address = map->GetAddress() + code_offset;
74 size_t code_length = file->Length() - code_offset;
75 if (mprotect(code_address, code_length, PROT_READ | PROT_EXEC) != 0) {
76 PLOG(ERROR) << "Failed to make oat code executable.";
77 return false;
78 }
79 } else {
80 // its possible to have no code if all the methods were abstract, native, etc
81 DCHECK_EQ(code_offset, RoundUp(file->Length(), kPageSize));
82 }
83
84 const byte* oat = map->GetAddress();
85 oat += sizeof(OatHeader);
86 CHECK_LT(oat, map->GetLimit());
87 for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
88 size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
89 oat += sizeof(dex_file_location_size);
90 CHECK_LT(oat, map->GetLimit());
91
92 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
93 oat += dex_file_location_size;
94 CHECK_LT(oat, map->GetLimit());
95
96 std::string dex_file_location(dex_file_location_data, dex_file_location_size);
97
98 uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
99 oat += sizeof(dex_file_checksum);
100 CHECK_LT(oat, map->GetLimit());
101
102 uint32_t classes_offset = *reinterpret_cast<const uint32_t*>(oat);
103 CHECK_GT(classes_offset, 0U);
104 CHECK_LT(classes_offset, static_cast<uint32_t>(file->Length()));
105 oat += sizeof(classes_offset);
106 CHECK_LT(oat, map->GetLimit());
107
108 uint32_t* classes_pointer = reinterpret_cast<uint32_t*>(map->GetAddress() + classes_offset);
109
110 oat_dex_files_[dex_file_location] = new OatDexFile(this,
111 dex_file_location,
112 dex_file_checksum,
113 classes_pointer);
114 }
115
116 mem_map_.reset(map.release());
117 return true;
118}
119
120const OatHeader& OatFile::GetOatHeader() const {
121 return *reinterpret_cast<const OatHeader*>(GetBase());
122}
123
124const byte* OatFile::GetBase() const {
125 CHECK(mem_map_->GetAddress() != NULL);
126 return mem_map_->GetAddress();
127}
128
129const byte* OatFile::GetLimit() const {
130 CHECK(mem_map_->GetLimit() != NULL);
131 return mem_map_->GetLimit();
132}
133
Brian Carlstromaded5f72011-10-07 17:15:04 -0700134const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_file_location) 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()) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700137 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
138 return NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700139 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700140 return it->second;
141}
142
143std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const {
144 std::vector<const OatFile::OatDexFile*> result;
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700145 for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700146 result.push_back(it->second);
147 }
148 return result;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700149}
150
151OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
152 std::string dex_file_location,
153 uint32_t dex_file_checksum,
154 uint32_t* classes_pointer)
155 : oat_file_(oat_file),
156 dex_file_location_(dex_file_location),
157 dex_file_checksum_(dex_file_checksum),
158 classes_pointer_(classes_pointer) {}
159
160OatFile::OatDexFile::~OatDexFile() {}
161
Brian Carlstromaded5f72011-10-07 17:15:04 -0700162const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700163 uint32_t methods_offset = classes_pointer_[class_def_index];
164 const byte* methods_pointer = oat_file_->GetBase() + methods_offset;
165 CHECK_LT(methods_pointer, oat_file_->GetLimit());
Brian Carlstromaded5f72011-10-07 17:15:04 -0700166 return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700167}
168
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700169OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer)
Brian Carlstrome24fa612011-09-29 00:53:55 -0700170 : oat_file_(oat_file), methods_pointer_(methods_pointer) {}
171
172OatFile::OatClass::~OatClass() {}
173
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700174const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
175 const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index];
176 return OatMethod(
177 GetOatPointer<const void*>(oat_method_offsets.code_offset_),
178 oat_method_offsets.frame_size_in_bytes_,
179 oat_method_offsets.return_pc_offset_in_bytes_,
180 oat_method_offsets.core_spill_mask_,
181 oat_method_offsets.fp_spill_mask_,
182 GetOatPointer<const uint32_t*>(oat_method_offsets.mapping_table_offset_),
183 GetOatPointer<const uint16_t*>(oat_method_offsets.vmap_table_offset_),
184 GetOatPointer<const Method::InvokeStub*>(oat_method_offsets.invoke_stub_offset_));
185}
186
187OatFile::OatMethod::OatMethod(const void* code,
188 const size_t frame_size_in_bytes,
189 const size_t return_pc_offset_in_bytes,
190 const uint32_t core_spill_mask,
191 const uint32_t fp_spill_mask,
192 const uint32_t* mapping_table,
193 const uint16_t* vmap_table,
194 const Method::InvokeStub* invoke_stub) :
195 code_(code),
196 frame_size_in_bytes_(frame_size_in_bytes),
197 return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
198 core_spill_mask_(core_spill_mask),
199 fp_spill_mask_(fp_spill_mask),
200 mapping_table_(mapping_table),
201 vmap_table_(vmap_table),
202 invoke_stub_(invoke_stub) {}
203
204OatFile::OatMethod::~OatMethod() {}
205
Brian Carlstromaded5f72011-10-07 17:15:04 -0700206void OatFile::OatMethod::LinkMethod(Method* method) const {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700207 CHECK(method != NULL);
208 method->SetCode(code_);
209 method->SetFrameSizeInBytes(frame_size_in_bytes_);
210 method->SetReturnPcOffsetInBytes(return_pc_offset_in_bytes_);
211 method->SetCoreSpillMask(core_spill_mask_);
212 method->SetFpSpillMask(fp_spill_mask_);
213 method->SetMappingTable(mapping_table_);
214 method->SetVmapTable(vmap_table_);
215 method->SetInvokeStub(invoke_stub_);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700216}
217
218} // namespace art