[DebugInfo] Add flag to enable function-level debug line attribution by alx32 · Pull Request #93985 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-llvm-binary-utilities

Author: None (alx32)

Changes

This patch introduces a new Clang flag, -mllvm -emit-func-debug-line-table-offsets, which enables the generation of additional debug information to facilitate the attribution of debug line data to their corresponding functions (DW_TAG_subprogram).

Context:
Currently, Clang generates function line information in the debug_line section without directly linking the line entries to their originating functions. This becomes problematic when post-compile tools, such as the Identical Code Folding (ICF) in the LLD linker, merge multiple functions together, resulting in overlapping address ranges and conflicting line information.

To address this issue, this patch adds a new attribute, DW_AT_META_stmt_sequence, to each DW_TAG_subprogram, which represents an offset into the line table where the line data for the subprogram begins. Additionally, a DW_LNE_end_sequence is added to the line table to mark the end of the line information for a particular subprogram. These changes enable the correct attribution of line entries to their originating functions, even when functions share the same address space after optimization.

NOTE: While this change is functional, it requires additional tooling support to be fully utilized, particularly for symbol resolution in cases where multiple functions share the same address space. This will be addressed in future changes.

Previous changes: #93137 - Added an LLD option to generate debug information for ICF'ed functions.


Full diff: https://github.com/llvm/llvm-project/pull/93985.diff

8 Files Affected:

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index adcf24eb83b03..6124babc40927 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -578,6 +578,8 @@ HANDLE_DW_AT(0x2904, GO_runtime_type, 0, GO)

HANDLE_DW_AT(0x3210, UPC_threads_scaled, 0, UPC)

+HANDLE_DW_AT(0x3600, META_stmt_sequence, 0, META) + HANDLE_DW_AT(0x393e, IBM_wsa_addr, 0, IBM) HANDLE_DW_AT(0x393f, IBM_home_location, 0, IBM) HANDLE_DW_AT(0x3940, IBM_alt_srcview, 0, IBM) diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h index 74c4d6ff3a716..3e42dc240fcc0 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -84,6 +84,7 @@ enum LLVMConstants : uint32_t { DWARF_VENDOR_PGI, DWARF_VENDOR_SUN, DWARF_VENDOR_UPC,

diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index 18056c5fdf816..b6f87dc8b6c8a 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -122,6 +122,8 @@ class MCDwarfLoc { private: // MCContext manages these friend class MCContext; friend class MCDwarfLineEntry;

@@ -194,14 +196,27 @@ class MCDwarfLineEntry : public MCDwarfLoc {

public: // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.

@@ -227,7 +242,7 @@ class MCLineSection {

// Add an end entry by cloning the last entry, if exists, for the section // the given EndLabel belongs to. The label is replaced by the given EndLabel.

diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index b7468cf70a664..559acabee4082 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -254,6 +254,15 @@ class MCStreamer { /// discussion for future inclusion. bool AllowAutoPadding = false;

@@ -310,6 +319,24 @@ class MCStreamer { void setAllowAutoPadding(bool v) { AllowAutoPadding = v; } bool getAllowAutoPadding() const { return AllowAutoPadding; }

diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index b9c02aed848cc..6b987792c3db3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -170,6 +170,12 @@ static cl::optDwarfDebug::MinimizeAddrInV5 MinimizeAddrInV5Option( "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default));

+static cl::opt EmitFuncLineTableOffsetsOption(

@@ -440,6 +446,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A) Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);

}

// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h. @@ -2222,6 +2230,10 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) { if (SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) return;

@@ -2250,7 +2262,8 @@ void DwarfDebug::terminateLineTable(const DwarfCompileUnit *CU) { getDwarfCompileUnitIDForLineTable(*CU)); // Add the last range label for the given CU. LineTable.getMCLineSections().addEndEntry(

}

void DwarfDebug::skippedNonDebugFunction() { @@ -2343,6 +2356,21 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { // Construct call site entries. constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);

@@ -144,7 +154,8 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) { return Res; }

-void MCLineSection::addEndEntry(MCSymbol *EndLabel) { +void MCLineSection::addEndEntry(MCSymbol *EndLabel,

} }

@@ -187,8 +202,11 @@ void MCDwarfLineTable::emitOne( bool EndEntryEmitted = false; for (const MCDwarfLineEntry &LineEntry : LineEntries) { MCSymbol *Label = LineEntry.getLabel();