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 23 namespace art { 24 25 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; 26 const uint8_t OatHeader::kOatVersion[] = { '0', '4', '5', '\0' }; 27 28 static 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 41 OatHeader* 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 62 OatHeader::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 115 bool 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 131 const char* OatHeader::GetMagic() const { 132 CHECK(IsValid()); 133 return reinterpret_cast<const char*>(magic_); 134 } 135 136 uint32_t OatHeader::GetChecksum() const { 137 CHECK(IsValid()); 138 return adler32_checksum_; 139 } 140 141 void 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 147 InstructionSet OatHeader::GetInstructionSet() const { 148 CHECK(IsValid()); 149 return instruction_set_; 150 } 151 152 const InstructionSetFeatures& OatHeader::GetInstructionSetFeatures() const { 153 CHECK(IsValid()); 154 return instruction_set_features_; 155 } 156 157 uint32_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 164 void 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 174 const void* OatHeader::GetInterpreterToInterpreterBridge() const { 175 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset(); 176 } 177 178 uint32_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 185 void 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 194 const void* OatHeader::GetInterpreterToCompiledCodeBridge() const { 195 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset(); 196 } 197 198 uint32_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 204 void 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 213 const void* OatHeader::GetJniDlsymLookup() const { 214 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset(); 215 } 216 217 uint32_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 223 void 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 232 const void* OatHeader::GetPortableImtConflictTrampoline() const { 233 return reinterpret_cast<const uint8_t*>(this) + GetPortableImtConflictTrampolineOffset(); 234 } 235 236 uint32_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 242 void 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 251 const void* OatHeader::GetPortableResolutionTrampoline() const { 252 return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset(); 253 } 254 255 uint32_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 261 void 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 270 const void* OatHeader::GetPortableToInterpreterBridge() const { 271 return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset(); 272 } 273 274 uint32_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 280 void 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 289 const void* OatHeader::GetQuickGenericJniTrampoline() const { 290 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset(); 291 } 292 293 uint32_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 299 void 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 308 const void* OatHeader::GetQuickImtConflictTrampoline() const { 309 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset(); 310 } 311 312 uint32_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 318 void 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 327 const void* OatHeader::GetQuickResolutionTrampoline() const { 328 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset(); 329 } 330 331 uint32_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 337 void 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 346 const void* OatHeader::GetQuickToInterpreterBridge() const { 347 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset(); 348 } 349 350 uint32_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 356 void 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 365 int32_t OatHeader::GetImagePatchDelta() const { 366 CHECK(IsValid()); 367 return image_patch_delta_; 368 } 369 370 void 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 379 void OatHeader::SetImagePatchDelta(int32_t off) { 380 CHECK(IsValid()); 381 CHECK_ALIGNED(off, kPageSize); 382 image_patch_delta_ = off; 383 } 384 385 uint32_t OatHeader::GetImageFileLocationOatChecksum() const { 386 CHECK(IsValid()); 387 return image_file_location_oat_checksum_; 388 } 389 390 uint32_t OatHeader::GetImageFileLocationOatDataBegin() const { 391 CHECK(IsValid()); 392 return image_file_location_oat_data_begin_; 393 } 394 395 uint32_t OatHeader::GetKeyValueStoreSize() const { 396 CHECK(IsValid()); 397 return key_value_store_size_; 398 } 399 400 const 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. 406 static const char* ParseString(const char* start, const char* end) { 407 while (start < end && *start != 0) { 408 start++; 409 } 410 return start; 411 } 412 413 const 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 438 bool 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 469 size_t OatHeader::GetHeaderSize() const { 470 return sizeof(OatHeader) + key_value_store_size_; 471 } 472 473 bool OatHeader::IsPic() const { 474 const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey); 475 static const char kTrue[] = "true"; 476 return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0); 477 } 478 479 void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) { 480 char* data_ptr = reinterpret_cast<char*>(&key_value_store_); 481 if (key_value_store != nullptr) { 482 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin(); 483 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end(); 484 for ( ; it != end; ++it) { 485 strcpy(data_ptr, it->first.c_str()); 486 data_ptr += it->first.length() + 1; 487 strcpy(data_ptr, it->second.c_str()); 488 data_ptr += it->second.length() + 1; 489 } 490 } 491 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_); 492 } 493 494 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) { 495 } 496 497 OatMethodOffsets::~OatMethodOffsets() {} 498 499 OatQuickMethodHeader::OatQuickMethodHeader( 500 uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t gc_map_offset, 501 uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask, 502 uint32_t code_size) 503 : mapping_table_offset_(mapping_table_offset), vmap_table_offset_(vmap_table_offset), 504 gc_map_offset_(gc_map_offset), 505 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), code_size_(code_size) { 506 } 507 508 OatQuickMethodHeader::~OatQuickMethodHeader() {} 509 510 } // namespace art 511