25GsymReader::GsymReader(std::unique_ptr<MemoryBuffer> Buffer)
51 "invalid memory buffer");
52 GsymReader GR(std::move(MemBuffer));
55 return std::move(Err);
65 if (FileData.readObject(Hdr))
67 "not enough data for a GSYM header");
72 Endian = HostByteOrder;
78 Swap.reset(
new SwappedData);
90 Swap->Hdr = ExpectedHdr.get();
92 return ExpectedHdr.takeError();
109 FileData.readArray(AddrOffsets,
112 "failed to read address table");
115 if (FileData.padToAlignment(4) ||
118 "failed to read address info offsets table");
122 if (FileData.readInteger(NumFiles) || FileData.readArray(Files, NumFiles))
124 "failed to read file table");
130 "failed to read string table");
136 DataExtractor
Data(MemBuffer->getBuffer(), DataIsLittleEndian, 4);
140 Swap->AddrOffsets.resize(Hdr->NumAddresses * Hdr->AddrOffSize);
141 switch (Hdr->AddrOffSize) {
143 if (!
Data.getU8(&
Offset, Swap->AddrOffsets.data(), Hdr->NumAddresses))
145 "failed to read address table");
149 reinterpret_cast<uint16_t *
>(Swap->AddrOffsets.data()),
152 "failed to read address table");
156 reinterpret_cast<uint32_t *
>(Swap->AddrOffsets.data()),
159 "failed to read address table");
163 reinterpret_cast<uint64_t *
>(Swap->AddrOffsets.data()),
166 "failed to read address table");
168 AddrOffsets = ArrayRef<uint8_t>(Swap->AddrOffsets);
172 Swap->AddrInfoOffsets.resize(Hdr->NumAddresses);
173 if (
Data.getU32(&
Offset, Swap->AddrInfoOffsets.data(), Hdr->NumAddresses))
174 AddrInfoOffsets = ArrayRef<uint32_t>(Swap->AddrInfoOffsets);
177 "failed to read address table");
179 const uint32_t NumFiles =
Data.getU32(&
Offset);
181 Swap->Files.resize(NumFiles);
182 if (
Data.getU32(&
Offset, &Swap->Files[0].Dir, NumFiles*2))
186 "failed to read file table");
189 StrTab.Data = MemBuffer->getBuffer().substr(Hdr->StrtabOffset,
191 if (StrTab.Data.empty())
193 "failed to read string table");
208 switch (Hdr->AddrOffSize) {
218 const auto NumAddrInfoOffsets = AddrInfoOffsets.size();
219 if (Index < NumAddrInfoOffsets)
220 return AddrInfoOffsets[Index];
226 if (Addr >= Hdr->BaseAddress) {
227 const uint64_t AddrOffset = Addr - Hdr->BaseAddress;
228 std::optional<uint64_t> AddrOffsetIndex;
229 switch (Hdr->AddrOffSize) {
244 "unsupported address offset size %u",
248 return *AddrOffsetIndex;
251 "address 0x%" PRIx64
" is not in GSYM", Addr);
259 if (!ExpectedAddrIdx)
261 const uint64_t FirstAddrIdx = *ExpectedAddrIdx;
265 std::optional<uint64_t> FirstFuncStartAddr;
267 for (
uint64_t AddrIdx = FirstAddrIdx; AddrIdx < NumAddresses; ++AddrIdx) {
276 if (FirstFuncStartAddr.has_value()) {
277 if (*FirstFuncStartAddr != FuncStartAddr)
280 FirstFuncStartAddr = FuncStartAddr;
295 "address 0x%" PRIx64
" is not in GSYM", Addr);
303 "invalid address index %" PRIu64, AddrIdx);
304 const uint32_t AddrInfoOffset = AddrInfoOffsets[AddrIdx];
306 "Endian must be either big or little");
310 "invalid address info offset 0x%" PRIx32,
312 std::optional<uint64_t> OptFuncStartAddr =
getAddress(AddrIdx);
313 if (!OptFuncStartAddr)
315 "failed to extract address[%" PRIu64
"]", AddrIdx);
316 FuncStartAddr = *OptFuncStartAddr;
325 return ExpectedData.takeError();
334 return ExpectedData.takeError();
339 std::optional<DataExtractor> *MergedFunctionsData)
const {
343 MergedFunctionsData);
345 return ExpectedData.takeError();
350 std::vector<LookupResult>
Results;
351 std::optional<DataExtractor> MergedFunctionsData;
354 auto MainResult =
lookup(Addr, &MergedFunctionsData);
356 return MainResult.takeError();
359 Results.push_back(std::move(*MainResult));
362 if (MergedFunctionsData) {
364 auto ExpectedMergedFuncExtractors =
366 if (!ExpectedMergedFuncExtractors)
367 return ExpectedMergedFuncExtractors.takeError();
370 for (
DataExtractor &MergedData : *ExpectedMergedFuncExtractors) {
372 MainResult->FuncRange.start(), Addr)) {
373 Results.push_back(std::move(*FI));
375 return FI.takeError();
388 OS <<
"Address Table:\n";
389 OS <<
"INDEX OFFSET";
391 switch (Hdr->AddrOffSize) {
392 case 1: OS <<
"8 ";
break;
393 case 2: OS <<
"16";
break;
394 case 4: OS <<
"32";
break;
395 case 8: OS <<
"64";
break;
396 default: OS <<
"??";
break;
398 OS <<
" (ADDRESS)\n";
399 OS <<
"====== =============================== \n";
402 switch (Hdr->AddrOffSize) {
403 case 1: OS << HEX8(getAddrOffsets<uint8_t>()[
I]);
break;
404 case 2: OS << HEX16(getAddrOffsets<uint16_t>()[
I]);
break;
405 case 4: OS << HEX32(getAddrOffsets<uint32_t>()[
I]);
break;
406 case 8: OS << HEX32(getAddrOffsets<uint64_t>()[
I]);
break;
412 OS <<
"\nAddress Info Offsets:\n";
413 OS <<
"INDEX Offset\n";
414 OS <<
"====== ==========\n";
416 OS <<
format(
"[%4u] ",
I) <<
HEX32(AddrInfoOffsets[
I]) <<
"\n";
419 OS <<
"INDEX DIRECTORY BASENAME PATH\n";
420 OS <<
"====== ========== ========== ==============================\n";
427 OS <<
"\n" << StrTab <<
"\n";
430 OS <<
"FunctionInfo @ " <<
HEX32(AddrInfoOffsets[
I]) <<
": ";
451 assert(Indent == 0 &&
"MergedFunctionsInfo should only exist at top level");
458 OS <<
"++ Merged FunctionInfos[" << inx <<
"]:\n";
467 auto addFlag = [&](
const char *Flag) {
477 addFlag(
"InternalCall");
480 addFlag(
"ExternalCall");
482 OS <<
" Flags[" << Flags <<
"]";
485 OS <<
" MatchRegex[";
498 OS <<
"CallSites (by relative return offset):\n";
509 OS <<
"LineTable:\n";
512 OS <<
" " <<
HEX64(LE.Addr) <<
' ';
515 OS <<
':' << LE.Line <<
'\n';
521 OS <<
"InlineInfo:\n";
525 if (
II.CallFile != 0) {
527 OS <<
" called from ";
529 OS <<
':' <<
II.CallLine;
533 for (
const auto &ChildII:
II.Children)
534 dump(OS, ChildII, Indent + 2);
540 if (FE->Dir == 0 && FE->Base == 0)
546 if (Dir.contains(
'\\') && !Dir.contains(
'/'))
557 OS <<
"<invalid-file>";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
uint64_t IntrinsicInst * II
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
A class that represents an address range.
Provides read only access to a subclass of BinaryStream.
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 "-".
StringRef - Represent a constant reference to a string, i.e.
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
empty - Check if the string is empty.
GsymReader is used to read GSYM data from a file or buffer.
std::optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
LLVM_ABI void dump(raw_ostream &OS)
Dump the entire Gsym data contained in this object.
uint32_t getNumAddresses() const
Get the number of addresses in this Gsym file.
static LLVM_ABI llvm::Expected< GsymReader > openFile(StringRef Path)
Construct a GsymReader from a file on disk.
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.
StringRef getString(uint32_t Offset) const
Get a string from the string table.
LLVM_ABI llvm::Expected< FunctionInfo > getFunctionInfo(uint64_t Addr) const
Get the full function info for an address.
LLVM_ABI const Header & getHeader() const
Access the GSYM header.
std::optional< uint64_t > addressForIndex(size_t Index) const
Get an appropriate address from the address table.
LLVM_ABI llvm::Expected< llvm::DataExtractor > getFunctionInfoDataAtIndex(uint64_t AddrIdx, uint64_t &FuncStartAddr) const
Get the function data and address given an address index.
LLVM_ABI Expected< uint64_t > getAddressIndex(const uint64_t Addr) const
Given an address, find the address index.
static LLVM_ABI llvm::Expected< GsymReader > copyBuffer(StringRef Bytes)
Construct a GsymReader from a buffer.
LLVM_ABI llvm::Expected< LookupResult > lookup(uint64_t Addr, std::optional< DataExtractor > *MergedFuncsData=nullptr) const
Lookup an address in the a GSYM.
static LLVM_ABI llvm::Expected< llvm::gsym::GsymReader > create(std::unique_ptr< MemoryBuffer > &MemBuffer)
Create a GSYM from a memory buffer.
LLVM_ABI llvm::Expected< FunctionInfo > getFunctionInfoAtIndex(uint64_t AddrIdx) const
Get the full function info given an address index.
LLVM_ABI llvm::Expected< llvm::DataExtractor > getFunctionInfoDataForAddress(uint64_t Addr, uint64_t &FuncStartAddr) const
Given an address, find the correct function info data and function address.
LLVM_ABI llvm::Expected< std::vector< LookupResult > > lookupAll(uint64_t Addr) const
Lookup all merged functions for a given address.
std::optional< uint64_t > getAddressOffsetIndex(const uint64_t AddrOffset) const
Lookup an address offset in the AddrOffsets table.
LineTable class contains deserialized versions of line tables for each function's address ranges.
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.
constexpr uint32_t GSYM_MAGIC
constexpr uint32_t GSYM_CIGAM
constexpr bool IsBigEndianHost
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
Implement std::hash so that hash_code can be used in STL containers.
std::vector< CallSiteInfo > CallSites
std::vector< uint32_t > MatchRegex
Offsets into the string table for function names regex patterns.
uint64_t ReturnOffset
The return offset of the call site - relative to the function start.
Function information in GSYM files encodes information for one contiguous address range.
std::optional< InlineInfo > Inline
std::optional< MergedFunctionsInfo > MergedFunctions
std::optional< CallSiteInfoCollection > CallSites
static LLVM_ABI llvm::Expected< LookupResult > lookup(DataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr, std::optional< DataExtractor > *MergedFuncsData=nullptr)
Lookup an address within a FunctionInfo object's data stream.
uint32_t Name
String table offset in the string table.
std::optional< LineTable > OptLineTable
static LLVM_ABI llvm::Expected< FunctionInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an object 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< DataExtractor > > getFuncsDataExtractors(DataExtractor &Data)
Get a vector of DataExtractor objects for the functions in this MergedFunctionsInfo object.
std::vector< FunctionInfo > MergedFunctions