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