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( ...@@ -462,7 +462,8 @@ bool Dwarf::findLocation(
const LocationInfoMode mode, const LocationInfoMode mode,
detail::CompilationUnit& cu, detail::CompilationUnit& cu,
LocationInfo& locationInfo, 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); detail::Die die = getDieAtOffset(cu, cu.firstDie);
// Partial compilation unit (DW_TAG_partial_unit) is not supported. // Partial compilation unit (DW_TAG_partial_unit) is not supported.
FOLLY_SAFE_CHECK( FOLLY_SAFE_CHECK(
...@@ -511,8 +512,10 @@ bool Dwarf::findLocation( ...@@ -511,8 +512,10 @@ bool Dwarf::findLocation(
lineVM.findAddress(address, locationInfo.file, locationInfo.line); lineVM.findAddress(address, locationInfo.file, locationInfo.line);
// Look up whether inline function. // Look up whether inline function.
if (mode == LocationInfoMode::FULL_WITH_INLINE && !inlineFrames.empty() && bool checkInline =
locationInfo.hasFileAndLine) { (mode == LocationInfoMode::FULL_WITH_INLINE && !inlineFrames.empty());
if (locationInfo.hasFileAndLine && (checkInline || eachParameterName)) {
// Re-get the compilation unit with abbreviation cached. // Re-get the compilation unit with abbreviation cached.
std::array<detail::DIEAbbreviation, kMaxAbbreviationEntries> abbrs; std::array<detail::DIEAbbreviation, kMaxAbbreviationEntries> abbrs;
cu.abbrCache = folly::range(abbrs); cu.abbrCache = folly::range(abbrs);
...@@ -522,8 +525,23 @@ bool Dwarf::findLocation( ...@@ -522,8 +525,23 @@ bool Dwarf::findLocation(
detail::Die subprogram; detail::Die subprogram;
findSubProgramDieForAddress(cu, die, address, 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. // 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 // 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 // they can be used for the second last location when we don't have
// enough inline frames for all inline functions call stack. // enough inline frames for all inline functions call stack.
...@@ -606,7 +624,9 @@ bool Dwarf::findAddress( ...@@ -606,7 +624,9 @@ bool Dwarf::findAddress(
uintptr_t address, uintptr_t address,
LocationInfoMode mode, LocationInfoMode mode,
LocationInfo& locationInfo, LocationInfo& locationInfo,
folly::Range<SymbolizedFrame*> inlineFrames) const { folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(const folly::StringPiece name)> eachParameterName)
const {
if (mode == LocationInfoMode::DISABLED) { if (mode == LocationInfoMode::DISABLED) {
return false; return false;
} }
...@@ -622,7 +642,8 @@ bool Dwarf::findAddress( ...@@ -622,7 +642,8 @@ bool Dwarf::findAddress(
if (findDebugInfoOffset(address, debugAranges_, offset)) { if (findDebugInfoOffset(address, debugAranges_, offset)) {
// Read compilation unit header from .debug_info // Read compilation unit header from .debug_info
auto unit = getCompilationUnit(debugInfo_, offset); auto unit = getCompilationUnit(debugInfo_, offset);
findLocation(address, mode, unit, locationInfo, inlineFrames); findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
return locationInfo.hasFileAndLine; return locationInfo.hasFileAndLine;
} else if (mode == LocationInfoMode::FAST) { } else if (mode == LocationInfoMode::FAST) {
// NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries // NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries
...@@ -645,7 +666,8 @@ bool Dwarf::findAddress( ...@@ -645,7 +666,8 @@ bool Dwarf::findAddress(
while (offset < debugInfo_.size() && !locationInfo.hasFileAndLine) { while (offset < debugInfo_.size() && !locationInfo.hasFileAndLine) {
auto unit = getCompilationUnit(debugInfo_, offset); auto unit = getCompilationUnit(debugInfo_, offset);
offset += unit.size; offset += unit.size;
findLocation(address, mode, unit, locationInfo, inlineFrames); findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
} }
return locationInfo.hasFileAndLine; return locationInfo.hasFileAndLine;
} }
......
...@@ -87,12 +87,18 @@ class Dwarf { ...@@ -87,12 +87,18 @@ class Dwarf {
*/ */
static const uint32_t kMaxInlineLocationInfoPerFrame = 10; 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( bool findAddress(
uintptr_t address, uintptr_t address,
LocationInfoMode mode, LocationInfoMode mode,
LocationInfo& info, LocationInfo& info,
folly::Range<SymbolizedFrame*> inlineFrames = {}) const; folly::Range<SymbolizedFrame*> inlineFrames = {},
folly::FunctionRef<void(const folly::StringPiece name)>
eachParameterName = {}) const;
private: private:
using AttributeValue = boost::variant<uint64_t, folly::StringPiece>; using AttributeValue = boost::variant<uint64_t, folly::StringPiece>;
...@@ -110,14 +116,17 @@ class Dwarf { ...@@ -110,14 +116,17 @@ class Dwarf {
/** /**
* Finds location info (file and line) for a given address in the given * 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( bool findLocation(
uintptr_t address, uintptr_t address,
const LocationInfoMode mode, const LocationInfoMode mode,
detail::CompilationUnit& cu, detail::CompilationUnit& cu,
LocationInfo& info, 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 * Finds a subprogram debugging info entry that contains a given address among
......
...@@ -432,6 +432,34 @@ TEST(SymbolizerTest, InlineFunctionWithCache) { ...@@ -432,6 +432,34 @@ TEST(SymbolizerTest, InlineFunctionWithCache) {
compareFrames(frames, frames2); 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 test
} // namespace symbolizer } // namespace symbolizer
} // namespace folly } // 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