Commit 63cdc1c1 authored by Hasnain Lakhani's avatar Hasnain Lakhani Committed by Facebook GitHub Bot

Extend findAddress to provide function parameter names

Summary:
We provide an optional callback that callers can use to save parameter names
where desired.

Differential Revision: D22399275

fbshipit-source-id: 7f9440a46cbcc4085d48a2387ca3d2db51f2fe7e
parent 5ea745d4
......@@ -462,7 +462,8 @@ bool Dwarf::findLocation(
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& locationInfo,
folly::Range<SymbolizedFrame*> inlineFrames) const {
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(folly::StringPiece)> eachParameterName) const {
detail::Die die = getDieAtOffset(cu, cu.firstDie);
// Partial compilation unit (DW_TAG_partial_unit) is not supported.
FOLLY_SAFE_CHECK(
......@@ -511,8 +512,10 @@ bool Dwarf::findLocation(
lineVM.findAddress(address, locationInfo.file, locationInfo.line);
// Look up whether inline function.
if (mode == LocationInfoMode::FULL_WITH_INLINE && !inlineFrames.empty() &&
locationInfo.hasFileAndLine) {
bool checkInline =
(mode == LocationInfoMode::FULL_WITH_INLINE && !inlineFrames.empty());
if (locationInfo.hasFileAndLine && (checkInline || eachParameterName)) {
// Re-get the compilation unit with abbreviation cached.
std::array<detail::DIEAbbreviation, kMaxAbbreviationEntries> abbrs;
cu.abbrCache = folly::range(abbrs);
......@@ -522,8 +525,23 @@ bool Dwarf::findLocation(
detail::Die subprogram;
findSubProgramDieForAddress(cu, die, address, subprogram);
if (eachParameterName) {
forEachChild(cu, subprogram, [&](const detail::Die& child) {
if (child.abbr.tag == DW_TAG_formal_parameter) {
forEachAttribute(cu, child, [&](const detail::Attribute& attribute) {
if (attribute.spec.name == DW_AT_name) {
eachParameterName(
boost::get<folly::StringPiece>(attribute.attrValue));
}
return true;
});
}
return true;
});
}
// Subprogram is the DIE of caller function.
if (subprogram.abbr.hasChildren) {
if (checkInline && subprogram.abbr.hasChildren) {
// Use an extra location and get its call file and call line, so that
// they can be used for the second last location when we don't have
// enough inline frames for all inline functions call stack.
......@@ -606,7 +624,9 @@ bool Dwarf::findAddress(
uintptr_t address,
LocationInfoMode mode,
LocationInfo& locationInfo,
folly::Range<SymbolizedFrame*> inlineFrames) const {
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(const folly::StringPiece name)> eachParameterName)
const {
if (mode == LocationInfoMode::DISABLED) {
return false;
}
......@@ -622,7 +642,8 @@ bool Dwarf::findAddress(
if (findDebugInfoOffset(address, debugAranges_, offset)) {
// Read compilation unit header from .debug_info
auto unit = getCompilationUnit(debugInfo_, offset);
findLocation(address, mode, unit, locationInfo, inlineFrames);
findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
return locationInfo.hasFileAndLine;
} else if (mode == LocationInfoMode::FAST) {
// NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries
......@@ -645,7 +666,8 @@ bool Dwarf::findAddress(
while (offset < debugInfo_.size() && !locationInfo.hasFileAndLine) {
auto unit = getCompilationUnit(debugInfo_, offset);
offset += unit.size;
findLocation(address, mode, unit, locationInfo, inlineFrames);
findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
}
return locationInfo.hasFileAndLine;
}
......
......@@ -87,12 +87,18 @@ class Dwarf {
*/
static const uint32_t kMaxInlineLocationInfoPerFrame = 10;
/** Find the file and line number information corresponding to address. */
/**
* Find the file and line number information corresponding to address.
* If `eachParameterName` is provided, the callback will be invoked once
* for each parameter of the function.
*/
bool findAddress(
uintptr_t address,
LocationInfoMode mode,
LocationInfo& info,
folly::Range<SymbolizedFrame*> inlineFrames = {}) const;
folly::Range<SymbolizedFrame*> inlineFrames = {},
folly::FunctionRef<void(const folly::StringPiece name)>
eachParameterName = {}) const;
private:
using AttributeValue = boost::variant<uint64_t, folly::StringPiece>;
......@@ -110,14 +116,17 @@ class Dwarf {
/**
* Finds location info (file and line) for a given address in the given
* compilation unit.
* compilation unit. Invokes `eachParameterName`, if set, for each parameter
* of the given function.
*/
bool findLocation(
uintptr_t address,
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& info,
folly::Range<SymbolizedFrame*> inlineFrames = {}) const;
folly::Range<SymbolizedFrame*> inlineFrames = {},
folly::FunctionRef<void(folly::StringPiece)> eachParameterName = {})
const;
/**
* Finds a subprogram debugging info entry that contains a given address among
......
......@@ -432,6 +432,34 @@ TEST(SymbolizerTest, InlineFunctionWithCache) {
compareFrames(frames, frames2);
}
int64_t functionWithTwoParameters(size_t a, int32_t b) {
return a + b;
}
TEST(Dwarf, FindParameterNames) {
SKIP_IF(!Symbolizer::isAvailable());
auto address = reinterpret_cast<uintptr_t>(functionWithTwoParameters);
Symbolizer symbolizer;
SymbolizedFrame frame;
ASSERT_TRUE(symbolizer.symbolize(address, frame));
std::vector<folly::StringPiece> names;
Dwarf dwarf(frame.file.get());
LocationInfo info;
folly::Range<SymbolizedFrame*> extraInlineFrames = {};
dwarf.findAddress(
address,
LocationInfoMode::FAST,
info,
extraInlineFrames,
[&](const folly::StringPiece name) { names.push_back(name); });
ASSERT_EQ(2, names.size());
ASSERT_EQ("a", names[0]);
ASSERT_EQ("b", names[1]);
}
} // namespace test
} // namespace symbolizer
} // namespace folly
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment