oat.cc revision 524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02
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 19#include <string.h> 20#include <zlib.h> 21 22#include "arch/instruction_set_features.h" 23#include "base/bit_utils.h" 24#include "base/stringprintf.h" 25 26namespace art { 27 28constexpr uint8_t OatHeader::kOatMagic[4]; 29constexpr uint8_t OatHeader::kOatVersion[4]; 30constexpr const char OatHeader::kTrueValue[]; 31constexpr const char OatHeader::kFalseValue[]; 32 33static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) { 34 size_t estimate = 0U; 35 if (variable_data != nullptr) { 36 SafeMap<std::string, std::string>::const_iterator it = variable_data->begin(); 37 SafeMap<std::string, std::string>::const_iterator end = variable_data->end(); 38 for ( ; it != end; ++it) { 39 estimate += it->first.length() + 1; 40 estimate += it->second.length() + 1; 41 } 42 } 43 return sizeof(OatHeader) + estimate; 44} 45 46OatHeader* OatHeader::Create(InstructionSet instruction_set, 47 const InstructionSetFeatures* instruction_set_features, 48 const std::vector<const DexFile*>* dex_files, 49 uint32_t image_file_location_oat_checksum, 50 uint32_t image_file_location_oat_data_begin, 51 const SafeMap<std::string, std::string>* variable_data) { 52 // Estimate size of optional data. 53 size_t needed_size = ComputeOatHeaderSize(variable_data); 54 55 // Reserve enough memory. 56 void* memory = operator new (needed_size); 57 58 // Create the OatHeader in-place. 59 return new (memory) OatHeader(instruction_set, 60 instruction_set_features, 61 dex_files, 62 image_file_location_oat_checksum, 63 image_file_location_oat_data_begin, 64 variable_data); 65} 66 67OatHeader::OatHeader(InstructionSet instruction_set, 68 const InstructionSetFeatures* instruction_set_features, 69 const std::vector<const DexFile*>* dex_files, 70 uint32_t image_file_location_oat_checksum, 71 uint32_t image_file_location_oat_data_begin, 72 const SafeMap<std::string, std::string>* variable_data) { 73 // Don't want asserts in header as they would be checked in each file that includes it. But the 74 // fields are private, so we check inside a method. 75 static_assert(sizeof(magic_) == sizeof(kOatMagic), 76 "Oat magic and magic_ have different lengths."); 77 static_assert(sizeof(version_) == sizeof(kOatVersion), 78 "Oat version and version_ have different lengths."); 79 80 memcpy(magic_, kOatMagic, sizeof(kOatMagic)); 81 memcpy(version_, kOatVersion, sizeof(kOatVersion)); 82 executable_offset_ = 0; 83 image_patch_delta_ = 0; 84 85 adler32_checksum_ = adler32(0L, Z_NULL, 0); 86 87 CHECK_NE(instruction_set, kNone); 88 instruction_set_ = instruction_set; 89 UpdateChecksum(&instruction_set_, sizeof(instruction_set_)); 90 91 instruction_set_features_bitmap_ = instruction_set_features->AsBitmap(); 92 UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_)); 93 94 dex_file_count_ = dex_files->size(); 95 UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); 96 97 image_file_location_oat_checksum_ = image_file_location_oat_checksum; 98 UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_)); 99 100 CHECK_ALIGNED(image_file_location_oat_data_begin, kPageSize); 101 image_file_location_oat_data_begin_ = image_file_location_oat_data_begin; 102 UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_)); 103 104 // Flatten the map. Will also update variable_size_data_size_. 105 Flatten(variable_data); 106 107 // Update checksum for variable data size. 108 UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_)); 109 110 // Update for data, if existing. 111 if (key_value_store_size_ > 0U) { 112 UpdateChecksum(&key_value_store_, key_value_store_size_); 113 } 114 115 interpreter_to_interpreter_bridge_offset_ = 0; 116 interpreter_to_compiled_code_bridge_offset_ = 0; 117 jni_dlsym_lookup_offset_ = 0; 118 quick_generic_jni_trampoline_offset_ = 0; 119 quick_imt_conflict_trampoline_offset_ = 0; 120 quick_resolution_trampoline_offset_ = 0; 121 quick_to_interpreter_bridge_offset_ = 0; 122} 123 124bool OatHeader::IsValid() const { 125 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) { 126 return false; 127 } 128 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) { 129 return false; 130 } 131 if (!IsAligned<kPageSize>(executable_offset_)) { 132 return false; 133 } 134 if (!IsAligned<kPageSize>(image_patch_delta_)) { 135 return false; 136 } 137 if (!IsValidInstructionSet(instruction_set_)) { 138 return false; 139 } 140 return true; 141} 142 143std::string OatHeader::GetValidationErrorMessage() const { 144 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) { 145 static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length"); 146 return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.", 147 kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3], 148 magic_[0], magic_[1], magic_[2], magic_[3]); 149 } 150 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) { 151 static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length"); 152 return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.", 153 kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3], 154 version_[0], version_[1], version_[2], version_[3]); 155 } 156 if (!IsAligned<kPageSize>(executable_offset_)) { 157 return "Executable offset not page-aligned."; 158 } 159 if (!IsAligned<kPageSize>(image_patch_delta_)) { 160 return "Image patch delta not page-aligned."; 161 } 162 if (!IsValidInstructionSet(instruction_set_)) { 163 return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_)); 164 } 165 return ""; 166} 167 168const char* OatHeader::GetMagic() const { 169 CHECK(IsValid()); 170 return reinterpret_cast<const char*>(magic_); 171} 172 173uint32_t OatHeader::GetChecksum() const { 174 CHECK(IsValid()); 175 return adler32_checksum_; 176} 177 178void OatHeader::UpdateChecksum(const void* data, size_t length) { 179 DCHECK(IsValid()); 180 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); 181 adler32_checksum_ = adler32(adler32_checksum_, bytes, length); 182} 183 184InstructionSet OatHeader::GetInstructionSet() const { 185 CHECK(IsValid()); 186 return instruction_set_; 187} 188 189uint32_t OatHeader::GetInstructionSetFeaturesBitmap() const { 190 CHECK(IsValid()); 191 return instruction_set_features_bitmap_; 192} 193 194uint32_t OatHeader::GetExecutableOffset() const { 195 DCHECK(IsValid()); 196 DCHECK_ALIGNED(executable_offset_, kPageSize); 197 CHECK_GT(executable_offset_, sizeof(OatHeader)); 198 return executable_offset_; 199} 200 201void OatHeader::SetExecutableOffset(uint32_t executable_offset) { 202 DCHECK_ALIGNED(executable_offset, kPageSize); 203 CHECK_GT(executable_offset, sizeof(OatHeader)); 204 DCHECK(IsValid()); 205 DCHECK_EQ(executable_offset_, 0U); 206 207 executable_offset_ = executable_offset; 208 UpdateChecksum(&executable_offset_, sizeof(executable_offset)); 209} 210 211const void* OatHeader::GetInterpreterToInterpreterBridge() const { 212 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset(); 213} 214 215uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const { 216 DCHECK(IsValid()); 217 CHECK(interpreter_to_interpreter_bridge_offset_ == 0 || 218 interpreter_to_interpreter_bridge_offset_ >= executable_offset_); 219 return interpreter_to_interpreter_bridge_offset_; 220} 221 222void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) { 223 CHECK(offset == 0 || offset >= executable_offset_); 224 DCHECK(IsValid()); 225 DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset; 226 227 interpreter_to_interpreter_bridge_offset_ = offset; 228 UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset)); 229} 230 231const void* OatHeader::GetInterpreterToCompiledCodeBridge() const { 232 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset(); 233} 234 235uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const { 236 DCHECK(IsValid()); 237 CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_); 238 return interpreter_to_compiled_code_bridge_offset_; 239} 240 241void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) { 242 CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_); 243 DCHECK(IsValid()); 244 DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset; 245 246 interpreter_to_compiled_code_bridge_offset_ = offset; 247 UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset)); 248} 249 250const void* OatHeader::GetJniDlsymLookup() const { 251 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset(); 252} 253 254uint32_t OatHeader::GetJniDlsymLookupOffset() const { 255 DCHECK(IsValid()); 256 CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_); 257 return jni_dlsym_lookup_offset_; 258} 259 260void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) { 261 CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_); 262 DCHECK(IsValid()); 263 DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset; 264 265 jni_dlsym_lookup_offset_ = offset; 266 UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset)); 267} 268 269const void* OatHeader::GetQuickGenericJniTrampoline() const { 270 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset(); 271} 272 273uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const { 274 DCHECK(IsValid()); 275 CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_); 276 return quick_generic_jni_trampoline_offset_; 277} 278 279void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) { 280 CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_); 281 DCHECK(IsValid()); 282 DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset; 283 284 quick_generic_jni_trampoline_offset_ = offset; 285 UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset)); 286} 287 288const void* OatHeader::GetQuickImtConflictTrampoline() const { 289 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset(); 290} 291 292uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const { 293 DCHECK(IsValid()); 294 CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_); 295 return quick_imt_conflict_trampoline_offset_; 296} 297 298void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) { 299 CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_); 300 DCHECK(IsValid()); 301 DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset; 302 303 quick_imt_conflict_trampoline_offset_ = offset; 304 UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset)); 305} 306 307const void* OatHeader::GetQuickResolutionTrampoline() const { 308 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset(); 309} 310 311uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const { 312 DCHECK(IsValid()); 313 CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_); 314 return quick_resolution_trampoline_offset_; 315} 316 317void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) { 318 CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_); 319 DCHECK(IsValid()); 320 DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset; 321 322 quick_resolution_trampoline_offset_ = offset; 323 UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset)); 324} 325 326const void* OatHeader::GetQuickToInterpreterBridge() const { 327 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset(); 328} 329 330uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const { 331 DCHECK(IsValid()); 332 CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_); 333 return quick_to_interpreter_bridge_offset_; 334} 335 336void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) { 337 CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_); 338 DCHECK(IsValid()); 339 DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset; 340 341 quick_to_interpreter_bridge_offset_ = offset; 342 UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset)); 343} 344 345int32_t OatHeader::GetImagePatchDelta() const { 346 CHECK(IsValid()); 347 return image_patch_delta_; 348} 349 350void OatHeader::RelocateOat(off_t delta) { 351 CHECK(IsValid()); 352 CHECK_ALIGNED(delta, kPageSize); 353 image_patch_delta_ += delta; 354 if (image_file_location_oat_data_begin_ != 0) { 355 image_file_location_oat_data_begin_ += delta; 356 } 357} 358 359void OatHeader::SetImagePatchDelta(int32_t off) { 360 CHECK(IsValid()); 361 CHECK_ALIGNED(off, kPageSize); 362 image_patch_delta_ = off; 363} 364 365uint32_t OatHeader::GetImageFileLocationOatChecksum() const { 366 CHECK(IsValid()); 367 return image_file_location_oat_checksum_; 368} 369 370uint32_t OatHeader::GetImageFileLocationOatDataBegin() const { 371 CHECK(IsValid()); 372 return image_file_location_oat_data_begin_; 373} 374 375uint32_t OatHeader::GetKeyValueStoreSize() const { 376 CHECK(IsValid()); 377 return key_value_store_size_; 378} 379 380const uint8_t* OatHeader::GetKeyValueStore() const { 381 CHECK(IsValid()); 382 return key_value_store_; 383} 384 385// Advance start until it is either end or \0. 386static const char* ParseString(const char* start, const char* end) { 387 while (start < end && *start != 0) { 388 start++; 389 } 390 return start; 391} 392 393const char* OatHeader::GetStoreValueByKey(const char* key) const { 394 const char* ptr = reinterpret_cast<const char*>(&key_value_store_); 395 const char* end = ptr + key_value_store_size_; 396 397 while (ptr < end) { 398 // Scan for a closing zero. 399 const char* str_end = ParseString(ptr, end); 400 if (str_end < end) { 401 if (strcmp(key, ptr) == 0) { 402 // Same as key. Check if value is OK. 403 if (ParseString(str_end + 1, end) < end) { 404 return str_end + 1; 405 } 406 } else { 407 // Different from key. Advance over the value. 408 ptr = ParseString(str_end + 1, end) + 1; 409 } 410 } else { 411 break; 412 } 413 } 414 // Not found. 415 return nullptr; 416} 417 418bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key, 419 const char** value) const { 420 const char* ptr = reinterpret_cast<const char*>(&key_value_store_); 421 const char* end = ptr + key_value_store_size_; 422 ssize_t counter = static_cast<ssize_t>(index); 423 424 while (ptr < end && counter >= 0) { 425 // Scan for a closing zero. 426 const char* str_end = ParseString(ptr, end); 427 if (str_end < end) { 428 const char* maybe_key = ptr; 429 ptr = ParseString(str_end + 1, end) + 1; 430 if (ptr <= end) { 431 if (counter == 0) { 432 *key = maybe_key; 433 *value = str_end + 1; 434 return true; 435 } else { 436 counter--; 437 } 438 } else { 439 return false; 440 } 441 } else { 442 break; 443 } 444 } 445 // Not found. 446 return false; 447} 448 449size_t OatHeader::GetHeaderSize() const { 450 return sizeof(OatHeader) + key_value_store_size_; 451} 452 453bool OatHeader::IsPic() const { 454 return IsKeyEnabled(OatHeader::kPicKey); 455} 456 457bool OatHeader::IsDebuggable() const { 458 return IsKeyEnabled(OatHeader::kDebuggableKey); 459} 460 461bool OatHeader::IsKeyEnabled(const char* key) const { 462 const char* key_value = GetStoreValueByKey(key); 463 return (key_value != nullptr && strncmp(key_value, kTrueValue, sizeof(kTrueValue)) == 0); 464} 465 466void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) { 467 char* data_ptr = reinterpret_cast<char*>(&key_value_store_); 468 if (key_value_store != nullptr) { 469 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin(); 470 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end(); 471 for ( ; it != end; ++it) { 472 strcpy(data_ptr, it->first.c_str()); 473 data_ptr += it->first.length() + 1; 474 strcpy(data_ptr, it->second.c_str()); 475 data_ptr += it->second.length() + 1; 476 } 477 } 478 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_); 479} 480 481OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) { 482} 483 484OatMethodOffsets::~OatMethodOffsets() {} 485 486} // namespace art 487