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; +struct MCDwarf { + // Emit the common part of the DWARF 5 range/locations list tables header. + static void emitListsTableHeaderStart(MCStreamer *MCS, MCSymbol *TableStart, + MCSymbol *TableEnd); +}; + /// 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->emitIntValue(S->getContext().getDwarfVersion(), 2); + S->AddComment("Address size"); + S->emitIntValue(S->getContext().getAsmInfo()->getCodePointerSize(), 1); + S->AddComment("Segment selector size"); + S->emitIntValue(0, 1); +} + /// 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 *RangesStartSymbol) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -950,7 +963,8 @@ // Earlier versions have abbrev offset, address size. const MCAsmInfo &AsmInfo = *context.getAsmInfo(); int AddrSize = AsmInfo.getCodePointerSize(); - if (context.getDwarfVersion() >= 5) { + bool DWARF5 = context.getDwarfVersion() >= 5; + if (DWARF5) { MCOS->emitIntValue(dwarf::DW_UT_compile, 1); MCOS->emitIntValue(AddrSize, 1); } @@ -961,7 +975,7 @@ else MCOS->emitSymbolValue(AbbrevSectionSymbol, 4, AsmInfo.needsDwarfSectionOffsetDirective()); - if (context.getDwarfVersion() <= 4) + if (!DWARF5) MCOS->emitIntValue(AddrSize, 1); // Second part: the compile_unit DIE. @@ -977,13 +991,11 @@ else MCOS->emitIntValue(0, 4); - 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 (RangesStartSymbol) { + // 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(RangesStartSymbol, 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 +1108,63 @@ // 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 *RangesStart; - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + 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->emitIntValue(0, 4); + RangesStart = context.createTempSymbol("debug_rnglist0_start", true, true); + MCOS->emitLabel(RangesStart); + for (MCSection *Sec : Sections) { + const MCSymbol *StartSymbol = Sec->getBeginSymbol(); + const MCSymbol *EndSymbol = Sec->getEndSymbol(context); + MCOS->emitIntValue(dwarf::DW_RLE_start_length, 1); + MCOS->emitValue(MCSymbolRefExpr::create( + StartSymbol, MCSymbolRefExpr::VK_None, context), + AddrSize); + MCOS->emitULEB128Value( + MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0)); + } + MCOS->emitIntValue(dwarf::DW_RLE_end_of_list, 1); + MCOS->emitLabel(EndSymbol); + } else { + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + RangesStart = context.createTempSymbol("debug_ranges_start", true, true); + MCOS->emitLabel(RangesStart); + for (MCSection *Sec : Sections) { + const MCSymbol *StartSymbol = Sec->getBeginSymbol(); + const MCSymbol *EndSymbol = Sec->getEndSymbol(context); - 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 section start. + MCOS->emitFill(AddrSize, 0xFF); + MCOS->emitValue(MCSymbolRefExpr::create( + StartSymbol, MCSymbolRefExpr::VK_None, context), + AddrSize); - // 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. + MCOS->emitIntValue(0, AddrSize); + emitAbsValue(*MCOS, + MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0), + 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 RangesStart; } // @@ -1145,7 +1183,7 @@ LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); MCSymbol *AbbrevSectionSymbol = nullptr; MCSymbol *InfoSectionSymbol = nullptr; - MCSymbol *RangesSectionSymbol = nullptr; + MCSymbol *RangesStartSymbol = nullptr; // Create end symbols for each section, and remove empty sections MCOS->getContext().finalizeDwarfSections(*MCOS); @@ -1172,15 +1210,6 @@ 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()); @@ -1188,14 +1217,14 @@ EmitGenDwarfAranges(MCOS, InfoSectionSymbol); if (UseRangesSection) - EmitGenDwarfRanges(MCOS); + RangesStartSymbol = emitGenDwarfRanges(MCOS); // Output the data for .debug_abbrev section. EmitGenDwarfAbbrev(MCOS); // Output the data for .debug_info section. EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, - RangesSectionSymbol); + RangesStartSymbol); } // 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,9 +1,9 @@ // 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-prefix 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-prefix 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-prefix DWARF -check-prefix 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-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 3 -fdebug-compilation-dir=/tmp @@ -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") @@ -74,6 +77,12 @@ // DWARF: 00000000 00000000 00000004 // DWARF: 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. @@ -82,24 +91,29 @@ // RELOC4-NEXT: 00000006 R_ARM_ABS32 .debug_abbrev // RELOC4-NEXT: 0000000c R_ARM_ABS32 .debug_line // RELOC4-NEXT: 00000010 R_ARM_ABS32 .debug_ranges -// RELOC5-NEXT: OFFSET TYPE VALUE +// RELOC5: 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 +// 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 + +// 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