diff options
author | Greg Clayton <gclayton@fb.com> | 2019-12-03 16:44:02 -0800 |
---|---|---|
committer | Greg Clayton <gclayton@fb.com> | 2019-12-05 16:49:53 -0800 |
commit | aeda128a96c4ac9eecef7563f4cf07dfcd2af0db (patch) | |
tree | 2452f0050027c3a641fee592fdfa16b0bfc9e9fc /llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp | |
parent | 6470497817eafe3fe2d15e11ade78fd99753d7ca (diff) | |
download | bcm5719-llvm-aeda128a96c4ac9eecef7563f4cf07dfcd2af0db.tar.gz bcm5719-llvm-aeda128a96c4ac9eecef7563f4cf07dfcd2af0db.zip |
Add lookup functions for efficient lookups of addresses when using GsymReader classes.
Summary:
Lookup functions are designed to not fully decode a FunctionInfo, LineTable or InlineInfo, they decode only what is needed into a LookupResult object. This allows lookups to avoid costly memory allocations and avoid parsing large amounts of information one a suitable match is found.
LookupResult objects contain the address that was looked up, the concrete function address range, the name of the concrete function, and a list of source locations. One for each inline function, and one for the concrete function. This allows one address to turn into multiple frames and improves the signal you get when symbolicating addresses in GSYM files.
Reviewers: labath, aprantl
Subscribers: mgorny, hiraditya, llvm-commits, lldb-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D70993
Diffstat (limited to 'llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp index e234a13fe06..26aab06108b 100644 --- a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp +++ b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/GSYM/FunctionInfo.h" #include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/DebugInfo/GSYM/GsymReader.h" #include "llvm/DebugInfo/GSYM/LineTable.h" #include "llvm/DebugInfo/GSYM/InlineInfo.h" #include "llvm/Support/DataExtractor.h" @@ -145,3 +146,104 @@ llvm::Expected<uint64_t> FunctionInfo::encode(FileWriter &O) const { O.writeU32(0); return FuncInfoOffset; } + + +llvm::Expected<LookupResult> FunctionInfo::lookup(DataExtractor &Data, + const GsymReader &GR, + uint64_t FuncAddr, + uint64_t Addr) { + LookupResult LR; + LR.LookupAddr = Addr; + LR.FuncRange.Start = FuncAddr; + uint64_t Offset = 0; + LR.FuncRange.End = FuncAddr + Data.getU32(&Offset); + uint32_t NameOffset = Data.getU32(&Offset); + // The "lookup" functions doesn't report errors as accurately as the "decode" + // function as it is meant to be fast. For more accurage errors we could call + // "decode". + if (!Data.isValidOffset(Offset)) + return createStringError(std::errc::io_error, + "FunctionInfo data is truncated"); + // This function will be called with the result of a binary search of the + // address table, we must still make sure the address does not fall into a + // gap between functions are after the last function. + if (Addr >= LR.FuncRange.End) + return createStringError(std::errc::io_error, + "address 0x%" PRIx64 " is not in GSYM", Addr); + + if (NameOffset == 0) + return createStringError(std::errc::io_error, + "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x00000000", + Offset - 4); + LR.FuncName = GR.getString(NameOffset); + bool Done = false; + Optional<LineEntry> LineEntry; + Optional<DataExtractor> InlineInfoData; + while (!Done) { + if (!Data.isValidOffsetForDataOfSize(Offset, 8)) + return createStringError(std::errc::io_error, + "FunctionInfo data is truncated"); + const uint32_t InfoType = Data.getU32(&Offset); + const uint32_t InfoLength = Data.getU32(&Offset); + const StringRef InfoBytes = Data.getData().substr(Offset, InfoLength); + if (InfoLength != InfoBytes.size()) + return createStringError(std::errc::io_error, + "FunctionInfo data is truncated"); + DataExtractor InfoData(InfoBytes, Data.isLittleEndian(), + Data.getAddressSize()); + switch (InfoType) { + case InfoType::EndOfList: + Done = true; + break; + + case InfoType::LineTableInfo: + if (auto ExpectedLE = LineTable::lookup(InfoData, FuncAddr, Addr)) + LineEntry = ExpectedLE.get(); + else + return ExpectedLE.takeError(); + break; + + case InfoType::InlineInfo: + // We will parse the inline info after our line table, but only if + // we have a line entry. + InlineInfoData = InfoData; + break; + + default: + break; + } + Offset += InfoLength; + } + + if (!LineEntry) { + // We don't have a valid line entry for our address, fill in our source + // location as best we can and return. + SourceLocation SrcLoc; + SrcLoc.Name = LR.FuncName; + LR.Locations.push_back(SrcLoc); + return LR; + } + + Optional<FileEntry> LineEntryFile = GR.getFile(LineEntry->File); + if (!LineEntryFile) + return createStringError(std::errc::invalid_argument, + "failed to extract file[%" PRIu32 "]", + LineEntry->File); + + SourceLocation SrcLoc; + SrcLoc.Name = LR.FuncName; + SrcLoc.Dir = GR.getString(LineEntryFile->Dir); + SrcLoc.Base = GR.getString(LineEntryFile->Base); + SrcLoc.Line = LineEntry->Line; + LR.Locations.push_back(SrcLoc); + // If we don't have inline information, we are done. + if (!InlineInfoData) + return LR; + // We have inline information. Try to augment the lookup result with this + // data. + llvm::Error Err = InlineInfo::lookup(GR, *InlineInfoData, FuncAddr, Addr, + LR.Locations); + if (Err) + return std::move(Err); + return LR; +} |