[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / include / llvm / DebugInfo / GSYM / GsymReader.h
blob113bcee9c9a34c2f696f669e0e49c63c136074dd
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 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H
11 #define LLVM_DEBUGINFO_GSYM_GSYMREADER_H
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/DebugInfo/GSYM/FileEntry.h"
16 #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
17 #include "llvm/DebugInfo/GSYM/Header.h"
18 #include "llvm/DebugInfo/GSYM/LineEntry.h"
19 #include "llvm/DebugInfo/GSYM/StringTable.h"
20 #include "llvm/Support/DataExtractor.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/ErrorOr.h"
24 #include <inttypes.h>
25 #include <memory>
26 #include <stdint.h>
27 #include <string>
28 #include <vector>
30 namespace llvm {
31 class MemoryBuffer;
32 class raw_ostream;
34 namespace gsym {
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(...).
48 class GsymReader {
49 GsymReader(std::unique_ptr<MemoryBuffer> Buffer);
50 llvm::Error parse();
52 std::unique_ptr<MemoryBuffer> MemBuffer;
53 StringRef GsymBytes;
54 llvm::support::endianness Endian;
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;
70 std::unique_ptr<SwappedData> Swap;
72 public:
73 GsymReader(GsymReader &&RHS);
74 ~GsymReader();
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.
81 static llvm::Expected<GsymReader> openFile(StringRef Path);
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.
89 static llvm::Expected<GsymReader> copyBuffer(StringRef Bytes);
91 /// Access the GSYM header.
92 /// \returns A native endian version of the GSYM header.
93 const Header &getHeader() const;
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;
103 /// Get a string from the string table.
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]; }
109 protected:
110 /// Gets an address from the address table.
112 /// Addresses are stored as offsets frrom the gsym::Header::BaseAddress.
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;
119 /// Get the a file entry for the suppplied file index.
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.
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,
128 Optional<FileEntry> getFile(uint32_t Index) const {
129 if (Index < Files.size())
130 return Files[Index];
131 return llvm::None;
134 /// Get an appropriate address info offsets array.
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.
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));
150 /// Get an appropriate address from the address table.
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.
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;
169 /// Lookup an address offset in the AddrOffsets table.
171 /// Given an address offset, look it up using a binary search of the
172 /// AddrOffsets table.
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);
189 /// Create a GSYM from a memory buffer.
191 /// Called by both openFile() and copyBuffer(), this function does all of the
192 /// work of parsing the GSYM file and returning an error.
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.
198 static llvm::Expected<llvm::gsym::GsymReader>
199 create(std::unique_ptr<MemoryBuffer> &MemBuffer);
202 /// Given an address, find the address index.
204 /// Binary search the address table and find the matching address index.
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;
213 /// Given an address index, get the offset for the FunctionInfo.
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.
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;
225 } // namespace gsym
226 } // namespace llvm
228 #endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H