mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 22:26:07 +00:00
Update unmatched and nested subprogram DIEs.
Summary: readelf was showing some errors because we weren't updating DIEs that were not shallow in the DIE tree, or DIEs of functions with addresses we don't recognize (mostly functions with address 0, which could have been removed by the Linker Script but still have debugging information there). These DIEs need to be updated because their abbreviations are patched. (cherry picked from FBD3159335)
This commit is contained in:
parent
665b03a464
commit
2694e58fa2
@ -95,6 +95,32 @@ void findLexicalBlocks(const DWARFCompileUnit *Unit,
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively finds DWARF DW_TAG_subprogram DIEs and match them with
|
||||
// BinaryFunctions. Record DIEs for unknown subprograms (mostly functions that
|
||||
// are never called and removed from the binary) in Unknown.
|
||||
void findSubprograms(const DWARFCompileUnit *Unit,
|
||||
const DWARFDebugInfoEntryMinimal *DIE,
|
||||
std::map<uint64_t, BinaryFunction> &BinaryFunctions,
|
||||
BinaryContext::DIECompileUnitVector &Unknown) {
|
||||
if (DIE->isSubprogramDIE()) {
|
||||
uint64_t LowPC, HighPC;
|
||||
if (DIE->getLowAndHighPC(Unit, LowPC, HighPC)) {
|
||||
auto It = BinaryFunctions.find(LowPC);
|
||||
if (It != BinaryFunctions.end()) {
|
||||
It->second.addSubprocedureDIE(Unit, DIE);
|
||||
} else {
|
||||
Unknown.emplace_back(DIE, Unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ChildDIE = DIE->getFirstChild();
|
||||
ChildDIE != nullptr && !ChildDIE->isNULL();
|
||||
ChildDIE = ChildDIE->getSibling()) {
|
||||
findSubprograms(Unit, ChildDIE, BinaryFunctions, Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace llvm {
|
||||
@ -130,26 +156,11 @@ void BinaryContext::preprocessDebugInfo() {
|
||||
|
||||
void BinaryContext::preprocessFunctionDebugInfo(
|
||||
std::map<uint64_t, BinaryFunction> &BinaryFunctions) {
|
||||
// For each CU, iterate over its children DIEs and match subroutine DIEs to
|
||||
// For each CU, iterate over its children DIEs and match subprogram DIEs to
|
||||
// BinaryFunctions.
|
||||
for (const auto &CU : DwCtx->compile_units()) {
|
||||
const auto *UnitDIE = CU->getUnitDIE(false);
|
||||
if (!UnitDIE->hasChildren())
|
||||
continue;
|
||||
|
||||
for (auto ChildDIE = UnitDIE->getFirstChild();
|
||||
ChildDIE != nullptr && !ChildDIE->isNULL();
|
||||
ChildDIE = ChildDIE->getSibling()) {
|
||||
if (ChildDIE->isSubprogramDIE()) {
|
||||
uint64_t LowPC, HighPC;
|
||||
if (ChildDIE->getLowAndHighPC(CU.get(), LowPC, HighPC)) {
|
||||
auto It = BinaryFunctions.find(LowPC);
|
||||
if (It != BinaryFunctions.end()) {
|
||||
It->second.addSubprocedureDIE(CU.get(), ChildDIE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
findSubprograms(CU.get(), CU->getUnitDIE(false), BinaryFunctions,
|
||||
UnknownFunctions);
|
||||
}
|
||||
|
||||
// Iterate over DIE trees finding lexical blocks.
|
||||
|
@ -40,6 +40,9 @@
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFDebugInfoEntryMinimal;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class BinaryFunction;
|
||||
@ -78,6 +81,14 @@ public:
|
||||
/// List of DWARF location lists in .debug_loc.
|
||||
std::vector<LocationList> LocationLists;
|
||||
|
||||
using DIECompileUnitVector =
|
||||
std::vector<std::pair<const DWARFDebugInfoEntryMinimal *,
|
||||
const DWARFCompileUnit *>> ;
|
||||
|
||||
/// List of subprocedure DIEs that have addresses that don't match any
|
||||
/// function, along with their CU.
|
||||
DIECompileUnitVector UnknownFunctions;
|
||||
|
||||
std::unique_ptr<MCContext> Ctx;
|
||||
|
||||
std::unique_ptr<DWARFContext> DwCtx;
|
||||
|
@ -65,6 +65,14 @@ void DebugRangesSectionsWriter::WriteRangesSection(MCObjectWriter *Writer) {
|
||||
const auto &AddressRanges = BFAddressRangesPair.second;
|
||||
SectionOffset += WriteAddressRanges(Writer, AddressRanges, false);
|
||||
}
|
||||
|
||||
// Write an empty address list to be used for objects with unknown address
|
||||
// ranges.
|
||||
EmptyRangesListOffset = SectionOffset;
|
||||
SectionOffset += WriteAddressRanges(
|
||||
Writer,
|
||||
std::vector<std::pair<uint64_t, uint64_t>>{},
|
||||
false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -65,6 +65,10 @@ public:
|
||||
return RangesSectionOffsetCUMap;
|
||||
}
|
||||
|
||||
/// Returns an offset of an empty address ranges list that is always written
|
||||
/// to .debug_ranges
|
||||
uint32_t getEmptyRangesListOffset() const { return EmptyRangesListOffset; }
|
||||
|
||||
private:
|
||||
// Map from compile unit offset to the list of address intervals that belong
|
||||
// to that compile unit. Each interval is a pair
|
||||
@ -77,6 +81,9 @@ private:
|
||||
std::map<AddressRangesOwner *, std::vector<std::pair<uint64_t, uint64_t>>>
|
||||
ObjectAddressRanges;
|
||||
|
||||
// Offset of an empty address ranges list.
|
||||
uint32_t EmptyRangesListOffset;
|
||||
|
||||
/// When writing data to .debug_ranges remember offset per CU.
|
||||
RangesCUMapType RangesSectionOffsetCUMap;
|
||||
};
|
||||
|
@ -2182,6 +2182,14 @@ void RewriteInstance::updateDWARFAddressRanges() {
|
||||
}
|
||||
}
|
||||
|
||||
// Update address ranges of DIEs with addresses that don't match functions.
|
||||
for (auto &DIECompileUnitPair : BC->UnknownFunctions) {
|
||||
updateDWARFObjectAddressRanges(
|
||||
RangesSectionsWriter.getEmptyRangesListOffset(),
|
||||
DIECompileUnitPair.second,
|
||||
DIECompileUnitPair.first);
|
||||
}
|
||||
|
||||
// Update address ranges of lexical blocks.
|
||||
for (const auto &LB : BC->LexicalBlocks) {
|
||||
updateDWARFObjectAddressRanges(
|
||||
|
Loading…
x
Reference in New Issue
Block a user