41 "data too small to be a GSYM file");
53 FileEndian = HostEndian;
61 "not a GSYM file (bad magic)");
65 return std::make_pair(Version, FileEndian);
68llvm::Expected<std::unique_ptr<GsymReader>>
76 auto &Buf = BuffOrErr.
get();
77 Buf->randomAccessIfMmap();
91 "invalid memory buffer");
94 if (!VersionEndianOrErr)
99 std::unique_ptr<GsymReader> GR;
109 "unsupported GSYM version %u",
Version);
111 if (
auto Err = GR->parse())
112 return std::move(Err);
113 return std::move(GR);
128 std::errc::invalid_argument,
"missing required section type %s (%u)",
134 "AddrOffsets section size mismatch");
139 "AddrInfoOffsets section size mismatch");
173 "GlobalData section not supported in GSYM V1");
181 return GDOrErr.takeError();
189 "GlobalData section type %u has zero size",
194 std::errc::invalid_argument,
195 "GlobalData section type %u extends beyond "
196 "buffer (offset=%" PRIu64
", size=%" PRIu64
", bufsize=%" PRIu64
")",
202 "GlobalData array not terminated by EndOfList");
208 const size_t TotalBytes = NumAddrs * AddrOffSize;
209 if (Bytes.
size() < TotalBytes)
211 "failed to read address table");
216 reinterpret_cast<const uint8_t *
>(Bytes.
data()), TotalBytes);
224 switch (AddrOffSize) {
228 "failed to read address table");
235 "failed to read address table");
242 "failed to read address table");
249 "failed to read address table");
275 "FileTable section too small for %u files",
298 std::errc::invalid_argument,
299 "missing bytes for %s, GSYM file might be truncated", TypeName);
301 "missing required section type %s", TypeName);
304std::optional<StringRef>
310 if (GD->FileSize == 0 || GD->FileOffset + GD->FileSize > Buf.
size())
312 return Buf.
substr(GD->FileOffset, GD->FileSize);
339 return AddrInfoOffset;
344 if (Addr >= BaseAddr) {
345 const uint64_t AddrOffset = Addr - BaseAddr;
346 std::optional<uint64_t> AddrOffsetIndex;
362 "unsupported address offset size %u",
366 return *AddrOffsetIndex;
369 "address 0x%" PRIx64
" is not in GSYM", Addr);
376 if (!ExpectedAddrIdx)
378 const uint64_t FirstAddrIdx = *ExpectedAddrIdx;
382 std::optional<uint64_t> FirstFuncStartAddr;
384 for (
uint64_t AddrIdx = FirstAddrIdx; AddrIdx < NumAddresses; ++AddrIdx) {
393 if (FirstFuncStartAddr.has_value()) {
394 if (*FirstFuncStartAddr != FuncStartAddr)
397 FirstFuncStartAddr = FuncStartAddr;
412 "address 0x%" PRIx64
" is not in GSYM", Addr);
419 if (AddrInfoOffset == std::nullopt)
421 "invalid address index %" PRIu64, AddrIdx);
423 "Endian must be either big or little");
427 "invalid address info offset 0x%" PRIx64,
429 std::optional<uint64_t> OptFuncStartAddr =
getAddress(AddrIdx);
430 if (!OptFuncStartAddr)
432 "failed to extract address[%" PRIu64
"]", AddrIdx);
433 FuncStartAddr = *OptFuncStartAddr;
443 return ExpectedData.takeError();
452 return ExpectedData.takeError();
457 std::optional<GsymDataExtractor> *MergedFunctionsData)
const {
461 MergedFunctionsData);
463 return ExpectedData.takeError();
468 std::vector<LookupResult>
Results;
469 std::optional<GsymDataExtractor> MergedFunctionsData;
472 auto MainResult =
lookup(Addr, &MergedFunctionsData);
474 return MainResult.takeError();
477 Results.push_back(std::move(*MainResult));
480 if (MergedFunctionsData) {
482 auto ExpectedMergedFuncExtractors =
484 if (!ExpectedMergedFuncExtractors)
485 return ExpectedMergedFuncExtractors.takeError();
490 MainResult->FuncRange.start(), Addr)) {
491 Results.push_back(std::move(*FI));
493 return FI.takeError();
504 std::string Hex =
toHex(Bytes,
false);
505 if (Bytes.
size() == 16) {
529 const uint64_t AddrInfoOffsetsSize =
550 uint64_t MinSectionOffset = FileSize;
552 MinSectionOffset = std::min(MinSectionOffset, KV.second.FileOffset);
553 HeaderSize = MinSectionOffset;
557 const uint64_t KnownSize = HeaderSize + GlobalDataDirSize + UUIDSize +
558 AddrTableSize + AddrInfoOffsetsSize +
559 FileTableSize + StrtabSize + FuncInfoSize;
560 const uint64_t PaddingSize = FileSize > KnownSize ? FileSize - KnownSize : 0;
582 FuncInfoSize > FIAttributed ? FuncInfoSize - FIAttributed : 0;
589 {
"infotype_infolength_count_and_fnsize",
591 {
"size_and_name",
static_cast<int64_t
>(Merged.
SizeAndName)},
592 {
"line_table_info",
static_cast<int64_t
>(Merged.
LineTableInfo)},
593 {
"inline_info",
static_cast<int64_t
>(Merged.
InlineInfo)},
594 {
"call_site_info",
static_cast<int64_t
>(Merged.
CallSiteInfo)},
595 {
"merged_func_info",
static_cast<int64_t
>(Merged.
MergedFuncInfo)},
596 {
"end_of_list",
static_cast<int64_t
>(Merged.
EndOfList)}};
599 {
"size_and_name",
static_cast<int64_t
>(FI.
SizeAndName)},
601 {
"inline_info",
static_cast<int64_t
>(FI.
InlineInfo)},
602 {
"call_site_info",
static_cast<int64_t
>(FI.
CallSiteInfo)},
604 {
"end_of_list",
static_cast<int64_t
>(FI.
EndOfList)},
605 {
"padding",
static_cast<int64_t
>(Padding)},
606 {
"merged_func_info_type_sizes", std::move(MergedTypes)}};
609 {
"file_size",
static_cast<int64_t
>(FileSize)},
610 {
"header",
static_cast<int64_t
>(HeaderSize)},
611 {
"global_data_directory",
static_cast<int64_t
>(GlobalDataDirSize)},
612 {
"uuid_section",
static_cast<int64_t
>(UUIDSize)},
613 {
"padding",
static_cast<int64_t
>(PaddingSize)},
614 {
"address_table",
static_cast<int64_t
>(AddrTableSize)},
615 {
"addr_info_offsets",
static_cast<int64_t
>(AddrInfoOffsetsSize)},
616 {
"file_table",
static_cast<int64_t
>(FileTableSize)},
617 {
"string_table",
static_cast<int64_t
>(StrtabSize)},
618 {
"function_info_data",
static_cast<int64_t
>(FuncInfoSize)},
619 {
"function_info_type_sizes", std::move(FuncTypes)}};
623 {
"num_addresses",
static_cast<int64_t
>(NumAddresses)},
624 {
"byte-sizes", std::move(ByteSizes)}};
628 OS <<
formatv(
"{0:2}", V) <<
"\n";
636 std::string Num = std::to_string(
Value);
642 return std::string(std::max((
size_t)0, 14 - Num.length()),
' ') + Num;
646 snprintf(Buf,
sizeof(Buf),
"(%5.2f%%)", 100.0 *
Value / FileSize);
650 OS <<
"GSYM statistics for \"" << GSYMPath <<
"\":\n";
651 OS <<
" UUID: " << UUIDStr <<
"\n";
652 OS <<
" Number of addresses: " << Fmt(NumAddresses) <<
"\n";
653 OS <<
" File size: " << Fmt(FileSize) <<
" bytes\n";
654 OS <<
" Header: " << Fmt(HeaderSize) <<
" bytes "
655 << Pct(HeaderSize) <<
"\n";
656 OS <<
" Global data dir: " << Fmt(GlobalDataDirSize) <<
" bytes "
657 << Pct(GlobalDataDirSize) <<
"\n";
658 OS <<
" UUID section: " << Fmt(UUIDSize) <<
" bytes " << Pct(UUIDSize)
660 OS <<
" Address table: " << Fmt(AddrTableSize) <<
" bytes "
661 << Pct(AddrTableSize) <<
"\n";
662 OS <<
" Addr info offsets: " << Fmt(AddrInfoOffsetsSize) <<
" bytes "
663 << Pct(AddrInfoOffsetsSize) <<
"\n";
664 OS <<
" File table: " << Fmt(FileTableSize) <<
" bytes "
665 << Pct(FileTableSize) <<
"\n";
666 OS <<
" String table: " << Fmt(StrtabSize) <<
" bytes "
667 << Pct(StrtabSize) <<
"\n";
668 OS <<
" Function info data: " << Fmt(FuncInfoSize) <<
" bytes "
669 << Pct(FuncInfoSize) <<
"\n";
670 OS <<
" Size and name: " << Fmt(FI.
SizeAndName) <<
" bytes "
672 OS <<
" Line table info: " << Fmt(FI.
LineTableInfo) <<
" bytes "
674 OS <<
" Inline info: " << Fmt(FI.
InlineInfo) <<
" bytes "
676 OS <<
" Call site info: " << Fmt(FI.
CallSiteInfo) <<
" bytes "
678 OS <<
" End of list: " << Fmt(FI.
EndOfList) <<
" bytes "
680 OS <<
" Padding: " << Fmt(Padding) <<
" bytes " << Pct(Padding)
682 OS <<
" Merged func info: " << Fmt(FI.
MergedFuncInfo) <<
" bytes "
684 OS <<
" InfoType/InfoLength/Count/FnSize: "
687 OS <<
" Size and name: " << Fmt(Merged.
SizeAndName) <<
" bytes "
689 OS <<
" Line table info: " << Fmt(Merged.
LineTableInfo) <<
" bytes "
691 OS <<
" Inline info: " << Fmt(Merged.
InlineInfo) <<
" bytes "
693 OS <<
" Call site info: " << Fmt(Merged.
CallSiteInfo) <<
" bytes "
695 OS <<
" Merged func info:" << Fmt(Merged.
MergedFuncInfo) <<
" bytes "
697 OS <<
" End of list: " << Fmt(Merged.
EndOfList) <<
" bytes "
699 OS <<
" Padding: " << Fmt(PaddingSize) <<
" bytes "
700 << Pct(PaddingSize) <<
"\n";
716 assert(Indent == 0 &&
"MergedFunctionsInfo should only exist at top level");
723 OS <<
"++ Merged FunctionInfos[" << inx <<
"]:\n";
732 auto addFlag = [&](
const char *Flag) {
742 addFlag(
"InternalCall");
745 addFlag(
"ExternalCall");
747 OS <<
" Flags[" << Flags <<
"]";
750 OS <<
" MatchRegex[";
763 OS <<
"CallSites (by relative return offset):\n";
774 OS <<
"LineTable:\n";
775 for (
auto &LE : LT) {
777 OS <<
" " <<
HEX64(LE.Addr) <<
' ';
780 OS <<
':' << LE.Line <<
'\n';
786 OS <<
"InlineInfo:\n";
790 if (
II.CallFile != 0) {
792 OS <<
" called from ";
794 OS <<
':' <<
II.CallLine;
798 for (
const auto &ChildII :
II.Children)
799 dump(OS, ChildII, Indent + 2);
805 if (FE->Dir == 0 && FE->Base == 0)
811 if (Dir.contains(
'\\') && !Dir.contains(
'/'))
822 OS <<
"<invalid-file>";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static Expected< std::pair< uint16_t, llvm::endianness > > checkMagicAndDetectVersionEndian(StringRef Bytes)
Check magic bytes, determine endianness, and return the GSYM version and endianness.
static std::string formatGsymUUID(StringRef Bytes)
Format raw UUID bytes as a hex string, using the canonical 8-4-4-4-12 dashed layout for the common 16...
This file supports working with JSON data.
uint64_t IntrinsicInst * II
static constexpr StringLiteral Filename
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
A class that represents an address range.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
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 "-".
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
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.
LLVM_ABI llvm::Error setAddrInfoOffsetsData(StringRef Bytes)
Set address info offsets section bytes into AddrInfoOffsetsData.
LLVM_ABI llvm::Error parseGlobalDataEntries(uint64_t Offset)
Parse GlobalData entries starting at Offset into GlobalDataSections.
GsymDataExtractor FileEntryData
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.
bool isLittleEndian() const
LLVM_ABI std::optional< GlobalData > getGlobalData(GlobalInfoType Type) const
Get the GlobalData entry for a section type.
ArrayRef< uint8_t > AddrOffsets
LLVM_ABI llvm::Error setFileTableData(StringRef Bytes)
Set file table section bytes into FileEntryData.
GsymDataExtractor AddrInfoOffsetsData
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.
LLVM_ABI GsymReader(std::unique_ptr< MemoryBuffer > Buffer, llvm::endianness Endian)
virtual uint16_t getVersion() const =0
Get the GSYM version for this reader.
LLVM_ABI 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 void dumpStatistics(raw_ostream &OS, StatisticsFormat Format=StatisticsFormat::Text, StringRef GSYMPath="")
Dump statistics about the GSYM data contained in this object.
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.
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
LLVM_ABI 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.
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
virtual void dump(raw_ostream &OS)=0
Dump the entire Gsym data contained in this object.
virtual StringRef getUUID() const =0
Get the raw UUID bytes for this GSYM file, or an empty ref if none.
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_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.
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.
An Object is a JSON object, which maps strings to heterogenous JSON values.
A Value is an JSON value of unknown type.
This class implements an extremely fast bulk output stream that can only output to a stream.
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...
constexpr uint32_t GSYM_MAGIC
constexpr uint32_t GSYM_CIGAM
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
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.
Byte-size accounting for a FunctionInfo, broken down by field / InfoType.
uint64_t InfoTypeInfoLengthCountAndFnSize
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
static LLVM_ABI void parseStatistics(GsymDataExtractor &Data, FunctionInfoStats &Stats, FunctionInfoStats *MergedFuncInfoStats=nullptr)
Parse the function info data and accumulate the byte size of each field / InfoType into Stats.
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.
static LLVM_ABI llvm::Expected< GlobalData > decode(GsymDataExtractor &GsymData, uint64_t &Offset)
Decode a GlobalData entry from a binary data stream.
Inline information stores the name of the inline function along with an array of address ranges.
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