Skip to content

[Cherry-Pick] Patches for DWARFLinker and DebugNames #8115

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b1112b0
[BOLT][DWARF] Update handling of size 1 ranges and fix sub-programs w…
ayermolo Jul 31, 2023
63dd9fc
[BOLT][DWARF] Fix handling of inlined subroutine with no output PC
ayermolo Aug 1, 2023
3302d88
[BOLT][DWARF] Delete DW_AT_low_pc when converting to ranges
ayermolo Aug 3, 2023
87d027b
[BOLT][DWARF] Fix setting DW_AT_ranges offset of Skeleton CU
ayermolo Aug 3, 2023
bf70505
[BOLT][DWARF][NFC] Add function to print DIE
ayermolo Aug 9, 2023
cf5102e
[BOLT][DWARF] Always use new low_pc for exprloc
ayermolo Aug 9, 2023
c127f2c
[BOLT][DWARF] Always use new low_pc for call_site
ayermolo Aug 9, 2023
7aeb0a9
[BOLT][DWARF] Fix location list order
ayermolo Aug 15, 2023
e7ccd63
[BOLT] Fix typo in comment
eymay Aug 24, 2023
5dd4514
[BOLT][DWARF] Refactor address ranges processing (#71225)
maksfb Nov 6, 2023
519d27b
Add support for parsing type unit entries in .debug_names. (#72952)
clayborg Nov 28, 2023
830aa3f
[CodeGen] Remove unused forward declarations (NFC)
kazutakahirata Dec 17, 2023
537ba25
[LLVM][DWARF] Add compilation directory and dwo name to TU in dwo sec…
ayermolo Dec 12, 2023
3f7d6a6
[AsmPrinter][Dwarf5][nfc] Remove template from AccelTable class (#76296)
felipepiovezan Jan 5, 2024
aba424a
[DWARFLinker] Support MD5 checksums in the line table (#77151)
JDevlieghere Jan 6, 2024
e1ffce4
[AccelTable][nfc] Add helper function to cast AccelTableData (#77100)
felipepiovezan Jan 8, 2024
1d997c9
[DWARFLinker][DWARFLinkerParallel][NFC] Refactor DWARFLinker&DWARFLin…
avl-llvm Jan 9, 2024
eb1e9b8
[DWARFLinker] backport line table patch into the DWARFLinkerParallel.…
avl-llvm Jan 10, 2024
089977e
[DWARFLinker][NFC] Move common code into the base library: Utils.h (#…
avl-llvm Jan 11, 2024
b5fc304
[DWARFLinker][NFC] Rename libraries to match with directories name. (…
avl-llvm Jan 12, 2024
6247264
[dsymutil] Use StringRef::consume_front (NFC)
kazutakahirata Jan 16, 2024
a0d081f
[dsymutil][llvm-dwarfutil] Rename command line options to avoid using…
avl-llvm Jan 18, 2024
906d136
[DWARFLinker][NFC] Move common code into the base library: IndexedVal…
avl-llvm Jan 18, 2024
90234a9
[DWARFLinker][NFC] Decrease DWARFLinker dependence on DwarfStreamer. …
avl-llvm Jan 19, 2024
1af2ff6
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
felipepiovezan Jan 19, 2024
5605fff
[dsymutil] Add --linker parallel to more tests. (#78581)
avl-llvm Jan 23, 2024
38794a0
[DebugNames] Implement Entry::GetParentEntry query (#78760)
felipepiovezan Jan 24, 2024
56bb721
[DebugNames] Use hashes to quickly filter false positives (#79755)
felipepiovezan Jan 30, 2024
32f645e
[DebugNames] Compare TableEntry names more efficiently (#79759)
felipepiovezan Jan 30, 2024
34e1602
[lldb][nfc] Mark function as const (#76974)
felipepiovezan Jan 4, 2024
bcda8da
[lldb][DWARFIndex][nfc] Factor out fully qualified name query (#76977)
felipepiovezan Jan 8, 2024
7e8b96a
[lldb][DWARFUnit] Implement PeekDIEName query (#78486)
felipepiovezan Jan 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 4 additions & 9 deletions bolt/include/bolt/Core/BinaryFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2298,15 +2298,10 @@ class BinaryFunction {
/// removed.
uint64_t translateInputToOutputAddress(uint64_t Address) const;

/// Take address ranges corresponding to the input binary and translate
/// them to address ranges in the output binary.
DebugAddressRangesVector translateInputToOutputRanges(
const DWARFAddressRangesVector &InputRanges) const;

/// Similar to translateInputToOutputRanges() but operates on location lists
/// and moves associated data to output location lists.
DebugLocationsVector
translateInputToOutputLocationList(const DebugLocationsVector &InputLL) const;
/// Translate a contiguous range of addresses in the input binary into a set
/// of ranges in the output binary.
DebugAddressRangesVector
translateInputToOutputRange(DebugAddressRange InRange) const;

/// Return true if the function is an AArch64 linker inserted veneer
bool isAArch64Veneer() const;
Expand Down
1 change: 0 additions & 1 deletion bolt/include/bolt/Core/DIEBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ class DIEBuilder {
return Die->replaceValue(getState().DIEAlloc, Attribute, Form, NewValue);
}

template <class T>
bool deleteValue(DIEValueList *Die, dwarf::Attribute Attribute) {
return Die->deleteValue(Attribute);
}
Expand Down
19 changes: 19 additions & 0 deletions bolt/include/bolt/Core/DebugData.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/CodeGen/DIE.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
Expand Down Expand Up @@ -95,6 +96,12 @@ static inline bool operator<(const DebugAddressRange &LHS,
return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
}

inline raw_ostream &operator<<(raw_ostream &OS,
const DebugAddressRange &Range) {
OS << formatv("[{0:x}, {1:x})", Range.LowPC, Range.HighPC);
return OS;
}

/// DebugAddressRangesVector - represents a set of absolute address ranges.
using DebugAddressRangesVector = SmallVector<DebugAddressRange, 2>;

Expand All @@ -106,6 +113,18 @@ struct DebugLocationEntry {
SmallVector<uint8_t, 4> Expr;
};

inline raw_ostream &operator<<(raw_ostream &OS,
const DebugLocationEntry &Entry) {
OS << formatv("[{0:x}, {1:x}) : [", Entry.LowPC, Entry.HighPC);
const char *Sep = "";
for (unsigned Byte : Entry.Expr) {
OS << Sep << Byte;
Sep = ", ";
}
OS << "]";
return OS;
}

using DebugLocationsVector = SmallVector<DebugLocationEntry, 4>;

/// References a row in a DWARFDebugLine::LineTable by the DWARF
Expand Down
4 changes: 2 additions & 2 deletions bolt/include/bolt/Rewrite/DWARFRewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class DWARFRewriter {
/// attribute.
void updateDWARFObjectAddressRanges(
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
uint64_t DebugRangesOffset, uint64_t LowPCToUse,
uint64_t DebugRangesOffset,
std::optional<uint64_t> RangesBase = std::nullopt);

std::unique_ptr<DebugBufferVector>
Expand Down Expand Up @@ -173,7 +173,7 @@ class DWARFRewriter {
void convertToRangesPatchDebugInfo(
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
DIEValue &HighPCAttrInfo, uint64_t LowPCToUse,
DIEValue &HighPCAttrInfo,
std::optional<uint64_t> RangesBase = std::nullopt);

/// Adds a \p Str to .debug_str section.
Expand Down
224 changes: 67 additions & 157 deletions bolt/lib/Core/BinaryFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4195,92 +4195,88 @@ uint64_t BinaryFunction::translateInputToOutputAddress(uint64_t Address) const {
BB->getOutputAddressRange().second);
}

DebugAddressRangesVector BinaryFunction::translateInputToOutputRanges(
const DWARFAddressRangesVector &InputRanges) const {
DebugAddressRangesVector OutputRanges;
DebugAddressRangesVector
BinaryFunction::translateInputToOutputRange(DebugAddressRange InRange) const {
DebugAddressRangesVector OutRanges;

// The function was removed from the output. Return an empty range.
if (isFolded())
return OutputRanges;
return OutRanges;

// If the function hasn't changed return the same ranges.
// If the function hasn't changed return the same range.
if (!isEmitted()) {
OutputRanges.resize(InputRanges.size());
llvm::transform(InputRanges, OutputRanges.begin(),
[](const DWARFAddressRange &Range) {
return DebugAddressRange(Range.LowPC, Range.HighPC);
});
return OutputRanges;
OutRanges.emplace_back(InRange);
return OutRanges;
}

if (!containsAddress(InRange.LowPC))
return OutRanges;

// Special case of an empty range [X, X). Some tools expect X to be updated.
if (InRange.LowPC == InRange.HighPC) {
if (uint64_t NewPC = translateInputToOutputAddress(InRange.LowPC))
OutRanges.push_back(DebugAddressRange{NewPC, NewPC});
return OutRanges;
}

// Even though we will merge ranges in a post-processing pass, we attempt to
// merge them in a main processing loop as it improves the processing time.
uint64_t PrevEndAddress = 0;
for (const DWARFAddressRange &Range : InputRanges) {
if (!containsAddress(Range.LowPC)) {
uint64_t InputOffset = InRange.LowPC - getAddress();
const uint64_t InputEndOffset =
std::min(InRange.HighPC - getAddress(), getSize());

auto BBI = llvm::upper_bound(BasicBlockOffsets,
BasicBlockOffset(InputOffset, nullptr),
CompareBasicBlockOffsets());
assert(BBI != BasicBlockOffsets.begin());

// Iterate over blocks in the input order using BasicBlockOffsets.
for (--BBI; InputOffset < InputEndOffset && BBI != BasicBlockOffsets.end();
InputOffset = BBI->second->getEndOffset(), ++BBI) {
const BinaryBasicBlock &BB = *BBI->second;
if (InputOffset < BB.getOffset() || InputOffset >= BB.getEndOffset()) {
LLVM_DEBUG(
dbgs() << "BOLT-DEBUG: invalid debug address range detected for "
<< *this << " : [0x" << Twine::utohexstr(Range.LowPC) << ", 0x"
<< Twine::utohexstr(Range.HighPC) << "]\n");
PrevEndAddress = 0;
continue;
<< *this << " : [0x" << Twine::utohexstr(InRange.LowPC)
<< ", 0x" << Twine::utohexstr(InRange.HighPC) << "]\n");
break;
}
uint64_t InputOffset = Range.LowPC - getAddress();
const uint64_t InputEndOffset =
std::min(Range.HighPC - getAddress(), getSize());

auto BBI = llvm::upper_bound(BasicBlockOffsets,
BasicBlockOffset(InputOffset, nullptr),
CompareBasicBlockOffsets());
--BBI;
do {
const BinaryBasicBlock *BB = BBI->second;
if (InputOffset < BB->getOffset() || InputOffset >= BB->getEndOffset()) {
LLVM_DEBUG(
dbgs() << "BOLT-DEBUG: invalid debug address range detected for "
<< *this << " : [0x" << Twine::utohexstr(Range.LowPC)
<< ", 0x" << Twine::utohexstr(Range.HighPC) << "]\n");
PrevEndAddress = 0;
break;
}

// Skip the range if the block was deleted.
if (const uint64_t OutputStart = BB->getOutputAddressRange().first) {
const uint64_t StartAddress =
OutputStart + InputOffset - BB->getOffset();
uint64_t EndAddress = BB->getOutputAddressRange().second;
if (InputEndOffset < BB->getEndOffset())
EndAddress = StartAddress + InputEndOffset - InputOffset;

if (StartAddress == PrevEndAddress) {
OutputRanges.back().HighPC =
std::max(OutputRanges.back().HighPC, EndAddress);
} else {
OutputRanges.emplace_back(StartAddress,
std::max(StartAddress, EndAddress));
}
PrevEndAddress = OutputRanges.back().HighPC;
}
// Skip the block if it wasn't emitted.
if (!BB.getOutputAddressRange().first)
continue;

InputOffset = BB->getEndOffset();
++BBI;
} while (InputOffset < InputEndOffset);
}
// Find output address for an instruction with an offset greater or equal
// to /p Offset. The output address should fall within the same basic
// block boundaries.
auto translateBlockOffset = [&](const uint64_t Offset) {
const uint64_t OutAddress = BB.getOutputAddressRange().first + Offset;
return OutAddress;
};

// Post-processing pass to sort and merge ranges.
llvm::sort(OutputRanges);
DebugAddressRangesVector MergedRanges;
PrevEndAddress = 0;
for (const DebugAddressRange &Range : OutputRanges) {
if (Range.LowPC <= PrevEndAddress) {
MergedRanges.back().HighPC =
std::max(MergedRanges.back().HighPC, Range.HighPC);
} else {
MergedRanges.emplace_back(Range.LowPC, Range.HighPC);
uint64_t OutLowPC = BB.getOutputAddressRange().first;
if (InputOffset > BB.getOffset())
OutLowPC = translateBlockOffset(InputOffset - BB.getOffset());

uint64_t OutHighPC = BB.getOutputAddressRange().second;
if (InputEndOffset < BB.getEndOffset()) {
assert(InputEndOffset >= BB.getOffset());
OutHighPC = translateBlockOffset(InputEndOffset - BB.getOffset());
}
PrevEndAddress = MergedRanges.back().HighPC;

// Check if we can expand the last translated range.
if (!OutRanges.empty() && OutRanges.back().HighPC == OutLowPC)
OutRanges.back().HighPC = std::max(OutRanges.back().HighPC, OutHighPC);
else
OutRanges.emplace_back(OutLowPC, std::max(OutLowPC, OutHighPC));
}

return MergedRanges;
LLVM_DEBUG({
dbgs() << "BOLT-DEBUG: translated address range " << InRange << " -> ";
for (const DebugAddressRange &R : OutRanges)
dbgs() << R << ' ';
dbgs() << '\n';
});

return OutRanges;
}

MCInst *BinaryFunction::getInstructionAtOffset(uint64_t Offset) {
Expand Down Expand Up @@ -4311,92 +4307,6 @@ MCInst *BinaryFunction::getInstructionAtOffset(uint64_t Offset) {
}
}

DebugLocationsVector BinaryFunction::translateInputToOutputLocationList(
const DebugLocationsVector &InputLL) const {
DebugLocationsVector OutputLL;

if (isFolded())
return OutputLL;

// If the function hasn't changed - there's nothing to update.
if (!isEmitted())
return InputLL;

uint64_t PrevEndAddress = 0;
SmallVectorImpl<uint8_t> *PrevExpr = nullptr;
for (const DebugLocationEntry &Entry : InputLL) {
const uint64_t Start = Entry.LowPC;
const uint64_t End = Entry.HighPC;
if (!containsAddress(Start)) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: invalid debug address range detected "
"for "
<< *this << " : [0x" << Twine::utohexstr(Start)
<< ", 0x" << Twine::utohexstr(End) << "]\n");
continue;
}
uint64_t InputOffset = Start - getAddress();
const uint64_t InputEndOffset = std::min(End - getAddress(), getSize());
auto BBI = llvm::upper_bound(BasicBlockOffsets,
BasicBlockOffset(InputOffset, nullptr),
CompareBasicBlockOffsets());
--BBI;
do {
const BinaryBasicBlock *BB = BBI->second;
if (InputOffset < BB->getOffset() || InputOffset >= BB->getEndOffset()) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: invalid debug address range detected "
"for "
<< *this << " : [0x" << Twine::utohexstr(Start)
<< ", 0x" << Twine::utohexstr(End) << "]\n");
PrevEndAddress = 0;
break;
}

// Skip the range if the block was deleted.
if (const uint64_t OutputStart = BB->getOutputAddressRange().first) {
const uint64_t StartAddress =
OutputStart + InputOffset - BB->getOffset();
uint64_t EndAddress = BB->getOutputAddressRange().second;
if (InputEndOffset < BB->getEndOffset())
EndAddress = StartAddress + InputEndOffset - InputOffset;

if (StartAddress == PrevEndAddress && Entry.Expr == *PrevExpr) {
OutputLL.back().HighPC = std::max(OutputLL.back().HighPC, EndAddress);
} else {
OutputLL.emplace_back(DebugLocationEntry{
StartAddress, std::max(StartAddress, EndAddress), Entry.Expr});
}
PrevEndAddress = OutputLL.back().HighPC;
PrevExpr = &OutputLL.back().Expr;
}

++BBI;
InputOffset = BB->getEndOffset();
} while (InputOffset < InputEndOffset);
}

// Sort and merge adjacent entries with identical location.
llvm::stable_sort(
OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) {
return A.LowPC < B.LowPC;
});
DebugLocationsVector MergedLL;
PrevEndAddress = 0;
PrevExpr = nullptr;
for (const DebugLocationEntry &Entry : OutputLL) {
if (Entry.LowPC <= PrevEndAddress && *PrevExpr == Entry.Expr) {
MergedLL.back().HighPC = std::max(Entry.HighPC, MergedLL.back().HighPC);
} else {
const uint64_t Begin = std::max(Entry.LowPC, PrevEndAddress);
const uint64_t End = std::max(Begin, Entry.HighPC);
MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr});
}
PrevEndAddress = MergedLL.back().HighPC;
PrevExpr = &MergedLL.back().Expr;
}

return MergedLL;
}

void BinaryFunction::printLoopInfo(raw_ostream &OS) const {
if (!opts::shouldPrint(*this))
return;
Expand Down
1 change: 1 addition & 0 deletions bolt/lib/Rewrite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
Object
Support
DWARFLinker
DWARFLinkerClassic
AsmPrinter
TargetParser
)
Expand Down
Loading