xref: /aosp_15_r20/external/google-breakpad/src/common/dwarf/elf_reader.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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