1 // Copyright 2005 Google LLC 2 // Author: [email protected] (Andrew Chatham) 3 // Author: [email protected] (Satoru Takabayashi) 4 // 5 // ElfReader handles reading in ELF. It can extract symbols from the 6 // current process, which may be used to symbolize stack traces 7 // without having to make a potentially dangerous call to fork(). 8 // 9 // ElfReader dynamically allocates memory, so it is not appropriate to 10 // use once the address space might be corrupted, such as during 11 // process death. 12 // 13 // ElfReader supports both 32-bit and 64-bit ELF binaries. 14 15 #ifndef COMMON_DWARF_ELF_READER_H__ 16 #define COMMON_DWARF_ELF_READER_H__ 17 18 #include <string> 19 #include <string_view> 20 #include <vector> 21 22 #include "common/dwarf/types.h" 23 #include "common/using_std_string.h" 24 25 using std::vector; 26 using std::pair; 27 28 namespace google_breakpad { 29 30 class SymbolMap; 31 class Elf32; 32 class Elf64; 33 template<typename ElfArch> 34 class ElfReaderImpl; 35 36 class ElfReader { 37 public: 38 explicit ElfReader(const string& path); 39 ~ElfReader(); 40 41 // Parse the ELF prologue of this file and return whether it was 42 // successfully parsed and matches the word size and byte order of 43 // the current process. 44 bool IsNativeElfFile() const; 45 46 // Similar to IsNativeElfFile but checks if it's a 32-bit ELF file. 47 bool IsElf32File() const; 48 49 // Similar to IsNativeElfFile but checks if it's a 64-bit ELF file. 50 bool IsElf64File() const; 51 52 // Checks if it's an ELF file of type ET_DYN (shared object file). 53 bool IsDynamicSharedObject(); 54 55 // Add symbols in the given ELF file into the provided SymbolMap, 56 // assuming that the file has been loaded into the specified 57 // offset. 58 // 59 // The remaining arguments are typically taken from a 60 // ProcMapsIterator (base/sysinfo.h) and describe which portions of 61 // the ELF file are mapped into which parts of memory: 62 // 63 // mem_offset - position at which the segment is mapped into memory 64 // file_offset - offset in the file where the mapping begins 65 // length - length of the mapped segment 66 void AddSymbols(SymbolMap* symbols, 67 uint64_t mem_offset, uint64_t file_offset, 68 uint64_t length); 69 70 class SymbolSink { 71 public: ~SymbolSink()72 virtual ~SymbolSink() {} 73 virtual void AddSymbol(const char* name, uint64_t address, 74 uint64_t size) = 0; 75 }; 76 77 // Like AddSymbols above, but with no address correction. 78 // Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section. 79 void VisitSymbols(SymbolSink* sink); 80 81 // Like VisitSymbols above, but for a specific symbol binding/type. 82 // A negative value for the binding and type parameters means any 83 // binding or type. 84 void VisitSymbols(SymbolSink* sink, int symbol_binding, int symbol_type); 85 86 // Like VisitSymbols above but can optionally export raw symbol values instead 87 // of adjusted ones. 88 void VisitSymbols(SymbolSink* sink, int symbol_binding, int symbol_type, 89 bool get_raw_symbol_values); 90 91 // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD 92 // segments are present. This is the address an ELF image was linked 93 // (by static linker) to be loaded at. Usually (but not always) 0 for 94 // shared libraries and position-independent executables. 95 uint64_t VaddrOfFirstLoadSegment(); 96 97 // Return the name of section "shndx". Returns NULL if the section 98 // is not found. 99 const char* GetSectionName(int shndx); 100 101 // Return the number of sections in the given ELF file. 102 uint64_t GetNumSections(); 103 104 // Get section "shndx" from the given ELF file. On success, return 105 // the pointer to the section and store the size in "size". 106 // On error, return NULL. The returned section data is only valid 107 // until the ElfReader gets destroyed. 108 const char* GetSectionByIndex(int shndx, size_t* size); 109 110 // Get section with "section_name" (ex. ".text", ".symtab") in the 111 // given ELF file. On success, return the pointer to the section 112 // and store the size in "size". On error, return NULL. The 113 // returned section data is only valid until the ElfReader gets 114 // destroyed. 115 const char* GetSectionByName(const string& section_name, size_t* size); 116 117 // This is like GetSectionByName() but it returns a lot of extra information 118 // about the section. The SectionInfo structure is almost identical to 119 // the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined 120 // here so that the many short macro names in <elf.h> don't have to be 121 // added to our already cluttered namespace. 122 struct SectionInfo { 123 uint32_t type; // Section type (SHT_xxx constant from elf.h). 124 uint64_t flags; // Section flags (SHF_xxx constants from elf.h). 125 uint64_t addr; // Section virtual address at execution. 126 uint64_t offset; // Section file offset. 127 uint64_t size; // Section size in bytes. 128 uint32_t link; // Link to another section. 129 uint32_t info; // Additional section information. 130 uint64_t addralign; // Section alignment. 131 uint64_t entsize; // Entry size if section holds a table. 132 }; 133 const char* GetSectionInfoByName(const string& section_name, 134 SectionInfo* info); 135 136 // Check if "path" is an ELF binary that has not been stripped of symbol 137 // tables. This function supports both 32-bit and 64-bit ELF binaries. 138 static bool IsNonStrippedELFBinary(const string& path); 139 140 // Check if "path" is an ELF binary that has not been stripped of debug 141 // info. Unlike IsNonStrippedELFBinary, this function will return 142 // false for binaries passed through "strip -S". 143 static bool IsNonDebugStrippedELFBinary(const string& path); 144 145 // Match a requested section name with the section name as it 146 // appears in the elf-file, adjusting for compressed debug section 147 // names. For example, returns true if name == ".debug_abbrev" and 148 // sh_name == ".zdebug_abbrev" 149 static bool SectionNamesMatch(std::string_view name, 150 std::string_view sh_name); 151 152 private: 153 // Lazily initialize impl32_ and return it. 154 ElfReaderImpl<Elf32>* GetImpl32(); 155 // Ditto for impl64_. 156 ElfReaderImpl<Elf64>* GetImpl64(); 157 158 // Path of the file we're reading. 159 const string path_; 160 // Read-only file descriptor for the file. May be -1 if there was an 161 // error during open. 162 int fd_; 163 ElfReaderImpl<Elf32>* impl32_; 164 ElfReaderImpl<Elf64>* impl64_; 165 }; 166 167 } // namespace google_breakpad 168 169 #endif // COMMON_DWARF_ELF_READER_H__ 170