1 /* 2 * Copyright (C) 2012 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 "elf_file.h" 18 19 #include <inttypes.h> 20 #include <sys/mman.h> // For the PROT_* and MAP_* constants. 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include "android-base/stringprintf.h" 25 #include "android-base/strings.h" 26 27 #include "arch/instruction_set.h" 28 #include "base/leb128.h" 29 #include "base/stl_util.h" 30 #include "base/unix_file/fd_file.h" 31 #include "base/utils.h" 32 #include "elf/elf_utils.h" 33 #include "elf_file_impl.h" 34 35 namespace art { 36 37 using android::base::StringPrintf; 38 39 template <typename ElfTypes> 40 ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable, bool program_header_only) 41 : writable_(writable), 42 program_header_only_(program_header_only), 43 header_(nullptr), 44 base_address_(nullptr), 45 program_headers_start_(nullptr), 46 section_headers_start_(nullptr), 47 dynamic_program_header_(nullptr), 48 dynamic_section_start_(nullptr), 49 symtab_section_start_(nullptr), 50 dynsym_section_start_(nullptr), 51 strtab_section_start_(nullptr), 52 dynstr_section_start_(nullptr), 53 hash_section_start_(nullptr), 54 symtab_symbol_table_(nullptr), 55 dynsym_symbol_table_(nullptr) { 56 CHECK(file != nullptr); 57 } 58 59 template <typename ElfTypes> 60 ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file, 61 bool writable, 62 bool program_header_only, 63 bool low_4gb, 64 std::string* error_msg) { 65 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file( 66 new ElfFileImpl<ElfTypes>(file, writable, program_header_only)); 67 int prot; 68 int flags; 69 if (writable) { 70 prot = PROT_READ | PROT_WRITE; 71 flags = MAP_SHARED; 72 } else { 73 prot = PROT_READ; 74 flags = MAP_PRIVATE; 75 } 76 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) { 77 return nullptr; 78 } 79 return elf_file.release(); 80 } 81 82 template <typename ElfTypes> 83 ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file, 84 int prot, 85 int flags, 86 bool low_4gb, 87 std::string* error_msg) { 88 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file( 89 new ElfFileImpl<ElfTypes>(file, (prot & PROT_WRITE) != 0, /* program_header_only= */ false)); 90 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) { 91 return nullptr; 92 } 93 return elf_file.release(); 94 } 95 96 template <typename ElfTypes> 97 bool ElfFileImpl<ElfTypes>::Setup(File* file, 98 int prot, 99 int flags, 100 bool low_4gb, 101 std::string* error_msg) { 102 int64_t temp_file_length = file->GetLength(); 103 if (temp_file_length < 0) { 104 errno = -temp_file_length; 105 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s", 106 file->GetPath().c_str(), file->Fd(), strerror(errno)); 107 return false; 108 } 109 size_t file_length = static_cast<size_t>(temp_file_length); 110 if (file_length < sizeof(Elf_Ehdr)) { 111 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of " 112 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr), 113 file->GetPath().c_str()); 114 return false; 115 } 116 117 if (program_header_only_) { 118 // first just map ELF header to get program header size information 119 size_t elf_header_size = sizeof(Elf_Ehdr); 120 if (!SetMap(file, 121 MemMap::MapFile(elf_header_size, 122 prot, 123 flags, 124 file->Fd(), 125 0, 126 low_4gb, 127 file->GetPath().c_str(), 128 error_msg), 129 error_msg)) { 130 return false; 131 } 132 // then remap to cover program header 133 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum); 134 if (file_length < program_header_size) { 135 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program " 136 "header of %zd bytes: '%s'", file_length, 137 sizeof(Elf_Ehdr), file->GetPath().c_str()); 138 return false; 139 } 140 if (!SetMap(file, 141 MemMap::MapFile(program_header_size, 142 prot, 143 flags, 144 file->Fd(), 145 0, 146 low_4gb, 147 file->GetPath().c_str(), 148 error_msg), 149 error_msg)) { 150 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str()); 151 return false; 152 } 153 } else { 154 // otherwise map entire file 155 if (!SetMap(file, 156 MemMap::MapFile(file->GetLength(), 157 prot, 158 flags, 159 file->Fd(), 160 0, 161 low_4gb, 162 file->GetPath().c_str(), 163 error_msg), 164 error_msg)) { 165 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str()); 166 return false; 167 } 168 } 169 170 if (program_header_only_) { 171 program_headers_start_ = Begin() + GetHeader().e_phoff; 172 } else { 173 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) { 174 return false; 175 } 176 177 // Setup section headers. 178 if (!CheckAndSet(GetHeader().e_shoff, "section headers", §ion_headers_start_, error_msg)) { 179 return false; 180 } 181 182 // Find shstrtab. 183 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection(); 184 if (shstrtab_section_header == nullptr) { 185 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'", 186 file->GetPath().c_str()); 187 return false; 188 } 189 190 // Find .dynamic section info from program header 191 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC); 192 if (dynamic_program_header_ == nullptr) { 193 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", 194 file->GetPath().c_str()); 195 return false; 196 } 197 198 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section", 199 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) { 200 return false; 201 } 202 203 // Find other sections from section headers 204 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 205 Elf_Shdr* section_header = GetSectionHeader(i); 206 if (section_header == nullptr) { 207 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'", 208 i, file->GetPath().c_str()); 209 return false; 210 } 211 switch (section_header->sh_type) { 212 case SHT_SYMTAB: { 213 if (!CheckAndSet(section_header->sh_offset, "symtab", 214 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) { 215 return false; 216 } 217 break; 218 } 219 case SHT_DYNSYM: { 220 if (!CheckAndSet(section_header->sh_offset, "dynsym", 221 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) { 222 return false; 223 } 224 break; 225 } 226 case SHT_STRTAB: { 227 // TODO: base these off of sh_link from .symtab and .dynsym above 228 if ((section_header->sh_flags & SHF_ALLOC) != 0) { 229 // Check that this is named ".dynstr" and ignore otherwise. 230 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name); 231 if (strncmp(".dynstr", header_name, 8) == 0) { 232 if (!CheckAndSet(section_header->sh_offset, "dynstr", 233 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) { 234 return false; 235 } 236 } 237 } else { 238 // Check that this is named ".strtab" and ignore otherwise. 239 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name); 240 if (strncmp(".strtab", header_name, 8) == 0) { 241 if (!CheckAndSet(section_header->sh_offset, "strtab", 242 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) { 243 return false; 244 } 245 } 246 } 247 break; 248 } 249 case SHT_DYNAMIC: { 250 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) != 251 Begin() + section_header->sh_offset) { 252 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in " 253 << file->GetPath() << ": " << std::hex 254 << reinterpret_cast<void*>(dynamic_section_start_) 255 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset); 256 return false; 257 } 258 break; 259 } 260 case SHT_HASH: { 261 if (!CheckAndSet(section_header->sh_offset, "hash section", 262 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) { 263 return false; 264 } 265 break; 266 } 267 } 268 } 269 270 // Check for the existence of some sections. 271 if (!CheckSectionsExist(file, error_msg)) { 272 return false; 273 } 274 } 275 276 return true; 277 } 278 279 template <typename ElfTypes> 280 ElfFileImpl<ElfTypes>::~ElfFileImpl() { 281 delete symtab_symbol_table_; 282 delete dynsym_symbol_table_; 283 } 284 285 template <typename ElfTypes> 286 bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label, 287 uint8_t** target, std::string* error_msg) { 288 if (Begin() + offset >= End()) { 289 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label, 290 file_path_.c_str()); 291 return false; 292 } 293 *target = Begin() + offset; 294 return true; 295 } 296 297 template <typename ElfTypes> 298 bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source, 299 const uint8_t* target) const { 300 // Only works in whole-program mode, as we need to iterate over the sections. 301 // Note that we normally can't search by type, as duplicates are allowed for most section types. 302 if (program_header_only_) { 303 return true; 304 } 305 306 Elf_Shdr* source_section = nullptr; 307 Elf_Word target_index = 0; 308 bool target_found = false; 309 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 310 Elf_Shdr* section_header = GetSectionHeader(i); 311 312 if (Begin() + section_header->sh_offset == source) { 313 // Found the source. 314 source_section = section_header; 315 if (target_index) { 316 break; 317 } 318 } else if (Begin() + section_header->sh_offset == target) { 319 target_index = i; 320 target_found = true; 321 if (source_section != nullptr) { 322 break; 323 } 324 } 325 } 326 327 return target_found && source_section != nullptr && source_section->sh_link == target_index; 328 } 329 330 template <typename ElfTypes> 331 bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const { 332 if (!program_header_only_) { 333 // If in full mode, need section headers. 334 if (section_headers_start_ == nullptr) { 335 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str()); 336 return false; 337 } 338 } 339 340 // This is redundant, but defensive. 341 if (dynamic_program_header_ == nullptr) { 342 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", 343 file->GetPath().c_str()); 344 return false; 345 } 346 347 // Need a dynamic section. This is redundant, but defensive. 348 if (dynamic_section_start_ == nullptr) { 349 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'", 350 file->GetPath().c_str()); 351 return false; 352 } 353 354 // Symtab validation. These is not really a hard failure, as we are currently not using the 355 // symtab internally, but it's nice to be defensive. 356 if (symtab_section_start_ != nullptr) { 357 // When there's a symtab, there should be a strtab. 358 if (strtab_section_start_ == nullptr) { 359 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str()); 360 return false; 361 } 362 363 // The symtab should link to the strtab. 364 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_), 365 reinterpret_cast<const uint8_t*>(strtab_section_start_))) { 366 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'", 367 file->GetPath().c_str()); 368 return false; 369 } 370 } 371 372 // We always need a dynstr & dynsym. 373 if (dynstr_section_start_ == nullptr) { 374 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str()); 375 return false; 376 } 377 if (dynsym_section_start_ == nullptr) { 378 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str()); 379 return false; 380 } 381 382 // Need a hash section for dynamic symbol lookup. 383 if (hash_section_start_ == nullptr) { 384 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'", 385 file->GetPath().c_str()); 386 return false; 387 } 388 389 // And the hash section should be linking to the dynsym. 390 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_), 391 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) { 392 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'", 393 file->GetPath().c_str()); 394 return false; 395 } 396 397 // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for 398 // us). This is usually the last in an oat file, and a good indicator of whether writing was 399 // successful (or the process crashed and left garbage). 400 if (program_header_only_) { 401 // It might not be mapped, but we can compare against the file size. 402 int64_t offset = static_cast<int64_t>(GetHeader().e_shoff + 403 (GetHeader().e_shstrndx * GetHeader().e_shentsize)); 404 if (offset >= file->GetLength()) { 405 *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'", 406 file->GetPath().c_str()); 407 return false; 408 } 409 } 410 411 return true; 412 } 413 414 template <typename ElfTypes> 415 bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap&& map, std::string* error_msg) { 416 if (!map.IsValid()) { 417 // MemMap::Open should have already set an error. 418 DCHECK(!error_msg->empty()); 419 return false; 420 } 421 map_ = std::move(map); 422 CHECK(map_.IsValid()) << file->GetPath(); 423 CHECK(map_.Begin() != nullptr) << file->GetPath(); 424 425 header_ = reinterpret_cast<Elf_Ehdr*>(map_.Begin()); 426 if ((ELFMAG0 != header_->e_ident[EI_MAG0]) 427 || (ELFMAG1 != header_->e_ident[EI_MAG1]) 428 || (ELFMAG2 != header_->e_ident[EI_MAG2]) 429 || (ELFMAG3 != header_->e_ident[EI_MAG3])) { 430 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d", 431 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 432 file->GetPath().c_str(), 433 header_->e_ident[EI_MAG0], 434 header_->e_ident[EI_MAG1], 435 header_->e_ident[EI_MAG2], 436 header_->e_ident[EI_MAG3]); 437 return false; 438 } 439 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32; 440 if (elf_class != header_->e_ident[EI_CLASS]) { 441 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d", 442 elf_class, 443 file->GetPath().c_str(), 444 header_->e_ident[EI_CLASS]); 445 return false; 446 } 447 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) { 448 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d", 449 ELFDATA2LSB, 450 file->GetPath().c_str(), 451 header_->e_ident[EI_CLASS]); 452 return false; 453 } 454 if (EV_CURRENT != header_->e_ident[EI_VERSION]) { 455 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d", 456 EV_CURRENT, 457 file->GetPath().c_str(), 458 header_->e_ident[EI_CLASS]); 459 return false; 460 } 461 if (ET_DYN != header_->e_type) { 462 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d", 463 ET_DYN, 464 file->GetPath().c_str(), 465 header_->e_type); 466 return false; 467 } 468 if (EV_CURRENT != header_->e_version) { 469 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d", 470 EV_CURRENT, 471 file->GetPath().c_str(), 472 header_->e_version); 473 return false; 474 } 475 if (0 != header_->e_entry) { 476 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d", 477 0, 478 file->GetPath().c_str(), 479 static_cast<int32_t>(header_->e_entry)); 480 return false; 481 } 482 if (0 == header_->e_phoff) { 483 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s", 484 file->GetPath().c_str()); 485 return false; 486 } 487 if (0 == header_->e_shoff) { 488 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s", 489 file->GetPath().c_str()); 490 return false; 491 } 492 if (0 == header_->e_ehsize) { 493 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s", 494 file->GetPath().c_str()); 495 return false; 496 } 497 if (0 == header_->e_phentsize) { 498 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s", 499 file->GetPath().c_str()); 500 return false; 501 } 502 if (0 == header_->e_phnum) { 503 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s", 504 file->GetPath().c_str()); 505 return false; 506 } 507 if (0 == header_->e_shentsize) { 508 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s", 509 file->GetPath().c_str()); 510 return false; 511 } 512 if (0 == header_->e_shnum) { 513 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s", 514 file->GetPath().c_str()); 515 return false; 516 } 517 if (0 == header_->e_shstrndx) { 518 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s", 519 file->GetPath().c_str()); 520 return false; 521 } 522 if (header_->e_shstrndx >= header_->e_shnum) { 523 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s", 524 header_->e_shstrndx, 525 header_->e_shnum, 526 file->GetPath().c_str()); 527 return false; 528 } 529 530 if (!program_header_only_) { 531 if (header_->e_phoff >= Size()) { 532 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s", 533 static_cast<uint64_t>(header_->e_phoff), 534 Size(), 535 file->GetPath().c_str()); 536 return false; 537 } 538 if (header_->e_shoff >= Size()) { 539 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s", 540 static_cast<uint64_t>(header_->e_shoff), 541 Size(), 542 file->GetPath().c_str()); 543 return false; 544 } 545 } 546 return true; 547 } 548 549 template <typename ElfTypes> 550 typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const { 551 CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check. 552 return *header_; 553 } 554 555 template <typename ElfTypes> 556 uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const { 557 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity 558 // check. 559 return program_headers_start_; 560 } 561 562 template <typename ElfTypes> 563 uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const { 564 CHECK(!program_header_only_); // Only used in "full" mode. 565 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check. 566 return section_headers_start_; 567 } 568 569 template <typename ElfTypes> 570 typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const { 571 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check. 572 return *dynamic_program_header_; 573 } 574 575 template <typename ElfTypes> 576 typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const { 577 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check. 578 return dynamic_section_start_; 579 } 580 581 template <typename ElfTypes> 582 typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart( 583 Elf_Word section_type) const { 584 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; 585 switch (section_type) { 586 case SHT_SYMTAB: { 587 return symtab_section_start_; 588 break; 589 } 590 case SHT_DYNSYM: { 591 return dynsym_section_start_; 592 break; 593 } 594 default: { 595 LOG(FATAL) << section_type; 596 return nullptr; 597 } 598 } 599 } 600 601 template <typename ElfTypes> 602 const char* ElfFileImpl<ElfTypes>::GetStringSectionStart( 603 Elf_Word section_type) const { 604 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; 605 switch (section_type) { 606 case SHT_SYMTAB: { 607 return strtab_section_start_; 608 } 609 case SHT_DYNSYM: { 610 return dynstr_section_start_; 611 } 612 default: { 613 LOG(FATAL) << section_type; 614 return nullptr; 615 } 616 } 617 } 618 619 template <typename ElfTypes> 620 const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type, 621 Elf_Word i) const { 622 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; 623 if (i == 0) { 624 return nullptr; 625 } 626 const char* string_section_start = GetStringSectionStart(section_type); 627 if (string_section_start == nullptr) { 628 return nullptr; 629 } 630 return string_section_start + i; 631 } 632 633 // WARNING: The following methods do not check for an error condition (non-existent hash section). 634 // It is the caller's job to do this. 635 636 template <typename ElfTypes> 637 typename ElfTypes::Word* ElfFileImpl<ElfTypes>::GetHashSectionStart() const { 638 return hash_section_start_; 639 } 640 641 template <typename ElfTypes> 642 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucketNum() const { 643 return GetHashSectionStart()[0]; 644 } 645 646 template <typename ElfTypes> 647 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChainNum() const { 648 return GetHashSectionStart()[1]; 649 } 650 651 template <typename ElfTypes> 652 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucket(size_t i, bool* ok) const { 653 if (i >= GetHashBucketNum()) { 654 *ok = false; 655 return 0; 656 } 657 *ok = true; 658 // 0 is nbucket, 1 is nchain 659 return GetHashSectionStart()[2 + i]; 660 } 661 662 template <typename ElfTypes> 663 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChain(size_t i, bool* ok) const { 664 if (i >= GetHashChainNum()) { 665 *ok = false; 666 return 0; 667 } 668 *ok = true; 669 // 0 is nbucket, 1 is nchain, & chains are after buckets 670 return GetHashSectionStart()[2 + GetHashBucketNum() + i]; 671 } 672 673 template <typename ElfTypes> 674 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const { 675 return GetHeader().e_phnum; 676 } 677 678 template <typename ElfTypes> 679 typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const { 680 CHECK_LT(i, GetProgramHeaderNum()) << file_path_; // Sanity check for caller. 681 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize); 682 CHECK_LT(program_header, End()); 683 return reinterpret_cast<Elf_Phdr*>(program_header); 684 } 685 686 template <typename ElfTypes> 687 typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::FindProgamHeaderByType(Elf_Word type) const { 688 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) { 689 Elf_Phdr* program_header = GetProgramHeader(i); 690 if (program_header->p_type == type) { 691 return program_header; 692 } 693 } 694 return nullptr; 695 } 696 697 template <typename ElfTypes> 698 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const { 699 return GetHeader().e_shnum; 700 } 701 702 template <typename ElfTypes> 703 typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const { 704 // Can only access arbitrary sections when we have the whole file, not just program header. 705 // Even if we Load(), it doesn't bring in all the sections. 706 CHECK(!program_header_only_) << file_path_; 707 if (i >= GetSectionHeaderNum()) { 708 return nullptr; // Failure condition. 709 } 710 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize); 711 if (section_header >= End()) { 712 return nullptr; // Failure condition. 713 } 714 return reinterpret_cast<Elf_Shdr*>(section_header); 715 } 716 717 template <typename ElfTypes> 718 typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const { 719 // Can only access arbitrary sections when we have the whole file, not just program header. 720 // We could change this to switch on known types if they were detected during loading. 721 CHECK(!program_header_only_) << file_path_; 722 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 723 Elf_Shdr* section_header = GetSectionHeader(i); 724 if (section_header->sh_type == type) { 725 return section_header; 726 } 727 } 728 return nullptr; 729 } 730 731 // from bionic 732 static unsigned elfhash(const char *_name) { 733 const unsigned char *name = (const unsigned char *) _name; 734 unsigned h = 0, g; 735 736 while (*name) { 737 h = (h << 4) + *name++; 738 g = h & 0xf0000000; 739 h ^= g; 740 h ^= g >> 24; 741 } 742 return h; 743 } 744 745 template <typename ElfTypes> 746 typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const { 747 return GetSectionHeader(GetHeader().e_shstrndx); 748 } 749 750 template <typename ElfTypes> 751 const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress( 752 const std::string& symbol_name) const { 753 // Check that we have a hash section. 754 if (GetHashSectionStart() == nullptr) { 755 return nullptr; // Failure condition. 756 } 757 const Elf_Sym* sym = FindDynamicSymbol(symbol_name); 758 if (sym != nullptr) { 759 // TODO: we need to change this to calculate base_address_ in ::Open, 760 // otherwise it will be wrongly 0 if ::Load has not yet been called. 761 return base_address_ + sym->st_value; 762 } else { 763 return nullptr; 764 } 765 } 766 767 // WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section. 768 template <typename ElfTypes> 769 const typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindDynamicSymbol( 770 const std::string& symbol_name) const { 771 if (GetHashBucketNum() == 0) { 772 // No dynamic symbols at all. 773 return nullptr; 774 } 775 Elf_Word hash = elfhash(symbol_name.c_str()); 776 Elf_Word bucket_index = hash % GetHashBucketNum(); 777 bool ok; 778 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok); 779 if (!ok) { 780 return nullptr; 781 } 782 while (symbol_and_chain_index != 0 /* STN_UNDEF */) { 783 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index); 784 if (symbol == nullptr) { 785 return nullptr; // Failure condition. 786 } 787 const char* name = GetString(SHT_DYNSYM, symbol->st_name); 788 if (symbol_name == name) { 789 return symbol; 790 } 791 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok); 792 if (!ok) { 793 return nullptr; 794 } 795 } 796 return nullptr; 797 } 798 799 template <typename ElfTypes> 800 bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) { 801 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM)); 802 } 803 804 template <typename ElfTypes> 805 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const { 806 CHECK(IsSymbolSectionType(section_header.sh_type)) 807 << file_path_ << " " << section_header.sh_type; 808 CHECK_NE(0U, section_header.sh_entsize) << file_path_; 809 return section_header.sh_size / section_header.sh_entsize; 810 } 811 812 template <typename ElfTypes> 813 typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, Elf_Word i) const { 814 Elf_Sym* sym_start = GetSymbolSectionStart(section_type); 815 if (sym_start == nullptr) { 816 return nullptr; 817 } 818 return sym_start + i; 819 } 820 821 template <typename ElfTypes> 822 typename ElfFileImpl<ElfTypes>::SymbolTable** 823 ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) { 824 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; 825 switch (section_type) { 826 case SHT_SYMTAB: { 827 return &symtab_symbol_table_; 828 } 829 case SHT_DYNSYM: { 830 return &dynsym_symbol_table_; 831 } 832 default: { 833 LOG(FATAL) << section_type; 834 return nullptr; 835 } 836 } 837 } 838 839 template <typename ElfTypes> 840 typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName( 841 Elf_Word section_type, const std::string& symbol_name, bool build_map) { 842 CHECK(!program_header_only_) << file_path_; 843 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; 844 845 SymbolTable** symbol_table = GetSymbolTable(section_type); 846 if (*symbol_table != nullptr || build_map) { 847 if (*symbol_table == nullptr) { 848 DCHECK(build_map); 849 *symbol_table = new SymbolTable; 850 Elf_Shdr* symbol_section = FindSectionByType(section_type); 851 if (symbol_section == nullptr) { 852 return nullptr; // Failure condition. 853 } 854 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link); 855 if (string_section == nullptr) { 856 return nullptr; // Failure condition. 857 } 858 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { 859 Elf_Sym* symbol = GetSymbol(section_type, i); 860 if (symbol == nullptr) { 861 return nullptr; // Failure condition. 862 } 863 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) 864 ? ELF64_ST_TYPE(symbol->st_info) 865 : ELF32_ST_TYPE(symbol->st_info); 866 if (type == STT_NOTYPE) { 867 continue; 868 } 869 const char* name = GetString(*string_section, symbol->st_name); 870 if (name == nullptr) { 871 continue; 872 } 873 std::pair<typename SymbolTable::iterator, bool> result = 874 (*symbol_table)->insert(std::make_pair(name, symbol)); 875 if (!result.second) { 876 // If a duplicate, make sure it has the same logical value. Seen on x86. 877 if ((symbol->st_value != result.first->second->st_value) || 878 (symbol->st_size != result.first->second->st_size) || 879 (symbol->st_info != result.first->second->st_info) || 880 (symbol->st_other != result.first->second->st_other) || 881 (symbol->st_shndx != result.first->second->st_shndx)) { 882 return nullptr; // Failure condition. 883 } 884 } 885 } 886 } 887 CHECK(*symbol_table != nullptr); 888 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name); 889 if (it == (*symbol_table)->end()) { 890 return nullptr; 891 } 892 return it->second; 893 } 894 895 // Fall back to linear search 896 Elf_Shdr* symbol_section = FindSectionByType(section_type); 897 if (symbol_section == nullptr) { 898 return nullptr; 899 } 900 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link); 901 if (string_section == nullptr) { 902 return nullptr; 903 } 904 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { 905 Elf_Sym* symbol = GetSymbol(section_type, i); 906 if (symbol == nullptr) { 907 return nullptr; // Failure condition. 908 } 909 const char* name = GetString(*string_section, symbol->st_name); 910 if (name == nullptr) { 911 continue; 912 } 913 if (symbol_name == name) { 914 return symbol; 915 } 916 } 917 return nullptr; 918 } 919 920 template <typename ElfTypes> 921 typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress( 922 Elf_Word section_type, const std::string& symbol_name, bool build_map) { 923 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map); 924 if (symbol == nullptr) { 925 return 0; 926 } 927 return symbol->st_value; 928 } 929 930 template <typename ElfTypes> 931 const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section, 932 Elf_Word i) const { 933 CHECK(!program_header_only_) << file_path_; 934 // TODO: remove this static_cast from enum when using -std=gnu++0x 935 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) { 936 return nullptr; // Failure condition. 937 } 938 if (i >= string_section.sh_size) { 939 return nullptr; 940 } 941 if (i == 0) { 942 return nullptr; 943 } 944 uint8_t* strings = Begin() + string_section.sh_offset; 945 uint8_t* string = strings + i; 946 if (string >= End()) { 947 return nullptr; 948 } 949 return reinterpret_cast<const char*>(string); 950 } 951 952 template <typename ElfTypes> 953 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const { 954 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn); 955 } 956 957 template <typename ElfTypes> 958 typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const { 959 CHECK_LT(i, GetDynamicNum()) << file_path_; 960 return *(GetDynamicSectionStart() + i); 961 } 962 963 template <typename ElfTypes> 964 typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::FindDynamicByType(Elf_Sword type) const { 965 for (Elf_Word i = 0; i < GetDynamicNum(); i++) { 966 Elf_Dyn* dyn = &GetDynamic(i); 967 if (dyn->d_tag == type) { 968 return dyn; 969 } 970 } 971 return nullptr; 972 } 973 974 template <typename ElfTypes> 975 typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword type) const { 976 Elf_Dyn* dyn = FindDynamicByType(type); 977 if (dyn == nullptr) { 978 return 0; 979 } else { 980 return dyn->d_un.d_val; 981 } 982 } 983 984 template <typename ElfTypes> 985 typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const { 986 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 987 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset); 988 } 989 990 template <typename ElfTypes> 991 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const { 992 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 993 CHECK_NE(0U, section_header.sh_entsize) << file_path_; 994 return section_header.sh_size / section_header.sh_entsize; 995 } 996 997 template <typename ElfTypes> 998 typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const { 999 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 1000 CHECK_LT(i, GetRelNum(section_header)) << file_path_; 1001 return *(GetRelSectionStart(section_header) + i); 1002 } 1003 1004 template <typename ElfTypes> 1005 typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const { 1006 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 1007 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset); 1008 } 1009 1010 template <typename ElfTypes> 1011 typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const { 1012 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 1013 return section_header.sh_size / section_header.sh_entsize; 1014 } 1015 1016 template <typename ElfTypes> 1017 typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const { 1018 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type; 1019 CHECK_LT(i, GetRelaNum(section_header)) << file_path_; 1020 return *(GetRelaSectionStart(section_header) + i); 1021 } 1022 1023 template <typename ElfTypes> 1024 bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const { 1025 uint8_t* vaddr_begin; 1026 return GetLoadedAddressRange(&vaddr_begin, size, error_msg); 1027 } 1028 1029 // Base on bionic phdr_table_get_load_size 1030 template <typename ElfTypes> 1031 bool ElfFileImpl<ElfTypes>::GetLoadedAddressRange(/*out*/uint8_t** vaddr_begin, 1032 /*out*/size_t* vaddr_size, 1033 /*out*/std::string* error_msg) const { 1034 Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1); 1035 Elf_Addr max_vaddr = 0u; 1036 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) { 1037 Elf_Phdr* program_header = GetProgramHeader(i); 1038 if (program_header->p_type != PT_LOAD) { 1039 continue; 1040 } 1041 Elf_Addr begin_vaddr = program_header->p_vaddr; 1042 if (begin_vaddr < min_vaddr) { 1043 min_vaddr = begin_vaddr; 1044 } 1045 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz; 1046 if (UNLIKELY(begin_vaddr > end_vaddr)) { 1047 std::ostringstream oss; 1048 oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex 1049 << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr 1050 << " in ELF file \"" << file_path_ << "\""; 1051 *error_msg = oss.str(); 1052 *vaddr_begin = nullptr; 1053 *vaddr_size = static_cast<size_t>(-1); 1054 return false; 1055 } 1056 if (end_vaddr > max_vaddr) { 1057 max_vaddr = end_vaddr; 1058 } 1059 } 1060 min_vaddr = RoundDown(min_vaddr, kPageSize); 1061 max_vaddr = RoundUp(max_vaddr, kPageSize); 1062 CHECK_LT(min_vaddr, max_vaddr) << file_path_; 1063 // Check that the range fits into the runtime address space. 1064 if (UNLIKELY(max_vaddr - 1u > std::numeric_limits<size_t>::max())) { 1065 std::ostringstream oss; 1066 oss << "Loaded range is 0x" << std::hex << min_vaddr << "-0x" << max_vaddr 1067 << " but maximum size_t is 0x" << std::numeric_limits<size_t>::max() 1068 << " for ELF file \"" << file_path_ << "\""; 1069 *error_msg = oss.str(); 1070 *vaddr_begin = nullptr; 1071 *vaddr_size = static_cast<size_t>(-1); 1072 return false; 1073 } 1074 *vaddr_begin = reinterpret_cast<uint8_t*>(min_vaddr); 1075 *vaddr_size = dchecked_integral_cast<size_t>(max_vaddr - min_vaddr); 1076 return true; 1077 } 1078 1079 static InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) { 1080 switch (e_machine) { 1081 case EM_ARM: 1082 return InstructionSet::kArm; 1083 case EM_AARCH64: 1084 return InstructionSet::kArm64; 1085 case EM_386: 1086 return InstructionSet::kX86; 1087 case EM_X86_64: 1088 return InstructionSet::kX86_64; 1089 case EM_MIPS: { 1090 if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 || 1091 (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) { 1092 return InstructionSet::kMips; 1093 } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) { 1094 return InstructionSet::kMips64; 1095 } 1096 break; 1097 } 1098 } 1099 return InstructionSet::kNone; 1100 } 1101 1102 template <typename ElfTypes> 1103 bool ElfFileImpl<ElfTypes>::Load(File* file, 1104 bool executable, 1105 bool low_4gb, 1106 /*inout*/MemMap* reservation, 1107 /*out*/std::string* error_msg) { 1108 CHECK(program_header_only_) << file->GetPath(); 1109 1110 if (executable) { 1111 InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags); 1112 if (elf_ISA != kRuntimeISA) { 1113 std::ostringstream oss; 1114 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA; 1115 *error_msg = oss.str(); 1116 return false; 1117 } 1118 } 1119 1120 bool reserved = false; 1121 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) { 1122 Elf_Phdr* program_header = GetProgramHeader(i); 1123 1124 // Record .dynamic header information for later use 1125 if (program_header->p_type == PT_DYNAMIC) { 1126 dynamic_program_header_ = program_header; 1127 continue; 1128 } 1129 1130 // Not something to load, move on. 1131 if (program_header->p_type != PT_LOAD) { 1132 continue; 1133 } 1134 1135 // Found something to load. 1136 1137 // Before load the actual segments, reserve a contiguous chunk 1138 // of required size and address for all segments, but with no 1139 // permissions. We'll then carve that up with the proper 1140 // permissions as we load the actual segments. If p_vaddr is 1141 // non-zero, the segments require the specific address specified, 1142 // which either was specified in the file because we already set 1143 // base_address_ after the first zero segment). 1144 int64_t temp_file_length = file->GetLength(); 1145 if (temp_file_length < 0) { 1146 errno = -temp_file_length; 1147 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s", 1148 file->GetPath().c_str(), file->Fd(), strerror(errno)); 1149 return false; 1150 } 1151 size_t file_length = static_cast<size_t>(temp_file_length); 1152 if (!reserved) { 1153 uint8_t* vaddr_begin; 1154 size_t vaddr_size; 1155 if (!GetLoadedAddressRange(&vaddr_begin, &vaddr_size, error_msg)) { 1156 DCHECK(!error_msg->empty()); 1157 return false; 1158 } 1159 std::string reservation_name = "ElfFile reservation for " + file->GetPath(); 1160 MemMap local_reservation = MemMap::MapAnonymous( 1161 reservation_name.c_str(), 1162 (reservation != nullptr) ? reservation->Begin() : nullptr, 1163 vaddr_size, 1164 PROT_NONE, 1165 low_4gb, 1166 /* reuse= */ false, 1167 reservation, 1168 error_msg); 1169 if (!local_reservation.IsValid()) { 1170 *error_msg = StringPrintf("Failed to allocate %s: %s", 1171 reservation_name.c_str(), 1172 error_msg->c_str()); 1173 return false; 1174 } 1175 reserved = true; 1176 1177 // Base address is the difference of actual mapped location and the vaddr_begin. 1178 base_address_ = reinterpret_cast<uint8_t*>( 1179 static_cast<uintptr_t>(local_reservation.Begin() - vaddr_begin)); 1180 // By adding the p_vaddr of a section/symbol to base_address_ we will always get the 1181 // dynamic memory address of where that object is actually mapped 1182 // 1183 // TODO: base_address_ needs to be calculated in ::Open, otherwise 1184 // FindDynamicSymbolAddress returns the wrong values until Load is called. 1185 segments_.push_back(std::move(local_reservation)); 1186 } 1187 // empty segment, nothing to map 1188 if (program_header->p_memsz == 0) { 1189 continue; 1190 } 1191 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr; 1192 int prot = 0; 1193 if (executable && ((program_header->p_flags & PF_X) != 0)) { 1194 prot |= PROT_EXEC; 1195 } 1196 if ((program_header->p_flags & PF_W) != 0) { 1197 prot |= PROT_WRITE; 1198 } 1199 if ((program_header->p_flags & PF_R) != 0) { 1200 prot |= PROT_READ; 1201 } 1202 int flags = 0; 1203 if (writable_) { 1204 prot |= PROT_WRITE; 1205 flags |= MAP_SHARED; 1206 } else { 1207 flags |= MAP_PRIVATE; 1208 } 1209 if (program_header->p_filesz > program_header->p_memsz) { 1210 *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s", 1211 static_cast<uint64_t>(program_header->p_filesz), 1212 static_cast<uint64_t>(program_header->p_memsz), 1213 file->GetPath().c_str()); 1214 return false; 1215 } 1216 if (program_header->p_filesz < program_header->p_memsz && 1217 !IsAligned<kPageSize>(program_header->p_filesz)) { 1218 *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64 1219 " < %" PRIu64 "): %s", 1220 static_cast<uint64_t>(program_header->p_filesz), 1221 static_cast<uint64_t>(program_header->p_memsz), 1222 file->GetPath().c_str()); 1223 return false; 1224 } 1225 if (file_length < (program_header->p_offset + program_header->p_filesz)) { 1226 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment " 1227 "%d of %" PRIu64 " bytes: '%s'", file_length, i, 1228 static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz), 1229 file->GetPath().c_str()); 1230 return false; 1231 } 1232 if (program_header->p_filesz != 0u) { 1233 MemMap segment = 1234 MemMap::MapFileAtAddress(p_vaddr, 1235 program_header->p_filesz, 1236 prot, 1237 flags, 1238 file->Fd(), 1239 program_header->p_offset, 1240 /* low_4gb= */ false, 1241 file->GetPath().c_str(), 1242 /* reuse= */ true, // implies MAP_FIXED 1243 /* reservation= */ nullptr, 1244 error_msg); 1245 if (!segment.IsValid()) { 1246 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s", 1247 i, file->GetPath().c_str(), error_msg->c_str()); 1248 return false; 1249 } 1250 if (segment.Begin() != p_vaddr) { 1251 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, " 1252 "instead mapped to %p", 1253 i, file->GetPath().c_str(), p_vaddr, segment.Begin()); 1254 return false; 1255 } 1256 segments_.push_back(std::move(segment)); 1257 } 1258 if (program_header->p_filesz < program_header->p_memsz) { 1259 std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s", 1260 static_cast<uint64_t>(i), file->GetPath().c_str()); 1261 MemMap segment = MemMap::MapAnonymous(name.c_str(), 1262 p_vaddr + program_header->p_filesz, 1263 program_header->p_memsz - program_header->p_filesz, 1264 prot, 1265 /* low_4gb= */ false, 1266 /* reuse= */ true, 1267 /* reservation= */ nullptr, 1268 error_msg); 1269 if (!segment.IsValid()) { 1270 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s", 1271 i, file->GetPath().c_str(), error_msg->c_str()); 1272 return false; 1273 } 1274 if (segment.Begin() != p_vaddr) { 1275 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s " 1276 "at expected address %p, instead mapped to %p", 1277 i, file->GetPath().c_str(), p_vaddr, segment.Begin()); 1278 return false; 1279 } 1280 segments_.push_back(std::move(segment)); 1281 } 1282 } 1283 1284 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash 1285 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr; 1286 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) { 1287 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s", 1288 file->GetPath().c_str()); 1289 return false; 1290 } 1291 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr); 1292 1293 for (Elf_Word i = 0; i < GetDynamicNum(); i++) { 1294 Elf_Dyn& elf_dyn = GetDynamic(i); 1295 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr; 1296 switch (elf_dyn.d_tag) { 1297 case DT_HASH: { 1298 if (!ValidPointer(d_ptr)) { 1299 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", 1300 d_ptr, file->GetPath().c_str()); 1301 return false; 1302 } 1303 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr); 1304 break; 1305 } 1306 case DT_STRTAB: { 1307 if (!ValidPointer(d_ptr)) { 1308 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", 1309 d_ptr, file->GetPath().c_str()); 1310 return false; 1311 } 1312 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr); 1313 break; 1314 } 1315 case DT_SYMTAB: { 1316 if (!ValidPointer(d_ptr)) { 1317 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s", 1318 d_ptr, file->GetPath().c_str()); 1319 return false; 1320 } 1321 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr); 1322 break; 1323 } 1324 case DT_NULL: { 1325 if (GetDynamicNum() != i+1) { 1326 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, " 1327 "expected %d as implied by size of PT_DYNAMIC segment in %s", 1328 i + 1, GetDynamicNum(), file->GetPath().c_str()); 1329 return false; 1330 } 1331 break; 1332 } 1333 } 1334 } 1335 1336 // Check for the existence of some sections. 1337 if (!CheckSectionsExist(file, error_msg)) { 1338 return false; 1339 } 1340 1341 return true; 1342 } 1343 1344 template <typename ElfTypes> 1345 bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const { 1346 for (const MemMap& segment : segments_) { 1347 if (segment.Begin() <= start && start < segment.End()) { 1348 return true; 1349 } 1350 } 1351 return false; 1352 } 1353 1354 1355 template <typename ElfTypes> 1356 typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName( 1357 const std::string& name) const { 1358 CHECK(!program_header_only_); 1359 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection(); 1360 if (shstrtab_sec == nullptr) { 1361 return nullptr; 1362 } 1363 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) { 1364 Elf_Shdr* shdr = GetSectionHeader(i); 1365 if (shdr == nullptr) { 1366 return nullptr; 1367 } 1368 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name); 1369 if (sec_name == nullptr) { 1370 continue; 1371 } 1372 if (name == sec_name) { 1373 return shdr; 1374 } 1375 } 1376 return nullptr; 1377 } 1378 1379 template <typename ElfTypes> 1380 bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) { 1381 if (base_address_delta == 0) { 1382 return true; 1383 } 1384 return ApplyOatPatchesTo(".debug_frame", base_address_delta) && 1385 ApplyOatPatchesTo(".debug_info", base_address_delta) && 1386 ApplyOatPatchesTo(".debug_line", base_address_delta); 1387 } 1388 1389 template <typename ElfTypes> 1390 bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo( 1391 const char* target_section_name, Elf_Addr delta) { 1392 auto target_section = FindSectionByName(target_section_name); 1393 if (target_section == nullptr) { 1394 return true; 1395 } 1396 std::string patches_name = target_section_name + std::string(".oat_patches"); 1397 auto patches_section = FindSectionByName(patches_name.c_str()); 1398 if (patches_section == nullptr) { 1399 LOG(ERROR) << patches_name << " section not found."; 1400 return false; 1401 } 1402 if (patches_section->sh_type != SHT_OAT_PATCH) { 1403 LOG(ERROR) << "Unexpected type of " << patches_name; 1404 return false; 1405 } 1406 ApplyOatPatches( 1407 Begin() + patches_section->sh_offset, 1408 Begin() + patches_section->sh_offset + patches_section->sh_size, 1409 delta, 1410 Begin() + target_section->sh_offset, 1411 Begin() + target_section->sh_offset + target_section->sh_size); 1412 return true; 1413 } 1414 1415 // Apply LEB128 encoded patches to given section. 1416 template <typename ElfTypes> 1417 void ElfFileImpl<ElfTypes>::ApplyOatPatches( 1418 const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta, 1419 uint8_t* to_patch, const uint8_t* to_patch_end) { 1420 using UnalignedAddress __attribute__((__aligned__(1))) = Elf_Addr; 1421 while (patches < patches_end) { 1422 to_patch += DecodeUnsignedLeb128(&patches); 1423 DCHECK_LE(patches, patches_end) << "Unexpected end of patch list."; 1424 DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section."; 1425 *reinterpret_cast<UnalignedAddress*>(to_patch) += delta; 1426 } 1427 } 1428 1429 template <typename ElfTypes> 1430 bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) { 1431 // ELF files produced by MCLinker look roughly like this 1432 // 1433 // +------------+ 1434 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first 1435 // +------------+ 1436 // | Elf_Phdr | program headers 1437 // | Elf_Phdr | 1438 // | ... | 1439 // | Elf_Phdr | 1440 // +------------+ 1441 // | section | mixture of needed and unneeded sections 1442 // +------------+ 1443 // | section | 1444 // +------------+ 1445 // | ... | 1446 // +------------+ 1447 // | section | 1448 // +------------+ 1449 // | Elf_Shdr | section headers 1450 // | Elf_Shdr | 1451 // | ... | contains offset to section start 1452 // | Elf_Shdr | 1453 // +------------+ 1454 // 1455 // To strip: 1456 // - leave the Elf_Ehdr and Elf_Phdr values in place. 1457 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep 1458 // - move the sections are keeping up to fill in gaps of sections we want to strip 1459 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr 1460 // - truncate rest of file 1461 // 1462 1463 std::vector<Elf_Shdr> section_headers; 1464 std::vector<Elf_Word> section_headers_original_indexes; 1465 section_headers.reserve(GetSectionHeaderNum()); 1466 1467 1468 Elf_Shdr* string_section = GetSectionNameStringSection(); 1469 CHECK(string_section != nullptr); 1470 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 1471 Elf_Shdr* sh = GetSectionHeader(i); 1472 CHECK(sh != nullptr); 1473 const char* name = GetString(*string_section, sh->sh_name); 1474 if (name == nullptr) { 1475 CHECK_EQ(0U, i); 1476 section_headers.push_back(*sh); 1477 section_headers_original_indexes.push_back(0); 1478 continue; 1479 } 1480 if (android::base::StartsWith(name, ".debug") 1481 || (strcmp(name, ".strtab") == 0) 1482 || (strcmp(name, ".symtab") == 0)) { 1483 continue; 1484 } 1485 section_headers.push_back(*sh); 1486 section_headers_original_indexes.push_back(i); 1487 } 1488 CHECK_NE(0U, section_headers.size()); 1489 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size()); 1490 1491 // section 0 is the null section, sections start at offset of first section 1492 CHECK(GetSectionHeader(1) != nullptr); 1493 Elf_Off offset = GetSectionHeader(1)->sh_offset; 1494 for (size_t i = 1; i < section_headers.size(); i++) { 1495 Elf_Shdr& new_sh = section_headers[i]; 1496 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]); 1497 CHECK(old_sh != nullptr); 1498 CHECK_EQ(new_sh.sh_name, old_sh->sh_name); 1499 if (old_sh->sh_addralign > 1) { 1500 offset = RoundUp(offset, old_sh->sh_addralign); 1501 } 1502 if (old_sh->sh_offset == offset) { 1503 // already in place 1504 offset += old_sh->sh_size; 1505 continue; 1506 } 1507 // shift section earlier 1508 memmove(Begin() + offset, 1509 Begin() + old_sh->sh_offset, 1510 old_sh->sh_size); 1511 new_sh.sh_offset = offset; 1512 offset += old_sh->sh_size; 1513 } 1514 1515 Elf_Off shoff = offset; 1516 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr); 1517 memcpy(Begin() + offset, §ion_headers[0], section_headers_size_in_bytes); 1518 offset += section_headers_size_in_bytes; 1519 1520 GetHeader().e_shnum = section_headers.size(); 1521 GetHeader().e_shoff = shoff; 1522 int result = ftruncate(file->Fd(), offset); 1523 if (result != 0) { 1524 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s", 1525 file->GetPath().c_str(), strerror(errno)); 1526 return false; 1527 } 1528 return true; 1529 } 1530 1531 static const bool DEBUG_FIXUP = false; 1532 1533 template <typename ElfTypes> 1534 bool ElfFileImpl<ElfTypes>::Fixup(Elf_Addr base_address) { 1535 if (!FixupDynamic(base_address)) { 1536 LOG(WARNING) << "Failed to fixup .dynamic in " << file_path_; 1537 return false; 1538 } 1539 if (!FixupSectionHeaders(base_address)) { 1540 LOG(WARNING) << "Failed to fixup section headers in " << file_path_; 1541 return false; 1542 } 1543 if (!FixupProgramHeaders(base_address)) { 1544 LOG(WARNING) << "Failed to fixup program headers in " << file_path_; 1545 return false; 1546 } 1547 if (!FixupSymbols(base_address, true)) { 1548 LOG(WARNING) << "Failed to fixup .dynsym in " << file_path_; 1549 return false; 1550 } 1551 if (!FixupSymbols(base_address, false)) { 1552 LOG(WARNING) << "Failed to fixup .symtab in " << file_path_; 1553 return false; 1554 } 1555 if (!FixupRelocations(base_address)) { 1556 LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_path_; 1557 return false; 1558 } 1559 static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision."); 1560 if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) { 1561 LOG(WARNING) << "Failed to fixup debug sections in " << file_path_; 1562 return false; 1563 } 1564 return true; 1565 } 1566 1567 template <typename ElfTypes> 1568 bool ElfFileImpl<ElfTypes>::FixupDynamic(Elf_Addr base_address) { 1569 for (Elf_Word i = 0; i < GetDynamicNum(); i++) { 1570 Elf_Dyn& elf_dyn = GetDynamic(i); 1571 Elf_Word d_tag = elf_dyn.d_tag; 1572 if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) { 1573 Elf_Addr d_ptr = elf_dyn.d_un.d_ptr; 1574 if (DEBUG_FIXUP) { 1575 LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1576 file_path_.c_str(), i, 1577 static_cast<uint64_t>(d_ptr), 1578 static_cast<uint64_t>(d_ptr + base_address)); 1579 } 1580 d_ptr += base_address; 1581 elf_dyn.d_un.d_ptr = d_ptr; 1582 } 1583 } 1584 return true; 1585 } 1586 1587 template <typename ElfTypes> 1588 bool ElfFileImpl<ElfTypes>::FixupSectionHeaders(Elf_Addr base_address) { 1589 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 1590 Elf_Shdr* sh = GetSectionHeader(i); 1591 CHECK(sh != nullptr); 1592 // 0 implies that the section will not exist in the memory of the process 1593 if (sh->sh_addr == 0) { 1594 continue; 1595 } 1596 if (DEBUG_FIXUP) { 1597 LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1598 file_path_.c_str(), i, 1599 static_cast<uint64_t>(sh->sh_addr), 1600 static_cast<uint64_t>(sh->sh_addr + base_address)); 1601 } 1602 sh->sh_addr += base_address; 1603 } 1604 return true; 1605 } 1606 1607 template <typename ElfTypes> 1608 bool ElfFileImpl<ElfTypes>::FixupProgramHeaders(Elf_Addr base_address) { 1609 // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now. 1610 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) { 1611 Elf_Phdr* ph = GetProgramHeader(i); 1612 CHECK(ph != nullptr); 1613 CHECK_EQ(ph->p_vaddr, ph->p_paddr) << file_path_ << " i=" << i; 1614 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) 1615 << file_path_ << " i=" << i; 1616 if (DEBUG_FIXUP) { 1617 LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1618 file_path_.c_str(), i, 1619 static_cast<uint64_t>(ph->p_vaddr), 1620 static_cast<uint64_t>(ph->p_vaddr + base_address)); 1621 } 1622 ph->p_vaddr += base_address; 1623 ph->p_paddr += base_address; 1624 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)))) 1625 << file_path_ << " i=" << i; 1626 } 1627 return true; 1628 } 1629 1630 template <typename ElfTypes> 1631 bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) { 1632 Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB; 1633 // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile 1634 Elf_Shdr* symbol_section = FindSectionByType(section_type); 1635 if (symbol_section == nullptr) { 1636 // file is missing optional .symtab 1637 CHECK(!dynamic) << file_path_; 1638 return true; 1639 } 1640 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { 1641 Elf_Sym* symbol = GetSymbol(section_type, i); 1642 CHECK(symbol != nullptr); 1643 if (symbol->st_value != 0) { 1644 if (DEBUG_FIXUP) { 1645 LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1646 file_path_.c_str(), i, 1647 static_cast<uint64_t>(symbol->st_value), 1648 static_cast<uint64_t>(symbol->st_value + base_address)); 1649 } 1650 symbol->st_value += base_address; 1651 } 1652 } 1653 return true; 1654 } 1655 1656 template <typename ElfTypes> 1657 bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) { 1658 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { 1659 Elf_Shdr* sh = GetSectionHeader(i); 1660 CHECK(sh != nullptr); 1661 if (sh->sh_type == SHT_REL) { 1662 for (uint32_t j = 0; j < GetRelNum(*sh); j++) { 1663 Elf_Rel& rel = GetRel(*sh, j); 1664 if (DEBUG_FIXUP) { 1665 LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1666 file_path_.c_str(), j, 1667 static_cast<uint64_t>(rel.r_offset), 1668 static_cast<uint64_t>(rel.r_offset + base_address)); 1669 } 1670 rel.r_offset += base_address; 1671 } 1672 } else if (sh->sh_type == SHT_RELA) { 1673 for (uint32_t j = 0; j < GetRelaNum(*sh); j++) { 1674 Elf_Rela& rela = GetRela(*sh, j); 1675 if (DEBUG_FIXUP) { 1676 LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64, 1677 file_path_.c_str(), j, 1678 static_cast<uint64_t>(rela.r_offset), 1679 static_cast<uint64_t>(rela.r_offset + base_address)); 1680 } 1681 rela.r_offset += base_address; 1682 } 1683 } 1684 } 1685 return true; 1686 } 1687 1688 // Explicit instantiations 1689 template class ElfFileImpl<ElfTypes32>; 1690 template class ElfFileImpl<ElfTypes64>; 1691 1692 ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) { 1693 } 1694 1695 ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) { 1696 } 1697 1698 ElfFile::~ElfFile() { 1699 // Should never have 32 and 64-bit impls. 1700 CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr); 1701 } 1702 1703 ElfFile* ElfFile::Open(File* file, 1704 bool writable, 1705 bool program_header_only, 1706 bool low_4gb, 1707 /*out*/std::string* error_msg) { 1708 if (file->GetLength() < EI_NIDENT) { 1709 *error_msg = StringPrintf("File %s is too short to be a valid ELF file", 1710 file->GetPath().c_str()); 1711 return nullptr; 1712 } 1713 MemMap map = MemMap::MapFile(EI_NIDENT, 1714 PROT_READ, 1715 MAP_PRIVATE, 1716 file->Fd(), 1717 0, 1718 low_4gb, 1719 file->GetPath().c_str(), 1720 error_msg); 1721 if (!map.IsValid() || map.Size() != EI_NIDENT) { 1722 return nullptr; 1723 } 1724 uint8_t* header = map.Begin(); 1725 if (header[EI_CLASS] == ELFCLASS64) { 1726 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, 1727 writable, 1728 program_header_only, 1729 low_4gb, 1730 error_msg); 1731 if (elf_file_impl == nullptr) { 1732 return nullptr; 1733 } 1734 return new ElfFile(elf_file_impl); 1735 } else if (header[EI_CLASS] == ELFCLASS32) { 1736 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, 1737 writable, 1738 program_header_only, 1739 low_4gb, 1740 error_msg); 1741 if (elf_file_impl == nullptr) { 1742 return nullptr; 1743 } 1744 return new ElfFile(elf_file_impl); 1745 } else { 1746 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d", 1747 ELFCLASS32, ELFCLASS64, 1748 file->GetPath().c_str(), 1749 header[EI_CLASS]); 1750 return nullptr; 1751 } 1752 } 1753 1754 ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, /*out*/std::string* error_msg) { 1755 // low_4gb support not required for this path. 1756 constexpr bool low_4gb = false; 1757 if (file->GetLength() < EI_NIDENT) { 1758 *error_msg = StringPrintf("File %s is too short to be a valid ELF file", 1759 file->GetPath().c_str()); 1760 return nullptr; 1761 } 1762 MemMap map = MemMap::MapFile(EI_NIDENT, 1763 PROT_READ, 1764 MAP_PRIVATE, 1765 file->Fd(), 1766 /* start= */ 0, 1767 low_4gb, 1768 file->GetPath().c_str(), 1769 error_msg); 1770 if (!map.IsValid() || map.Size() != EI_NIDENT) { 1771 return nullptr; 1772 } 1773 uint8_t* header = map.Begin(); 1774 if (header[EI_CLASS] == ELFCLASS64) { 1775 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, 1776 mmap_prot, 1777 mmap_flags, 1778 low_4gb, 1779 error_msg); 1780 if (elf_file_impl == nullptr) { 1781 return nullptr; 1782 } 1783 return new ElfFile(elf_file_impl); 1784 } else if (header[EI_CLASS] == ELFCLASS32) { 1785 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, 1786 mmap_prot, 1787 mmap_flags, 1788 low_4gb, 1789 error_msg); 1790 if (elf_file_impl == nullptr) { 1791 return nullptr; 1792 } 1793 return new ElfFile(elf_file_impl); 1794 } else { 1795 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d", 1796 ELFCLASS32, ELFCLASS64, 1797 file->GetPath().c_str(), 1798 header[EI_CLASS]); 1799 return nullptr; 1800 } 1801 } 1802 1803 #define DELEGATE_TO_IMPL(func, ...) \ 1804 if (elf64_.get() != nullptr) { \ 1805 return elf64_->func(__VA_ARGS__); \ 1806 } else { \ 1807 DCHECK(elf32_.get() != nullptr); \ 1808 return elf32_->func(__VA_ARGS__); \ 1809 } 1810 1811 bool ElfFile::Load(File* file, 1812 bool executable, 1813 bool low_4gb, 1814 /*inout*/MemMap* reservation, 1815 /*out*/std::string* error_msg) { 1816 DELEGATE_TO_IMPL(Load, file, executable, low_4gb, reservation, error_msg); 1817 } 1818 1819 const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const { 1820 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name); 1821 } 1822 1823 size_t ElfFile::Size() const { 1824 DELEGATE_TO_IMPL(Size); 1825 } 1826 1827 uint8_t* ElfFile::Begin() const { 1828 DELEGATE_TO_IMPL(Begin); 1829 } 1830 1831 uint8_t* ElfFile::End() const { 1832 DELEGATE_TO_IMPL(End); 1833 } 1834 1835 const std::string& ElfFile::GetFilePath() const { 1836 DELEGATE_TO_IMPL(GetFilePath); 1837 } 1838 1839 bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, 1840 uint64_t* size) const { 1841 if (elf32_.get() == nullptr) { 1842 CHECK(elf64_.get() != nullptr); 1843 1844 Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name); 1845 if (shdr == nullptr) { 1846 return false; 1847 } 1848 if (offset != nullptr) { 1849 *offset = shdr->sh_offset; 1850 } 1851 if (size != nullptr) { 1852 *size = shdr->sh_size; 1853 } 1854 return true; 1855 } else { 1856 Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name); 1857 if (shdr == nullptr) { 1858 return false; 1859 } 1860 if (offset != nullptr) { 1861 *offset = shdr->sh_offset; 1862 } 1863 if (size != nullptr) { 1864 *size = shdr->sh_size; 1865 } 1866 return true; 1867 } 1868 } 1869 1870 bool ElfFile::HasSection(const std::string& name) const { 1871 if (elf64_.get() != nullptr) { 1872 return elf64_->FindSectionByName(name) != nullptr; 1873 } else { 1874 return elf32_->FindSectionByName(name) != nullptr; 1875 } 1876 } 1877 1878 uint64_t ElfFile::FindSymbolAddress(unsigned section_type, 1879 const std::string& symbol_name, 1880 bool build_map) { 1881 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map); 1882 } 1883 1884 bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const { 1885 DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg); 1886 } 1887 1888 bool ElfFile::Strip(File* file, std::string* error_msg) { 1889 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb=*/false, error_msg)); 1890 if (elf_file.get() == nullptr) { 1891 return false; 1892 } 1893 1894 if (elf_file->elf64_.get() != nullptr) { 1895 return elf_file->elf64_->Strip(file, error_msg); 1896 } else { 1897 return elf_file->elf32_->Strip(file, error_msg); 1898 } 1899 } 1900 1901 bool ElfFile::Fixup(uint64_t base_address) { 1902 if (elf64_.get() != nullptr) { 1903 return elf64_->Fixup(static_cast<Elf64_Addr>(base_address)); 1904 } else { 1905 DCHECK(elf32_.get() != nullptr); 1906 CHECK(IsUint<32>(base_address)) << std::hex << base_address; 1907 return elf32_->Fixup(static_cast<Elf32_Addr>(base_address)); 1908 } 1909 DELEGATE_TO_IMPL(Fixup, base_address); 1910 } 1911 1912 } // namespace art 1913