oat_file.cc revision ae826983f7903bc0a6bbbe8426bf393fb2f6d747
1// 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 13std::string OatFile::DexFilenameToOatFilename(const std::string& location) { 14 CHECK(IsValidDexFilename(location) || IsValidZipFilename(location)); 15 std::string oat_location = location.substr(0, location.size()-3); 16 oat_location += "oat"; 17 return oat_location; 18} 19 20OatFile* 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 133const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_file_location) const { 134 Table::const_iterator it = oat_dex_files_.find(dex_file_location); 135 if (it == oat_dex_files_.end()) { 136 LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location; 137 return NULL; 138 } 139 return it->second; 140} 141 142std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const { 143 std::vector<const OatFile::OatDexFile*> result; 144 for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) { 145 result.push_back(it->second); 146 } 147 return result; 148} 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 161const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const { 162 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()); 165 return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); 166} 167 168OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer) 169 : oat_file_(oat_file), methods_pointer_(methods_pointer) {} 170 171OatFile::OatClass::~OatClass() {} 172 173const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { 174 const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index]; 175 return OatMethod( 176 oat_file_->GetBase(), 177 oat_method_offsets.code_offset_, 178 oat_method_offsets.frame_size_in_bytes_, 179 oat_method_offsets.core_spill_mask_, 180 oat_method_offsets.fp_spill_mask_, 181 oat_method_offsets.mapping_table_offset_, 182 oat_method_offsets.vmap_table_offset_, 183 oat_method_offsets.invoke_stub_offset_); 184} 185 186OatFile::OatMethod::OatMethod(const byte* base, 187 const uint32_t code_offset, 188 const size_t frame_size_in_bytes, 189 const uint32_t core_spill_mask, 190 const uint32_t fp_spill_mask, 191 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), 196 frame_size_in_bytes_(frame_size_in_bytes), 197 core_spill_mask_(core_spill_mask), 198 fp_spill_mask_(fp_spill_mask), 199 mapping_table_offset_(mapping_table_offset), 200 vmap_table_offset_(vmap_table_offset), 201 invoke_stub_offset_(invoke_stub_offset) { 202 203#ifndef NDEBUG 204 if (mapping_table_offset_ != 0) { // implies non-native, non-stub code 205 if (vmap_table_offset_ == 0) { 206 DCHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_))); 207 } else { 208 const uint16_t* vmap_table_ = reinterpret_cast<const uint16_t*>(base_ + vmap_table_offset_); 209 DCHECK_EQ(vmap_table_[0], static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + __builtin_popcount(fp_spill_mask_))); 210 } 211 } else { 212 DCHECK(vmap_table_offset_ == 0); 213 } 214#endif 215} 216 217OatFile::OatMethod::~OatMethod() {} 218 219void OatFile::OatMethod::LinkMethodPointers(Method* method) const { 220 CHECK(method != NULL); 221 method->SetCode(GetCode()); 222 method->SetFrameSizeInBytes(frame_size_in_bytes_); 223 method->SetCoreSpillMask(core_spill_mask_); 224 method->SetFpSpillMask(fp_spill_mask_); 225 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()); 239} 240 241} // namespace art 242