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