[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