Skip to content

Commit

Permalink
Speed up findLocation in the absence of .debug_aranges
Browse files Browse the repository at this point in the history
  • Loading branch information
tudor committed Jun 16, 2021
1 parent 6afdcee commit 88e2595
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 13 deletions.
90 changes: 78 additions & 12 deletions folly/experimental/symbolizer/Dwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,18 @@ bool Dwarf::findDebugInfoOffset(
* Best effort:
* - fills @inlineFrames if mode == FULL_WITH_INLINE,
* - calls @eachParameterName on the function parameters.
*
* if @checkAddress is true, we verify that the address is mapped to
* a range in this CU before running the line number VM
*/
bool Dwarf::findLocation(
uintptr_t address,
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& locationInfo,
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(folly::StringPiece)> eachParameterName) const {
folly::FunctionRef<void(folly::StringPiece)> eachParameterName,
bool checkAddress) const {
detail::Die die = getDieAtOffset(cu, cu.firstDie);
// Partial compilation unit (DW_TAG_partial_unit) is not supported.
FOLLY_SAFE_CHECK(
Expand All @@ -477,41 +481,101 @@ bool Dwarf::findLocation(
folly::StringPiece compilationDirectory;
folly::Optional<folly::StringPiece> mainFileName;
folly::Optional<uint64_t> baseAddrCU;
folly::Optional<uint64_t> lowPC;
folly::Optional<uint64_t> highPC;
folly::Optional<uint64_t> rangesOffset;
bool seenLowPC = false;
bool seenHighPC = false;
enum : unsigned {
kStmtList = 1U << 0,
kCompDir = 1U << 1,
kName = 1U << 2,
kLowPC = 1U << 3,
kHighPCOrRanges = 1U << 4,
};
unsigned expectedAttributes =
(kStmtList | kCompDir | kName | kLowPC | kHighPCOrRanges);
bool foundAddress = !checkAddress;
if (!foundAddress) {
expectedAttributes |= kHighPCOrRanges;
}
forEachAttribute(cu, die, [&](const detail::Attribute& attr) {
switch (attr.spec.name) {
case DW_AT_stmt_list:
expectedAttributes &= ~kStmtList;
// Offset in .debug_line for the line number VM program for this
// compilation unit
lineOffset = boost::get<uint64_t>(attr.attrValue);
break;
case DW_AT_comp_dir:
expectedAttributes &= ~kCompDir;
// Compilation directory
compilationDirectory = boost::get<folly::StringPiece>(attr.attrValue);
break;
case DW_AT_name:
expectedAttributes &= ~kName;
// File name of main file being compiled
mainFileName = boost::get<folly::StringPiece>(attr.attrValue);
break;
case DW_AT_low_pc:
case DW_AT_entry_pc:
// 2.17.1: historically DW_AT_low_pc was used. DW_AT_entry_pc was
// introduced in DWARF3. Support either to determine the base address of
// the CU.
expectedAttributes &= ~kLowPC;
baseAddrCU = boost::get<uint64_t>(attr.attrValue);
if (!foundAddress) {
if (address < *baseAddrCU) {
return false;
}
seenLowPC = true;
if (seenHighPC) {
foundAddress = true;
} else if (rangesOffset) {
if (!isAddrInRangeList(address, baseAddrCU, *rangesOffset,
cu.addrSize)) {
return false;
}
foundAddress = true;
}
}
break;
case DW_AT_high_pc:
expectedAttributes &= ~kHighPCOrRanges;
if (!foundAddress) {
if (address >= boost::get<uint64_t>(attr.attrValue)) {
return false;
}
seenHighPC = true;
foundAddress = seenLowPC;
}
break;
case DW_AT_ranges:
// 3.1.1: CU entries have:
// - either DW_AT_low_pc and DW_AT_high_pc
// OR
// - DW_AT_ranges and optional DW_AT_low_pc
expectedAttributes &= ~kHighPCOrRanges;
if (!foundAddress) {
rangesOffset = boost::get<uint64_t>(attr.attrValue);
if (seenLowPC) {
if (!isAddrInRangeList(address, baseAddrCU, *rangesOffset,
cu.addrSize)) {
return false;
}
foundAddress = true;
}
}
break;
}
return true; // continue forEachAttribute
return (expectedAttributes != 0); // continue forEachAttribute
});

if (!foundAddress || !lineOffset) {
return false;
}

if (mainFileName) {
locationInfo.hasMainFile = true;
locationInfo.mainFile = Path(compilationDirectory, "", *mainFileName);
}

if (!lineOffset) {
return false;
}

folly::StringPiece lineSection(debugLine_);
lineSection.advance(*lineOffset);
LineNumberVM lineVM(lineSection, compilationDirectory);
Expand Down Expand Up @@ -660,7 +724,8 @@ bool Dwarf::findAddress(
// Read compilation unit header from .debug_info
auto unit = getCompilationUnit(debugInfo_, offset);
return findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
address, mode, unit, locationInfo, inlineFrames, eachParameterName,
false /*checkAddress*/);
} else if (mode == LocationInfoMode::FAST) {
// NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries
// in .debug_aranges for some functions, but always generates
Expand Down Expand Up @@ -688,7 +753,8 @@ bool Dwarf::findAddress(
unit,
locationInfo,
inlineFrames,
eachParameterName)) {
eachParameterName,
true /*checkAddress*/)) {
return true;
}
}
Expand Down
6 changes: 5 additions & 1 deletion folly/experimental/symbolizer/Dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,18 @@ class Dwarf {
* Best effort:
* - fills @inlineFrames if mode == FULL_WITH_INLINE,
* - calls @eachParameterName on the function parameters.
*
* if @checkAddress is true, we verify that the address is mapped to
* a range in this CU before running the line number VM
*/
bool findLocation(
uintptr_t address,
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& info,
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(folly::StringPiece)> eachParameterName) const;
folly::FunctionRef<void(folly::StringPiece)> eachParameterName,
bool checkAddress = true) const;

/**
* Finds a subprogram debugging info entry that contains a given address among
Expand Down

0 comments on commit 88e2595

Please sign in to comment.