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 | |