Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -20,6 +20,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include +#include #include // FIXME: Shouldn't be needed. namespace llvm { @@ -123,11 +124,13 @@ /// assembly source files. unsigned GenDwarfFileNumber; - /// The default initial text section that we generate dwarf debugging line - /// info for when generating dwarf assembly source files. - const MCSection *GenDwarfSection; - /// Symbols created for the start and end of this section. - MCSymbol *GenDwarfSectionStartSym, *GenDwarfSectionEndSym; + /// The sections that we generate dwarf debugging line info for when + /// generating dwarf assembly source files. + std::set GenDwarfSections; + /// Symbols created for the start and end of each section, used for + /// generating the debug_aranges section + DenseMap GenDwarfSectionStartSyms; + DenseMap GenDwarfSectionEndSyms; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. @@ -141,6 +144,9 @@ /// non-empty. StringRef DwarfDebugProducer; + /// The maximum version of dwarf that we should emit. + unsigned DwarfVersion; + /// Honor temporary labels, this is useful for debugging semantic /// differences between temporary and non-temporary labels (primarily on /// Darwin). @@ -371,15 +377,25 @@ void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; } unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; } unsigned nextGenDwarfFileNumber() { return ++GenDwarfFileNumber; } - const MCSection *getGenDwarfSection() { return GenDwarfSection; } - void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; } - MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; } - void setGenDwarfSectionStartSym(MCSymbol *Sym) { - GenDwarfSectionStartSym = Sym; + std::set &getGenDwarfSections() { return GenDwarfSections; } + void addGenDwarfSection(const MCSection *Sec) { GenDwarfSections.insert(Sec); } + MCSymbol *getGenDwarfSectionStartSym(const MCSection* Sec) { + DenseMap::iterator Sym = GenDwarfSectionStartSyms.find(Sec); + if (Sym != GenDwarfSectionStartSyms.end()) + return Sym->second; + return NULL; + } + void setGenDwarfSectionStartSym(const MCSection *Sec, MCSymbol *Sym) { + GenDwarfSectionStartSyms[Sec] = Sym; } - MCSymbol *getGenDwarfSectionEndSym() { return GenDwarfSectionEndSym; } - void setGenDwarfSectionEndSym(MCSymbol *Sym) { - GenDwarfSectionEndSym = Sym; + MCSymbol *getGenDwarfSectionEndSym(const MCSection* Sec) { + DenseMap::iterator Sym = GenDwarfSectionEndSyms.find(Sec); + if (Sym != GenDwarfSectionEndSyms.end()) + return Sym->second; + return NULL; + } + void setGenDwarfSectionEndSym(const MCSection *Sec, MCSymbol *Sym) { + GenDwarfSectionEndSyms[Sec] = Sym; } const std::vector &getMCGenDwarfLabelEntries() const { @@ -395,6 +411,9 @@ void setDwarfDebugProducer(StringRef S) { DwarfDebugProducer = S; } StringRef getDwarfDebugProducer() { return DwarfDebugProducer; } + void setDwarfVersion(unsigned v) { DwarfVersion = v; } + unsigned getDwarfVersion() const { return DwarfVersion; } + /// @} char *getSecureLogFile() { return SecureLogFile; } Index: include/llvm/MC/MCObjectStreamer.h =================================================================== --- include/llvm/MC/MCObjectStreamer.h +++ include/llvm/MC/MCObjectStreamer.h @@ -116,6 +116,10 @@ virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); + + virtual bool hasInstructions() const { + return getCurrentSectionData()->hasInstructions(); + } }; } // end namespace llvm Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -698,6 +698,8 @@ virtual void FinishImpl() = 0; /// Finish - Finish emission of machine code. void Finish(); + + virtual bool hasInstructions() const { return false; } }; /// createNullStreamer - Create a dummy machine code streamer, which does Index: lib/MC/MCDwarf.cpp =================================================================== --- lib/MC/MCDwarf.cpp +++ lib/MC/MCDwarf.cpp @@ -16,7 +16,9 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" @@ -455,7 +457,7 @@ // When generating dwarf for assembly source files this emits // the data for .debug_abbrev section which contains three DIEs. -static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { +static void EmitGenDwarfAbbrev(MCStreamer *MCOS, bool UseRangesSection) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); @@ -464,8 +466,12 @@ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); - EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); - EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + if (UseRangesSection) { + EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); + } else { + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + } EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); if (!context.getCompilationDir().empty()) EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); @@ -505,13 +511,23 @@ const MCSymbol *InfoSectionSymbol) { MCContext &context = MCOS->getContext(); - // Create a symbol at the end of the section that we are creating the dwarf + std::set &Sections = context.getGenDwarfSections(); + std::set ValidSections; + + // Create a symbol at the end of each section that we are creating the dwarf // debugging info to use later in here as part of the expression to calculate // the size of the section for the table. - MCOS->SwitchSection(context.getGenDwarfSection()); - MCSymbol *SectionEndSym = context.CreateTempSymbol(); - MCOS->EmitLabel(SectionEndSym); - context.setGenDwarfSectionEndSym(SectionEndSym); + for (std::set::const_iterator sec = Sections.begin(); + sec != Sections.end(); sec++) { + MCOS->SwitchSection(*sec); + MCSymbol *SectionEndSym = context.CreateTempSymbol(); + MCOS->EmitLabel(SectionEndSym); + context.setGenDwarfSectionEndSym(*sec, SectionEndSym); + + if (MCOS->hasInstructions()) { + ValidSections.insert(*sec); + } + } MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); @@ -530,7 +546,7 @@ // Add the size of the pair of PointerSize'ed values for the address and size // of the one default .text section we have in the table. - Length += 2 * AddrSize; + Length += 2 * AddrSize * ValidSections.size(); // And the pair of terminating zeros. Length += 2 * AddrSize; @@ -555,13 +571,16 @@ MCOS->EmitIntValue(0, 1); // Now emit the table of pairs of PointerSize'ed values for the section(s) - // address and size, in our case just the one default .text section. - const MCExpr *Addr = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, - *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); - MCOS->EmitAbsValue(Addr, AddrSize); - MCOS->EmitAbsValue(Size, AddrSize); + // address and size + for (std::set::const_iterator sec = ValidSections.begin(); + sec != ValidSections.end(); sec++) { + const MCExpr *Addr = MCSymbolRefExpr::Create( + context.getGenDwarfSectionStartSym(*sec), MCSymbolRefExpr::VK_None, context); + const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, + *context.getGenDwarfSectionStartSym(*sec), *context.getGenDwarfSectionEndSym(*sec), 0); + MCOS->EmitAbsValue(Addr, AddrSize); + MCOS->EmitAbsValue(Size, AddrSize); + } // And finally the pair of terminating zeros. MCOS->EmitIntValue(0, AddrSize); @@ -573,7 +592,8 @@ // DIE and a list of label DIEs. static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCSymbol *AbbrevSectionSymbol, - const MCSymbol *LineSectionSymbol) { + const MCSymbol *LineSectionSymbol, + const MCSymbol *RangesSectionSymbol) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -591,8 +611,8 @@ const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); MCOS->EmitAbsValue(Length, 4); - // The 2 byte DWARF version, which is 2. - MCOS->EmitIntValue(2, 2); + // The 2 byte DWARF version. + MCOS->EmitIntValue(context.getDwarfVersion(), 2); // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, // it is at the start of that section so this is zero. @@ -620,15 +640,38 @@ MCOS->EmitIntValue(0, 4); } - // AT_low_pc, the first address of the default .text section. - const MCExpr *Start = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitAbsValue(Start, AddrSize); + if (RangesSectionSymbol) { + // There are multiple sections containing code, so we must use the + // .debug_ranges sections. - // AT_high_pc, the last address of the default .text section. - const MCExpr *End = MCSymbolRefExpr::Create( - context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitAbsValue(End, AddrSize); + // 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(LineSectionSymbol, 4); + } else { + // If we only have one non-empty code section, we can use the simpler + // AT_low_pc and AT_high_pc attributes. + + // Find the first (and only) non-empty text section + std::set &Sections = context.getGenDwarfSections(); + std::set::const_iterator TextSection = Sections.begin(); + while (true) { + assert(TextSection != Sections.end() && "No text section found"); + MCOS->SwitchSection(*TextSection); + if (MCOS->hasInstructions()) break; + ++TextSection; + } + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); + + // AT_low_pc, the first address of the default .text section. + const MCExpr *Start = MCSymbolRefExpr::Create( + context.getGenDwarfSectionStartSym(*TextSection), MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(Start, AddrSize); + + // AT_high_pc, the last address of the default .text section. + const MCExpr *End = MCSymbolRefExpr::Create( + context.getGenDwarfSectionEndSym(*TextSection), MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(End, AddrSize); + } // AT_name, the name of the source file. Reconstruct from the first directory // and file table entries. @@ -725,6 +768,43 @@ MCOS->EmitLabel(InfoEnd); } +// When generating dwarf for assembly source files this emits the data for +// .debug_ranges section. We currently only emit one range list, which spans +// all of the executable sections of this file. +static void EmitGenDwarfRanges(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + std::set Sections = context.getGenDwarfSections(); + + const MCAsmInfo *asmInfo = context.getAsmInfo(); + int AddrSize = asmInfo->getPointerSize(); + + for (std::set::const_iterator sec = Sections.begin(); + sec != Sections.end(); sec++) { + MCOS->SwitchSection(*sec); + if (!MCOS->hasInstructions()) continue; + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + + MCSymbol* StartSymbol = context.getGenDwarfSectionStartSym(*sec); + MCSymbol* EndSymbol = context.getGenDwarfSectionEndSym(*sec); + + // 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->EmitAbsValue(SectionStartAddr, AddrSize); + + // Emit a range list entry spanning this section + const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, + *StartSymbol, *EndSymbol, 0); + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitAbsValue(SectionSize, AddrSize); + } + + // Emit end of list entry + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitIntValue(0, AddrSize); +} + // // When generating dwarf for assembly source files this emits the Dwarf // sections. @@ -739,6 +819,20 @@ LineSectionSymbol = NULL; MCSymbol *AbbrevSectionSymbol = NULL; MCSymbol *InfoSectionSymbol = NULL; + MCSymbol *RangesSectionSymbol = NULL; + + int NumSectionsWithInstructions = 0; + std::set Sections = MCOS->getContext().getGenDwarfSections(); + for (std::set::const_iterator sec = Sections.begin(); + sec != Sections.end(); sec++) { + MCOS->SwitchSection(*sec); + if (MCOS->hasInstructions()) ++NumSectionsWithInstructions; + } + // We only need to use the .debug_ranges section if we have multiple + // non-empty code sections. + const bool UseRangesSection = NumSectionsWithInstructions > 1; + CreateDwarfSectionSymbols |= UseRangesSection; + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); if (CreateDwarfSectionSymbols) { InfoSectionSymbol = context.CreateTempSymbol(); @@ -749,20 +843,34 @@ AbbrevSectionSymbol = context.CreateTempSymbol(); MCOS->EmitLabel(AbbrevSectionSymbol); } - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + if (UseRangesSection) { + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + if (CreateDwarfSectionSymbols) { + RangesSectionSymbol = context.CreateTempSymbol(); + MCOS->EmitLabel(RangesSectionSymbol); + } + } // If there are no line table entries then do not emit any section contents. if (context.getMCLineSections().empty()) return; + assert((RangesSectionSymbol != NULL) || !UseRangesSection); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + // Output the data for .debug_aranges section. EmitGenDwarfAranges(MCOS, InfoSectionSymbol); + if (UseRangesSection) + EmitGenDwarfRanges(MCOS); + // Output the data for .debug_abbrev section. - EmitGenDwarfAbbrev(MCOS); + EmitGenDwarfAbbrev(MCOS, UseRangesSection); // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); + EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, + RangesSectionSymbol); } // @@ -774,11 +882,11 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc) { // We won't create dwarf labels for temporary symbols or symbols not in - // the default text. + // a section which we are emitting dwarf for. if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) + if (!context.getGenDwarfSections().count(MCOS->getCurrentSection().first)) return; // The dwarf label's name does not have the symbol name's leading Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -625,10 +625,10 @@ // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - getContext().setGenDwarfSection(getStreamer().getCurrentSection().first); + getContext().addGenDwarfSection(getStreamer().getCurrentSection().first); MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSym); - getContext().setGenDwarfSectionStartSym(SectionStartSym); + getContext().setGenDwarfSectionStartSym(getStreamer().getCurrentSection().first, SectionStartSym); getStreamer().EmitDwarfFileDirective(getContext().nextGenDwarfFileNumber(), StringRef(), getContext().getMainFileName()); @@ -1565,12 +1565,11 @@ printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } - // If we are generating dwarf for assembly source files and the current - // section is the initial text section then generate a .loc directive for - // the instruction. + // If we are generating dwarf for the current section then generate a .loc + // directive for the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && - getContext().getGenDwarfSection() == - getStreamer().getCurrentSection().first) { + getContext().getGenDwarfSections().count( + getStreamer().getCurrentSection().first)) { unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); Index: lib/MC/MCParser/ELFAsmParser.cpp =================================================================== --- lib/MC/MCParser/ELFAsmParser.cpp +++ lib/MC/MCParser/ELFAsmParser.cpp @@ -150,7 +150,7 @@ private: bool ParseSectionName(StringRef &SectionName); - bool ParseSectionArguments(bool IsPush); + bool ParseSectionArguments(bool IsPush, SMLoc loc); }; } @@ -325,7 +325,7 @@ bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { getStreamer().PushSection(); - if (ParseSectionArguments(/*IsPush=*/true)) { + if (ParseSectionArguments(/*IsPush=*/true, loc)) { getStreamer().PopSection(); return true; } @@ -340,11 +340,11 @@ } // FIXME: This is a work in progress. -bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { - return ParseSectionArguments(/*IsPush=*/false); +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { + return ParseSectionArguments(/*IsPush=*/false, loc); } -bool ELFAsmParser::ParseSectionArguments(bool IsPush) { +bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef SectionName; if (ParseSectionName(SectionName)) @@ -482,10 +482,23 @@ } SectionKind Kind = computeSectionKind(Flags); - getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, - Flags, Kind, Size, - GroupName), - Subsection); + const MCSection* ELFSection = getContext().getELFSection( + SectionName, Type, Flags, Kind, Size, GroupName); + getStreamer().SwitchSection(ELFSection, Subsection); + + if (!getContext().getGenDwarfSections().count(ELFSection)) { + getContext().addGenDwarfSection(ELFSection); + if ( getContext().getDwarfVersion() <= 2 + && getContext().getGenDwarfSections().size() > 1) + Error(loc, "DWARF2 only supports one section per compilation unit"); + } + + if (!getContext().getGenDwarfSectionStartSym(ELFSection)) { + MCSymbol* SectionStartSymbol = getContext().CreateTempSymbol(); + getStreamer().EmitLabel(SectionStartSymbol); + getContext().setGenDwarfSectionStartSym(ELFSection, SectionStartSymbol); + } + return false; } Index: test/MC/ARM/dwarf-asm-multiple-sections.s =================================================================== --- /dev/null +++ test/MC/ARM/dwarf-asm-multiple-sections.s @@ -0,0 +1,67 @@ +// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g +// RUN: llvm-dwarfdump %t | FileCheck -check-prefix DWARF %s +// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC %s +// RUN: not llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -gdwarf-2 2>&1 | FileCheck -check-prefix VERSION %s + .section .text, "ax" +a: + mov r0, r0 + + .section foo, "ax" +b: + mov r1, r1 + +// DWARF: .debug_abbrev contents: +// DWARF: Abbrev table for offset: 0x00000000 +// DWARF: [1] DW_TAG_compile_unit DW_CHILDREN_yes +// DWARF: DW_AT_stmt_list DW_FORM_data4 +// DWARF: DW_AT_ranges DW_FORM_data4 +// DWARF: DW_AT_name DW_FORM_string +// DWARF: DW_AT_comp_dir DW_FORM_string +// DWARF: DW_AT_producer DW_FORM_string +// DWARF: DW_AT_language DW_FORM_data2 + +// DWARF: .debug_info contents: +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_compile_unit [1] +// CHECK-NOT-DWARF: DW_TAG_ +// DWARF: DW_AT_ranges [DW_FORM_data4] (0x00000000) + +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] * +// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("a") + +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] * +// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("b") + + +// DWARF: .debug_aranges contents: +// DWARF-NEXT: Address Range Header: length = 0x00000024, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x04, seg_size = 0x00 +// DWARF-NEXT: [0x00000000 - 0x00000004) +// DWARF-NEXT: [0x00000000 - 0x00000004) + + +// DWARF: .debug_line contents: +// DWARF: 0x0000000000000000 7 0 1 0 is_stmt +// DWARF-NEXT: 0x0000000000000004 7 0 1 0 is_stmt end_sequence +// DWARF-NEXT: 0x0000000000000000 11 0 1 0 is_stmt +// DWARF-NEXT: 0x0000000000000004 11 0 1 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 + + + +// RELOC: RELOCATION RECORDS FOR [.rel.debug_ranges]: +// RELOC-NEXT: 4 R_ARM_ABS32 .text +// RELOC-NEXT: 20 R_ARM_ABS32 foo + +// RELOC: RELOCATION RECORDS FOR [.rel.debug_aranges]: +// RELOC-NEXT: 6 R_ARM_ABS32 .debug_info +// RELOC-NEXT: 16 R_ARM_ABS32 .text +// RELOC-NEXT: 24 R_ARM_ABS32 foo + + +// VERSION: {{.*}} error: DWARF2 only supports one section per compilation unit Index: test/MC/ARM/dwarf-asm-nonstandard-section.s =================================================================== --- /dev/null +++ test/MC/ARM/dwarf-asm-nonstandard-section.s @@ -0,0 +1,50 @@ +// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g +// RUN: llvm-dwarfdump %t | FileCheck -check-prefix DWARF %s +// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC %s + + .section foo, "ax" +b: + mov r1, r1 + +// DWARF: .debug_abbrev contents: +// DWARF: Abbrev table for offset: 0x00000000 +// DWARF: [1] DW_TAG_compile_unit DW_CHILDREN_yes +// DWARF: DW_AT_stmt_list DW_FORM_data4 +// DWARF: DW_AT_low_pc DW_FORM_addr +// DWARF: DW_AT_high_pc DW_FORM_addr +// DWARF: DW_AT_name DW_FORM_string +// DWARF: DW_AT_comp_dir DW_FORM_string +// DWARF: DW_AT_producer DW_FORM_string +// DWARF: DW_AT_language DW_FORM_data2 + +// DWARF: .debug_info contents: +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_compile_unit [1] +// DWARF-NOT: DW_TAG_ +// DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +// DWARF: DW_AT_high_pc [DW_FORM_addr] (0x0000000000000004) + +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] * +// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("b") + + +// DWARF: .debug_aranges contents: +// DWARF-NEXT: Address Range Header: length = 0x0000001c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x04, seg_size = 0x00 +// DWARF-NEXT: [0x00000000 - 0x00000004) + + +// DWARF: .debug_line contents: +// DWARF: 0x0000000000000000 7 0 1 0 is_stmt +// DWARF-NEXT: 0x0000000000000004 7 0 1 0 is_stmt end_sequence + + +// DWARF: .debug_ranges contents: +// DWARF-NOT: {{0-9a-f}} +// DWARF: .debug_pubnames contents: + + + +// RELOC-NOT: RELOCATION RECORDS FOR [.rel.debug_ranges]: + +// RELOC: RELOCATION RECORDS FOR [.rel.debug_aranges]: +// RELOC-NEXT: 6 R_ARM_ABS32 .debug_info +// RELOC-NEXT: 16 R_ARM_ABS32 foo Index: test/MC/ARM/dwarf-asm-single-section.s =================================================================== --- /dev/null +++ test/MC/ARM/dwarf-asm-single-section.s @@ -0,0 +1,49 @@ +// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g +// RUN: llvm-dwarfdump %t | FileCheck -check-prefix DWARF %s +// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC %s + + .section .text, "ax" +a: + mov r0, r0 + + +// DWARF: .debug_abbrev contents: +// DWARF: Abbrev table for offset: 0x00000000 +// DWARF: [1] DW_TAG_compile_unit DW_CHILDREN_yes +// DWARF: DW_AT_stmt_list DW_FORM_data4 +// DWARF: DW_AT_low_pc DW_FORM_addr +// DWARF: DW_AT_high_pc DW_FORM_addr +// DWARF: DW_AT_name DW_FORM_string +// DWARF: DW_AT_comp_dir DW_FORM_string +// DWARF: DW_AT_producer DW_FORM_string +// DWARF: DW_AT_language DW_FORM_data2 + +// DWARF: .debug_info contents: +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_compile_unit [1] +// CHECK-NOT-DWARF: DW_TAG_ +// DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +// DWARF: DW_AT_high_pc [DW_FORM_addr] (0x0000000000000004) + +// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] * +// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("a") + + +// DWARF: .debug_aranges contents: +// DWARF-NEXT: Address Range Header: length = 0x0000001c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x04, seg_size = 0x00 +// DWARF-NEXT: [0x00000000 - 0x00000004) + +// DWARF: .debug_line contents: +// DWARF: 0x0000000000000000 7 0 1 0 is_stmt +// DWARF-NEXT: 0x0000000000000004 7 0 1 0 is_stmt end_sequence + + +// DWARF: .debug_ranges contents: +// DWARF-NOT: {{0-9a-f}} +// DWARF: .debug_pubnames contents: + + +// RELOC-NOT: RELOCATION RECORDS FOR [.rel.debug_ranges]: + +// RELOC: RELOCATION RECORDS FOR [.rel.debug_aranges]: +// RELOC-NEXT: 6 R_ARM_ABS32 .debug_info +// RELOC-NEXT: 16 R_ARM_ABS32 .text Index: test/MC/ARM/ldr-pseudo.s =================================================================== --- test/MC/ARM/ldr-pseudo.s +++ test/MC/ARM/ldr-pseudo.s @@ -16,20 +16,20 @@ @ CHECK-LABEL: f3: f3: ldr r0, =0x10001 -@ CHECK: ldr r0, .Ltmp0 +@ CHECK: ldr r0, .Ltmp[[TMP0:[0-9]+]] @ loading multiple constants .section c,"ax",%progbits @ CHECK-LABEL: f4: f4: ldr r0, =0x10002 -@ CHECK: ldr r0, .Ltmp1 +@ CHECK: ldr r0, .Ltmp[[TMP1:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 ldr r0, =0x10003 -@ CHECK: ldr r0, .Ltmp2 +@ CHECK: ldr r0, .Ltmp[[TMP2:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 @@ -38,7 +38,7 @@ @ CHECK-LABEL: f5: f5: ldr r0, =0x10004 -@ CHECK: ldr r0, .Ltmp3 +@ CHECK: ldr r0, .Ltmp[[TMP3:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 @@ -47,7 +47,7 @@ adds r0, r0, #1 adds r0, r0, #1 ldr r0, =0x10004 -@ CHECK: ldr r0, .Ltmp4 +@ CHECK: ldr r0, .Ltmp[[TMP4:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 @@ -60,7 +60,7 @@ @ CHECK-LABEL: f6: f6: ldr r0, =0x10006 -@ CHECK: ldr r0, .Ltmp5 +@ CHECK: ldr r0, .Ltmp[[TMP5:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 @@ -77,7 +77,7 @@ f8: adds r0, r0, #1 ldr r0, =0x10007 -@ CHECK: ldr r0, .Ltmp6 +@ CHECK: ldr r0, .Ltmp[[TMP6:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 @@ -90,21 +90,21 @@ @ CHECK-LABEL: f9: f9: ldr r0, =foo -@ CHECK: ldr r0, .Ltmp7 +@ CHECK: ldr r0, .Ltmp[[TMP7:[0-9]+]] @ load a symbol from another section .section h,"ax",%progbits @ CHECK-LABEL: f10: f10: ldr r0, =f5 -@ CHECK: ldr r0, .Ltmp8 +@ CHECK: ldr r0, .Ltmp[[TMP8:[0-9]+]] @ load a symbol from the same section .section i,"ax",%progbits @ CHECK-LABEL: f11: f11: ldr r0, =f12 -@ CHECK: ldr r0, .Ltmp9 +@ CHECK: ldr r0, .Ltmp[[TMP9:[0-9]+]] @ CHECK-LABEL: f12: f12: @@ -118,11 +118,11 @@ adds r0, r0, #1 adds r0, r0, #1 ldr r0, =0x101 -@ CHECK: ldr r0, .Ltmp10 +@ CHECK: ldr r0, .Ltmp[[TMP10:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 ldr r0, =bar -@ CHECK: ldr r0, .Ltmp11 +@ CHECK: ldr r0, .Ltmp[[TMP11:[0-9]+]] adds r0, r0, #1 adds r0, r0, #1 @ @@ -138,18 +138,18 @@ @ CHECK-LABEL: f14: f14: useit_in_a_macro -@ CHECK: ldr r0, .Ltmp12 -@ CHECK: ldr r0, .Ltmp13 +@ CHECK: ldr r0, .Ltmp[[TMP12:[0-9]+]] +@ CHECK: ldr r0, .Ltmp[[TMP13:[0-9]+]] @ usage with expressions .section l, "ax", %progbits @ CHECK-LABEL: f15: f15: ldr r0, =0x10001+8 -@ CHECK: ldr r0, .Ltmp14 +@ CHECK: ldr r0, .Ltmp[[TMP14:[0-9]+]] adds r0, r0, #1 ldr r0, =bar+4 -@ CHECK: ldr r0, .Ltmp15 +@ CHECK: ldr r0, .Ltmp[[TMP15:[0-9]+]] adds r0, r0, #1 @ @@ -157,28 +157,28 @@ @ @ CHECK: .section b,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp0: +@ CHECK: .Ltmp[[TMP0]] @ CHECK: .long 65537 @ CHECK: .section c,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp1: +@ CHECK: .Ltmp[[TMP1]] @ CHECK: .long 65538 -@ CHECK-LABEL: .Ltmp2: +@ CHECK: .Ltmp[[TMP2]] @ CHECK: .long 65539 @ CHECK: .section d,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp3: +@ CHECK: .Ltmp[[TMP3]] @ CHECK: .long 65540 -@ CHECK-LABEL: .Ltmp4: +@ CHECK: .Ltmp[[TMP4]] @ CHECK: .long 65540 @ CHECK: .section e,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp5: +@ CHECK: .Ltmp[[TMP5]] @ CHECK: .long 65542 -@ CHECK-LABEL: .Ltmp6: +@ CHECK: .Ltmp[[TMP6]] @ CHECK: .long 65543 @ Should not switch to section because it has no constant pool @@ -186,36 +186,36 @@ @ CHECK: .section g,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp7: +@ CHECK: .Ltmp[[TMP7]] @ CHECK: .long foo @ CHECK: .section h,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp8: +@ CHECK: .Ltmp[[TMP8]] @ CHECK: .long f5 @ CHECK: .section i,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp9: +@ CHECK: .Ltmp[[TMP9]] @ CHECK: .long f12 @ CHECK: .section j,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp10: +@ CHECK: .Ltmp[[TMP10]] @ CHECK: .long 257 -@ CHECK-LABEL: .Ltmp11: +@ CHECK: .Ltmp[[TMP11]] @ CHECK: .long bar @ CHECK: .section k,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp12: +@ CHECK: .Ltmp[[TMP12]] @ CHECK: .long 65544 -@ CHECK-LABEL: .Ltmp13: +@ CHECK: .Ltmp[[TMP13]] @ CHECK: .long baz @ CHECK: .section l,"ax",%progbits @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp14: +@ CHECK: .Ltmp[[TMP14]] @ CHECK: .long 65545 -@ CHECK-LABEL: .Ltmp15: +@ CHECK: .Ltmp[[TMP15]] @ CHECK: .long bar+4 Index: test/MC/ARM/ltorg.s =================================================================== --- test/MC/ARM/ltorg.s +++ test/MC/ARM/ltorg.s @@ -13,14 +13,14 @@ @ CHECK-LABEL: f2: f2: ldr r0, =0x10001 -@ CHECK: ldr r0, .Ltmp0 +@ CHECK: ldr r0, .Ltmp[[TMP0:[0-9+]]] adds r0, r0, #1 adds r0, r0, #1 b f3 .ltorg @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp0: +@ CHECK: .Ltmp[[TMP0]] @ CHECK: .long 65537 @ CHECK-LABEL: f3: @@ -33,14 +33,14 @@ @ CHECK-LABEL: f4: f4: ldr r0, =0x10002 -@ CHECK: ldr r0, .Ltmp1 +@ CHECK: ldr r0, .Ltmp[[TMP1:[0-9+]]] adds r0, r0, #1 adds r0, r0, #1 b f5 .ltorg @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp1: +@ CHECK: .Ltmp[[TMP1]] @ CHECK: .long 65538 @ CHECK-LABEL: f5: @@ -48,13 +48,13 @@ adds r0, r0, #1 adds r0, r0, #1 ldr r0, =0x10003 -@ CHECK: ldr r0, .Ltmp2 +@ CHECK: ldr r0, .Ltmp[[TMP2:[0-9+]]] adds r0, r0, #1 b f6 .ltorg @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp2: +@ CHECK: .Ltmp[[TMP2]] @ CHECK: .long 65539 @ CHECK-LABEL: f6: @@ -79,7 +79,7 @@ adds r0, r0, #1 adds r0, r0, #1 ldr r0, =bar -@ CHECK: ldr r0, .Ltmp3 +@ CHECK: ldr r0, .Ltmp[[TMP3:[0-9+]]] adds r0, r0, #1 adds r0, r0, #1 adds r0, r0, #1 @@ -87,7 +87,7 @@ .ltorg @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp3: +@ CHECK: .Ltmp[[TMP3]] @ CHECK: .long bar @ CHECK-LABEL: f10: @@ -102,18 +102,18 @@ adds r0, r0, #1 adds r0, r0, #1 ldr r0, =0x10004 -@ CHECK: ldr r0, .Ltmp4 +@ CHECK: ldr r0, .Ltmp[[TMP4:[0-9+]]] b f12 .ltorg @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp4: +@ CHECK: .Ltmp[[TMP4]] @ CHECK: .long 65540 @ CHECK-LABEL: f12: f12: adds r0, r0, #1 ldr r0, =0x10005 -@ CHECK: ldr r0, .Ltmp5 +@ CHECK: ldr r0, .Ltmp[[TMP5:[0-9+]]] .section f,"ax",%progbits @ CHECK-LABEL: f13 @@ -131,7 +131,7 @@ @ CHECK: .section e,"ax",%progbits @ constant pool @ CHECK: .align 2 -@ CHECK-LABEL: .Ltmp5: +@ CHECK: .Ltmp[[TMP5]] @ CHECK: .long 65541 @ should not have a constant pool at end of section with empty constant pools Index: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -153,6 +153,23 @@ GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " "source files")); +enum DwarfVersionNumber { + DWARF2 = 2, + DWARF3 = 3, + DWARF4 = 4 +}; + +static cl::opt +DwarfVersion(cl::desc("Dwarf version"), + cl::init(DWARF3), + cl::values(clEnumValN(DWARF2, "gdwarf-2", + "Dwarf version 2"), + clEnumValN(DWARF3, "gdwarf-3", + "Dwarf version 3"), + clEnumValN(DWARF4, "gdwarf-4", + "Dwarf version 4"), + clEnumValEnd)); + static cl::opt DebugCompilationDir("fdebug-compilation-dir", cl::desc("Specifies the debug info's compilation dir")); @@ -395,6 +412,7 @@ Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); + Ctx.setDwarfVersion(DwarfVersion); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty())