Index: llvm/include/llvm/BinaryFormat/Dwarf.h =================================================================== --- llvm/include/llvm/BinaryFormat/Dwarf.h +++ llvm/include/llvm/BinaryFormat/Dwarf.h @@ -479,7 +479,7 @@ StringRef LNStandardString(unsigned Standard); StringRef LNExtendedString(unsigned Encoding); StringRef MacinfoString(unsigned Encoding); -StringRef MacroString(unsigned Encoding); +StringRef MacroString(unsigned Encoding, bool GNU); StringRef RangeListEncodingString(unsigned Encoding); StringRef LocListEncodingString(unsigned Encoding); StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch); Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -96,6 +96,9 @@ MacroHeader Header; SmallVector Macros; uint64_t Offset; + + /// Whether or not this is a .debug_macro section. + bool IsDebugMacro; }; /// A list of all the macro entries in the debug_macinfo section. Index: llvm/lib/BinaryFormat/Dwarf.cpp =================================================================== --- llvm/lib/BinaryFormat/Dwarf.cpp +++ llvm/lib/BinaryFormat/Dwarf.cpp @@ -477,7 +477,21 @@ .Default(DW_MACINFO_invalid); } -StringRef llvm::dwarf::MacroString(unsigned Encoding) { +static StringRef getGnuMacroString(unsigned Encoding) { + switch (Encoding) { + default: + return StringRef(); +#define HANDLE_DW_MACRO_GNU(ID, NAME) \ + case DW_MACRO_GNU_##NAME: \ + return "DW_MACRO_GNU_" #NAME; +#include "llvm/BinaryFormat/Dwarf.def" + } +} + +StringRef llvm::dwarf::MacroString(unsigned Encoding, bool GNU) { + if (GNU) + return getGnuMacroString(Encoding); + switch (Encoding) { default: return StringRef(); Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -529,9 +529,10 @@ void emitDebugMacinfoImpl(MCSection *Section); void emitMacro(DIMacro &M); void emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U); - void emitMacroFileImpl(DIMacroFile &F, DwarfCompileUnit &U, - unsigned StartFile, unsigned EndFile, - StringRef (*MacroFormToString)(unsigned Form)); + void + emitMacroFileImpl(DIMacroFile &F, DwarfCompileUnit &U, unsigned StartFile, + unsigned EndFile, + std::function MacroFormToString); void handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U); /// DWARF 5 Experimental Split Dwarf Emitters Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -3000,7 +3000,7 @@ unsigned Type = M.getMacinfoType() == dwarf::DW_MACINFO_define ? dwarf::DW_MACRO_define_strx : dwarf::DW_MACRO_undef_strx; - Asm->OutStreamer->AddComment(dwarf::MacroString(Type)); + Asm->OutStreamer->AddComment(dwarf::MacroString(Type, /*GNU=*/false)); Asm->emitULEB128(Type); Asm->OutStreamer->AddComment("Line Number"); Asm->emitULEB128(M.getLine()); @@ -3034,7 +3034,7 @@ void DwarfDebug::emitMacroFileImpl( DIMacroFile &F, DwarfCompileUnit &U, unsigned StartFile, unsigned EndFile, - StringRef (*MacroFormToString)(unsigned Form)) { + std::function MacroFormToString) { Asm->OutStreamer->AddComment(MacroFormToString(StartFile)); Asm->emitULEB128(StartFile); @@ -3051,10 +3051,13 @@ // DWARFv5 macro and DWARFv4 macinfo share some common encodings, // so for readibility/uniformity, We are explicitly emitting those. assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); - if (UseDebugMacroSection) + if (UseDebugMacroSection) { + auto FormToString = [](unsigned Form) { + return dwarf::MacroString(Form, /*GNU=*/false); + }; emitMacroFileImpl(F, U, dwarf::DW_MACRO_start_file, - dwarf::DW_MACRO_end_file, dwarf::MacroString); - else + dwarf::DW_MACRO_end_file, FormToString); + } else emitMacroFileImpl(F, U, dwarf::DW_MACINFO_start_file, dwarf::DW_MACINFO_end_file, dwarf::MacinfoString); } Index: llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -40,7 +40,7 @@ unsigned IndLevel = 0; for (const auto &Macros : MacroLists) { OS << format("0x%08" PRIx64 ":\n", Macros.Offset); - if (Macros.Header.Version >= 5) + if (Macros.IsDebugMacro) Macros.Header.dumpMacroHeader(OS); for (const Entry &E : Macros.Macros) { // There should not be DW_MACINFO_end_file when IndLevel is Zero. However, @@ -52,8 +52,9 @@ OS << " "; IndLevel += (E.Type == DW_MACINFO_start_file); // Based on which version we are handling choose appropriate macro forms. - if (Macros.Header.Version >= 5) - WithColor(OS, HighlightColor::Macro).get() << MacroString(E.Type); + if (Macros.IsDebugMacro) + WithColor(OS, HighlightColor::Macro).get() + << MacroString(E.Type, /*GNU=*/Macros.Header.Version < 5); else WithColor(OS, HighlightColor::Macro).get() << MacinfoString(E.Type); switch (E.Type) { @@ -67,6 +68,9 @@ // DW_MACRO_start_file == DW_MACINFO_start_file // DW_MACRO_end_file == DW_MACINFO_end_file // For readability/uniformity we are using DW_MACRO_*. + // + // The GNU .debug_macro extension's entries have the same encoding + // as DWARF 5's DW_MACRO_* entries, so we only use the latter here. case DW_MACRO_define: case DW_MACRO_undef: case DW_MACRO_define_strp: @@ -118,6 +122,7 @@ MacroLists.emplace_back(); M = &MacroLists.back(); M->Offset = Offset; + M->IsDebugMacro = IsMacro; if (IsMacro) { auto Err = M->Header.parseMacroHeader(Data, &Offset); if (Err) Index: llvm/test/DebugInfo/X86/debug-macro-gnu.s =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/debug-macro-gnu.s @@ -0,0 +1,59 @@ +## This test checks that llvm-dwarfdump can dump a .debug_macro section +## with the GNU extension format. + +# RUN: llvm-mc -triple x86_64-unknown-linux -filetype=obj %s -o -| \ +# RUN: llvm-dwarfdump -debug-macro - | FileCheck -strict-whitespace -match-full-lines %s + +# CHECK:.debug_macro contents: +# CHECK-NEXT:0x00000000: +# CHECK-NEXT:macro header: version = 0x0004, flags = 0x02, format = DWARF32, debug_line_offset = 0x00000000 +# CHECK-NEXT:DW_MACRO_GNU_start_file - lineno: 0 filenum: 0 +# CHECK-NEXT: DW_MACRO_GNU_start_file - lineno: 1 filenum: 6 +# CHECK-NEXT: DW_MACRO_GNU_define_indirect - lineno: 1 macro: FOO 5 +# CHECK-NEXT: DW_MACRO_GNU_end_file +# CHECK-NEXT: DW_MACRO_GNU_undef_indirect - lineno: 8 macro: WORLD1 +# CHECK-NEXT: DW_MACRO_GNU_transparent_include - import offset: 0x[[OFFSET:[0-9]+]] +# CHECK-NEXT:DW_MACRO_GNU_end_file + +# CHECK:0x[[OFFSET]]: +# CHECK-NEXT:macro header: version = 0x0004, flags = 0x00, format = DWARF32 +# CHECK-NEXT:DW_MACRO_GNU_define_indirect - lineno: 0 macro: WORLD 2 + + .section .debug_macro,"",@progbits +.Lcu_macro_begin0: + .short 4 # Macro information version + .byte 2 # Flags: 32 bit, debug_line_offset present + .long 0 # debug_line_offset + .byte 3 # DW_MACRO_GNU_start_file + .byte 0 # Line Number + .byte 0 # File Number + .byte 3 # DW_MACRO_GNU_start_file + .byte 1 # Line Number + .byte 6 # File Number + .byte 5 # DW_MACRO_GNU_define_indirect + .byte 1 # Line Number + .long .Linfo_string0 # Macro String + .byte 4 # DW_MACRO_GNU_end_file + .byte 6 # DW_MACRO_GNU_undef_indirect + .byte 8 # Line Number + .long .Linfo_string1 # Macro String + .byte 7 # DW_MACRO_GNU_transparent_include + .long .Lmacro1 # Macro Unit Offset + .byte 4 # DW_MACRO_GNU_end_file + .byte 0 # End Of Macro List Mark + +.Lmacro1: + .short 4 # Macro information version + .byte 0 # Flags: 32 bit + .byte 5 # DW_MACRO_GNU_define_indirect + .byte 0 # Line Number + .long .Linfo_string2 # Macro String + .byte 0 # End Of Macro List Mark + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "FOO 5" +.Linfo_string1: + .asciz "WORLD1" +.Linfo_string2: + .asciz "WORLD 2"