oat.cc revision 03c9785a8a6d712775cf406c4371d0227c44148f
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "oat.h" 18#include "utils.h" 19 20#include <string.h> 21#include <zlib.h> 22 23namespace art { 24 25const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; 26const uint8_t OatHeader::kOatVersion[] = { '0', '3', '9', '\0' }; 27 28static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) { 29 size_t estimate = 0U; 30 if (variable_data != nullptr) { 31 SafeMap<std::string, std::string>::const_iterator it = variable_data->begin(); 32 SafeMap<std::string, std::string>::const_iterator end = variable_data->end(); 33 for ( ; it != end; ++it) { 34 estimate += it->first.length() + 1; 35 estimate += it->second.length() + 1; 36 } 37 } 38 return sizeof(OatHeader) + estimate; 39} 40 41OatHeader* OatHeader::Create(InstructionSet instruction_set, 42 const InstructionSetFeatures& instruction_set_features, 43 const std::vector<const DexFile*>* dex_files, 44 uint32_t image_file_location_oat_checksum, 45 uint32_t image_file_location_oat_data_begin, 46 const SafeMap<std::string, std::string>* variable_data) { 47 // Estimate size of optional data. 48 size_t needed_size = ComputeOatHeaderSize(variable_data); 49 50 // Reserve enough memory. 51 void* memory = operator new (needed_size); 52 53 // Create the OatHeader in-place. 54 return new (memory) OatHeader(instruction_set, 55 instruction_set_features, 56 dex_files, 57 image_file_location_oat_checksum, 58 image_file_location_oat_data_begin, 59 variable_data); 60} 61 62OatHeader::OatHeader(InstructionSet instruction_set, 63 const InstructionSetFeatures& instruction_set_features, 64 const std::vector<const DexFile*>* dex_files, 65 uint32_t image_file_location_oat_checksum, 66 uint32_t image_file_location_oat_data_begin, 67 const SafeMap<std::string, std::string>* variable_data) { 68 memcpy(magic_, kOatMagic, sizeof(kOatMagic)); 69 memcpy(version_, kOatVersion, sizeof(kOatVersion)); 70 executable_offset_ = 0; 71 image_patch_delta_ = 0; 72 73 adler32_checksum_ = adler32(0L, Z_NULL, 0); 74 75 CHECK_NE(instruction_set, kNone); 76 instruction_set_ = instruction_set; 77 UpdateChecksum(&instruction_set_, sizeof(instruction_set_)); 78 79 instruction_set_features_ = instruction_set_features; 80 UpdateChecksum(&instruction_set_features_, sizeof(instruction_set_features_)); 81 82 dex_file_count_ = dex_files->size(); 83 UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); 84 85 image_file_location_oat_checksum_ = image_file_location_oat_checksum; 86 UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_)); 87 88 CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin)); 89 image_file_location_oat_data_begin_ = image_file_location_oat_data_begin; 90 UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_)); 91 92 // Flatten the map. Will also update variable_size_data_size_. 93 Flatten(variable_data); 94 95 // Update checksum for variable data size. 96 UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_)); 97 98 // Update for data, if existing. 99 if (key_value_store_size_ > 0U) { 100 UpdateChecksum(&key_value_store_, key_value_store_size_); 101 } 102 103 interpreter_to_interpreter_bridge_offset_ = 0; 104 interpreter_to_compiled_code_bridge_offset_ = 0; 105 jni_dlsym_lookup_offset_ = 0; 106 portable_imt_conflict_trampoline_offset_ = 0; 107 portable_resolution_trampoline_offset_ = 0; 108 portable_to_interpreter_bridge_offset_ = 0; 109 quick_generic_jni_trampoline_offset_ = 0; 110 quick_imt_conflict_trampoline_offset_ = 0; 111 quick_resolution_trampoline_offset_ = 0; 112 quick_to_interpreter_bridge_offset_ = 0; 113} 114 115bool OatHeader::IsValid() const { 116 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) { 117 return false; 118 } 119 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) { 120 return false; 121 } 122 if (!IsAligned<kPageSize>(executable_offset_)) { 123 return false; 124 } 125 if (!IsAligned<kPageSize>(image_patch_delta_)) { 126 return false; 127 } 128 return true; 129} 130 131const char* OatHeader::GetMagic() const { 132 CHECK(IsValid()); 133 return reinterpret_cast<const char*>(magic_); 134} 135 136uint32_t OatHeader::GetChecksum() const { 137 CHECK(IsValid()); 138 return adler32_checksum_; 139} 140 141void OatHeader::UpdateChecksum(const void* data, size_t length) { 142 DCHECK(IsValid()); 143 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); 144 adler32_checksum_ = adler32(adler32_checksum_, bytes, length); 145} 146 147InstructionSet OatHeader::GetInstructionSet() const { 148 CHECK(IsValid()); 149 return instruction_set_; 150} 151 152const InstructionSetFeatures& OatHeader::GetInstructionSetFeatures() const { 153 CHECK(IsValid()); 154 return instruction_set_features_; 155} 156 157uint32_t OatHeader::GetExecutableOffset() const { 158 DCHECK(IsValid()); 159 DCHECK_ALIGNED(executable_offset_, kPageSize); 160 CHECK_GT(executable_offset_, sizeof(OatHeader)); 161 return executable_offset_; 162} 163 164void OatHeader::SetExecutableOffset(uint32_t executable_offset) { 165 DCHECK_ALIGNED(executable_offset, kPageSize); 166 CHECK_GT(executable_offset, sizeof(OatHeader)); 167 DCHECK(IsValid()); 168 DCHECK_EQ(executable_offset_, 0U); 169 170 executable_offset_ = executable_offset; 171 UpdateChecksum(&executable_offset_, sizeof(executable_offset)); 172} 173 174const void* OatHeader::GetInterpreterToInterpreterBridge() const { 175 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset(); 176} 177 178uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const { 179 DCHECK(IsValid()); 180 CHECK(interpreter_to_interpreter_bridge_offset_ == 0 || 181 interpreter_to_interpreter_bridge_offset_ >= executable_offset_); 182 return interpreter_to_interpreter_bridge_offset_; 183} 184 185void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) { 186 CHECK(offset == 0 || offset >= executable_offset_); 187 DCHECK(IsValid()); 188 DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset; 189 190 interpreter_to_interpreter_bridge_offset_ = offset; 191 UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset)); 192} 193 194const void* OatHeader::GetInterpreterToCompiledCodeBridge() const { 195 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset(); 196} 197 198uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const { 199 DCHECK(IsValid()); 200 CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_); 201 return interpreter_to_compiled_code_bridge_offset_; 202} 203 204void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) { 205 CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_); 206 DCHECK(IsValid()); 207 DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset; 208 209 interpreter_to_compiled_code_bridge_offset_ = offset; 210 UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset)); 211} 212 213const void* OatHeader::GetJniDlsymLookup() const { 214 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset(); 215} 216 217uint32_t OatHeader::GetJniDlsymLookupOffset() const { 218 DCHECK(IsValid()); 219 CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_); 220 return jni_dlsym_lookup_offset_; 221} 222 223void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) { 224 CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_); 225 DCHECK(IsValid()); 226 DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset; 227 228 jni_dlsym_lookup_offset_ = offset; 229 UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset)); 230} 231 232const void* OatHeader::GetPortableImtConflictTrampoline() const { 233 return reinterpret_cast<const uint8_t*>(this) + GetPortableImtConflictTrampolineOffset(); 234} 235 236uint32_t OatHeader::GetPortableImtConflictTrampolineOffset() const { 237 DCHECK(IsValid()); 238 CHECK_GE(portable_imt_conflict_trampoline_offset_, jni_dlsym_lookup_offset_); 239 return portable_imt_conflict_trampoline_offset_; 240} 241 242void OatHeader::SetPortableImtConflictTrampolineOffset(uint32_t offset) { 243 CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_); 244 DCHECK(IsValid()); 245 DCHECK_EQ(portable_imt_conflict_trampoline_offset_, 0U) << offset; 246 247 portable_imt_conflict_trampoline_offset_ = offset; 248 UpdateChecksum(&portable_imt_conflict_trampoline_offset_, sizeof(offset)); 249} 250 251const void* OatHeader::GetPortableResolutionTrampoline() const { 252 return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset(); 253} 254 255uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const { 256 DCHECK(IsValid()); 257 CHECK_GE(portable_resolution_trampoline_offset_, portable_imt_conflict_trampoline_offset_); 258 return portable_resolution_trampoline_offset_; 259} 260 261void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) { 262 CHECK(offset == 0 || offset >= portable_imt_conflict_trampoline_offset_); 263 DCHECK(IsValid()); 264 DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset; 265 266 portable_resolution_trampoline_offset_ = offset; 267 UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset)); 268} 269 270const void* OatHeader::GetPortableToInterpreterBridge() const { 271 return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset(); 272} 273 274uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const { 275 DCHECK(IsValid()); 276 CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_); 277 return portable_to_interpreter_bridge_offset_; 278} 279 280void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) { 281 CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_); 282 DCHECK(IsValid()); 283 DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset; 284 285 portable_to_interpreter_bridge_offset_ = offset; 286 UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset)); 287} 288 289const void* OatHeader::GetQuickGenericJniTrampoline() const { 290 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset(); 291} 292 293uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const { 294 DCHECK(IsValid()); 295 CHECK_GE(quick_generic_jni_trampoline_offset_, portable_to_interpreter_bridge_offset_); 296 return quick_generic_jni_trampoline_offset_; 297} 298 299void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) { 300 CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_); 301 DCHECK(IsValid()); 302 DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset; 303 304 quick_generic_jni_trampoline_offset_ = offset; 305 UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset)); 306} 307 308const void* OatHeader::GetQuickImtConflictTrampoline() const { 309 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset(); 310} 311 312uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const { 313 DCHECK(IsValid()); 314 CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_); 315 return quick_imt_conflict_trampoline_offset_; 316} 317 318void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) { 319 CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_); 320 DCHECK(IsValid()); 321 DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset; 322 323 quick_imt_conflict_trampoline_offset_ = offset; 324 UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset)); 325} 326 327const void* OatHeader::GetQuickResolutionTrampoline() const { 328 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset(); 329} 330 331uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const { 332 DCHECK(IsValid()); 333 CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_); 334 return quick_resolution_trampoline_offset_; 335} 336 337void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) { 338 CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_); 339 DCHECK(IsValid()); 340 DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset; 341 342 quick_resolution_trampoline_offset_ = offset; 343 UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset)); 344} 345 346const void* OatHeader::GetQuickToInterpreterBridge() const { 347 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset(); 348} 349 350uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const { 351 DCHECK(IsValid()); 352 CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_); 353 return quick_to_interpreter_bridge_offset_; 354} 355 356void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) { 357 CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_); 358 DCHECK(IsValid()); 359 DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset; 360 361 quick_to_interpreter_bridge_offset_ = offset; 362 UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset)); 363} 364 365int32_t OatHeader::GetImagePatchDelta() const { 366 CHECK(IsValid()); 367 return image_patch_delta_; 368} 369 370void OatHeader::RelocateOat(off_t delta) { 371 CHECK(IsValid()); 372 CHECK_ALIGNED(delta, kPageSize); 373 image_patch_delta_ += delta; 374 if (image_file_location_oat_data_begin_ != 0) { 375 image_file_location_oat_data_begin_ += delta; 376 } 377} 378 379void OatHeader::SetImagePatchDelta(int32_t off) { 380 CHECK(IsValid()); 381 CHECK_ALIGNED(off, kPageSize); 382 image_patch_delta_ = off; 383} 384 385uint32_t OatHeader::GetImageFileLocationOatChecksum() const { 386 CHECK(IsValid()); 387 return image_file_location_oat_checksum_; 388} 389 390uint32_t OatHeader::GetImageFileLocationOatDataBegin() const { 391 CHECK(IsValid()); 392 return image_file_location_oat_data_begin_; 393} 394 395uint32_t OatHeader::GetKeyValueStoreSize() const { 396 CHECK(IsValid()); 397 return key_value_store_size_; 398} 399 400const uint8_t* OatHeader::GetKeyValueStore() const { 401 CHECK(IsValid()); 402 return key_value_store_; 403} 404 405// Advance start until it is either end or \0. 406static const char* ParseString(const char* start, const char* end) { 407 while (start < end && *start != 0) { 408 start++; 409 } 410 return start; 411} 412 413const char* OatHeader::GetStoreValueByKey(const char* key) const { 414 const char* ptr = reinterpret_cast<const char*>(&key_value_store_); 415 const char* end = ptr + key_value_store_size_; 416 417 while (ptr < end) { 418 // Scan for a closing zero. 419 const char* str_end = ParseString(ptr, end); 420 if (str_end < end) { 421 if (strcmp(key, ptr) == 0) { 422 // Same as key. Check if value is OK. 423 if (ParseString(str_end + 1, end) < end) { 424 return str_end + 1; 425 } 426 } else { 427 // Different from key. Advance over the value. 428 ptr = ParseString(str_end + 1, end) + 1; 429 } 430 } else { 431 break; 432 } 433 } 434 // Not found. 435 return nullptr; 436} 437 438bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key, 439 const char** value) const { 440 const char* ptr = reinterpret_cast<const char*>(&key_value_store_); 441 const char* end = ptr + key_value_store_size_; 442 ssize_t counter = static_cast<ssize_t>(index); 443 444 while (ptr < end && counter >= 0) { 445 // Scan for a closing zero. 446 const char* str_end = ParseString(ptr, end); 447 if (str_end < end) { 448 const char* maybe_key = ptr; 449 ptr = ParseString(str_end + 1, end) + 1; 450 if (ptr <= end) { 451 if (counter == 0) { 452 *key = maybe_key; 453 *value = str_end + 1; 454 return true; 455 } else { 456 counter--; 457 } 458 } else { 459 return false; 460 } 461 } else { 462 break; 463 } 464 } 465 // Not found. 466 return false; 467} 468 469size_t OatHeader::GetHeaderSize() const { 470 return sizeof(OatHeader) + key_value_store_size_; 471} 472 473void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) { 474 char* data_ptr = reinterpret_cast<char*>(&key_value_store_); 475 if (key_value_store != nullptr) { 476 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin(); 477 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end(); 478 for ( ; it != end; ++it) { 479 strcpy(data_ptr, it->first.c_str()); 480 data_ptr += it->first.length() + 1; 481 strcpy(data_ptr, it->second.c_str()); 482 data_ptr += it->second.length() + 1; 483 } 484 } 485 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_); 486} 487 488OatMethodOffsets::OatMethodOffsets() 489 : code_offset_(0), 490 gc_map_offset_(0) 491{} 492 493OatMethodOffsets::OatMethodOffsets(uint32_t code_offset, 494 uint32_t gc_map_offset 495 ) 496 : code_offset_(code_offset), 497 gc_map_offset_(gc_map_offset) 498{} 499 500OatMethodOffsets::~OatMethodOffsets() {} 501 502OatQuickMethodHeader::OatQuickMethodHeader() 503 : mapping_table_offset_(0), 504 vmap_table_offset_(0), 505 frame_info_(0, 0, 0), 506 code_size_(0) 507{} 508 509OatQuickMethodHeader::OatQuickMethodHeader( 510 uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t frame_size_in_bytes, 511 uint32_t core_spill_mask, uint32_t fp_spill_mask, uint32_t code_size) 512 : mapping_table_offset_(mapping_table_offset), 513 vmap_table_offset_(vmap_table_offset), 514 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), 515 code_size_(code_size) 516{} 517 518OatQuickMethodHeader::~OatQuickMethodHeader() {} 519 520} // namespace art 521