Skip to content

Commit

Permalink
DebugInfo: Use base address selection entries for debug_loc
Browse files Browse the repository at this point in the history
Unify the range and loc emission (for both DWARFv4 and DWARFv5 style lists) and take advantage of that unification to use strategic base addresses for loclists.

Differential Revision: https://reviews.llvm.org/D68620

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374600 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
dwblaikie committed Oct 11, 2019
1 parent 8ef67fd commit 86b0b37
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 272 deletions.
265 changes: 115 additions & 150 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2293,14 +2293,121 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm,
return TableEnd;
}

template <typename Ranges, typename PayloadEmitter>
static void emitRangeList(
DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R,
const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair,
unsigned StartxLength, unsigned EndOfList,
StringRef (*StringifyEnum)(unsigned),
bool ShouldUseBaseAddress,
PayloadEmitter EmitPayload) {

auto Size = Asm->MAI->getCodePointerSize();
bool UseDwarf5 = DD.getDwarfVersion() >= 5;

// Emit our symbol so we can find the beginning of the range.
Asm->OutStreamer->EmitLabel(Sym);

// Gather all the ranges that apply to the same section so they can share
// a base address entry.
MapVector<const MCSection *, std::vector<decltype(&*R.begin())>> SectionRanges;

for (const auto &Range : R)
SectionRanges[&Range.Begin->getSection()].push_back(&Range);

const MCSymbol *CUBase = CU.getBaseAddress();
bool BaseIsSet = false;
for (const auto &P : SectionRanges) {
auto *Base = CUBase;
if (!Base && ShouldUseBaseAddress) {
const MCSymbol *Begin = P.second.front()->Begin;
const MCSymbol *NewBase = DD.getSectionLabel(&Begin->getSection());
if (!UseDwarf5) {
Base = NewBase;
BaseIsSet = true;
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->AddComment(" base address");
Asm->OutStreamer->EmitSymbolValue(Base, Size);
} else if (NewBase != Begin || P.second.size() > 1) {
// Only use a base address if
// * the existing pool address doesn't match (NewBase != Begin)
// * or, there's more than one entry to share the base address
Base = NewBase;
BaseIsSet = true;
Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));
Asm->emitInt8(BaseAddressx);
Asm->OutStreamer->AddComment(" base address index");
Asm->EmitULEB128(DD.getAddressPool().getIndex(Base));
}
} else if (BaseIsSet && !UseDwarf5) {
BaseIsSet = false;
assert(!Base);
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}

for (const auto *RS : P.second) {
const MCSymbol *Begin = RS->Begin;
const MCSymbol *End = RS->End;
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
if (Base) {
if (UseDwarf5) {
// Emit offset_pair when we have a base.
Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));
Asm->emitInt8(OffsetPair);
Asm->OutStreamer->AddComment(" starting offset");
Asm->EmitLabelDifferenceAsULEB128(Begin, Base);
Asm->OutStreamer->AddComment(" ending offset");
Asm->EmitLabelDifferenceAsULEB128(End, Base);
} else {
Asm->EmitLabelDifference(Begin, Base, Size);
Asm->EmitLabelDifference(End, Base, Size);
}
} else if (UseDwarf5) {
Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
Asm->emitInt8(StartxLength);
Asm->OutStreamer->AddComment(" start index");
Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin));
Asm->OutStreamer->AddComment(" length");
Asm->EmitLabelDifferenceAsULEB128(End, Begin);
} else {
Asm->OutStreamer->EmitSymbolValue(Begin, Size);
Asm->OutStreamer->EmitSymbolValue(End, Size);
}
EmitPayload(*RS);
}
}

if (UseDwarf5) {
Asm->OutStreamer->AddComment(StringifyEnum(EndOfList));
Asm->emitInt8(EndOfList);
} else {
// Terminate the list with two 0 values.
Asm->OutStreamer->EmitIntValue(0, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}
}

