[llvm] 55a5604 - [MCDwarf] Generate DWARF v5 .debug_rnglists for assembly files
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 3 09:06:17 PST 2020
Author: Fangrui Song
Date: 2020-03-03T09:03:34-08:00
New Revision: 55a56041d1da59dacb8f9abb1f3bfa841798e6cc
URL: https://github.com/llvm/llvm-project/commit/55a56041d1da59dacb8f9abb1f3bfa841798e6cc
DIFF: https://github.com/llvm/llvm-project/commit/55a56041d1da59dacb8f9abb1f3bfa841798e6cc.diff
LOG: [MCDwarf] Generate DWARF v5 .debug_rnglists for assembly files
```
// clang -c -gdwarf-5 a.s -o a.o
.section .init; ret
.text; ret
```
.debug_info contains DW_AT_ranges and llvm-dwarfdump will report
a verification error because .debug_rnglists does not exist (not
implemented).
This patch generates .debug_rnglists for assembly files.
emitListsTableHeaderStart() in DwarfDebug.cpp can be shared with
MCDwarf.cpp. Because CodeGen depends on MC, I move the function to
MCDwarf.cpp
Reviewed By: probinson
Differential Revision: https://reviews.llvm.org/D75375
Added:
Modified:
llvm/include/llvm/MC/MCDwarf.h
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/lib/MC/MCDwarf.cpp
llvm/test/MC/ARM/dwarf-asm-multiple-sections.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h
index 9dead61eb737..2938245d5669 100644
--- a/llvm/include/llvm/MC/MCDwarf.h
+++ b/llvm/include/llvm/MC/MCDwarf.h
@@ -41,6 +41,12 @@ class raw_ostream;
class SMLoc;
class SourceMgr;
+namespace mcdwarf {
+// Emit the common part of the DWARF 5 range/locations list tables header.
+void emitListsTableHeaderStart(MCStreamer *S, MCSymbol *TableStart,
+ MCSymbol *TableEnd);
+} // namespace mcdwarf
+
/// Instances of this class represent the name of the dwarf .file directive and
/// its associated dwarf file number in the MC file. MCDwarfFile's are created
/// and uniqued by the MCContext class. In Dwarf 4 file numbers start from 1;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 40ab350a110e..dfa09d7a8c0d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2400,25 +2400,6 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry,
emitDebugLocEntry(Streamer, Entry, CU);
}
-// Emit the common part of the DWARF 5 range/locations list tables header.
-static void emitListsTableHeaderStart(AsmPrinter *Asm,
- MCSymbol *TableStart,
- MCSymbol *TableEnd) {
- // Build the table header, which starts with the length field.
- Asm->OutStreamer->AddComment("Length");
- Asm->emitLabelDifference(TableEnd, TableStart, 4);
- Asm->OutStreamer->emitLabel(TableStart);
- // Version number (DWARF v5 and later).
- Asm->OutStreamer->AddComment("Version");
- Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion());
- // Address size.
- Asm->OutStreamer->AddComment("Address size");
- Asm->emitInt8(Asm->MAI->getCodePointerSize());
- // Segment selector size.
- Asm->OutStreamer->AddComment("Segment selector size");
- Asm->emitInt8(0);
-}
-
// Emit the header of a DWARF 5 range list table list table. Returns the symbol
// that designates the end of the table for the caller to emit when the table is
// complete.
@@ -2426,7 +2407,8 @@ static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm,
const DwarfFile &Holder) {
MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start");
MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end");
- emitListsTableHeaderStart(Asm, TableStart, TableEnd);
+ mcdwarf::emitListsTableHeaderStart(Asm->OutStreamer.get(), TableStart,
+ TableEnd);
Asm->OutStreamer->AddComment("Offset entry count");
Asm->emitInt32(Holder.getRangeLists().size());
@@ -2445,7 +2427,8 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm,
const DwarfDebug &DD) {
MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start");
MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end");
- emitListsTableHeaderStart(Asm, TableStart, TableEnd);
+ mcdwarf::emitListsTableHeaderStart(Asm->OutStreamer.get(), TableStart,
+ TableEnd);
const auto &DebugLocs = DD.getDebugLocs();
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index ecf7581b3ef3..a0d47569e01c 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -45,6 +45,19 @@
using namespace llvm;
+void mcdwarf::emitListsTableHeaderStart(MCStreamer *S, MCSymbol *TableStart,
+ MCSymbol *TableEnd) {
+ S->AddComment("Length");
+ S->emitAbsoluteSymbolDiff(TableEnd, TableStart, 4);
+ S->emitLabel(TableStart);
+ S->AddComment("Version");
+ S->emitInt16(S->getContext().getDwarfVersion());
+ S->AddComment("Address size");
+ S->emitInt8(S->getContext().getAsmInfo()->getCodePointerSize());
+ S->AddComment("Segment selector size");
+ S->emitInt8(0);
+}
+
/// Manage the .debug_line_str section contents, if we use it.
class llvm::MCDwarfLineStr {
MCSymbol *LineStrLabel = nullptr;
@@ -925,7 +938,7 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
static void EmitGenDwarfInfo(MCStreamer *MCOS,
const MCSymbol *AbbrevSectionSymbol,
const MCSymbol *LineSectionSymbol,
- const MCSymbol *RangesSectionSymbol) {
+ const MCSymbol *RangesSymbol) {
MCContext &context = MCOS->getContext();
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
@@ -977,13 +990,11 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
else
MCOS->emitInt32(0);
- if (RangesSectionSymbol) {
- // There are multiple sections containing code, so we must use the
- // .debug_ranges sections.
-
- // AT_ranges, the 4 byte offset from the start of the .debug_ranges section
- // to the address range list for this compilation unit.
- MCOS->emitSymbolValue(RangesSectionSymbol, 4);
+ if (RangesSymbol) {
+ // There are multiple sections containing code, so we must use
+ // .debug_ranges/.debug_rnglists. AT_ranges, the 4 byte offset from the
+ // start of the .debug_ranges/.debug_rnglists.
+ MCOS->emitSymbolValue(RangesSymbol, 4);
} else {
// If we only have one non-empty code section, we can use the simpler
// AT_low_pc and AT_high_pc attributes.
@@ -1096,37 +1107,65 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
// When generating dwarf for assembly source files this emits the data for
// .debug_ranges section. We only emit one range list, which spans all of the
// executable sections of this file.
-static void EmitGenDwarfRanges(MCStreamer *MCOS) {
+static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
auto &Sections = context.getGenDwarfSectionSyms();
const MCAsmInfo *AsmInfo = context.getAsmInfo();
int AddrSize = AsmInfo->getCodePointerSize();
+ MCSymbol *RangesSymbol;
+
+ if (MCOS->getContext().getDwarfVersion() >= 5) {
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());
+ MCSymbol *StartSymbol =
+ context.createTempSymbol("debug_rnglists_start", true, true);
+ MCSymbol *EndSymbol =
+ context.createTempSymbol("debug_rnglists_end", true, true);
+ mcdwarf::emitListsTableHeaderStart(MCOS, StartSymbol, EndSymbol);
+ MCOS->AddComment("Offset entry count");
+ MCOS->emitInt32(0);
+ RangesSymbol = context.createTempSymbol("debug_rnglist0_start", true, true);
+ MCOS->emitLabel(RangesSymbol);
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ const MCExpr *SectionSize =
+ MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0);
+ MCOS->emitInt8(dwarf::DW_RLE_start_length);
+ MCOS->emitValue(SectionStartAddr, AddrSize);
+ MCOS->emitULEB128Value(SectionSize);
+ }
+ MCOS->emitInt8(dwarf::DW_RLE_end_of_list);
+ MCOS->emitLabel(EndSymbol);
+ } else {
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
+ RangesSymbol = context.createTempSymbol("debug_ranges_start", true, true);
+ MCOS->emitLabel(RangesSymbol);
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+
+ // Emit a base address selection entry for the section start.
+ const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ MCOS->emitFill(AddrSize, 0xFF);
+ MCOS->emitValue(SectionStartAddr, AddrSize);
+
+ // Emit a range list entry spanning this section.
+ const MCExpr *SectionSize =
+ MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0);
+ MCOS->emitIntValue(0, AddrSize);
+ emitAbsValue(*MCOS, SectionSize, AddrSize);
+ }
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
-
- for (MCSection *Sec : Sections) {
- const MCSymbol *StartSymbol = Sec->getBeginSymbol();
- MCSymbol *EndSymbol = Sec->getEndSymbol(context);
- assert(StartSymbol && "StartSymbol must not be NULL");
- assert(EndSymbol && "EndSymbol must not be NULL");
-
- // Emit a base address selection entry for the start of this section
- const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
- StartSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->emitFill(AddrSize, 0xFF);
- MCOS->emitValue(SectionStartAddr, AddrSize);
-
- // Emit a range list entry spanning this section
- const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
- *StartSymbol, *EndSymbol, 0);
+ // Emit end of list entry
+ MCOS->emitIntValue(0, AddrSize);
MCOS->emitIntValue(0, AddrSize);
- emitAbsValue(*MCOS, SectionSize, AddrSize);
}
- // Emit end of list entry
- MCOS->emitIntValue(0, AddrSize);
- MCOS->emitIntValue(0, AddrSize);
+ return RangesSymbol;
}
//
@@ -1145,7 +1184,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
MCSymbol *AbbrevSectionSymbol = nullptr;
MCSymbol *InfoSectionSymbol = nullptr;
- MCSymbol *RangesSectionSymbol = nullptr;
+ MCSymbol *RangesSymbol = nullptr;
// Create end symbols for each section, and remove empty sections
MCOS->getContext().finalizeDwarfSections(*MCOS);
@@ -1172,30 +1211,22 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
AbbrevSectionSymbol = context.createTempSymbol();
MCOS->emitLabel(AbbrevSectionSymbol);
}
- if (UseRangesSection) {
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
- if (CreateDwarfSectionSymbols) {
- RangesSectionSymbol = context.createTempSymbol();
- MCOS->emitLabel(RangesSectionSymbol);
- }
- }
-
- assert((RangesSectionSymbol != nullptr) || !UseRangesSection);
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
// Output the data for .debug_aranges section.
EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
- if (UseRangesSection)
- EmitGenDwarfRanges(MCOS);
+ if (UseRangesSection) {
+ RangesSymbol = emitGenDwarfRanges(MCOS);
+ assert(RangesSymbol);
+ }
// Output the data for .debug_abbrev section.
EmitGenDwarfAbbrev(MCOS);
// Output the data for .debug_info section.
- EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
- RangesSectionSymbol);
+ EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
}
//
diff --git a/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s b/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s
index 69a45ed34950..ffcdfda39752 100644
--- a/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s
+++ b/llvm/test/MC/ARM/dwarf-asm-multiple-sections.s
@@ -1,13 +1,13 @@
// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 5 -fdebug-compilation-dir=/tmp
-// RUN: llvm-dwarfdump -v %t | FileCheck -check-prefix DWARF -check-prefix DWARF45 %s
+// RUN: llvm-dwarfdump -v %t | FileCheck --check-prefixes=DWARF,DWARF5 %s
// RUN: llvm-dwarfdump --debug-line %t | FileCheck -check-prefix DWARF-DL -check-prefix DWARF-DL-5 -DDWVER=5 -DDWFILE=0 %s
-// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC -check-prefix RELOC5 %s
+// RUN: llvm-objdump -r %t | FileCheck --check-prefixes=RELOC,RELOC5 %s
// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 4 -fdebug-compilation-dir=/tmp
-// RUN: llvm-dwarfdump -v %t | FileCheck -check-prefix DWARF -check-prefix DWARF45 %s
+// RUN: llvm-dwarfdump -v %t | FileCheck -check-prefixes=DWARF,DWARF34,DWARF4 %s
// RUN: llvm-dwarfdump --debug-line %t | FileCheck -check-prefix DWARF-DL -check-prefix DWARF-DL-4 -DDWVER=4 -DDWFILE=1 %s
-// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC -check-prefix RELOC4 %s
+// RUN: llvm-objdump -r %t | FileCheck --check-prefixes=RELOC,RELOC34,RELOC4 %s
// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 3 -fdebug-compilation-dir=/tmp
-// RUN: llvm-dwarfdump -v %t | FileCheck -check-prefix DWARF -check-prefix DWARF3 %s
+// RUN: llvm-dwarfdump -v %t | FileCheck --check-prefixes=DWARF,DWARF34,DWARF3 %s
// RUN: llvm-dwarfdump --debug-line %t | FileCheck -check-prefix DWARF-DL -DDWVER=3 -DDWFILE=1 %s
// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 2 2>&1 | FileCheck -check-prefix VERSION %s
// RUN: not llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 1 2>&1 | FileCheck -check-prefix DWARF1 %s
@@ -24,9 +24,11 @@ b:
// DWARF: Abbrev table for offset: 0x00000000
// DWARF: [1] DW_TAG_compile_unit DW_CHILDREN_yes
// DWARF3: DW_AT_stmt_list DW_FORM_data4
-// DWARF45: DW_AT_stmt_list DW_FORM_sec_offset
+// DWARF4: DW_AT_stmt_list DW_FORM_sec_offset
+// DWARF5: DW_AT_stmt_list DW_FORM_sec_offset
// DWARF3: DW_AT_ranges DW_FORM_data4
-// DWARF45: DW_AT_ranges DW_FORM_sec_offset
+// DWARF4: DW_AT_ranges DW_FORM_sec_offset
+// DWARF5: DW_AT_ranges DW_FORM_sec_offset
// DWARF: DW_AT_name DW_FORM_string
// DWARF: DW_AT_comp_dir DW_FORM_string
// DWARF: DW_AT_producer DW_FORM_string
@@ -36,7 +38,8 @@ b:
// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_compile_unit [1]
// DWARF-NOT: DW_TAG_
// DWARF3: DW_AT_ranges [DW_FORM_data4] (0x00000000
-// DWARF45: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
+// DWARF4: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
+// DWARF5: DW_AT_ranges [DW_FORM_sec_offset] (0x0000000c
// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] *
// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("a")
@@ -67,13 +70,19 @@ b:
// DWARF-DL-4-NEXT: 0x0000000000000004 21 0 1 0 0 is_stmt end_sequence
-// DWARF: .debug_ranges contents:
-// DWARF: 00000000 ffffffff 00000000
-// DWARF: 00000000 00000000 00000004
-// DWARF: 00000000 ffffffff 00000000
-// DWARF: 00000000 00000000 00000004
-// DWARF: 00000000 <End of list>
+// DWARF34: .debug_ranges contents:
+// DWARF34-NEXT: 00000000 ffffffff 00000000
+// DWARF34-NEXT: 00000000 00000000 00000004
+// DWARF34-NEXT: 00000000 ffffffff 00000000
+// DWARF34-NEXT: 00000000 00000000 00000004
+// DWARF34-NEXT: 00000000 <End of list>
+// DWARF5: .debug_rnglists contents:
+// DWARF5-NEXT: 0x00000000: range list header: length = 0x00000015, version = 0x0005, addr_size = 0x04, seg_size = 0x00, offset_entry_count = 0x00000000
+// DWARF5-NEXT: ranges:
+// DWARF5-NEXT: 0x0000000c: [DW_RLE_start_length]: 0x00000000, 0x00000004 => [0x00000000, 0x00000004)
+// DWARF5-NEXT: 0x00000012: [DW_RLE_start_length]: 0x00000000, 0x00000004 => [0x00000000, 0x00000004)
+// DWARF5-NEXT: 0x00000018: [DW_RLE_end_of_list ]
// Offsets are
diff erent in DWARF v5 due to
diff erent header layout.
@@ -85,21 +94,26 @@ b:
// RELOC5-NEXT: OFFSET TYPE VALUE
// RELOC5-NEXT: 00000008 R_ARM_ABS32 .debug_abbrev
// RELOC5-NEXT: 0000000d R_ARM_ABS32 .debug_line
-// RELOC5-NEXT: 00000011 R_ARM_ABS32 .debug_ranges
+// RELOC5-NEXT: 00000011 R_ARM_ABS32 .debug_rnglists
// RELOC-NEXT: R_ARM_ABS32 .text
// RELOC-NEXT: R_ARM_ABS32 foo
-// RELOC: RELOCATION RECORDS FOR [.debug_ranges]:
-// RELOC-NEXT: OFFSET TYPE VALUE
-// RELOC-NEXT: 00000004 R_ARM_ABS32 .text
-// RELOC-NEXT: 00000014 R_ARM_ABS32 foo
-
// RELOC: RELOCATION RECORDS FOR [.debug_aranges]:
// RELOC-NEXT: OFFSET TYPE VALUE
// RELOC-NEXT: 00000006 R_ARM_ABS32 .debug_info
// RELOC-NEXT: 00000010 R_ARM_ABS32 .text
// RELOC-NEXT: 00000018 R_ARM_ABS32 foo
+// RELOC34: RELOCATION RECORDS FOR [.debug_ranges]:
+// RELOC34-NEXT: OFFSET TYPE VALUE
+// RELOC34-NEXT: 00000004 R_ARM_ABS32 .text
+// RELOC34-NEXT: 00000014 R_ARM_ABS32 foo
+
+// RELOC5: RELOCATION RECORDS FOR [.debug_rnglists]:
+// RELOC5-NEXT: OFFSET TYPE VALUE
+// RELOC5-NEXT: 0000000d R_ARM_ABS32 .text
+// RELOC5-NEXT: 00000013 R_ARM_ABS32 foo
+
// VERSION: {{.*}} warning: DWARF2 only supports one section per compilation unit
More information about the llvm-commits
mailing list