Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up findLocation in the absence of .debug_aranges #1

Merged
merged 1 commit into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 75 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,98 @@ bool Dwarf::findLocation(
folly::StringPiece compilationDirectory;
folly::Optional<folly::StringPiece> mainFileName;
folly::Optional<uint64_t> baseAddrCU;
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;
bool foundAddress = !checkAddress;
if (!foundAddress) {
expectedAttributes |= kHighPCOrRanges;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit is already set

}
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 +721,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 +750,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