static void emitLocList(DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List) {
emitRangeList(
DD, Asm, List.Label, DD.getDebugLocs().getEntries(List), *List.CU,
dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
dwarf::DW_LLE_startx_length, dwarf::DW_LLE_end_of_list,
llvm::dwarf::LocListEncodingString,
/* ShouldUseBaseAddress */ true,
[&](const DebugLocStream::Entry &E) {
DD.emitDebugLocEntryLocation(E, List.CU);
});
}

// Emit locations into the .debug_loc/.debug_rnglists section.
void DwarfDebug::emitDebugLoc() {
if (DebugLocs.getLists().empty())
return;

bool IsLocLists = getDwarfVersion() >= 5;
MCSymbol *TableEnd = nullptr;
if (IsLocLists) {
if (getDwarfVersion() >= 5) {
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfLoclistsSection());
TableEnd = emitLoclistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder
Expand All @@ -2310,63 +2417,8 @@ void DwarfDebug::emitDebugLoc() {
Asm->getObjFileLowering().getDwarfLocSection());
}

unsigned char Size = Asm->MAI->getCodePointerSize();
for (const auto &List : DebugLocs.getLists()) {
Asm->OutStreamer->EmitLabel(List.Label);

const DwarfCompileUnit *CU = List.CU;
const MCSymbol *Base = CU->getBaseAddress();
for (const auto &Entry : DebugLocs.getEntries(List)) {
if (Base) {
// Set up the range. This range is relative to the entry point of the
// compile unit. This is a hard coded 0 for low_pc when we're emitting
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
if (IsLocLists) {
Asm->OutStreamer->AddComment("DW_LLE_offset_pair");
Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_offset_pair, 1);
Asm->OutStreamer->AddComment(" starting offset");
Asm->EmitLabelDifferenceAsULEB128(Entry.Begin, Base);
Asm->OutStreamer->AddComment(" ending offset");
Asm->EmitLabelDifferenceAsULEB128(Entry.End, Base);
} else {
Asm->EmitLabelDifference(Entry.Begin, Base, Size);
Asm->EmitLabelDifference(Entry.End, Base, Size);
}

emitDebugLocEntryLocation(Entry, CU);
continue;
}

// We have no base address.
if (IsLocLists) {
// TODO: Use DW_LLE_base_addressx + DW_LLE_offset_pair, or
// DW_LLE_startx_length in case if there is only a single range.
// That should reduce the size of the debug data emited.
// For now just use the DW_LLE_startx_length for all cases.
Asm->OutStreamer->AddComment("DW_LLE_startx_length");
Asm->emitInt8(dwarf::DW_LLE_startx_length);
Asm->OutStreamer->AddComment(" start idx");
Asm->EmitULEB128(AddrPool.getIndex(Entry.Begin));
Asm->OutStreamer->AddComment(" length");
Asm->EmitLabelDifferenceAsULEB128(Entry.End, Entry.Begin);
} else {
Asm->OutStreamer->EmitSymbolValue(Entry.Begin, Size);
Asm->OutStreamer->EmitSymbolValue(Entry.End, Size);
}

emitDebugLocEntryLocation(Entry, CU);
}

if (IsLocLists) {
// .debug_loclists section ends with DW_LLE_end_of_list.
Asm->OutStreamer->AddComment("DW_LLE_end_of_list");
Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_end_of_list, 1);
} else {
// Terminate the .debug_loc list with two 0 values.
Asm->OutStreamer->EmitIntValue(0, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}
}
for (const auto &List : DebugLocs.getLists())
emitLocList(*this, Asm, List);

if (TableEnd)
Asm->OutStreamer->EmitLabel(TableEnd);
Expand Down Expand Up @@ -2556,103 +2608,16 @@ void DwarfDebug::emitDebugARanges() {
}
}

