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