aboutsummaryrefslogtreecommitdiff
path: root/src/common/dwarf/elf_reader.h
blob: b1bb67a882d5e3c7f2c3f4aad706541b0e674c53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2005 Google Inc. All Rights Reserved.
// Author: chatham@google.com (Andrew Chatham)
// Author: satorux@google.com (Satoru Takabayashi)
//
// ElfReader handles reading in ELF. It can extract symbols from the
// current process, which may be used to symbolize stack traces
// without having to make a potentially dangerous call to fork().
//
// ElfReader dynamically allocates memory, so it is not appropriate to
// use once the address space might be corrupted, such as during
// process death.
//
// ElfReader supports both 32-bit and 64-bit ELF binaries.

#ifndef COMMON_DWARF_ELF_READER_H__
#define COMMON_DWARF_ELF_READER_H__

#include <string>
#include <vector>

#include "common/dwarf/types.h"
#include "common/using_std_string.h"

using std::vector;
using std::pair;

namespace dwarf2reader {

class SymbolMap;
class Elf32;
class Elf64;
template<typename ElfArch>
class ElfReaderImpl;

class ElfReader {
 public:
  explicit ElfReader(const string &path);
  ~ElfReader();

  // Parse the ELF prologue of this file and return whether it was
  // successfully parsed and matches the word size and byte order of
  // the current process.
  bool IsNativeElfFile() const;

  // Similar to IsNativeElfFile but checks if it's a 32-bit ELF file.
  bool IsElf32File() const;

  // Similar to IsNativeElfFile but checks if it's a 64-bit ELF file.
  bool IsElf64File() const;

  // Checks if it's an ELF file of type ET_DYN (shared object file).
  bool IsDynamicSharedObject();

  // Add symbols in the given ELF file into the provided SymbolMap,
  // assuming that the file has been loaded into the specified
  // offset.
  //
  // The remaining arguments are typically taken from a
  // ProcMapsIterator (base/sysinfo.h) and describe which portions of
  // the ELF file are mapped into which parts of memory:
  //
  // mem_offset - position at which the segment is mapped into memory
  // file_offset - offset in the file where the mapping begins
  // length - length of the mapped segment
  void AddSymbols(SymbolMap *symbols,
                  uint64 mem_offset, uint64 file_offset,
                  uint64 length);

  class SymbolSink {
   public:
    virtual ~SymbolSink() {}
    virtual void AddSymbol(const char *name, uint64 address, uint64 size) = 0;
  };

  // Like AddSymbols above, but with no address correction.
  // Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
  void VisitSymbols(SymbolSink *sink);

  // Like VisitSymbols above, but for a specific symbol binding/type.
  // A negative value for the binding and type parameters means any
  // binding or type.
  void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);

  // Like VisitSymbols above but can optionally export raw symbol values instead
  // of adjusted ones.
  void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
                    bool get_raw_symbol_values);

  // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
  // segments are present. This is the address an ELF image was linked
  // (by static linker) to be loaded at. Usually (but not always) 0 for
  // shared libraries and position-independent executables.
  uint64 VaddrOfFirstLoadSegment();

  // Return the name of section "shndx".  Returns NULL if the section
  // is not found.
  const char *GetSectionName(int shndx);

  // Return the number of sections in the given ELF file.
  uint64 GetNumSections();

  // Get section "shndx" from the given ELF file.  On success, return
  // the pointer to the section and store the size in "size".
  // On error, return NULL.  The returned section data is only valid
  // until the ElfReader gets destroyed.
  const char *GetSectionByIndex(int shndx, size_t *size);

  // Get section with "section_name" (ex. ".text", ".symtab") in the
  // given ELF file.  On success, return the pointer to the section
  // and store the size in "size".  On error, return NULL.  The
  // returned section data is only valid until the ElfReader gets
  // destroyed.
  const char *GetSectionByName(const string &section_name, size_t *size);

  // This is like GetSectionByName() but it returns a lot of extra information
  // about the section. The SectionInfo structure is almost identical to
  // the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined
  // here so that the many short macro names in <elf.h> don't have to be
  // added to our already cluttered namespace.
  struct SectionInfo {
    uint32 type;                // Section type (SHT_xxx constant from elf.h).
    uint64 flags;               // Section flags (SHF_xxx constants from elf.h).
    uint64 addr;                // Section virtual address at execution.
    uint64 offset;              // Section file offset.
    uint64 size;                // Section size in bytes.
    uint32 link;                // Link to another section.
    uint32 info;                // Additional section information.
    uint64 addralign;           // Section alignment.
    uint64 entsize;             // Entry size if section holds a table.
  };
  const char *GetSectionInfoByName(const string &section_name,
                                   SectionInfo *info);

  // Check if "path" is an ELF binary that has not been stripped of symbol
  // tables.  This function supports both 32-bit and 64-bit ELF binaries.
  static bool IsNonStrippedELFBinary(const string &path);

  // Check if "path" is an ELF binary that has not been stripped of debug
  // info. Unlike IsNonStrippedELFBinary, this function will return
  // false for binaries passed through "strip -S".
  static bool IsNonDebugStrippedELFBinary(const string &path);

  // Match a requested section name with the section name as it
  // appears in the elf-file, adjusting for compressed debug section
  // names.  For example, returns true if name == ".debug_abbrev" and
  // sh_name == ".zdebug_abbrev"
  static bool SectionNamesMatch(const string &name, const string &sh_name);

 private:
  // Lazily initialize impl32_ and return it.
  ElfReaderImpl<Elf32> *GetImpl32();
  // Ditto for impl64_.
  ElfReaderImpl<Elf64> *GetImpl64();

  // Path of the file we're reading.
  const string path_;
  // Read-only file descriptor for the file. May be -1 if there was an
  // error during open.
  int fd_;
  ElfReaderImpl<Elf32> *impl32_;
  ElfReaderImpl<Elf64> *impl64_;
};

}  // namespace dwarf2reader

#endif  // COMMON_DWARF_ELF_READER_H__