LLVM 20.0.0git
GsymReader.cpp
Go to the documentation of this file.
1//===- GsymReader.cpp -----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include <assert.h>
12#include <inttypes.h>
13#include <stdio.h>
14#include <stdlib.h>
15
21
22using namespace llvm;
23using namespace gsym;
24
25GsymReader::GsymReader(std::unique_ptr<MemoryBuffer> Buffer)
26 : MemBuffer(std::move(Buffer)), Endian(llvm::endianness::native) {}
27
28GsymReader::GsymReader(GsymReader &&RHS) = default;
29
30GsymReader::~GsymReader() = default;
31
33 // Open the input file and return an appropriate error if needed.
36 auto Err = BuffOrErr.getError();
37 if (Err)
38 return llvm::errorCodeToError(Err);
39 return create(BuffOrErr.get());
40}
41
43 auto MemBuffer = MemoryBuffer::getMemBufferCopy(Bytes, "GSYM bytes");
44 return create(MemBuffer);
45}
46
48GsymReader::create(std::unique_ptr<MemoryBuffer> &MemBuffer) {
49 if (!MemBuffer)
50 return createStringError(std::errc::invalid_argument,
51 "invalid memory buffer");
52 GsymReader GR(std::move(MemBuffer));
53 llvm::Error Err = GR.parse();
54 if (Err)
55 return std::move(Err);
56 return std::move(GR);
57}
58
60GsymReader::parse() {
61 BinaryStreamReader FileData(MemBuffer->getBuffer(), llvm::endianness::native);
62 // Check for the magic bytes. This file format is designed to be mmap'ed
63 // into a process and accessed as read only. This is done for performance
64 // and efficiency for symbolicating and parsing GSYM data.
65 if (FileData.readObject(Hdr))
66 return createStringError(std::errc::invalid_argument,
67 "not enough data for a GSYM header");
68
69 const auto HostByteOrder = llvm::endianness::native;
70 switch (Hdr->Magic) {
71 case GSYM_MAGIC:
72 Endian = HostByteOrder;
73 break;
74 case GSYM_CIGAM:
75 // This is a GSYM file, but not native endianness.
78 Swap.reset(new SwappedData);
79 break;
80 default:
81 return createStringError(std::errc::invalid_argument,
82 "not a GSYM file");
83 }
84
85 bool DataIsLittleEndian = HostByteOrder != llvm::endianness::little;
86 // Read a correctly byte swapped header if we need to.
87 if (Swap) {
88 DataExtractor Data(MemBuffer->getBuffer(), DataIsLittleEndian, 4);
89 if (auto ExpectedHdr = Header::decode(Data))
90 Swap->Hdr = ExpectedHdr.get();
91 else
92 return ExpectedHdr.takeError();
93 Hdr = &Swap->Hdr;
94 }
95
96 // Detect errors in the header and report any that are found. If we make it
97 // past this without errors, we know we have a good magic value, a supported
98 // version number, verified address offset size and a valid UUID size.
99 if (Error Err = Hdr->checkForError())
100 return Err;
101
102 if (!Swap) {
103 // This is the native endianness case that is most common and optimized for
104 // efficient lookups. Here we just grab pointers to the native data and
105 // use ArrayRef objects to allow efficient read only access.
106
107 // Read the address offsets.
108 if (FileData.padToAlignment(Hdr->AddrOffSize) ||
109 FileData.readArray(AddrOffsets,
110 Hdr->NumAddresses * Hdr->AddrOffSize))
111 return createStringError(std::errc::invalid_argument,
112 "failed to read address table");
113
114 // Read the address info offsets.
115 if (FileData.padToAlignment(4) ||
116 FileData.readArray(AddrInfoOffsets, Hdr->NumAddresses))
117 return createStringError(std::errc::invalid_argument,
118 "failed to read address info offsets table");
119
120 // Read the file table.
121 uint32_t NumFiles = 0;
122 if (FileData.readInteger(NumFiles) || FileData.readArray(Files, NumFiles))
123 return createStringError(std::errc::invalid_argument,
124 "failed to read file table");
125
126 // Get the string table.
127 FileData.setOffset(Hdr->StrtabOffset);
128 if (FileData.readFixedString(StrTab.Data, Hdr->StrtabSize))
129 return createStringError(std::errc::invalid_argument,
130 "failed to read string table");
131} else {
132 // This is the non native endianness case that is not common and not
133 // optimized for lookups. Here we decode the important tables into local
134 // storage and then set the ArrayRef objects to point to these swapped
135 // copies of the read only data so lookups can be as efficient as possible.
136 DataExtractor Data(MemBuffer->getBuffer(), DataIsLittleEndian, 4);
137
138 // Read the address offsets.
139 uint64_t Offset = alignTo(sizeof(Header), Hdr->AddrOffSize);
140 Swap->AddrOffsets.resize(Hdr->NumAddresses * Hdr->AddrOffSize);
141 switch (Hdr->AddrOffSize) {
142 case 1:
143 if (!Data.getU8(&Offset, Swap->AddrOffsets.data(), Hdr->NumAddresses))
144 return createStringError(std::errc::invalid_argument,
145 "failed to read address table");
146 break;
147 case 2:
148 if (!Data.getU16(&Offset,
149 reinterpret_cast<uint16_t *>(Swap->AddrOffsets.data()),
150 Hdr->NumAddresses))
151 return createStringError(std::errc::invalid_argument,
152 "failed to read address table");
153 break;
154 case 4:
155 if (!Data.getU32(&Offset,
156 reinterpret_cast<uint32_t *>(Swap->AddrOffsets.data()),
157 Hdr->NumAddresses))
158 return createStringError(std::errc::invalid_argument,
159 "failed to read address table");
160 break;
161 case 8:
162 if (!Data.getU64(&Offset,
163 reinterpret_cast<uint64_t *>(Swap->AddrOffsets.data()),
164 Hdr->NumAddresses))
165 return createStringError(std::errc::invalid_argument,
166 "failed to read address table");
167 }
168 AddrOffsets = ArrayRef<uint8_t>(Swap->AddrOffsets);
169
170 // Read the address info offsets.
171 Offset = alignTo(Offset, 4);
172 Swap->AddrInfoOffsets.resize(Hdr->NumAddresses);
173 if (Data.getU32(&Offset, Swap->AddrInfoOffsets.data(), Hdr->NumAddresses))
174 AddrInfoOffsets = ArrayRef<uint32_t>(Swap->AddrInfoOffsets);
175 else
176 return createStringError(std::errc::invalid_argument,
177 "failed to read address table");
178 // Read the file table.
179 const uint32_t NumFiles = Data.getU32(&Offset);
180 if (NumFiles > 0) {
181 Swap->Files.resize(NumFiles);
182 if (Data.getU32(&Offset, &Swap->Files[0].Dir, NumFiles*2))
183 Files = ArrayRef<FileEntry>(Swap->Files);
184 else
185 return createStringError(std::errc::invalid_argument,
186 "failed to read file table");
187 }
188 // Get the string table.
189 StrTab.Data = MemBuffer->getBuffer().substr(Hdr->StrtabOffset,
190 Hdr->StrtabSize);
191 if (StrTab.Data.empty())
192 return createStringError(std::errc::invalid_argument,
193 "failed to read string table");
194 }
195 return Error::success();
196
197}
198
200 // The only way to get a GsymReader is from GsymReader::openFile(...) or
201 // GsymReader::copyBuffer() and the header must be valid and initialized to
202 // a valid pointer value, so the assert below should not trigger.
203 assert(Hdr);
204 return *Hdr;
205}
206
207std::optional<uint64_t> GsymReader::getAddress(size_t Index) const {
208 switch (Hdr->AddrOffSize) {
209 case 1: return addressForIndex<uint8_t>(Index);
210 case 2: return addressForIndex<uint16_t>(Index);
211 case 4: return addressForIndex<uint32_t>(Index);
212 case 8: return addressForIndex<uint64_t>(Index);
213 }
214 return std::nullopt;
215}
216
217std::optional<uint64_t> GsymReader::getAddressInfoOffset(size_t Index) const {
218 const auto NumAddrInfoOffsets = AddrInfoOffsets.size();
219 if (Index < NumAddrInfoOffsets)
220 return AddrInfoOffsets[Index];
221 return std::nullopt;
222}
223
226 if (Addr >= Hdr->BaseAddress) {
227 const uint64_t AddrOffset = Addr - Hdr->BaseAddress;
228 std::optional<uint64_t> AddrOffsetIndex;
229 switch (Hdr->AddrOffSize) {
230 case 1:
231 AddrOffsetIndex = getAddressOffsetIndex<uint8_t>(AddrOffset);
232 break;
233 case 2:
234 AddrOffsetIndex = getAddressOffsetIndex<uint16_t>(AddrOffset);
235 break;
236 case 4:
237 AddrOffsetIndex = getAddressOffsetIndex<uint32_t>(AddrOffset);
238 break;
239 case 8:
240 AddrOffsetIndex = getAddressOffsetIndex<uint64_t>(AddrOffset);
241 break;
242 default:
243 return createStringError(std::errc::invalid_argument,
244 "unsupported address offset size %u",
245 Hdr->AddrOffSize);
246 }
247 if (AddrOffsetIndex)
248 return *AddrOffsetIndex;
249 }
250 return createStringError(std::errc::invalid_argument,
251 "address 0x%" PRIx64 " is not in GSYM", Addr);
252
253}
254
257 uint64_t &FuncStartAddr) const {
258 Expected<uint64_t> ExpectedAddrIdx = getAddressIndex(Addr);
259 if (!ExpectedAddrIdx)
260 return ExpectedAddrIdx.takeError();
261 const uint64_t FirstAddrIdx = *ExpectedAddrIdx;
262 // The AddrIdx is the first index of the function info entries that match
263 // \a Addr. We need to iterate over all function info objects that start with
264 // the same address until we find a range that contains \a Addr.
265 std::optional<uint64_t> FirstFuncStartAddr;
266 const size_t NumAddresses = getNumAddresses();
267 for (uint64_t AddrIdx = FirstAddrIdx; AddrIdx < NumAddresses; ++AddrIdx) {
268 auto ExpextedData = getFunctionInfoDataAtIndex(AddrIdx, FuncStartAddr);
269 // If there was an error, return the error.
270 if (!ExpextedData)
271 return ExpextedData;
272
273 // Remember the first function start address if it hasn't already been set.
274 // If it is already valid, check to see if it matches the first function
275 // start address and only continue if it matches.
276 if (FirstFuncStartAddr.has_value()) {
277 if (*FirstFuncStartAddr != FuncStartAddr)
278 break; // Done with consecutive function entries with same address.
279 } else {
280 FirstFuncStartAddr = FuncStartAddr;
281 }
282 // Make sure the current function address ranges contains \a Addr.
283 // Some symbols on Darwin don't have valid sizes, so if we run into a
284 // symbol with zero size, then we have found a match for our address.
285
286 // The first thing the encoding of a FunctionInfo object is the function
287 // size.
288 uint64_t Offset = 0;
289 uint32_t FuncSize = ExpextedData->getU32(&Offset);
290 if (FuncSize == 0 ||
291 AddressRange(FuncStartAddr, FuncStartAddr + FuncSize).contains(Addr))
292 return ExpextedData;
293 }
294 return createStringError(std::errc::invalid_argument,
295 "address 0x%" PRIx64 " is not in GSYM", Addr);
296}
297
300 uint64_t &FuncStartAddr) const {
301 if (AddrIdx >= getNumAddresses())
302 return createStringError(std::errc::invalid_argument,
303 "invalid address index %" PRIu64, AddrIdx);
304 const uint32_t AddrInfoOffset = AddrInfoOffsets[AddrIdx];
305 assert((Endian == endianness::big || Endian == endianness::little) &&
306 "Endian must be either big or little");
307 StringRef Bytes = MemBuffer->getBuffer().substr(AddrInfoOffset);
308 if (Bytes.empty())
309 return createStringError(std::errc::invalid_argument,
310 "invalid address info offset 0x%" PRIx32,
311 AddrInfoOffset);
312 std::optional<uint64_t> OptFuncStartAddr = getAddress(AddrIdx);
313 if (!OptFuncStartAddr)
314 return createStringError(std::errc::invalid_argument,
315 "failed to extract address[%" PRIu64 "]", AddrIdx);
316 FuncStartAddr = *OptFuncStartAddr;
317 return DataExtractor(Bytes, Endian == llvm::endianness::little, 4);
318}
319
321 uint64_t FuncStartAddr = 0;
322 if (auto ExpectedData = getFunctionInfoDataForAddress(Addr, FuncStartAddr))
323 return FunctionInfo::decode(*ExpectedData, FuncStartAddr);
324 else
325 return ExpectedData.takeError();
326}
327
330 uint64_t FuncStartAddr = 0;
331 if (auto ExpectedData = getFunctionInfoDataAtIndex(Idx, FuncStartAddr))
332 return FunctionInfo::decode(*ExpectedData, FuncStartAddr);
333 else
334 return ExpectedData.takeError();
335}
336
338 uint64_t FuncStartAddr = 0;
339 if (auto ExpectedData = getFunctionInfoDataForAddress(Addr, FuncStartAddr))
340 return FunctionInfo::lookup(*ExpectedData, *this, FuncStartAddr, Addr);
341 else
342 return ExpectedData.takeError();
343}
344
346 const auto &Header = getHeader();
347 // Dump the GSYM header.
348 OS << Header << "\n";
349 // Dump the address table.
350 OS << "Address Table:\n";
351 OS << "INDEX OFFSET";
352
353 switch (Hdr->AddrOffSize) {
354 case 1: OS << "8 "; break;
355 case 2: OS << "16"; break;
356 case 4: OS << "32"; break;
357 case 8: OS << "64"; break;
358 default: OS << "??"; break;
359 }
360 OS << " (ADDRESS)\n";
361 OS << "====== =============================== \n";
362 for (uint32_t I = 0; I < Header.NumAddresses; ++I) {
363 OS << format("[%4u] ", I);
364 switch (Hdr->AddrOffSize) {
365 case 1: OS << HEX8(getAddrOffsets<uint8_t>()[I]); break;
366 case 2: OS << HEX16(getAddrOffsets<uint16_t>()[I]); break;
367 case 4: OS << HEX32(getAddrOffsets<uint32_t>()[I]); break;
368 case 8: OS << HEX32(getAddrOffsets<uint64_t>()[I]); break;
369 default: break;
370 }
371 OS << " (" << HEX64(*getAddress(I)) << ")\n";
372 }
373 // Dump the address info offsets table.
374 OS << "\nAddress Info Offsets:\n";
375 OS << "INDEX Offset\n";
376 OS << "====== ==========\n";
377 for (uint32_t I = 0; I < Header.NumAddresses; ++I)
378 OS << format("[%4u] ", I) << HEX32(AddrInfoOffsets[I]) << "\n";
379 // Dump the file table.
380 OS << "\nFiles:\n";
381 OS << "INDEX DIRECTORY BASENAME PATH\n";
382 OS << "====== ========== ========== ==============================\n";
383 for (uint32_t I = 0; I < Files.size(); ++I) {
384 OS << format("[%4u] ", I) << HEX32(Files[I].Dir) << ' '
385 << HEX32(Files[I].Base) << ' ';
386 dump(OS, getFile(I));
387 OS << "\n";
388 }
389 OS << "\n" << StrTab << "\n";
390
391 for (uint32_t I = 0; I < Header.NumAddresses; ++I) {
392 OS << "FunctionInfo @ " << HEX32(AddrInfoOffsets[I]) << ": ";
393 if (auto FI = getFunctionInfoAtIndex(I))
394 dump(OS, *FI);
395 else
396 logAllUnhandledErrors(FI.takeError(), OS, "FunctionInfo:");
397 }
398}
399
401 uint32_t Indent) {
402 OS.indent(Indent);
403 OS << FI.Range << " \"" << getString(FI.Name) << "\"\n";
404 if (FI.OptLineTable)
405 dump(OS, *FI.OptLineTable, Indent);
406 if (FI.Inline)
407 dump(OS, *FI.Inline, Indent);
408
409 if (FI.CallSites)
410 dump(OS, *FI.CallSites, Indent);
411
412 if (FI.MergedFunctions) {
413 assert(Indent == 0 && "MergedFunctionsInfo should only exist at top level");
414 dump(OS, *FI.MergedFunctions);
415 }
416}
417
419 for (uint32_t inx = 0; inx < MFI.MergedFunctions.size(); inx++) {
420 OS << "++ Merged FunctionInfos[" << inx << "]:\n";
421 dump(OS, MFI.MergedFunctions[inx], 4);
422 }
423}
424
426 OS << HEX16(CSI.ReturnOffset);
427
428 std::string Flags;
429 auto addFlag = [&](const char *Flag) {
430 if (!Flags.empty())
431 Flags += " | ";
432 Flags += Flag;
433 };
434
436 Flags = "None";
437 else {
439 addFlag("InternalCall");
440
442 addFlag("ExternalCall");
443 }
444 OS << " Flags[" << Flags << "]";
445
446 if (!CSI.MatchRegex.empty()) {
447 OS << " MatchRegex[";
448 for (uint32_t i = 0; i < CSI.MatchRegex.size(); ++i) {
449 if (i > 0)
450 OS << ";";
451 OS << getString(CSI.MatchRegex[i]);
452 }
453 OS << "]";
454 }
455}
456
458 uint32_t Indent) {
459 OS.indent(Indent);
460 OS << "CallSites (by relative return offset):\n";
461 for (const auto &CS : CSIC.CallSites) {
462 OS.indent(Indent);
463 OS << " ";
464 dump(OS, CS);
465 OS << "\n";
466 }
467}
468
470 OS.indent(Indent);
471 OS << "LineTable:\n";
472 for (auto &LE: LT) {
473 OS.indent(Indent);
474 OS << " " << HEX64(LE.Addr) << ' ';
475 if (LE.File)
476 dump(OS, getFile(LE.File));
477 OS << ':' << LE.Line << '\n';
478 }
479}
480
482 if (Indent == 0)
483 OS << "InlineInfo:\n";
484 else
485 OS.indent(Indent);
486 OS << II.Ranges << ' ' << getString(II.Name);
487 if (II.CallFile != 0) {
488 if (auto File = getFile(II.CallFile)) {
489 OS << " called from ";
490 dump(OS, File);
491 OS << ':' << II.CallLine;
492 }
493 }
494 OS << '\n';
495 for (const auto &ChildII: II.Children)
496 dump(OS, ChildII, Indent + 2);
497}
498
499void GsymReader::dump(raw_ostream &OS, std::optional<FileEntry> FE) {
500 if (FE) {
501 // IF we have the file from index 0, then don't print anything
502 if (FE->Dir == 0 && FE->Base == 0)
503 return;
504 StringRef Dir = getString(FE->Dir);
505 StringRef Base = getString(FE->Base);
506 if (!Dir.empty()) {
507 OS << Dir;
508 if (Dir.contains('\\') && !Dir.contains('/'))
509 OS << '\\';
510 else
511 OS << '/';
512 }
513 if (!Base.empty()) {
514 OS << Base;
515 }
516 if (!Dir.empty() || !Base.empty())
517 return;
518 }
519 OS << "<invalid-file>";
520}
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Addr
#define HEX16(v)
Definition: ExtractRanges.h:18
#define HEX64(v)
Definition: ExtractRanges.h:20
#define HEX32(v)
Definition: ExtractRanges.h:19
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
endianness Endian
raw_pwrite_stream & OS
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
A class that represents an address range.
Definition: AddressRanges.h:22
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
Provides read only access to a subclass of BinaryStream.
Represents either an error or a value T.
Definition: ErrorOr.h:56
reference get()
Definition: ErrorOr.h:149
std::error_code getError() const
Definition: ErrorOr.h:152
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
GsymReader is used to read GSYM data from a file or buffer.
Definition: GsymReader.h:44
std::optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
Definition: GsymReader.h:150
void dump(raw_ostream &OS)
Dump the entire Gsym data contained in this object.
Definition: GsymReader.cpp:345
uint32_t getNumAddresses() const
Get the number of addresses in this Gsym file.
Definition: GsymReader.h:246
static llvm::Expected< GsymReader > openFile(StringRef Path)
Construct a GsymReader from a file on disk.
Definition: GsymReader.cpp:32
std::optional< uint64_t > getAddress(size_t Index) const
Gets an address from the address table.
Definition: GsymReader.cpp:207
std::optional< uint64_t > getAddressInfoOffset(size_t Index) const
Given an address index, get the offset for the FunctionInfo.
Definition: GsymReader.cpp:217
StringRef getString(uint32_t Offset) const
Get a string from the string table.
Definition: GsymReader.h:139
llvm::Expected< FunctionInfo > getFunctionInfo(uint64_t Addr) const
Get the full function info for an address.
Definition: GsymReader.cpp:320
const Header & getHeader() const
Access the GSYM header.
Definition: GsymReader.cpp:199
llvm::Expected< llvm::DataExtractor > getFunctionInfoDataAtIndex(uint64_t AddrIdx, uint64_t &FuncStartAddr) const
Get the function data and address given an address index.
Definition: GsymReader.cpp:299
Expected< uint64_t > getAddressIndex(const uint64_t Addr) const
Given an address, find the address index.
Definition: GsymReader.cpp:225
llvm::Expected< LookupResult > lookup(uint64_t Addr) const
Lookup an address in the a GSYM.
Definition: GsymReader.cpp:337
static llvm::Expected< GsymReader > copyBuffer(StringRef Bytes)
Construct a GsymReader from a buffer.
Definition: GsymReader.cpp:42
static llvm::Expected< llvm::gsym::GsymReader > create(std::unique_ptr< MemoryBuffer > &MemBuffer)
Create a GSYM from a memory buffer.
Definition: GsymReader.cpp:48
llvm::Expected< FunctionInfo > getFunctionInfoAtIndex(uint64_t AddrIdx) const
Get the full function info given an address index.
Definition: GsymReader.cpp:329
llvm::Expected< llvm::DataExtractor > getFunctionInfoDataForAddress(uint64_t Addr, uint64_t &FuncStartAddr) const
Given an address, find the correct function info data and function address.
Definition: GsymReader.cpp:256
LineTable class contains deserialized versions of line tables for each function's address ranges.
Definition: LineTable.h:118
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
constexpr uint32_t GSYM_MAGIC
Definition: Header.h:24
constexpr uint32_t GSYM_CIGAM
Definition: Header.h:25
constexpr bool IsBigEndianHost
Definition: SwapByteOrder.h:26
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:65
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1291
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1873
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:111
endianness
Definition: bit.h:70
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
std::vector< CallSiteInfo > CallSites
Definition: CallSiteInfo.h:68
std::vector< uint32_t > MatchRegex
Offsets into the string table for function names regex patterns.
Definition: CallSiteInfo.h:47
uint64_t ReturnOffset
The return offset of the call site - relative to the function start.
Definition: CallSiteInfo.h:44
Function information in GSYM files encodes information for one contiguous address range.
Definition: FunctionInfo.h:92
std::optional< InlineInfo > Inline
Definition: FunctionInfo.h:96
std::optional< MergedFunctionsInfo > MergedFunctions
Definition: FunctionInfo.h:97
std::optional< CallSiteInfoCollection > CallSites
Definition: FunctionInfo.h:98
static llvm::Expected< LookupResult > lookup(DataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr)
Lookup an address within a FunctionInfo object's data stream.
uint32_t Name
String table offset in the string table.
Definition: FunctionInfo.h:94
std::optional< LineTable > OptLineTable
Definition: FunctionInfo.h:95
static llvm::Expected< FunctionInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an object from a binary data stream.
The GSYM header.
Definition: Header.h:45
uint8_t AddrOffSize
The size in bytes of each address offset in the address offsets table.
Definition: Header.h:56
static llvm::Expected< Header > decode(DataExtractor &Data)
Decode an object from a binary data stream.
Definition: Header.cpp:64
uint32_t Magic
The magic bytes should be set to GSYM_MAGIC.
Definition: Header.h:49
uint32_t StrtabOffset
The file relative offset of the start of the string table for strings contained in the GSYM file.
Definition: Header.h:72
uint32_t StrtabSize
The size in bytes of the string table.
Definition: Header.h:80
llvm::Error checkForError() const
Check if a header is valid and return an error if anything is wrong.
Definition: Header.cpp:41
uint32_t NumAddresses
The number of addresses stored in the address offsets table.
Definition: Header.h:64
uint64_t BaseAddress
The 64 bit base address that all address offsets in the address offsets table are relative to.
Definition: Header.h:62
Inline information stores the name of the inline function along with an array of address ranges.
Definition: InlineInfo.h:59
std::vector< FunctionInfo > MergedFunctions