Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -144,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). @@ -408,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: lib/MC/MCDwarf.cpp =================================================================== --- lib/MC/MCDwarf.cpp +++ lib/MC/MCDwarf.cpp @@ -611,8 +611,8 @@ const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); MCOS->EmitAbsValue(Length, 4); - // The 2 byte DWARF version, which is 3. - MCOS->EmitIntValue(3, 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. 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)) @@ -488,6 +488,9 @@ 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)) { Index: test/MC/ARM/dwarf-asm-multiple-sections.s =================================================================== --- test/MC/ARM/dwarf-asm-multiple-sections.s +++ test/MC/ARM/dwarf-asm-multiple-sections.s @@ -1,7 +1,7 @@ // 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 @@ -62,3 +62,6 @@ // 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: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -153,6 +153,13 @@ GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " "source files")); +static cl::opt +DwarfVersion2("gdwarf-2", cl::desc("Limit debugging info to dwarf version 2")); +static cl::opt +DwarfVersion3("gdwarf-3", cl::desc("Limit debugging info to dwarf version 3")); +static cl::opt +DwarfVersion4("gdwarf-4", cl::desc("Limit debugging info to dwarf version 4")); + static cl::opt DebugCompilationDir("fdebug-compilation-dir", cl::desc("Specifies the debug info's compilation dir")); @@ -395,6 +402,14 @@ Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); + // Use the highest requested dwarf version, defaulting to 3 + Ctx.setDwarfVersion(3); + if (DwarfVersion2) + Ctx.setDwarfVersion(2); + if (DwarfVersion3) + Ctx.setDwarfVersion(3); + if (DwarfVersion4) + Ctx.setDwarfVersion(4); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty())