LLVM  10.0.0svn
GsymReader.h
Go to the documentation of this file.
1 //===- GsymReader.h ---------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H
11 #define LLVM_DEBUGINFO_GSYM_GSYMREADER_H
12 
13 
14 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/ErrorOr.h"
23 
24 #include <inttypes.h>
25 #include <memory>
26 #include <stdint.h>
27 #include <string>
28 #include <vector>
29 
30 namespace llvm {
31 class MemoryBuffer;
32 class raw_ostream;
33 
34 namespace gsym {
35 
36 /// GsymReader is used to read GSYM data from a file or buffer.
37 ///
38 /// This class is optimized for very quick lookups when the endianness matches
39 /// the host system. The Header, address table, address info offsets, and file
40 /// table is designed to be mmap'ed as read only into memory and used without
41 /// any parsing needed. If the endianness doesn't match, we swap these objects
42 /// and tables into GsymReader::SwappedData and then point our header and
43 /// ArrayRefs to this swapped internal data.
44 ///
45 /// GsymReader objects must use one of the static functions to create an
46 /// instance: GsymReader::openFile(...) and GsymReader::copyBuffer(...).
47 
48 class GsymReader {
49  GsymReader(std::unique_ptr<MemoryBuffer> Buffer);
51 
52  std::unique_ptr<MemoryBuffer> MemBuffer;
53  StringRef GsymBytes;
55  const Header *Hdr = nullptr;
56  ArrayRef<uint8_t> AddrOffsets;
57  ArrayRef<uint32_t> AddrInfoOffsets;
58  ArrayRef<FileEntry> Files;
59  StringTable StrTab;
60  /// When the GSYM file's endianness doesn't match the host system then
61  /// we must decode all data structures that need to be swapped into
62  /// local storage and set point the ArrayRef objects above to these swapped
63  /// copies.
64  struct SwappedData {
65  Header Hdr;
66  std::vector<uint8_t> AddrOffsets;
67  std::vector<uint32_t> AddrInfoOffsets;
68  std::vector<FileEntry> Files;
69  };
70  std::unique_ptr<SwappedData> Swap;
71 
72 public:
73  GsymReader(GsymReader &&RHS);
74  ~GsymReader();
75 
76  /// Construct a GsymReader from a file on disk.
77  ///
78  /// \param Path The file path the GSYM file to read.
79  /// \returns An expected GsymReader that contains the object or an error
80  /// object that indicates reason for failing to read the GSYM.
82 
83  /// Construct a GsymReader from a buffer.
84  ///
85  /// \param Bytes A set of bytes that will be copied and owned by the
86  /// returned object on success.
87  /// \returns An expected GsymReader that contains the object or an error
88  /// object that indicates reason for failing to read the GSYM.
90 
91  /// Access the GSYM header.
92  /// \returns A native endian version of the GSYM header.
93  const Header &getHeader() const;
94 
95  /// Get the full function info for an address.
96  ///
97  /// \param Addr A virtual address from the orignal object file to lookup.
98  /// \returns An expected FunctionInfo that contains the function info object
99  /// or an error object that indicates reason for failing to lookup the
100  /// address,
101  llvm::Expected<FunctionInfo> getFunctionInfo(uint64_t Addr) const;
102 
103  /// Get a string from the string table.
104  ///
105  /// \param Offset The string table offset for the string to retrieve.
106  /// \returns The string from the strin table.
107  StringRef getString(uint32_t Offset) const { return StrTab[Offset]; }
108 
109 protected:
110  /// Gets an address from the address table.
111  ///
112  /// Addresses are stored as offsets frrom the gsym::Header::BaseAddress.
113  ///
114  /// \param Index A index into the address table.
115  /// \returns A resolved virtual address for adddress in the address table
116  /// or llvm::None if Index is out of bounds.
117  Optional<uint64_t> getAddress(size_t Index) const;
118 
119  /// Get the a file entry for the suppplied file index.
120  ///
121  /// Used to convert any file indexes in the FunctionInfo data back into
122  /// files. This function can be used for iteration, but is more commonly used
123  /// for random access when doing lookups.
124  ///
125  /// \param Index An index into the file table.
126  /// \returns An optional FileInfo that will be valid if the file index is
127  /// valid, or llvm::None if the file index is out of bounds,
129  if (Index < Files.size())
130  return Files[Index];
131  return llvm::None;
132  }
133 
134  /// Get an appropriate address info offsets array.
135  ///
136  /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
137  /// byte offsets from the The gsym::Header::BaseAddress. The table is stored
138  /// internally as a array of bytes that are in the correct endianness. When
139  /// we access this table we must get an array that matches those sizes. This
140  /// templatized helper function is used when accessing address offsets in the
141  /// AddrOffsets member variable.
142  ///
143  /// \returns An ArrayRef of an appropriate address offset size.
144  template <class T> ArrayRef<T>
145  getAddrOffsets() const {
146  return ArrayRef<T>(reinterpret_cast<const T *>(AddrOffsets.data()),
147  AddrOffsets.size()/sizeof(T));
148  }
149 
150  /// Get an appropriate address from the address table.
151  ///
152  /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
153  /// byte address offsets from the The gsym::Header::BaseAddress. The table is
154  /// stored internally as a array of bytes that are in the correct endianness.
155  /// In order to extract an address from the address table we must access the
156  /// address offset using the correct size and then add it to the BaseAddress
157  /// in the header.
158  ///
159  /// \param Index An index into the AddrOffsets array.
160  /// \returns An virtual address that matches the original object file for the
161  /// address as the specified index, or llvm::None if Index is out of bounds.
162  template <class T> Optional<uint64_t>
163  addressForIndex(size_t Index) const {
164  ArrayRef<T> AIO = getAddrOffsets<T>();
165  if (Index < AIO.size())
166  return AIO[Index] + Hdr->BaseAddress;
167  return llvm::None;
168  }
169  /// Lookup an address offset in the AddrOffsets table.
170  ///
171  /// Given an address offset, look it up using a binary search of the
172  /// AddrOffsets table.
173  ///
174  /// \param AddrOffset An address offset, that has already been computed by
175  /// subtracting the gsym::Header::BaseAddress.
176  /// \returns The matching address offset index. This index will be used to
177  /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
178  template <class T>
179  uint64_t getAddressOffsetIndex(const uint64_t AddrOffset) const {
180  ArrayRef<T> AIO = getAddrOffsets<T>();
181  const auto Begin = AIO.begin();
182  const auto End = AIO.end();
183  auto Iter = std::lower_bound(Begin, End, AddrOffset);
184  if (Iter == End || AddrOffset < *Iter)
185  --Iter;
186  return std::distance(Begin, Iter);
187  }
188 
189  /// Create a GSYM from a memory buffer.
190  ///
191  /// Called by both openFile() and copyBuffer(), this function does all of the
192  /// work of parsing the GSYM file and returning an error.
193  ///
194  /// \param MemBuffer A memory buffer that will transfer ownership into the
195  /// GsymReader.
196  /// \returns An expected GsymReader that contains the object or an error
197  /// object that indicates reason for failing to read the GSYM.
199  create(std::unique_ptr<MemoryBuffer> &MemBuffer);
200 
201 
202  /// Given an address, find the address index.
203  ///
204  /// Binary search the address table and find the matching address index.
205  ///
206  /// \param Addr A virtual address that matches the original object file
207  /// to lookup.
208  /// \returns An index into the address table. This index can be used to
209  /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
210  /// Returns an error if the address isn't in the GSYM with details of why.
211  Expected<uint64_t> getAddressIndex(const uint64_t Addr) const;
212 
213  /// Given an address index, get the offset for the FunctionInfo.
214  ///
215  /// Looking up an address is done by finding the corresponding address
216  /// index for the address. This index is then used to get the offset of the
217  /// FunctionInfo data that we will decode using this function.
218  ///
219  /// \param Index An index into the address table.
220  /// \returns An optional GSYM data offset for the offset of the FunctionInfo
221  /// that needs to be decoded.
222  Optional<uint64_t> getAddressInfoOffset(size_t Index) const;
223 };
224 
225 } // namespace gsym
226 } // namespace llvm
227 
228 #endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H
auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1261
GsymReader is used to read GSYM data from a file or buffer.
Definition: GsymReader.h:48
static llvm::Expected< GsymReader > copyBuffer(StringRef Bytes)
Construct a GsymReader from a buffer.
Definition: GsymReader.cpp:45
const Header & getHeader() const
Access the GSYM header.
Definition: GsymReader.cpp:202
This class represents lattice values for constants.
Definition: AllocatorList.h:23
iterator begin() const
Definition: ArrayRef.h:136
uint64_t getAddressOffsetIndex(const uint64_t AddrOffset) const
Lookup an address offset in the AddrOffsets table.
Definition: GsymReader.h:179
uint64_t BaseAddress
The 64 bit base address that all address offsets in the address offsets table are relative to...
Definition: Header.h:62
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
Definition: regcomp.c:192
Optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
Definition: GsymReader.h:128
StringRef getString(uint32_t Offset) const
Get a string from the string table.
Definition: GsymReader.h:107
llvm::Expected< FunctionInfo > getFunctionInfo(uint64_t Addr) const
Get the full function info for an address.
Definition: GsymReader.cpp:245
Expected< uint64_t > getAddressIndex(const uint64_t Addr) const
Given an address, find the address index.
Definition: GsymReader.cpp:228
Optional< uint64_t > getAddress(size_t Index) const
Gets an address from the address table.
Definition: GsymReader.cpp:210
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
String tables in GSYM files are required to start with an empty string at offset zero.
Definition: StringTable.h:24
static llvm::Expected< GsymReader > openFile(StringRef Path)
Construct a GsymReader from a file on disk.
Definition: GsymReader.cpp:35
const T * data() const
Definition: ArrayRef.h:145
iterator end() const
Definition: ArrayRef.h:137
The GSYM header.
Definition: Header.h:45
static llvm::Expected< llvm::gsym::GsymReader > create(std::unique_ptr< MemoryBuffer > &MemBuffer)
Create a GSYM from a memory buffer.
Definition: GsymReader.cpp:51
Optional< uint64_t > addressForIndex(size_t Index) const
Get an appropriate address from the address table.
Definition: GsymReader.h:163
Provides ErrorOr<T> smart pointer.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
ArrayRef< T > getAddrOffsets() const
Get an appropriate address info offsets array.
Definition: GsymReader.h:145
Optional< uint64_t > getAddressInfoOffset(size_t Index) const
Given an address index, get the offset for the FunctionInfo.
Definition: GsymReader.cpp:220