Commit 490b287c authored by Lucian Grijincu's avatar Lucian Grijincu Committed by Facebook GitHub Bot

folly::symbolizer: add support for DWARF5

Summary:
folly::symbolizer now supports both DWARF4 and DWARF5 debug info
- http://www.dwarfstd.org/doc/DWARF4.pdf
- http://www.dwarfstd.org/doc/DWARF5.pdf

Split DWARF (Debug Fission)
- with `-fsplit-dwarf-inlining`: folly::symbolizer will use the debug info from the skeleton CU.
- without `-fsplit-dwarf-inlining`: folly::symbolizer won't read .dwo sections and can't symbolize it (yet).

Major things that changed between the standards that affect folly::symbolizer:
- new forms DW_FORM_addrx*, DW_FORM_loclistx, DW_FORM_rnglistx, DW_FORM_strx*, whose values are interpreted against new CU attributes DW_AT_addr_base, DW_AT_loclists_base, DW_AT_rnglists_base, DW_AT_str_offsets_base
- The .debug_line line header format is completely re-written and the constraint that the file register must be >= 1 was lifted.
- DWARF5 `.debug_loclists` replaces DWARF4 `.debug_ranges`

Differential Revision: D25521092

fbshipit-source-id: 5b48e8abed495f379d8b119177913f55ae11bd2b
parent 0c8f7e29
This diff is collapsed.
...@@ -165,6 +165,9 @@ class Dwarf { ...@@ -165,6 +165,9 @@ class Dwarf {
/** Get an ELF section by name. */ /** Get an ELF section by name. */
folly::StringPiece getSection(const char* name) const; folly::StringPiece getSection(const char* name) const;
detail::CompilationUnit getCompilationUnit(uint64_t offset) const;
detail::CompilationUnit findCompilationUnit(uint64_t targetOffset) const;
/** cu must exist during the life cycle of created detail::Die. */ /** cu must exist during the life cycle of created detail::Die. */
detail::Die getDieAtOffset( detail::Die getDieAtOffset(
const detail::CompilationUnit& cu, uint64_t offset) const; const detail::CompilationUnit& cu, uint64_t offset) const;
...@@ -191,6 +194,12 @@ class Dwarf { ...@@ -191,6 +194,12 @@ class Dwarf {
*/ */
detail::DIEAbbreviation getAbbreviation(uint64_t code, uint64_t offset) const; detail::DIEAbbreviation getAbbreviation(uint64_t code, uint64_t offset) const;
detail::Attribute readAttribute(
const detail::CompilationUnit& cu,
const detail::Die& die,
detail::AttributeSpec spec,
folly::StringPiece& info) const;
/** /**
* Iterates over all attributes of a debugging info entry, calling the given * Iterates over all attributes of a debugging info entry, calling the given
* callable for each. If all attributes are visited, then return the offset of * callable for each. If all attributes are visited, then return the offset of
...@@ -212,18 +221,24 @@ class Dwarf { ...@@ -212,18 +221,24 @@ class Dwarf {
* .debug_ranges. * .debug_ranges.
*/ */
bool isAddrInRangeList( bool isAddrInRangeList(
const detail::CompilationUnit& cu,
uint64_t address, uint64_t address,
folly::Optional<uint64_t> baseAddr, folly::Optional<uint64_t> baseAddr,
size_t offset, size_t offset,
uint8_t addrSize) const; uint8_t addrSize) const;
const ElfFile* elf_; const ElfFile* elf_;
const folly::StringPiece debugInfo_; // .debug_info
const folly::StringPiece debugAbbrev_; // .debug_abbrev const folly::StringPiece debugAbbrev_; // .debug_abbrev
const folly::StringPiece debugLine_; // .debug_line const folly::StringPiece debugAddr_; // .debug_addr (DWARF 5)
const folly::StringPiece debugStr_; // .debug_str
const folly::StringPiece debugAranges_; // .debug_aranges const folly::StringPiece debugAranges_; // .debug_aranges
const folly::StringPiece debugInfo_; // .debug_info
const folly::StringPiece debugLine_; // .debug_line
const folly::StringPiece debugLineStr_; // .debug_line_str (DWARF 5)
const folly::StringPiece debugLoclists_; // .debug_loclists (DWARF 5)
const folly::StringPiece debugRanges_; // .debug_ranges const folly::StringPiece debugRanges_; // .debug_ranges
const folly::StringPiece debugRnglists_; // .debug_rnglists (DWARF 5)
const folly::StringPiece debugStr_; // .debug_str
const folly::StringPiece debugStrOffsets_; // .debug_str_offsets (DWARF 5)
}; };
class Dwarf::Section { class Dwarf::Section {
...@@ -250,15 +265,15 @@ class Dwarf::Section { ...@@ -250,15 +265,15 @@ class Dwarf::Section {
class Dwarf::LineNumberVM { class Dwarf::LineNumberVM {
public: public:
LineNumberVM( LineNumberVM(
folly::StringPiece data, folly::StringPiece compilationDirectory); folly::StringPiece data,
folly::StringPiece compilationDirectory,
folly::StringPiece debugStr,
folly::StringPiece debugLineStr);
bool findAddress(uintptr_t target, Path& file, uint64_t& line); bool findAddress(uintptr_t target, Path& file, uint64_t& line);
/** Gets full file name at given index including directory. */ /** Gets full file name at given index including directory. */
Path getFullFileName(uint64_t index) const { Path getFullFileName(uint64_t index) const;
auto fn = getFileName(index);
return Path({}, getIncludeDirectory(fn.directoryIndex), fn.relativeName);
}
private: private:
void init(); void init();
...@@ -304,6 +319,8 @@ class Dwarf::LineNumberVM { ...@@ -304,6 +319,8 @@ class Dwarf::LineNumberVM {
bool is64Bit_; bool is64Bit_;
folly::StringPiece data_; folly::StringPiece data_;
folly::StringPiece compilationDirectory_; folly::StringPiece compilationDirectory_;
folly::StringPiece debugStr_; // needed for DWARF 5
folly::StringPiece debugLineStr_; // DWARF 5
// Header // Header
uint16_t version_; uint16_t version_;
...@@ -314,11 +331,25 @@ class Dwarf::LineNumberVM { ...@@ -314,11 +331,25 @@ class Dwarf::LineNumberVM {
uint8_t opcodeBase_; uint8_t opcodeBase_;
const uint8_t* standardOpcodeLengths_; const uint8_t* standardOpcodeLengths_;
folly::StringPiece includeDirectories_; // 6.2.4 The Line Number Program Header.
size_t includeDirectoryCount_; struct {
size_t includeDirectoryCount;
folly::StringPiece fileNames_; folly::StringPiece includeDirectories;
size_t fileNameCount_; size_t fileNameCount;
folly::StringPiece fileNames;
} v4_;
struct {
uint8_t directoryEntryFormatCount;
folly::StringPiece directoryEntryFormat;
uint64_t directoriesCount;
folly::StringPiece directories;
uint8_t fileNameEntryFormatCount;
folly::StringPiece fileNameEntryFormat;
uint64_t fileNamesCount;
folly::StringPiece fileNames;
} v5_;
// State machine registers // State machine registers
uint64_t address_; uint64_t address_;
......
...@@ -261,6 +261,8 @@ class ElfFile { ...@@ -261,6 +261,8 @@ class ElfFile {
/** Find the section containing the given address */ /** Find the section containing the given address */
const ElfShdr* getSectionContainingAddress(ElfAddr addr) const noexcept; const ElfShdr* getSectionContainingAddress(ElfAddr addr) const noexcept;
const char* filepath() const { return filepath_; }
private: private:
OpenResult init() noexcept; OpenResult init() noexcept;
void reset() noexcept; void reset() noexcept;
......
...@@ -151,9 +151,12 @@ void expectFrameEq( ...@@ -151,9 +151,12 @@ void expectFrameEq(
auto demangled = folly::demangle(frame.name); auto demangled = folly::demangle(frame.name);
EXPECT_TRUE(demangled == shortName || demangled == fullName) EXPECT_TRUE(demangled == shortName || demangled == fullName)
<< "Found: demangled=" << demangled << "Found: demangled=" << demangled
<< " expecting shortName=" << shortName << " or fullName=" << fullName; << " expecting shortName=" << shortName << " or fullName=" << fullName
<< " address: " << frame.addr << " hex(address): " << std::hex
<< frame.addr;
EXPECT_EQ(normalizePath(frame.location.file.toString()), normalizePath(file)) EXPECT_EQ(normalizePath(frame.location.file.toString()), normalizePath(file))
<< ' ' << fullName; << ' ' << fullName << " address: " << frame.addr
<< " hex(address): " << std::hex << frame.addr;
EXPECT_EQ(frame.location.line, lineno) << ' ' << fullName; EXPECT_EQ(frame.location.line, lineno) << ' ' << fullName;
} }
...@@ -474,6 +477,12 @@ TEST(Dwarf, FindParameterNames) { ...@@ -474,6 +477,12 @@ TEST(Dwarf, FindParameterNames) {
extraInlineFrames, extraInlineFrames,
[&](const folly::StringPiece name) { names.push_back(name); }); [&](const folly::StringPiece name) { names.push_back(name); });
if (names.empty()) {
// When using -fsplit-dwarf-inlining info about parameters will not be
// emitted for the inlined debug info.
return;
}
ASSERT_EQ(2, names.size()); ASSERT_EQ(2, names.size());
ASSERT_EQ("a", names[0]); ASSERT_EQ("a", names[0]);
ASSERT_EQ("b", names[1]); ASSERT_EQ("b", names[1]);
......
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