LLVM 23.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
23
24using namespace llvm;
25using namespace gsym;
26
27GsymReader::GsymReader(std::unique_ptr<MemoryBuffer> Buffer,
29 : MemBuffer(std::move(Buffer)), Endian(Endian),
31}
32
33/// Check magic bytes, determine endianness, and return the GSYM version and
34/// endianness. If magic bytes are invalid, return error.
37 if (Bytes.size() < 6)
38 return createStringError(std::errc::invalid_argument,
39 "data too small to be a GSYM file");
40 // Detect host endian
41 const auto HostEndian = llvm::endianness::native;
42 const bool IsHostLittleEndian = (HostEndian == llvm::endianness::little);
43 // Read magic bytes using host endian
44 GsymDataExtractor Data(Bytes, IsHostLittleEndian);
45 uint64_t Offset = 0;
46 uint32_t Magic = Data.getU32(&Offset);
47 llvm::endianness FileEndian;
48 // If magic bytes looks alright, the host and the file have the same
49 // endianness, vice versa.
50 if (Magic == GSYM_MAGIC) {
51 FileEndian = HostEndian;
52 } else if (Magic == GSYM_CIGAM) {
53 FileEndian =
55 // Re-create GsymDataExtractor with correct endianness to read version.
56 Data = GsymDataExtractor(Bytes, !IsHostLittleEndian);
57 } else {
58 return createStringError(std::errc::invalid_argument,
59 "not a GSYM file (bad magic)");
60 }
61 // Read version using the correct endian
62 uint16_t Version = Data.getU16(&Offset);
63 return std::make_pair(Version, FileEndian);
64}
65
66llvm::Expected<std::unique_ptr<GsymReader>>
68 // Open the input file and return an appropriate error if needed.
71 auto Err = BuffOrErr.getError();
72 if (Err)
73 return llvm::errorCodeToError(Err);
74 return create(BuffOrErr.get());
75}
76
79 auto MemBuffer = MemoryBuffer::getMemBufferCopy(Bytes, "GSYM bytes");
80 return create(MemBuffer);
81}
82
84GsymReader::create(std::unique_ptr<MemoryBuffer> &MemBuffer) {
85 if (!MemBuffer)
86 return createStringError(std::errc::invalid_argument,
87 "invalid memory buffer");
90 if (!VersionEndianOrErr)
91 return VersionEndianOrErr.takeError();
94 std::tie(Version, Endian) = *VersionEndianOrErr;
95 std::unique_ptr<GsymReader> GR;
96 switch (Version) {
97 case Header::getVersion():
98 GR.reset(new GsymReaderV1(std::move(MemBuffer), Endian));
99 break;
101 GR.reset(new GsymReaderV2(std::move(MemBuffer), Endian));
102 break;
103 default:
104 return createStringError(std::errc::invalid_argument,
105 "unsupported GSYM version %u", Version);
106 }
107 if (auto Err = GR->parse())
108 return std::move(Err);
109 return std::move(GR);
110}
111
113 // Step 1: Parse the version-specific header and populate GlobalDataSections.
114 if (auto Err = parseHeaderAndGlobalDataEntries())
115 return Err;
116
117 // Step 2: Validate that all required sections are present and consistent.
118 for (auto Type :
122 if (!GlobalDataSections.count(Type))
123 return createStringError(
124 std::errc::invalid_argument, "missing required section type %s (%u)",
126
129 return createStringError(std::errc::invalid_argument,
130 "AddrOffsets section size mismatch");
131
134 return createStringError(std::errc::invalid_argument,
135 "AddrInfoOffsets section size mismatch");
136
137 // Step 3: Parse each global data section.
140 if (!Bytes)
141 return Bytes.takeError();
142 if (auto Err = parseAddrOffsets(*Bytes))
143 return Err;
144
146 if (!Bytes)
147 return Bytes.takeError();
148 if (auto Err = setAddrInfoOffsetsData(*Bytes))
149 return Err;
150
152 if (!Bytes)
153 return Bytes.takeError();
154 if (auto Err = setStringTableData(*Bytes))
155 return Err;
156
158 if (!Bytes)
159 return Bytes.takeError();
160 if (auto Err = setFileTableData(*Bytes))
161 return Err;
162
163 return Error::success();
164}
165
168 return createStringError(std::errc::invalid_argument,
169 "GlobalData section not supported in GSYM V1");
170
171 const StringRef Buf = MemBuffer->getBuffer();
172 const uint64_t BufSize = Buf.size();
174 while (Offset + sizeof(GlobalData) <= BufSize) {
175 auto GDOrErr = GlobalData::decode(Data, Offset);
176 if (!GDOrErr)
177 return GDOrErr.takeError();
178 const GlobalData &GD = *GDOrErr;
179
181 return Error::success();
182
183 if (GD.FileSize == 0)
184 return createStringError(std::errc::invalid_argument,
185 "GlobalData section type %u has zero size",
186 static_cast<uint32_t>(GD.Type));
187
188 if (GD.FileOffset + GD.FileSize > BufSize)
189 return createStringError(
190 std::errc::invalid_argument,
191 "GlobalData section type %u extends beyond "
192 "buffer (offset=%" PRIu64 ", size=%" PRIu64 ", bufsize=%" PRIu64 ")",
193 static_cast<uint32_t>(GD.Type), GD.FileOffset, GD.FileSize, BufSize);
194
195 GlobalDataSections[GD.Type] = GD;
196 }
197 return createStringError(std::errc::invalid_argument,
198 "GlobalData array not terminated by EndOfList");
199}
200
202 const uint8_t AddrOffSize = getAddressOffsetSize();
203 const uint32_t NumAddrs = getNumAddresses();
204 const size_t TotalBytes = NumAddrs * AddrOffSize;
205 if (Bytes.size() < TotalBytes)
206 return createStringError(std::errc::invalid_argument,
207 "failed to read address table");
208
209 // Parse the non-swap case
212 reinterpret_cast<const uint8_t *>(Bytes.data()), TotalBytes);
213 return Error::success();
214 }
215
216 // Parse the swap case
218 uint64_t Offset = 0;
219 SwappedAddrOffsets.resize(TotalBytes);
220 switch (AddrOffSize) {
221 case 1:
222 if (!Data.getU8(&Offset, SwappedAddrOffsets.data(), NumAddrs))
223 return createStringError(std::errc::invalid_argument,
224 "failed to read address table");
225 break;
226 case 2:
227 if (!Data.getU16(&Offset,
228 reinterpret_cast<uint16_t *>(SwappedAddrOffsets.data()),
229 NumAddrs))
230 return createStringError(std::errc::invalid_argument,
231 "failed to read address table");
232 break;
233 case 4:
234 if (!Data.getU32(&Offset,
235 reinterpret_cast<uint32_t *>(SwappedAddrOffsets.data()),
236 NumAddrs))
237 return createStringError(std::errc::invalid_argument,
238 "failed to read address table");
239 break;
240 case 8:
241 if (!Data.getU64(&Offset,
242 reinterpret_cast<uint64_t *>(SwappedAddrOffsets.data()),
243 NumAddrs))
244 return createStringError(std::errc::invalid_argument,
245 "failed to read address table");
246 break;
247 }
249 return Error::success();
250}
251
256
258 StrTab.Data = Bytes;
259 return Error::success();
260}
263 const uint8_t StrpSize = getStringOffsetSize();
264 GsymDataExtractor Data(Bytes, isLittleEndian(), StrpSize);
265 uint64_t Offset = 0;
266 uint32_t NumFiles = Data.getU32(&Offset);
267 uint64_t EntriesSize =
268 static_cast<uint64_t>(NumFiles) * FileEntry::getEncodedSize(StrpSize);
269 if (Bytes.size() < Offset + EntriesSize)
270 return createStringError(std::errc::invalid_argument,
271 "FileTable section too small for %u files",
272 NumFiles);
275}
276
277std::optional<GlobalData> GsymReader::getGlobalData(GlobalInfoType Type) const {
278 auto It = GlobalDataSections.find(Type);
279 if (It == GlobalDataSections.end())
280 return std::nullopt;
281 return It->second;
282}
283
287 return *Data;
288 const char *TypeName = getNameForGlobalInfoType(Type).data();
289 std::optional<GlobalData> GD = getGlobalData(Type);
290 // We have a GlobalData entry but didn't get any bytes — the file may be
291 // truncated.
292 if (GD)
293 return createStringError(
294 std::errc::invalid_argument,
295 "missing bytes for %s, GSYM file might be truncated", TypeName);
296 return createStringError(std::errc::invalid_argument,
297 "missing required section type %s", TypeName);
298}
299
300std::optional<StringRef>
302 std::optional<GlobalData> GD = getGlobalData(Type);
303 if (!GD)
304 return std::nullopt;
305 StringRef Buf = MemBuffer->getBuffer();
306 if (GD->FileSize == 0 || GD->FileOffset + GD->FileSize > Buf.size())
307 return std::nullopt;
308 return Buf.substr(GD->FileOffset, GD->FileSize);
309}
310
311std::optional<uint64_t> GsymReader::getAddress(size_t Index) const {
312 switch (getAddressOffsetSize()) {
313 case 1: return addressForIndex<uint8_t>(Index);
314 case 2: return addressForIndex<uint16_t>(Index);
315 case 4: return addressForIndex<uint32_t>(Index);
316 case 8: return addressForIndex<uint64_t>(Index);
317 default:
318 llvm_unreachable("unsupported address offset size");
319 }
320 return std::nullopt;
321}
322
323std::optional<uint64_t> GsymReader::getAddressInfoOffset(size_t Index) const {
324 if (Index >= getNumAddresses())
325 return std::nullopt;
326 const uint8_t AddrInfoOffsetSize = getAddressInfoOffsetSize();
327 uint64_t Offset = Index * AddrInfoOffsetSize;
328 uint64_t AddrInfoOffset =
329 AddrInfoOffsetsData.getUnsigned(&Offset, AddrInfoOffsetSize);
330 // V1 stores absolute file offsets in AddrInfoOffsets, so no base offset is
331 // needed. V2+ stores offsets relative to the FunctionInfo section start.
333 AddrInfoOffset +=
335 return AddrInfoOffset;
336}
337
339 const uint64_t BaseAddr = getBaseAddress();
340 if (Addr >= BaseAddr) {
341 const uint64_t AddrOffset = Addr - BaseAddr;
342 std::optional<uint64_t> AddrOffsetIndex;
343 switch (getAddressOffsetSize()) {
344 case 1:
345 AddrOffsetIndex = getAddressOffsetIndex<uint8_t>(AddrOffset);
346 break;
347 case 2:
348 AddrOffsetIndex = getAddressOffsetIndex<uint16_t>(AddrOffset);
349 break;
350 case 4:
351 AddrOffsetIndex = getAddressOffsetIndex<uint32_t>(AddrOffset);
352 break;
353 case 8:
354 AddrOffsetIndex = getAddressOffsetIndex<uint64_t>(AddrOffset);
355 break;
356 default:
357 return createStringError(std::errc::invalid_argument,
358 "unsupported address offset size %u",
360 }
361 if (AddrOffsetIndex)
362 return *AddrOffsetIndex;
363 }
364 return createStringError(std::errc::invalid_argument,
365 "address 0x%" PRIx64 " is not in GSYM", Addr);
366}
367
370 uint64_t &FuncStartAddr) const {
371 Expected<uint64_t> ExpectedAddrIdx = getAddressIndex(Addr);
372 if (!ExpectedAddrIdx)
373 return ExpectedAddrIdx.takeError();
374 const uint64_t FirstAddrIdx = *ExpectedAddrIdx;
375 // The AddrIdx is the first index of the function info entries that match
376 // \a Addr. We need to iterate over all function info objects that start with
377 // the same address until we find a range that contains \a Addr.
378 std::optional<uint64_t> FirstFuncStartAddr;
379 const size_t NumAddresses = getNumAddresses();
380 for (uint64_t AddrIdx = FirstAddrIdx; AddrIdx < NumAddresses; ++AddrIdx) {
381 auto ExpextedData = getFunctionInfoDataAtIndex(AddrIdx, FuncStartAddr);
382 // If there was an error, return the error.
383 if (!ExpextedData)
384 return ExpextedData;
385
386 // Remember the first function start address if it hasn't already been set.
387 // If it is already valid, check to see if it matches the first function
388 // start address and only continue if it matches.
389 if (FirstFuncStartAddr.has_value()) {
390 if (*FirstFuncStartAddr != FuncStartAddr)
391 break; // Done with consecutive function entries with same address.
392 } else {
393 FirstFuncStartAddr = FuncStartAddr;
394 }
395 // Make sure the current function address ranges contains \a Addr.
396 // Some symbols on Darwin don't have valid sizes, so if we run into a
397 // symbol with zero size, then we have found a match for our address.
398
399 // The first thing the encoding of a FunctionInfo object is the function
400 // size.
401 uint64_t Offset = 0;
402 uint32_t FuncSize = ExpextedData->getU32(&Offset);
403 if (FuncSize == 0 ||
404 AddressRange(FuncStartAddr, FuncStartAddr + FuncSize).contains(Addr))
405 return ExpextedData;
406 }
407 return createStringError(std::errc::invalid_argument,
408 "address 0x%" PRIx64 " is not in GSYM", Addr);
409}
410
413 uint64_t &FuncStartAddr) const {
414 const std::optional<uint64_t> AddrInfoOffset = getAddressInfoOffset(AddrIdx);
415 if (AddrInfoOffset == std::nullopt)
416 return createStringError(std::errc::invalid_argument,
417 "invalid address index %" PRIu64, AddrIdx);
419 "Endian must be either big or little");
420 StringRef Bytes = MemBuffer->getBuffer().substr(*AddrInfoOffset);
421 if (Bytes.empty())
422 return createStringError(std::errc::invalid_argument,
423 "invalid address info offset 0x%" PRIx64,
424 *AddrInfoOffset);
425 std::optional<uint64_t> OptFuncStartAddr = getAddress(AddrIdx);
426 if (!OptFuncStartAddr)
427 return createStringError(std::errc::invalid_argument,
428 "failed to extract address[%" PRIu64 "]", AddrIdx);
429 FuncStartAddr = *OptFuncStartAddr;
431 return Data;
432}
433
435 uint64_t FuncStartAddr = 0;
436 if (auto ExpectedData = getFunctionInfoDataForAddress(Addr, FuncStartAddr))
437 return FunctionInfo::decode(*ExpectedData, FuncStartAddr);
438 else
439 return ExpectedData.takeError();
440}
441
444 uint64_t FuncStartAddr = 0;
445 if (auto ExpectedData = getFunctionInfoDataAtIndex(Idx, FuncStartAddr))
446 return FunctionInfo::decode(*ExpectedData, FuncStartAddr);
447 else
448 return ExpectedData.takeError();
449}
450
452 uint64_t Addr,
453 std::optional<GsymDataExtractor> *MergedFunctionsData) const {
454 uint64_t FuncStartAddr = 0;
455 if (auto ExpectedData = getFunctionInfoDataForAddress(Addr, FuncStartAddr))
456 return FunctionInfo::lookup(*ExpectedData, *this, FuncStartAddr, Addr,
457 MergedFunctionsData);
458 else
459 return ExpectedData.takeError();
460}
461
464 std::vector<LookupResult> Results;
465 std::optional<GsymDataExtractor> MergedFunctionsData;
466
467 // First perform a lookup to get the primary function info result.
468 auto MainResult = lookup(Addr, &MergedFunctionsData);
469 if (!MainResult)
470 return MainResult.takeError();
471
472 // Add the main result as the first entry.
473 Results.push_back(std::move(*MainResult));
474
475 // Now process any merged functions data that was found during the lookup.
476 if (MergedFunctionsData) {
477 // Get data extractors for each merged function.
478 auto ExpectedMergedFuncExtractors =
480 if (!ExpectedMergedFuncExtractors)
481 return ExpectedMergedFuncExtractors.takeError();
482
483 // Process each merged function data.
484 for (GsymDataExtractor &MergedData : *ExpectedMergedFuncExtractors) {
485 if (auto FI = FunctionInfo::lookup(MergedData, *this,
486 MainResult->FuncRange.start(), Addr)) {
487 Results.push_back(std::move(*FI));
488 } else {
489 return FI.takeError();
490 }
491 }
492 }
493
494 return Results;
495}
496
498 uint32_t Indent) {
499 OS.indent(Indent);
500 OS << FI.Range << " \"" << getString(FI.Name) << "\"\n";
501 if (FI.OptLineTable)
502 dump(OS, *FI.OptLineTable, Indent);
503 if (FI.Inline)
504 dump(OS, *FI.Inline, Indent);
505
506 if (FI.CallSites)
507 dump(OS, *FI.CallSites, Indent);
508
509 if (FI.MergedFunctions) {
510 assert(Indent == 0 && "MergedFunctionsInfo should only exist at top level");
511 dump(OS, *FI.MergedFunctions);
512 }
513}
514
516 for (uint32_t inx = 0; inx < MFI.MergedFunctions.size(); inx++) {
517 OS << "++ Merged FunctionInfos[" << inx << "]:\n";
518 dump(OS, MFI.MergedFunctions[inx], 4);
519 }
520}
521
523 OS << HEX16(CSI.ReturnOffset);
524
525 std::string Flags;
526 auto addFlag = [&](const char *Flag) {
527 if (!Flags.empty())
528 Flags += " | ";
529 Flags += Flag;
530 };
531
533 Flags = "None";
534 else {
536 addFlag("InternalCall");
537
539 addFlag("ExternalCall");
540 }
541 OS << " Flags[" << Flags << "]";
542
543 if (!CSI.MatchRegex.empty()) {
544 OS << " MatchRegex[";
545 for (uint32_t i = 0; i < CSI.MatchRegex.size(); ++i) {
546 if (i > 0)
547 OS << ";";
548 OS << getString(CSI.MatchRegex[i]);
549 }
550 OS << "]";
551 }
552}
553
555 uint32_t Indent) {
556 OS.indent(Indent);
557 OS << "CallSites (by relative return offset):\n";
558 for (const auto &CS : CSIC.CallSites) {
559 OS.indent(Indent);
560 OS << " ";
561 dump(OS, CS);
562 OS << "\n";
563 }
564}
565
566void GsymReader::dump(raw_ostream &OS, const LineTable &LT, uint32_t Indent) {
567 OS.indent(Indent);
568 OS << "LineTable:\n";
569 for (auto &LE : LT) {
570 OS.indent(Indent);
571 OS << " " << HEX64(LE.Addr) << ' ';
572 if (LE.File)
573 dump(OS, getFile(LE.File));
574 OS << ':' << LE.Line << '\n';
575 }
576}
577
579 if (Indent == 0)
580 OS << "InlineInfo:\n";
581 else
582 OS.indent(Indent);
583 OS << II.Ranges << ' ' << getString(II.Name);
584 if (II.CallFile != 0) {
585 if (auto File = getFile(II.CallFile)) {
586 OS << " called from ";
587 dump(OS, File);
588 OS << ':' << II.CallLine;
589 }
590 }
591 OS << '\n';
592 for (const auto &ChildII : II.Children)
593 dump(OS, ChildII, Indent + 2);
594}
595
596void GsymReader::dump(raw_ostream &OS, std::optional<FileEntry> FE) {
597 if (FE) {
598 // IF we have the file from index 0, then don't print anything
599 if (FE->Dir == 0 && FE->Base == 0)
600 return;
601 StringRef Dir = getString(FE->Dir);
602 StringRef Base = getString(FE->Base);
603 if (!Dir.empty()) {
604 OS << Dir;
605 if (Dir.contains('\\') && !Dir.contains('/'))
606 OS << '\\';
607 else
608 OS << '/';
609 }
610 if (!Base.empty()) {
611 OS << Base;
612 }
613 if (!Dir.empty() || !Base.empty())
614 return;
615 }
616 OS << "<invalid-file>";
617}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
#define HEX16(v)
#define HEX64(v)
static Expected< std::pair< uint16_t, llvm::endianness > > checkMagicAndDetectVersionEndian(StringRef Bytes)
Check magic bytes, determine endianness, and return the GSYM version and endianness.
uint64_t IntrinsicInst * II
static constexpr StringLiteral Filename
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:483
static Split data
A class that represents an address range.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
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:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:143
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:137
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
A DataExtractor subclass that adds GSYM-specific string offset support.
GsymReaderV1 reads GSYM V1 data from a buffer.
GsymReaderV2 reads GSYM V2 data from a buffer.
StringRef getString(gsym_strp_t Offset) const
Get a string from the string table.
Definition GsymReader.h:173
llvm::Error setAddrInfoOffsetsData(StringRef Bytes)
Set address info offsets section bytes into AddrInfoOffsetsData.
llvm::Error parseGlobalDataEntries(uint64_t Offset)
Parse GlobalData entries starting at Offset into GlobalDataSections.
GsymDataExtractor FileEntryData
Definition GsymReader.h:58
LLVM_ABI llvm::Expected< GsymDataExtractor > getFunctionInfoDataAtIndex(uint64_t AddrIdx, uint64_t &FuncStartAddr) const
Get the function data and address given an address index.
virtual uint8_t getStringOffsetSize() const =0
Get the string offset byte size for this GSYM file.
static LLVM_ABI llvm::Expected< std::unique_ptr< GsymReader > > copyBuffer(StringRef Bytes)
Construct a GsymReader from a buffer.
virtual llvm::Error parseHeaderAndGlobalDataEntries()=0
Parse the version-specific header and populate GlobalDataSections.
std::optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
Definition GsymReader.h:184
bool isLittleEndian() const
Definition GsymReader.h:67
LLVM_ABI std::optional< GlobalData > getGlobalData(GlobalInfoType Type) const
Get the GlobalData entry for a section type.
ArrayRef< uint8_t > AddrOffsets
Definition GsymReader.h:55
llvm::Error setFileTableData(StringRef Bytes)
Set file table section bytes into FileEntryData.
GsymDataExtractor AddrInfoOffsetsData
Definition GsymReader.h:57
static LLVM_ABI llvm::Expected< std::unique_ptr< GsymReader > > create(std::unique_ptr< MemoryBuffer > &MemBuffer)
Create a GSYM from a memory buffer.
LLVM_ABI std::optional< uint64_t > getAddress(size_t Index) const
Gets an address from the address table.
LLVM_ABI std::optional< uint64_t > getAddressInfoOffset(size_t Index) const
Given an address index, get the offset for the FunctionInfo.
GsymReader(std::unique_ptr< MemoryBuffer > Buffer, llvm::endianness Endian)
virtual uint16_t getVersion() const =0
Get the GSYM version for this reader.
llvm::Error setStringTableData(StringRef Bytes)
Set string table section bytes into StrTab.
LLVM_ABI llvm::Expected< StringRef > getRequiredGlobalDataBytes(GlobalInfoType Type) const
Get the raw bytes for a required GlobalData section as a StringRef.
LLVM_ABI llvm::Expected< FunctionInfo > getFunctionInfo(uint64_t Addr) const
Get the full function info for an address.
std::optional< uint64_t > addressForIndex(size_t Index) const
Get an appropriate address from the address table.
Definition GsymReader.h:422
LLVM_ABI llvm::Expected< LookupResult > lookup(uint64_t Addr, std::optional< GsymDataExtractor > *MergedFuncsData=nullptr) const
Lookup an address in the a GSYM.
std::vector< uint8_t > SwappedAddrOffsets
Definition GsymReader.h:56
llvm::Error parseAddrOffsets(StringRef Bytes)
Parse address offsets section bytes into AddrOffsets.
LLVM_ABI llvm::Expected< GsymDataExtractor > getFunctionInfoDataForAddress(uint64_t Addr, uint64_t &FuncStartAddr) const
Given an address, find the correct function info data and function address.
LLVM_ABI Expected< uint64_t > getAddressIndex(const uint64_t Addr) const
Given an address, find the address index.
virtual uint64_t getNumAddresses() const =0
Get the number of addresses in this GSYM file.
std::map< GlobalInfoType, GlobalData > GlobalDataSections
Parsed GlobalData entries, keyed by type.
Definition GsymReader.h:54
LLVM_ABI llvm::Error parse()
Parse the GSYM data from the memory buffer.
virtual uint8_t getAddressInfoOffsetSize() const =0
Get the address info offset byte size for this GSYM file.
std::unique_ptr< MemoryBuffer > MemBuffer
Definition GsymReader.h:50
virtual void dump(raw_ostream &OS)=0
Dump the entire Gsym data contained in this object.
static LLVM_ABI llvm::Expected< std::unique_ptr< GsymReader > > openFile(StringRef Path)
Construct a GsymReader from a file on disk.
LLVM_ABI llvm::Expected< FunctionInfo > getFunctionInfoAtIndex(uint64_t AddrIdx) const
Get the full function info given an address index.
virtual uint8_t getAddressOffsetSize() const =0
Get the address offset byte size for this GSYM file.
llvm::endianness Endian
Definition GsymReader.h:51
LLVM_ABI llvm::Expected< std::vector< LookupResult > > lookupAll(uint64_t Addr) const
Lookup all merged functions for a given address.
virtual uint64_t getBaseAddress() const =0
Get the base address of this GSYM file.
std::optional< uint64_t > getAddressOffsetIndex(const uint64_t AddrOffset) const
Lookup an address offset in the AddrOffsets table.
Definition GsymReader.h:440
LLVM_ABI std::optional< StringRef > getOptionalGlobalDataBytes(GlobalInfoType Type) const
Get the raw bytes for an optional GlobalData section as a StringRef.
LineTable class contains deserialized versions of line tables for each function's address ranges.
Definition LineTable.h:119
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getNameForGlobalInfoType(GlobalInfoType Type)
GlobalInfoType
GlobalInfoType allows GSYM files to encode global information within a GSYM file in a way that is ext...
Definition GlobalData.h:26
constexpr uint32_t GSYM_MAGIC
Definition Header.h:25
constexpr uint32_t GSYM_CIGAM
Definition Header.h:26
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:334
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
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:1917
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:107
endianness
Definition bit.h:71
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
std::vector< CallSiteInfo > CallSites
uint64_t ReturnOffset
The return offset of the call site - relative to the function start.
std::vector< gsym_strp_t > MatchRegex
Offsets into the string table for function names regex patterns.
static constexpr uint64_t getEncodedSize(uint8_t StringOffsetSize)
Returns the on-disk encoded size of a FileEntry for the given string offset size.
Definition FileEntry.h:38
Function information in GSYM files encodes information for one contiguous address range.
std::optional< InlineInfo > Inline
std::optional< MergedFunctionsInfo > MergedFunctions
static LLVM_ABI llvm::Expected< FunctionInfo > decode(GsymDataExtractor &Data, uint64_t BaseAddr)
Decode an object from a binary data stream.
std::optional< CallSiteInfoCollection > CallSites
gsym_strp_t Name
String table offset in the string table.
std::optional< LineTable > OptLineTable
static LLVM_ABI llvm::Expected< LookupResult > lookup(GsymDataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr, std::optional< GsymDataExtractor > *MergedFuncsData=nullptr)
Lookup an address within a FunctionInfo object's data stream.
GlobalData describes a section of data in a GSYM file by its type, file offset, and size.
Definition GlobalData.h:61
static LLVM_ABI llvm::Expected< GlobalData > decode(GsymDataExtractor &GsymData, uint64_t &Offset)
Decode a GlobalData entry from a binary data stream.
GlobalInfoType Type
Definition GlobalData.h:62
static constexpr uint32_t getVersion()
Return the version of this header.
Definition HeaderV2.h:83
static constexpr uint32_t getVersion()
Return the version of this header.
Definition Header.h:89
Inline information stores the name of the inline function along with an array of address ranges.
Definition InlineInfo.h:61
static LLVM_ABI llvm::Expected< std::vector< GsymDataExtractor > > getFuncsDataExtractors(GsymDataExtractor &Data)
Get a vector of GsymDataExtractor objects for the functions in this MergedFunctionsInfo object.
std::vector< FunctionInfo > MergedFunctions