/ src / common / dwarf / elf_reader.h
elf_reader.h
  1  // Copyright 2005 Google LLC
  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 <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:
 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__