template <typename Ranges>
static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym,
const Ranges &R, const DwarfCompileUnit &CU,
unsigned BaseAddressx, unsigned OffsetPair,
unsigned StartxLength, unsigned EndOfList,
StringRef (*StringifyEnum)(unsigned)) {
auto DwarfVersion = DD.getDwarfVersion();
// Emit our symbol so we can find the beginning of the range.
Asm->OutStreamer->EmitLabel(Sym);
// Gather all the ranges that apply to the same section so they can share
// a base address entry.
MapVector<const MCSection *, std::vector<const RangeSpan *>> SectionRanges;
// Size for our labels.
auto Size = Asm->MAI->getCodePointerSize();

for (const RangeSpan &Range : R)
SectionRanges[&Range.Begin->getSection()].push_back(&Range);

const MCSymbol *CUBase = CU.getBaseAddress();
bool BaseIsSet = false;
for (const auto &P : SectionRanges) {
// Don't bother with a base address entry if there's only one range in
// this section in this range list - for example ranges for a CU will
// usually consist of single regions from each of many sections
// (-ffunction-sections, or just C++ inline functions) except under LTO
// or optnone where there may be holes in a single CU's section
// contributions.
auto *Base = CUBase;
if (!Base && (P.second.size() > 1 || DwarfVersion < 5) &&
(CU.getCUNode()->getRangesBaseAddress() || DwarfVersion >= 5)) {
BaseIsSet = true;
Base = DD.getSectionLabel(&P.second.front()->Begin->getSection());
if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx));
Asm->OutStreamer->EmitIntValue(BaseAddressx, 1);
Asm->OutStreamer->AddComment(" base address index");
Asm->EmitULEB128(DD.getAddressPool().getIndex(Base));
} else {
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->AddComment(" base address");
Asm->OutStreamer->EmitSymbolValue(Base, Size);
}
} else if (BaseIsSet && DwarfVersion < 5) {
BaseIsSet = false;
assert(!Base);
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}

for (const auto *RS : P.second) {
const MCSymbol *Begin = RS->Begin;
const MCSymbol *End = RS->End;
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
if (Base) {
if (DwarfVersion >= 5) {
// Emit DW_RLE_offset_pair when we have a base.
Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair));
Asm->emitInt8(OffsetPair);
Asm->OutStreamer->AddComment(" starting offset");
Asm->EmitLabelDifferenceAsULEB128(Begin, Base);
Asm->OutStreamer->AddComment(" ending offset");
Asm->EmitLabelDifferenceAsULEB128(End, Base);
} else {
Asm->EmitLabelDifference(Begin, Base, Size);
Asm->EmitLabelDifference(End, Base, Size);
}
} else if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
Asm->emitInt8(StartxLength);
Asm->OutStreamer->AddComment(" start index");
Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin));
Asm->OutStreamer->AddComment(" length");
Asm->EmitLabelDifferenceAsULEB128(End, Begin);
} else {
Asm->OutStreamer->EmitSymbolValue(Begin, Size);
Asm->OutStreamer->EmitSymbolValue(End, Size);
}
}
}
if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment(StringifyEnum(EndOfList));
Asm->emitInt8(EndOfList);
} else {
// Terminate the list with two 0 values.
Asm->OutStreamer->EmitIntValue(0, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}
}

/// Emit a single range list. We handle both DWARF v5 and earlier.
static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm,
const RangeSpanList &List) {
emitRangeList(DD, Asm, List.getSym(), List.getRanges(), List.getCU(),
dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
dwarf::DW_RLE_startx_length, dwarf::DW_RLE_end_of_list,
llvm::dwarf::RangeListEncodingString);
llvm::dwarf::RangeListEncodingString,
List.getCU().getCUNode()->getRangesBaseAddress() ||
DD.getDwarfVersion() >= 5,
[](auto) {});
}

static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm,
Expand Down
Loading

0 comments on commit 86b0b37

Please sign in to comment.