elf_reader.cc
1 // Copyright 2005 Google LLC 2 // Author: chatham@google.com (Andrew Chatham) 3 // Author: satorux@google.com (Satoru Takabayashi) 4 // 5 // Code for reading in ELF files. 6 // 7 // For information on the ELF format, see 8 // http://www.x86.org/ftp/manuals/tools/elf.pdf 9 // 10 // I also liked: 11 // http://www.caldera.com/developers/gabi/1998-04-29/contents.html 12 // 13 // A note about types: When dealing with the file format, we use types 14 // like Elf32_Word, but in the public interfaces we treat all 15 // addresses as uint64. As a result, we should be able to symbolize 16 // 64-bit binaries from a 32-bit process (which we don't do, 17 // anyway). size_t should therefore be avoided, except where required 18 // by things like mmap(). 19 // 20 // Although most of this code can deal with arbitrary ELF files of 21 // either word size, the public ElfReader interface only examines 22 // files loaded into the current address space, which must all match 23 // the machine's native word size. This code cannot handle ELF files 24 // with a non-native byte ordering. 25 // 26 // TODO(chatham): It would be nice if we could accomplish this task 27 // without using malloc(), so we could use it as the process is dying. 28 29 #ifndef _GNU_SOURCE 30 #define _GNU_SOURCE // needed for pread() 31 #endif 32 33 #ifdef HAVE_CONFIG_H 34 #include <config.h> // Must come first 35 #endif 36 37 #include <fcntl.h> 38 #include <limits.h> 39 #include <string.h> 40 #include <sys/mman.h> 41 #include <sys/stat.h> 42 #include <sys/types.h> 43 #include <unistd.h> 44 45 #include <algorithm> 46 #include <map> 47 #include <string> 48 #include <string_view> 49 #include <vector> 50 // TODO(saugustine): Add support for compressed debug. 51 // Also need to add configure tests for zlib. 52 //#include "zlib.h" 53 54 #include "third_party/musl/include/elf.h" 55 #include "elf_reader.h" 56 #include "common/using_std_string.h" 57 58 // EM_AARCH64 is not defined by elf.h of GRTE v3 on x86. 59 // TODO(dougkwan): Remove this when v17 is retired. 60 #if !defined(EM_AARCH64) 61 #define EM_AARCH64 183 /* ARM AARCH64 */ 62 #endif 63 64 // Map Linux macros to their Apple equivalents. 65 #if __APPLE__ 66 #ifndef __LITTLE_ENDIAN 67 #define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ 68 #endif // __LITTLE_ENDIAN 69 #ifndef __BIG_ENDIAN 70 #define __BIG_ENDIAN __ORDER_BIG_ENDIAN__ 71 #endif // __BIG_ENDIAN 72 #ifndef __BYTE_ORDER 73 #define __BYTE_ORDER __BYTE_ORDER__ 74 #endif // __BYTE_ORDER 75 #endif // __APPLE__ 76 77 // TODO(dthomson): Can be removed once all Java code is using the Google3 78 // launcher. We need to avoid processing PLT functions as it causes memory 79 // fragmentation in malloc, which is fixed in tcmalloc - and if the Google3 80 // launcher is used the JVM will then use tcmalloc. b/13735638 81 //DEFINE_bool(elfreader_process_dynsyms, true, 82 // "Activate PLT function processing"); 83 84 using std::vector; 85 86 namespace { 87 88 // The lowest bit of an ARM symbol value is used to indicate a Thumb address. 89 const int kARMThumbBitOffset = 0; 90 91 // Converts an ARM Thumb symbol value to a true aligned address value. 92 template <typename T> 93 T AdjustARMThumbSymbolValue(const T& symbol_table_value) { 94 return symbol_table_value & ~(1 << kARMThumbBitOffset); 95 } 96 97 // Names of PLT-related sections. 98 const char kElfPLTRelSectionName[] = ".rel.plt"; // Use Rel struct. 99 const char kElfPLTRelaSectionName[] = ".rela.plt"; // Use Rela struct. 100 const char kElfPLTSectionName[] = ".plt"; 101 const char kElfDynSymSectionName[] = ".dynsym"; 102 103 const int kX86PLTCodeSize = 0x10; // Size of one x86 PLT function in bytes. 104 const int kARMPLTCodeSize = 0xc; 105 const int kAARCH64PLTCodeSize = 0x10; 106 107 const int kX86PLT0Size = 0x10; // Size of the special PLT0 entry. 108 const int kARMPLT0Size = 0x14; 109 const int kAARCH64PLT0Size = 0x20; 110 111 // Suffix for PLT functions when it needs to be explicitly identified as such. 112 const char kPLTFunctionSuffix[] = "@plt"; 113 114 // Replace callsites of this function to std::string_view::starts_with after 115 // adopting C++20. 116 bool StringViewStartsWith(std::string_view sv, std::string_view prefix) { 117 return sv.compare(0, prefix.size(), prefix) == 0; 118 } 119 120 } // namespace 121 122 namespace google_breakpad { 123 124 template <class ElfArch> class ElfReaderImpl; 125 126 // 32-bit and 64-bit ELF files are processed exactly the same, except 127 // for various field sizes. Elf32 and Elf64 encompass all of the 128 // differences between the two formats, and all format-specific code 129 // in this file is templated on one of them. 130 class Elf32 { 131 public: 132 typedef Elf32_Ehdr Ehdr; 133 typedef Elf32_Shdr Shdr; 134 typedef Elf32_Phdr Phdr; 135 typedef Elf32_Word Word; 136 typedef Elf32_Sym Sym; 137 typedef Elf32_Rel Rel; 138 typedef Elf32_Rela Rela; 139 140 // What should be in the EI_CLASS header. 141 static const int kElfClass = ELFCLASS32; 142 143 // Given a symbol pointer, return the binding type (eg STB_WEAK). 144 static char Bind(const Elf32_Sym* sym) { 145 return ELF32_ST_BIND(sym->st_info); 146 } 147 // Given a symbol pointer, return the symbol type (eg STT_FUNC). 148 static char Type(const Elf32_Sym* sym) { 149 return ELF32_ST_TYPE(sym->st_info); 150 } 151 152 // Extract the symbol index from the r_info field of a relocation. 153 static int r_sym(const Elf32_Word r_info) { 154 return ELF32_R_SYM(r_info); 155 } 156 }; 157 158 159 class Elf64 { 160 public: 161 typedef Elf64_Ehdr Ehdr; 162 typedef Elf64_Shdr Shdr; 163 typedef Elf64_Phdr Phdr; 164 typedef Elf64_Word Word; 165 typedef Elf64_Sym Sym; 166 typedef Elf64_Rel Rel; 167 typedef Elf64_Rela Rela; 168 169 // What should be in the EI_CLASS header. 170 static const int kElfClass = ELFCLASS64; 171 172 static char Bind(const Elf64_Sym* sym) { 173 return ELF64_ST_BIND(sym->st_info); 174 } 175 static char Type(const Elf64_Sym* sym) { 176 return ELF64_ST_TYPE(sym->st_info); 177 } 178 static int r_sym(const Elf64_Xword r_info) { 179 return ELF64_R_SYM(r_info); 180 } 181 }; 182 183 184 // ElfSectionReader mmaps a section of an ELF file ("section" is ELF 185 // terminology). The ElfReaderImpl object providing the section header 186 // must exist for the lifetime of this object. 187 // 188 // The motivation for mmaping individual sections of the file is that 189 // many Google executables are large enough when unstripped that we 190 // have to worry about running out of virtual address space. 191 // 192 // For compressed sections we have no choice but to allocate memory. 193 template<class ElfArch> 194 class ElfSectionReader { 195 public: 196 ElfSectionReader(const char* cname, const string& path, int fd, 197 const typename ElfArch::Shdr& section_header) 198 : contents_aligned_(NULL), 199 contents_(NULL), 200 header_(section_header) { 201 // Back up to the beginning of the page we're interested in. 202 const size_t additional = header_.sh_offset % getpagesize(); 203 const size_t offset_aligned = header_.sh_offset - additional; 204 section_size_ = header_.sh_size; 205 size_aligned_ = section_size_ + additional; 206 // If the section has been stripped or is empty, do not attempt 207 // to process its contents. 208 if (header_.sh_type == SHT_NOBITS || header_.sh_size == 0) 209 return; 210 // extra sh_type check for string table. 211 std::string_view name{cname}; 212 if ((name == ".strtab" || name == ".shstrtab") && 213 header_.sh_type != SHT_STRTAB) { 214 fprintf(stderr, 215 "Invalid sh_type for string table section: expected " 216 "SHT_STRTAB or SHT_DYNSYM, but got %d\n", 217 header_.sh_type); 218 return; 219 } 220 221 contents_aligned_ = mmap(NULL, size_aligned_, PROT_READ, MAP_SHARED, 222 fd, offset_aligned); 223 // Set where the offset really should begin. 224 contents_ = reinterpret_cast<char*>(contents_aligned_) + 225 (header_.sh_offset - offset_aligned); 226 227 // Check for and handle any compressed contents. 228 //if (StringViewStartsWith(name, ".zdebug_")) 229 // DecompressZlibContents(); 230 // TODO(saugustine): Add support for proposed elf-section flag 231 // "SHF_COMPRESS". 232 } 233 234 ~ElfSectionReader() { 235 if (contents_aligned_ != NULL) 236 munmap(contents_aligned_, size_aligned_); 237 else 238 delete[] contents_; 239 } 240 241 // Return the section header for this section. 242 typename ElfArch::Shdr const& header() const { return header_; } 243 244 // Return memory at the given offset within this section. 245 const char* GetOffset(typename ElfArch::Word bytes) const { 246 return contents_ + bytes; 247 } 248 249 const char* contents() const { return contents_; } 250 size_t section_size() const { return section_size_; } 251 252 private: 253 // page-aligned file contents 254 void* contents_aligned_; 255 // contents as usable by the client. For non-compressed sections, 256 // pointer within contents_aligned_ to where the section data 257 // begins; for compressed sections, pointer to the decompressed 258 // data. 259 char* contents_; 260 // size of contents_aligned_ 261 size_t size_aligned_; 262 // size of contents. 263 size_t section_size_; 264 const typename ElfArch::Shdr header_; 265 }; 266 267 // An iterator over symbols in a given section. It handles walking 268 // through the entries in the specified section and mapping symbol 269 // entries to their names in the appropriate string table (in 270 // another section). 271 template<class ElfArch> 272 class SymbolIterator { 273 public: 274 SymbolIterator(ElfReaderImpl<ElfArch>* reader, 275 typename ElfArch::Word section_type) 276 : symbol_section_(reader->GetSectionByType(section_type)), 277 string_section_(NULL), 278 num_symbols_in_section_(0), 279 symbol_within_section_(0) { 280 281 // If this section type doesn't exist, leave 282 // num_symbols_in_section_ as zero, so this iterator is already 283 // done(). 284 if (symbol_section_ != NULL) { 285 num_symbols_in_section_ = symbol_section_->header().sh_size / 286 symbol_section_->header().sh_entsize; 287 288 // Symbol sections have sh_link set to the section number of 289 // the string section containing the symbol names. 290 string_section_ = reader->GetSection(symbol_section_->header().sh_link); 291 } 292 } 293 294 // Return true iff we have passed all symbols in this section. 295 bool done() const { 296 return symbol_within_section_ >= num_symbols_in_section_; 297 } 298 299 // Advance to the next symbol in this section. 300 // REQUIRES: !done() 301 void Next() { ++symbol_within_section_; } 302 303 // Return a pointer to the current symbol. 304 // REQUIRES: !done() 305 const typename ElfArch::Sym* GetSymbol() const { 306 return reinterpret_cast<const typename ElfArch::Sym*>( 307 symbol_section_->GetOffset(symbol_within_section_ * 308 symbol_section_->header().sh_entsize)); 309 } 310 311 // Return the name of the current symbol, NULL if it has none. 312 // REQUIRES: !done() 313 const char* GetSymbolName() const { 314 int name_offset = GetSymbol()->st_name; 315 if (name_offset == 0) 316 return NULL; 317 return string_section_->GetOffset(name_offset); 318 } 319 320 int GetCurrentSymbolIndex() const { 321 return symbol_within_section_; 322 } 323 324 private: 325 const ElfSectionReader<ElfArch>* const symbol_section_; 326 const ElfSectionReader<ElfArch>* string_section_; 327 int num_symbols_in_section_; 328 int symbol_within_section_; 329 }; 330 331 332 // Copied from strings/strutil.h. Per chatham, 333 // this library should not depend on strings. 334 335 static inline bool MyHasSuffixString(const string& str, const string& suffix) { 336 int len = str.length(); 337 int suflen = suffix.length(); 338 return (suflen <= len) && (str.compare(len-suflen, suflen, suffix) == 0); 339 } 340 341 342 // ElfReader loads an ELF binary and can provide information about its 343 // contents. It is most useful for matching addresses to function 344 // names. It does not understand debugging formats (eg dwarf2), so it 345 // can't print line numbers. It takes a path to an elf file and a 346 // readable file descriptor for that file, which it does not assume 347 // ownership of. 348 template<class ElfArch> 349 class ElfReaderImpl { 350 public: 351 explicit ElfReaderImpl(const string& path, int fd) 352 : path_(path), 353 fd_(fd), 354 section_headers_(NULL), 355 program_headers_(NULL), 356 opd_section_(NULL), 357 base_for_text_(0), 358 plts_supported_(false), 359 plt_code_size_(0), 360 plt0_size_(0), 361 visited_relocation_entries_(false) { 362 string error; 363 is_dwp_ = MyHasSuffixString(path, ".dwp"); 364 ParseHeaders(fd, path); 365 // Currently we need some extra information for PowerPC64 binaries 366 // including a way to read the .opd section for function descriptors and a 367 // way to find the linked base for function symbols. 368 if (header_.e_machine == EM_PPC64) { 369 // "opd_section_" must always be checked for NULL before use. 370 opd_section_ = GetSectionInfoByName(".opd", &opd_info_); 371 for (unsigned int k = 0u; k < GetNumSections(); ++k) { 372 std::string_view name{GetSectionName(section_headers_[k].sh_name)}; 373 if (StringViewStartsWith(name, ".text")) { 374 base_for_text_ = 375 section_headers_[k].sh_addr - section_headers_[k].sh_offset; 376 break; 377 } 378 } 379 } 380 // Turn on PLTs. 381 if (header_.e_machine == EM_386 || header_.e_machine == EM_X86_64) { 382 plt_code_size_ = kX86PLTCodeSize; 383 plt0_size_ = kX86PLT0Size; 384 plts_supported_ = true; 385 } else if (header_.e_machine == EM_ARM) { 386 plt_code_size_ = kARMPLTCodeSize; 387 plt0_size_ = kARMPLT0Size; 388 plts_supported_ = true; 389 } else if (header_.e_machine == EM_AARCH64) { 390 plt_code_size_ = kAARCH64PLTCodeSize; 391 plt0_size_ = kAARCH64PLT0Size; 392 plts_supported_ = true; 393 } 394 } 395 396 ~ElfReaderImpl() { 397 for (unsigned int i = 0u; i < sections_.size(); ++i) 398 delete sections_[i]; 399 delete [] section_headers_; 400 delete [] program_headers_; 401 } 402 403 // Examine the headers of the file and return whether the file looks 404 // like an ELF file for this architecture. Takes an already-open 405 // file descriptor for the candidate file, reading in the prologue 406 // to see if the ELF file appears to match the current 407 // architecture. If error is non-NULL, it will be set with a reason 408 // in case of failure. 409 static bool IsArchElfFile(int fd, string* error) { 410 unsigned char header[EI_NIDENT]; 411 if (pread(fd, header, sizeof(header), 0) != sizeof(header)) { 412 if (error != NULL) *error = "Could not read header"; 413 return false; 414 } 415 416 if (memcmp(header, ELFMAG, SELFMAG) != 0) { 417 if (error != NULL) *error = "Missing ELF magic"; 418 return false; 419 } 420 421 if (header[EI_CLASS] != ElfArch::kElfClass) { 422 if (error != NULL) *error = "Different word size"; 423 return false; 424 } 425 426 int endian = 0; 427 if (header[EI_DATA] == ELFDATA2LSB) 428 endian = __LITTLE_ENDIAN; 429 else if (header[EI_DATA] == ELFDATA2MSB) 430 endian = __BIG_ENDIAN; 431 if (endian != __BYTE_ORDER) { 432 if (error != NULL) *error = "Different byte order"; 433 return false; 434 } 435 436 return true; 437 } 438 439 // Return true if we can use this symbol in Address-to-Symbol map. 440 bool CanUseSymbol(const char* name, const typename ElfArch::Sym* sym) { 441 // For now we only save FUNC and NOTYPE symbols. For now we just 442 // care about functions, but some functions written in assembler 443 // don't have a proper ELF type attached to them, so we store 444 // NOTYPE symbols as well. The remaining significant type is 445 // OBJECT (eg global variables), which represent about 25% of 446 // the symbols in a typical google3 binary. 447 if (ElfArch::Type(sym) != STT_FUNC && 448 ElfArch::Type(sym) != STT_NOTYPE) { 449 return false; 450 } 451 452 // Target specific filtering. 453 switch (header_.e_machine) { 454 case EM_AARCH64: 455 case EM_ARM: 456 // Filter out '$x' special local symbols used by tools 457 return name[0] != '$' || ElfArch::Bind(sym) != STB_LOCAL; 458 case EM_X86_64: 459 // Filter out read-only constants like .LC123. 460 return name[0] != '.' || ElfArch::Bind(sym) != STB_LOCAL; 461 default: 462 return true; 463 } 464 } 465 466 // Iterate over the symbols in a section, either SHT_DYNSYM or 467 // SHT_SYMTAB. Add all symbols to the given SymbolMap. 468 /* 469 void GetSymbolPositions(SymbolMap* symbols, 470 typename ElfArch::Word section_type, 471 uint64_t mem_offset, 472 uint64_t file_offset) { 473 // This map is used to filter out "nested" functions. 474 // See comment below. 475 AddrToSymMap addr_to_sym_map; 476 for (SymbolIterator<ElfArch> it(this, section_type); 477 !it.done(); it.Next()) { 478 const char* name = it.GetSymbolName(); 479 if (name == NULL) 480 continue; 481 const typename ElfArch::Sym* sym = it.GetSymbol(); 482 if (CanUseSymbol(name, sym)) { 483 const int sec = sym->st_shndx; 484 485 // We don't support special section indices. The most common 486 // is SHN_ABS, for absolute symbols used deep in the bowels of 487 // glibc. Also ignore any undefined symbols. 488 if (sec == SHN_UNDEF || 489 (sec >= SHN_LORESERVE && sec <= SHN_HIRESERVE)) { 490 continue; 491 } 492 493 const typename ElfArch::Shdr& hdr = section_headers_[sec]; 494 495 // Adjust for difference between where we expected to mmap 496 // this section, and where it was actually mmapped. 497 const int64_t expected_base = hdr.sh_addr - hdr.sh_offset; 498 const int64_t real_base = mem_offset - file_offset; 499 const int64_t adjust = real_base - expected_base; 500 501 uint64_t start = sym->st_value + adjust; 502 503 // Adjust function symbols for PowerPC64 by dereferencing and adjusting 504 // the function descriptor to get the function address. 505 if (header_.e_machine == EM_PPC64 && ElfArch::Type(sym) == STT_FUNC) { 506 const uint64_t opd_addr = 507 AdjustPPC64FunctionDescriptorSymbolValue(sym->st_value); 508 // Only adjust the returned value if the function address was found. 509 if (opd_addr != sym->st_value) { 510 const int64_t adjust_function_symbols = 511 real_base - base_for_text_; 512 start = opd_addr + adjust_function_symbols; 513 } 514 } 515 516 addr_to_sym_map.push_back(std::make_pair(start, sym)); 517 } 518 } 519 std::sort(addr_to_sym_map.begin(), addr_to_sym_map.end(), &AddrToSymSorter); 520 addr_to_sym_map.erase(std::unique(addr_to_sym_map.begin(), 521 addr_to_sym_map.end(), &AddrToSymEquals), 522 addr_to_sym_map.end()); 523 524 // Squeeze out any "nested functions". 525 // Nested functions are not allowed in C, but libc plays tricks. 526 // 527 // For example, here is disassembly of /lib64/tls/libc-2.3.5.so: 528 // 0x00000000000aa380 <read+0>: cmpl $0x0,0x2781b9(%rip) 529 // 0x00000000000aa387 <read+7>: jne 0xaa39b <read+27> 530 // 0x00000000000aa389 <__read_nocancel+0>: mov $0x0,%rax 531 // 0x00000000000aa390 <__read_nocancel+7>: syscall 532 // 0x00000000000aa392 <__read_nocancel+9>: cmp $0xfffffffffffff001,%rax 533 // 0x00000000000aa398 <__read_nocancel+15>: jae 0xaa3ef <read+111> 534 // 0x00000000000aa39a <__read_nocancel+17>: retq 535 // 0x00000000000aa39b <read+27>: sub $0x28,%rsp 536 // 0x00000000000aa39f <read+31>: mov %rdi,0x8(%rsp) 537 // ... 538 // Without removing __read_nocancel, symbolizer will return NULL 539 // given e.g. 0xaa39f (because the lower bound is __read_nocancel, 540 // but 0xaa39f is beyond its end. 541 if (addr_to_sym_map.empty()) { 542 return; 543 } 544 const ElfSectionReader<ElfArch>* const symbol_section = 545 this->GetSectionByType(section_type); 546 const ElfSectionReader<ElfArch>* const string_section = 547 this->GetSection(symbol_section->header().sh_link); 548 549 typename AddrToSymMap::iterator curr = addr_to_sym_map.begin(); 550 // Always insert the first symbol. 551 symbols->AddSymbol(string_section->GetOffset(curr->second->st_name), 552 curr->first, curr->second->st_size); 553 typename AddrToSymMap::iterator prev = curr++; 554 for (; curr != addr_to_sym_map.end(); ++curr) { 555 const uint64_t prev_addr = prev->first; 556 const uint64_t curr_addr = curr->first; 557 const typename ElfArch::Sym* const prev_sym = prev->second; 558 const typename ElfArch::Sym* const curr_sym = curr->second; 559 if (prev_addr + prev_sym->st_size <= curr_addr || 560 // The next condition is true if two symbols overlap like this: 561 // 562 // Previous symbol |----------------------------| 563 // Current symbol |-------------------------------| 564 // 565 // These symbols are not found in google3 codebase, but in 566 // jdk1.6.0_01_gg1/jre/lib/i386/server/libjvm.so. 567 // 568 // 0619e040 00000046 t CardTableModRefBS::write_region_work() 569 // 0619e070 00000046 t CardTableModRefBS::write_ref_array_work() 570 // 571 // We allow overlapped symbols rather than ignore these. 572 // Due to the way SymbolMap::GetSymbolAtPosition() works, 573 // lookup for any address in [curr_addr, curr_addr + its size) 574 // (e.g. 0619e071) will produce the current symbol, 575 // which is the desired outcome. 576 prev_addr + prev_sym->st_size < curr_addr + curr_sym->st_size) { 577 const char* name = string_section->GetOffset(curr_sym->st_name); 578 symbols->AddSymbol(name, curr_addr, curr_sym->st_size); 579 prev = curr; 580 } else { 581 // Current symbol is "nested" inside previous one like this: 582 // 583 // Previous symbol |----------------------------| 584 // Current symbol |---------------------| 585 // 586 // This happens within glibc, e.g. __read_nocancel is nested 587 // "inside" __read. Ignore "inner" symbol. 588 //DCHECK_LE(curr_addr + curr_sym->st_size, 589 // prev_addr + prev_sym->st_size); 590 ; 591 } 592 } 593 } 594 */ 595 596 void VisitSymbols(typename ElfArch::Word section_type, 597 ElfReader::SymbolSink* sink) { 598 VisitSymbols(section_type, sink, -1, -1, false); 599 } 600 601 void VisitSymbols(typename ElfArch::Word section_type, 602 ElfReader::SymbolSink* sink, 603 int symbol_binding, 604 int symbol_type, 605 bool get_raw_symbol_values) { 606 for (SymbolIterator<ElfArch> it(this, section_type); 607 !it.done(); it.Next()) { 608 const char* name = it.GetSymbolName(); 609 if (!name) continue; 610 const typename ElfArch::Sym* sym = it.GetSymbol(); 611 if ((symbol_binding < 0 || ElfArch::Bind(sym) == symbol_binding) && 612 (symbol_type < 0 || ElfArch::Type(sym) == symbol_type)) { 613 typename ElfArch::Sym symbol = *sym; 614 // Add a PLT symbol in addition to the main undefined symbol. 615 // Only do this for SHT_DYNSYM, because PLT symbols are dynamic. 616 int symbol_index = it.GetCurrentSymbolIndex(); 617 // TODO(dthomson): Can be removed once all Java code is using the 618 // Google3 launcher. 619 if (section_type == SHT_DYNSYM && 620 static_cast<unsigned int>(symbol_index) < symbols_plt_offsets_.size() && 621 symbols_plt_offsets_[symbol_index] != 0) { 622 string plt_name = string(name) + kPLTFunctionSuffix; 623 if (plt_function_names_[symbol_index].empty()) { 624 plt_function_names_[symbol_index] = plt_name; 625 } else if (plt_function_names_[symbol_index] != plt_name) { 626 ; 627 } 628 sink->AddSymbol(plt_function_names_[symbol_index].c_str(), 629 symbols_plt_offsets_[it.GetCurrentSymbolIndex()], 630 plt_code_size_); 631 } 632 if (!get_raw_symbol_values) 633 AdjustSymbolValue(&symbol); 634 sink->AddSymbol(name, symbol.st_value, symbol.st_size); 635 } 636 } 637 } 638 639 void VisitRelocationEntries() { 640 if (visited_relocation_entries_) { 641 return; 642 } 643 visited_relocation_entries_ = true; 644 645 if (!plts_supported_) { 646 return; 647 } 648 // First determine if PLTs exist. If not, then there is nothing to do. 649 ElfReader::SectionInfo plt_section_info; 650 const char* plt_section = 651 GetSectionInfoByName(kElfPLTSectionName, &plt_section_info); 652 if (!plt_section) { 653 return; 654 } 655 if (plt_section_info.size == 0) { 656 return; 657 } 658 659 // The PLTs could be referenced by either a Rel or Rela (Rel with Addend) 660 // section. 661 ElfReader::SectionInfo rel_section_info; 662 ElfReader::SectionInfo rela_section_info; 663 const char* rel_section = 664 GetSectionInfoByName(kElfPLTRelSectionName, &rel_section_info); 665 const char* rela_section = 666 GetSectionInfoByName(kElfPLTRelaSectionName, &rela_section_info); 667 668 const typename ElfArch::Rel* rel = 669 reinterpret_cast<const typename ElfArch::Rel*>(rel_section); 670 const typename ElfArch::Rela* rela = 671 reinterpret_cast<const typename ElfArch::Rela*>(rela_section); 672 673 if (!rel_section && !rela_section) { 674 return; 675 } 676 677 // Use either Rel or Rela section, depending on which one exists. 678 size_t section_size = rel_section ? rel_section_info.size 679 : rela_section_info.size; 680 size_t entry_size = rel_section ? sizeof(typename ElfArch::Rel) 681 : sizeof(typename ElfArch::Rela); 682 683 // Determine the number of entries in the dynamic symbol table. 684 ElfReader::SectionInfo dynsym_section_info; 685 const char* dynsym_section = 686 GetSectionInfoByName(kElfDynSymSectionName, &dynsym_section_info); 687 // The dynsym section might not exist, or it might be empty. In either case 688 // there is nothing to be done so return. 689 if (!dynsym_section || dynsym_section_info.size == 0) { 690 return; 691 } 692 size_t num_dynamic_symbols = 693 dynsym_section_info.size / dynsym_section_info.entsize; 694 symbols_plt_offsets_.resize(num_dynamic_symbols, 0); 695 696 // TODO(dthomson): Can be removed once all Java code is using the 697 // Google3 launcher. 698 // Make storage room for PLT function name strings. 699 plt_function_names_.resize(num_dynamic_symbols); 700 701 for (size_t i = 0; i < section_size / entry_size; ++i) { 702 // Determine symbol index from the |r_info| field. 703 int sym_index = ElfArch::r_sym(rel_section ? rel[i].r_info 704 : rela[i].r_info); 705 if (static_cast<unsigned int>(sym_index) >= symbols_plt_offsets_.size()) { 706 continue; 707 } 708 symbols_plt_offsets_[sym_index] = 709 plt_section_info.addr + plt0_size_ + i * plt_code_size_; 710 } 711 } 712 713 // Return an ElfSectionReader for the first section of the given 714 // type by iterating through all section headers. Returns NULL if 715 // the section type is not found. 716 const ElfSectionReader<ElfArch>* GetSectionByType( 717 typename ElfArch::Word section_type) { 718 for (unsigned int k = 0u; k < GetNumSections(); ++k) { 719 if (section_headers_[k].sh_type == section_type) { 720 return GetSection(k); 721 } 722 } 723 return NULL; 724 } 725 726 // Return the name of section "shndx". Returns NULL if the section 727 // is not found. 728 const char* GetSectionNameByIndex(int shndx) { 729 return GetSectionName(section_headers_[shndx].sh_name); 730 } 731 732 // Return a pointer to section "shndx", and store the size in 733 // "size". Returns NULL if the section is not found. 734 const char* GetSectionContentsByIndex(int shndx, size_t* size) { 735 const ElfSectionReader<ElfArch>* section = GetSection(shndx); 736 if (section != NULL) { 737 *size = section->section_size(); 738 return section->contents(); 739 } 740 return NULL; 741 } 742 743 // Return a pointer to the first section of the given name by 744 // iterating through all section headers, and store the size in 745 // "size". Returns NULL if the section name is not found. 746 const char* GetSectionContentsByName(const string& section_name, 747 size_t* size) { 748 for (unsigned int k = 0u; k < GetNumSections(); ++k) { 749 // When searching for sections in a .dwp file, the sections 750 // we're looking for will always be at the end of the section 751 // table, so reverse the direction of iteration. 752 int shndx = is_dwp_ ? GetNumSections() - k - 1 : k; 753 const char* name = GetSectionName(section_headers_[shndx].sh_name); 754 if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) { 755 const ElfSectionReader<ElfArch>* section = GetSection(shndx); 756 if (section == NULL) { 757 return NULL; 758 } else { 759 *size = section->section_size(); 760 return section->contents(); 761 } 762 } 763 } 764 return NULL; 765 } 766 767 // This is like GetSectionContentsByName() but it returns a lot of extra 768 // information about the section. 769 const char* GetSectionInfoByName(const string& section_name, 770 ElfReader::SectionInfo* info) { 771 for (unsigned int k = 0u; k < GetNumSections(); ++k) { 772 // When searching for sections in a .dwp file, the sections 773 // we're looking for will always be at the end of the section 774 // table, so reverse the direction of iteration. 775 int shndx = is_dwp_ ? GetNumSections() - k - 1 : k; 776 const char* name = GetSectionName(section_headers_[shndx].sh_name); 777 if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) { 778 const ElfSectionReader<ElfArch>* section = GetSection(shndx); 779 if (section == NULL) { 780 return NULL; 781 } else { 782 info->type = section->header().sh_type; 783 info->flags = section->header().sh_flags; 784 info->addr = section->header().sh_addr; 785 info->offset = section->header().sh_offset; 786 info->size = section->header().sh_size; 787 info->link = section->header().sh_link; 788 info->info = section->header().sh_info; 789 info->addralign = section->header().sh_addralign; 790 info->entsize = section->header().sh_entsize; 791 return section->contents(); 792 } 793 } 794 } 795 return NULL; 796 } 797 798 // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD 799 // segments are present. This is the address an ELF image was linked 800 // (by static linker) to be loaded at. Usually (but not always) 0 for 801 // shared libraries and position-independent executables. 802 uint64_t VaddrOfFirstLoadSegment() const { 803 // Relocatable objects (of type ET_REL) do not have LOAD segments. 804 if (header_.e_type == ET_REL) { 805 return 0; 806 } 807 for (int i = 0; i < GetNumProgramHeaders(); ++i) { 808 if (program_headers_[i].p_type == PT_LOAD) { 809 return program_headers_[i].p_vaddr; 810 } 811 } 812 return 0; 813 } 814 815 // According to the LSB ("ELF special sections"), sections with debug 816 // info are prefixed by ".debug". The names are not specified, but they 817 // look like ".debug_line", ".debug_info", etc. 818 bool HasDebugSections() { 819 // Debug sections are likely to be near the end, so reverse the 820 // direction of iteration. 821 for (int k = GetNumSections() - 1; k >= 0; --k) { 822 std::string_view name{GetSectionName(section_headers_[k].sh_name)}; 823 if (StringViewStartsWith(name, ".debug") || 824 StringViewStartsWith(name, ".zdebug")) { 825 return true; 826 } 827 } 828 return false; 829 } 830 831 bool IsDynamicSharedObject() const { 832 return header_.e_type == ET_DYN; 833 } 834 835 // Return the number of sections. 836 uint64_t GetNumSections() const { 837 if (HasManySections()) 838 return first_section_header_.sh_size; 839 return header_.e_shnum; 840 } 841 842 private: 843 typedef vector<pair<uint64_t, const typename ElfArch::Sym*> > AddrToSymMap; 844 845 static bool AddrToSymSorter(const typename AddrToSymMap::value_type& lhs, 846 const typename AddrToSymMap::value_type& rhs) { 847 return lhs.first < rhs.first; 848 } 849 850 static bool AddrToSymEquals(const typename AddrToSymMap::value_type& lhs, 851 const typename AddrToSymMap::value_type& rhs) { 852 return lhs.first == rhs.first; 853 } 854 855 // Does this ELF file have too many sections to fit in the program header? 856 bool HasManySections() const { 857 return header_.e_shnum == SHN_UNDEF; 858 } 859 860 // Return the number of program headers. 861 int GetNumProgramHeaders() const { 862 if (HasManySections() && header_.e_phnum == 0xffff && 863 first_section_header_.sh_info != 0) 864 return first_section_header_.sh_info; 865 return header_.e_phnum; 866 } 867 868 // Return the index of the string table. 869 int GetStringTableIndex() const { 870 if (HasManySections()) { 871 if (header_.e_shstrndx == 0xffff) 872 return first_section_header_.sh_link; 873 else if (header_.e_shstrndx >= GetNumSections()) 874 return 0; 875 } 876 return header_.e_shstrndx; 877 } 878 879 // Given an offset into the section header string table, return the 880 // section name. 881 const char* GetSectionName(typename ElfArch::Word sh_name) { 882 const ElfSectionReader<ElfArch>* shstrtab = 883 GetSection(GetStringTableIndex()); 884 if (shstrtab != NULL) { 885 return shstrtab->GetOffset(sh_name); 886 } 887 return NULL; 888 } 889 890 // Return an ElfSectionReader for the given section. The reader will 891 // be freed when this object is destroyed. 892 const ElfSectionReader<ElfArch>* GetSection(int num) { 893 const char* name; 894 // Hard-coding the name for the section-name string table prevents 895 // infinite recursion. 896 if (num == GetStringTableIndex()) 897 name = ".shstrtab"; 898 else 899 name = GetSectionNameByIndex(num); 900 ElfSectionReader<ElfArch>*& reader = sections_[num]; 901 if (reader == NULL) 902 reader = new ElfSectionReader<ElfArch>(name, path_, fd_, 903 section_headers_[num]); 904 return reader->contents() ? reader : nullptr; 905 } 906 907 // Parse out the overall header information from the file and assert 908 // that it looks sane. This contains information like the magic 909 // number and target architecture. 910 bool ParseHeaders(int fd, const string& path) { 911 // Read in the global ELF header. 912 if (pread(fd, &header_, sizeof(header_), 0) != sizeof(header_)) { 913 return false; 914 } 915 916 // Must be an executable, dynamic shared object or relocatable object 917 if (header_.e_type != ET_EXEC && 918 header_.e_type != ET_DYN && 919 header_.e_type != ET_REL) { 920 return false; 921 } 922 // Need a section header. 923 if (header_.e_shoff == 0) { 924 return false; 925 } 926 927 if (header_.e_shnum == SHN_UNDEF) { 928 // The number of sections in the program header is only a 16-bit value. In 929 // the event of overflow (greater than SHN_LORESERVE sections), e_shnum 930 // will read SHN_UNDEF and the true number of section header table entries 931 // is found in the sh_size field of the first section header. 932 // See: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html 933 if (pread(fd, &first_section_header_, sizeof(first_section_header_), 934 header_.e_shoff) != sizeof(first_section_header_)) { 935 return false; 936 } 937 } 938 939 // Dynamically allocate enough space to store the section headers 940 // and read them out of the file. 941 const int section_headers_size = 942 GetNumSections() * sizeof(*section_headers_); 943 section_headers_ = new typename ElfArch::Shdr[section_headers_size]; 944 if (pread(fd, section_headers_, section_headers_size, header_.e_shoff) != 945 section_headers_size) { 946 return false; 947 } 948 949 // Dynamically allocate enough space to store the program headers 950 // and read them out of the file. 951 //const int program_headers_size = 952 // GetNumProgramHeaders() * sizeof(*program_headers_); 953 program_headers_ = new typename ElfArch::Phdr[GetNumProgramHeaders()]; 954 955 // Presize the sections array for efficiency. 956 sections_.resize(GetNumSections(), NULL); 957 return true; 958 } 959 960 // Given the "value" of a function descriptor return the address of the 961 // function (i.e. the dereferenced value). Otherwise return "value". 962 uint64_t AdjustPPC64FunctionDescriptorSymbolValue(uint64_t value) { 963 if (opd_section_ != NULL && 964 opd_info_.addr <= value && 965 value < opd_info_.addr + opd_info_.size) { 966 uint64_t offset = value - opd_info_.addr; 967 return (*reinterpret_cast<const uint64_t*>(opd_section_ + offset)); 968 } 969 return value; 970 } 971 972 void AdjustSymbolValue(typename ElfArch::Sym* sym) { 973 switch (header_.e_machine) { 974 case EM_ARM: 975 // For ARM architecture, if the LSB of the function symbol offset is set, 976 // it indicates a Thumb function. This bit should not be taken literally. 977 // Clear it. 978 if (ElfArch::Type(sym) == STT_FUNC) 979 sym->st_value = AdjustARMThumbSymbolValue(sym->st_value); 980 break; 981 case EM_386: 982 // No adjustment needed for Intel x86 architecture. However, explicitly 983 // define this case as we use it quite often. 984 break; 985 case EM_PPC64: 986 // PowerPC64 currently has function descriptors as part of the ABI. 987 // Function symbols need to be adjusted accordingly. 988 if (ElfArch::Type(sym) == STT_FUNC) 989 sym->st_value = AdjustPPC64FunctionDescriptorSymbolValue(sym->st_value); 990 break; 991 default: 992 break; 993 } 994 } 995 996 friend class SymbolIterator<ElfArch>; 997 998 // The file we're reading. 999 const string path_; 1000 // Open file descriptor for path_. Not owned by this object. 1001 const int fd_; 1002 1003 // The global header of the ELF file. 1004 typename ElfArch::Ehdr header_; 1005 1006 // The header of the first section. This may be used to supplement the ELF 1007 // file header. 1008 typename ElfArch::Shdr first_section_header_; 1009 1010 // Array of GetNumSections() section headers, allocated when we read 1011 // in the global header. 1012 typename ElfArch::Shdr* section_headers_; 1013 1014 // Array of GetNumProgramHeaders() program headers, allocated when we read 1015 // in the global header. 1016 typename ElfArch::Phdr* program_headers_; 1017 1018 // An array of pointers to ElfSectionReaders. Sections are 1019 // mmaped as they're needed and not released until this object is 1020 // destroyed. 1021 vector<ElfSectionReader<ElfArch>*> sections_; 1022 1023 // For PowerPC64 we need to keep track of function descriptors when looking up 1024 // values for funtion symbols values. Function descriptors are kept in the 1025 // .opd section and are dereferenced to find the function address. 1026 ElfReader::SectionInfo opd_info_; 1027 const char* opd_section_; // Must be checked for NULL before use. 1028 int64_t base_for_text_; 1029 1030 // Read PLT-related sections for the current architecture. 1031 bool plts_supported_; 1032 // Code size of each PLT function for the current architecture. 1033 size_t plt_code_size_; 1034 // Size of the special first entry in the .plt section that calls the runtime 1035 // loader resolution routine, and that all other entries jump to when doing 1036 // lazy symbol binding. 1037 size_t plt0_size_; 1038 1039 // Maps a dynamic symbol index to a PLT offset. 1040 // The vector entry index is the dynamic symbol index. 1041 std::vector<uint64_t> symbols_plt_offsets_; 1042 1043 // Container for PLT function name strings. These strings are passed by 1044 // reference to SymbolSink::AddSymbol() so they need to be stored somewhere. 1045 std::vector<string> plt_function_names_; 1046 1047 bool visited_relocation_entries_; 1048 1049 // True if this is a .dwp file. 1050 bool is_dwp_; 1051 }; 1052 1053 ElfReader::ElfReader(const string& path) 1054 : path_(path), fd_(-1), impl32_(NULL), impl64_(NULL) { 1055 // linux 2.6.XX kernel can show deleted files like this: 1056 // /var/run/nscd/dbYLJYaE (deleted) 1057 // and the kernel-supplied vdso and vsyscall mappings like this: 1058 // [vdso] 1059 // [vsyscall] 1060 if (MyHasSuffixString(path, " (deleted)")) 1061 return; 1062 if (path == "[vdso]") 1063 return; 1064 if (path == "[vsyscall]") 1065 return; 1066 1067 fd_ = open(path.c_str(), O_RDONLY); 1068 } 1069 1070 ElfReader::~ElfReader() { 1071 if (fd_ != -1) 1072 close(fd_); 1073 if (impl32_ != NULL) 1074 delete impl32_; 1075 if (impl64_ != NULL) 1076 delete impl64_; 1077 } 1078 1079 1080 // The only word-size specific part of this file is IsNativeElfFile(). 1081 #if ULONG_MAX == 0xffffffff 1082 #define NATIVE_ELF_ARCH Elf32 1083 #elif ULONG_MAX == 0xffffffffffffffff 1084 #define NATIVE_ELF_ARCH Elf64 1085 #else 1086 #error "Invalid word size" 1087 #endif 1088 1089 template <typename ElfArch> 1090 static bool IsElfFile(const int fd, const string& path) { 1091 if (fd < 0) 1092 return false; 1093 if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) { 1094 // No error message here. IsElfFile gets called many times. 1095 return false; 1096 } 1097 return true; 1098 } 1099 1100 bool ElfReader::IsNativeElfFile() const { 1101 return IsElfFile<NATIVE_ELF_ARCH>(fd_, path_); 1102 } 1103 1104 bool ElfReader::IsElf32File() const { 1105 return IsElfFile<Elf32>(fd_, path_); 1106 } 1107 1108 bool ElfReader::IsElf64File() const { 1109 return IsElfFile<Elf64>(fd_, path_); 1110 } 1111 1112 /* 1113 void ElfReader::AddSymbols(SymbolMap* symbols, 1114 uint64_t mem_offset, uint64_t file_offset, 1115 uint64_t length) { 1116 if (fd_ < 0) 1117 return; 1118 // TODO(chatham): Actually use the information about file offset and 1119 // the length of the mapped section. On some machines the data 1120 // section gets mapped as executable, and we'll end up reading the 1121 // file twice and getting some of the offsets wrong. 1122 if (IsElf32File()) { 1123 GetImpl32()->GetSymbolPositions(symbols, SHT_SYMTAB, 1124 mem_offset, file_offset); 1125 GetImpl32()->GetSymbolPositions(symbols, SHT_DYNSYM, 1126 mem_offset, file_offset); 1127 } else if (IsElf64File()) { 1128 GetImpl64()->GetSymbolPositions(symbols, SHT_SYMTAB, 1129 mem_offset, file_offset); 1130 GetImpl64()->GetSymbolPositions(symbols, SHT_DYNSYM, 1131 mem_offset, file_offset); 1132 } 1133 } 1134 */ 1135 1136 void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink) { 1137 VisitSymbols(sink, -1, -1); 1138 } 1139 1140 void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink, 1141 int symbol_binding, 1142 int symbol_type) { 1143 VisitSymbols(sink, symbol_binding, symbol_type, false); 1144 } 1145 1146 void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink, 1147 int symbol_binding, 1148 int symbol_type, 1149 bool get_raw_symbol_values) { 1150 if (IsElf32File()) { 1151 GetImpl32()->VisitRelocationEntries(); 1152 GetImpl32()->VisitSymbols(SHT_SYMTAB, sink, symbol_binding, symbol_type, 1153 get_raw_symbol_values); 1154 GetImpl32()->VisitSymbols(SHT_DYNSYM, sink, symbol_binding, symbol_type, 1155 get_raw_symbol_values); 1156 } else if (IsElf64File()) { 1157 GetImpl64()->VisitRelocationEntries(); 1158 GetImpl64()->VisitSymbols(SHT_SYMTAB, sink, symbol_binding, symbol_type, 1159 get_raw_symbol_values); 1160 GetImpl64()->VisitSymbols(SHT_DYNSYM, sink, symbol_binding, symbol_type, 1161 get_raw_symbol_values); 1162 } 1163 } 1164 1165 uint64_t ElfReader::VaddrOfFirstLoadSegment() { 1166 if (IsElf32File()) { 1167 return GetImpl32()->VaddrOfFirstLoadSegment(); 1168 } else if (IsElf64File()) { 1169 return GetImpl64()->VaddrOfFirstLoadSegment(); 1170 } else { 1171 return 0; 1172 } 1173 } 1174 1175 const char* ElfReader::GetSectionName(int shndx) { 1176 if (shndx < 0 || static_cast<unsigned int>(shndx) >= GetNumSections()) return NULL; 1177 if (IsElf32File()) { 1178 return GetImpl32()->GetSectionNameByIndex(shndx); 1179 } else if (IsElf64File()) { 1180 return GetImpl64()->GetSectionNameByIndex(shndx); 1181 } else { 1182 return NULL; 1183 } 1184 } 1185 1186 uint64_t ElfReader::GetNumSections() { 1187 if (IsElf32File()) { 1188 return GetImpl32()->GetNumSections(); 1189 } else if (IsElf64File()) { 1190 return GetImpl64()->GetNumSections(); 1191 } else { 1192 return 0; 1193 } 1194 } 1195 1196 const char* ElfReader::GetSectionByIndex(int shndx, size_t* size) { 1197 if (IsElf32File()) { 1198 return GetImpl32()->GetSectionContentsByIndex(shndx, size); 1199 } else if (IsElf64File()) { 1200 return GetImpl64()->GetSectionContentsByIndex(shndx, size); 1201 } else { 1202 return NULL; 1203 } 1204 } 1205 1206 const char* ElfReader::GetSectionByName(const string& section_name, 1207 size_t* size) { 1208 if (IsElf32File()) { 1209 return GetImpl32()->GetSectionContentsByName(section_name, size); 1210 } else if (IsElf64File()) { 1211 return GetImpl64()->GetSectionContentsByName(section_name, size); 1212 } else { 1213 return NULL; 1214 } 1215 } 1216 1217 const char* ElfReader::GetSectionInfoByName(const string& section_name, 1218 SectionInfo* info) { 1219 if (IsElf32File()) { 1220 return GetImpl32()->GetSectionInfoByName(section_name, info); 1221 } else if (IsElf64File()) { 1222 return GetImpl64()->GetSectionInfoByName(section_name, info); 1223 } else { 1224 return NULL; 1225 } 1226 } 1227 1228 bool ElfReader::SectionNamesMatch(std::string_view name, 1229 std::string_view sh_name) { 1230 std::string_view debug_prefix{".debug_"}; 1231 std::string_view zdebug_prefix{".zdebug_"}; 1232 if (StringViewStartsWith(name, debug_prefix) && 1233 StringViewStartsWith(sh_name, zdebug_prefix)) { 1234 name.remove_prefix(debug_prefix.length()); 1235 sh_name.remove_prefix(zdebug_prefix.length()); 1236 return name == sh_name; 1237 } 1238 return name == sh_name; 1239 } 1240 1241 bool ElfReader::IsDynamicSharedObject() { 1242 if (IsElf32File()) { 1243 return GetImpl32()->IsDynamicSharedObject(); 1244 } else if (IsElf64File()) { 1245 return GetImpl64()->IsDynamicSharedObject(); 1246 } else { 1247 return false; 1248 } 1249 } 1250 1251 ElfReaderImpl<Elf32>* ElfReader::GetImpl32() { 1252 if (impl32_ == NULL) { 1253 impl32_ = new ElfReaderImpl<Elf32>(path_, fd_); 1254 } 1255 return impl32_; 1256 } 1257 1258 ElfReaderImpl<Elf64>* ElfReader::GetImpl64() { 1259 if (impl64_ == NULL) { 1260 impl64_ = new ElfReaderImpl<Elf64>(path_, fd_); 1261 } 1262 return impl64_; 1263 } 1264 1265 // Return true if file is an ELF binary of ElfArch, with unstripped 1266 // debug info (debug_only=true) or symbol table (debug_only=false). 1267 // Otherwise, return false. 1268 template <typename ElfArch> 1269 static bool IsNonStrippedELFBinaryImpl(const string& path, const int fd, 1270 bool debug_only) { 1271 if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) return false; 1272 ElfReaderImpl<ElfArch> elf_reader(path, fd); 1273 return debug_only ? 1274 elf_reader.HasDebugSections() 1275 : (elf_reader.GetSectionByType(SHT_SYMTAB) != NULL); 1276 } 1277 1278 // Helper for the IsNon[Debug]StrippedELFBinary functions. 1279 static bool IsNonStrippedELFBinaryHelper(const string& path, 1280 bool debug_only) { 1281 const int fd = open(path.c_str(), O_RDONLY); 1282 if (fd == -1) { 1283 return false; 1284 } 1285 1286 if (IsNonStrippedELFBinaryImpl<Elf32>(path, fd, debug_only) || 1287 IsNonStrippedELFBinaryImpl<Elf64>(path, fd, debug_only)) { 1288 close(fd); 1289 return true; 1290 } 1291 close(fd); 1292 return false; 1293 } 1294 1295 bool ElfReader::IsNonStrippedELFBinary(const string& path) { 1296 return IsNonStrippedELFBinaryHelper(path, false); 1297 } 1298 1299 bool ElfReader::IsNonDebugStrippedELFBinary(const string& path) { 1300 return IsNonStrippedELFBinaryHelper(path, true); 1301 } 1302 } // namespace google_breakpad