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