diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -41,6 +41,12 @@ 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 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2400,25 +2400,6 @@ 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 @@ 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 @@ 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 --- 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 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 @@ 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 @@ // 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 @@ 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 @@ 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 --- 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 @@ // 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 @@ // 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 @@ // 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 +// 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 +// 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 different in DWARF v5 due to different header layout. @@ -85,21 +94,26 @@ // 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