mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[DebugInfo] Allow GNU macro extension to be emitted
Allow the GNU .debug_macro extension to be emitted for DWARF versions earlier than 5. The extension is basically what became DWARF 5's format, except that a DW_AT_GNU_macros attribute is emitted, and some entries like the strx entries are missing. In this patch I emit GNU's indirect entries, which are the same as DWARF 5's strp entries. This patch adds the extension behind a hidden LLVM flag, -use-gnu-debug-macro. I would later want to enable it by default when tuning for GDB and targeting DWARF versions earlier than 5. The size of a Clang 8.0 binary built with RelWithDebInfo and the flags "-gdwarf-4 -fdebug-macro" reduces from 1533 MB to 1349 MB with .debug_macro (compared to 1296 MB without -fdebug-macro). Reviewed By: SouraVX, dblaikie Differential Revision: https://reviews.llvm.org/D82975
This commit is contained in:
parent
9a1cd64d35
commit
9857b3e63f
@ -147,6 +147,11 @@ static cl::opt<DefaultOnOff> DwarfSectionsAsReferences(
|
||||
clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
|
||||
cl::init(Default));
|
||||
|
||||
static cl::opt<bool>
|
||||
UseGNUDebugMacro("use-gnu-debug-macro", cl::Hidden,
|
||||
cl::desc("Emit the GNU .debug_macro format with DWARF <5"),
|
||||
cl::init(false));
|
||||
|
||||
enum LinkageNameOption {
|
||||
DefaultLinkageNames,
|
||||
AllLinkageNames,
|
||||
@ -428,7 +433,10 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
||||
// the debug entry values feature. It can also be enabled explicitly.
|
||||
EmitDebugEntryValues = Asm->TM.Options.ShouldEmitDebugEntryValues();
|
||||
|
||||
UseDebugMacroSection = DwarfVersion >= 5;
|
||||
// It is unclear if the GCC .debug_macro extension is well-specified
|
||||
// for split DWARF. For now, do not allow LLVM to emit it.
|
||||
UseDebugMacroSection =
|
||||
DwarfVersion >= 5 || (UseGNUDebugMacro && !useSplitDwarf());
|
||||
|
||||
Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
|
||||
}
|
||||
@ -1353,10 +1361,13 @@ void DwarfDebug::finalizeModuleInfo() {
|
||||
TheCU.addSectionDelta(
|
||||
TheCU.getUnitDie(), dwarf::DW_AT_macros, U.getMacroLabelBegin(),
|
||||
TLOF.getDwarfMacroDWOSection()->getBeginSymbol());
|
||||
else
|
||||
U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macros,
|
||||
U.getMacroLabelBegin(),
|
||||
else {
|
||||
dwarf::Attribute MacrosAttr = getDwarfVersion() >= 5
|
||||
? dwarf::DW_AT_macros
|
||||
: dwarf::DW_AT_GNU_macros;
|
||||
U.addSectionLabel(U.getUnitDie(), MacrosAttr, U.getMacroLabelBegin(),
|
||||
TLOF.getDwarfMacroSection()->getBeginSymbol());
|
||||
}
|
||||
} else {
|
||||
if (useSplitDwarf())
|
||||
TheCU.addSectionDelta(
|
||||
@ -2980,16 +2991,17 @@ void DwarfDebug::emitDebugRangesDWO() {
|
||||
Asm->getObjFileLowering().getDwarfRnglistsDWOSection());
|
||||
}
|
||||
|
||||
/// Emit the header of a DWARF 5 macro section.
|
||||
/// Emit the header of a DWARF 5 macro section, or the GNU extension for
|
||||
/// DWARF 4.
|
||||
static void emitMacroHeader(AsmPrinter *Asm, const DwarfDebug &DD,
|
||||
const DwarfCompileUnit &CU) {
|
||||
const DwarfCompileUnit &CU, uint16_t DwarfVersion) {
|
||||
enum HeaderFlagMask {
|
||||
#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_FLAG_##NAME = ID,
|
||||
#include "llvm/BinaryFormat/Dwarf.def"
|
||||
};
|
||||
uint8_t Flags = 0;
|
||||
Asm->OutStreamer->AddComment("Macro information version");
|
||||
Asm->emitInt16(5);
|
||||
Asm->emitInt16(DwarfVersion >= 5 ? DwarfVersion : 4);
|
||||
// We are setting Offset and line offset flags unconditionally here,
|
||||
// since we're only supporting DWARF32 and line offset should be mostly
|
||||
// present.
|
||||
@ -3024,16 +3036,31 @@ void DwarfDebug::emitMacro(DIMacro &M) {
|
||||
std::string Str = Value.empty() ? Name.str() : (Name + " " + Value).str();
|
||||
|
||||
if (UseDebugMacroSection) {
|
||||
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->emitULEB128(Type);
|
||||
Asm->OutStreamer->AddComment("Line Number");
|
||||
Asm->emitULEB128(M.getLine());
|
||||
Asm->OutStreamer->AddComment("Macro String");
|
||||
Asm->emitULEB128(
|
||||
InfoHolder.getStringPool().getIndexedEntry(*Asm, Str).getIndex());
|
||||
if (getDwarfVersion() >= 5) {
|
||||
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->emitULEB128(Type);
|
||||
Asm->OutStreamer->AddComment("Line Number");
|
||||
Asm->emitULEB128(M.getLine());
|
||||
Asm->OutStreamer->AddComment("Macro String");
|
||||
Asm->emitULEB128(
|
||||
InfoHolder.getStringPool().getIndexedEntry(*Asm, Str).getIndex());
|
||||
} else {
|
||||
unsigned Type = M.getMacinfoType() == dwarf::DW_MACINFO_define
|
||||
? dwarf::DW_MACRO_GNU_define_indirect
|
||||
: dwarf::DW_MACRO_GNU_undef_indirect;
|
||||
Asm->OutStreamer->AddComment(dwarf::GnuMacroString(Type));
|
||||
Asm->emitULEB128(Type);
|
||||
Asm->OutStreamer->AddComment("Line Number");
|
||||
Asm->emitULEB128(M.getLine());
|
||||
Asm->OutStreamer->AddComment("Macro String");
|
||||
// FIXME: Add support for DWARF64.
|
||||
Asm->OutStreamer->emitSymbolValue(
|
||||
InfoHolder.getStringPool().getEntry(*Asm, Str).getSymbol(),
|
||||
/*Size=*/4);
|
||||
}
|
||||
} else {
|
||||
Asm->OutStreamer->AddComment(dwarf::MacinfoString(M.getMacinfoType()));
|
||||
Asm->emitULEB128(M.getMacinfoType());
|
||||
@ -3071,8 +3098,9 @@ void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) {
|
||||
// so for readibility/uniformity, We are explicitly emitting those.
|
||||
assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file);
|
||||
if (UseDebugMacroSection)
|
||||
emitMacroFileImpl(F, U, dwarf::DW_MACRO_start_file,
|
||||
dwarf::DW_MACRO_end_file, dwarf::MacroString);
|
||||
emitMacroFileImpl(
|
||||
F, U, dwarf::DW_MACRO_start_file, dwarf::DW_MACRO_end_file,
|
||||
(getDwarfVersion() >= 5) ? dwarf::MacroString : dwarf::GnuMacroString);
|
||||
else
|
||||
emitMacroFileImpl(F, U, dwarf::DW_MACINFO_start_file,
|
||||
dwarf::DW_MACINFO_end_file, dwarf::MacinfoString);
|
||||
@ -3090,7 +3118,7 @@ void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) {
|
||||
Asm->OutStreamer->SwitchSection(Section);
|
||||
Asm->OutStreamer->emitLabel(U.getMacroLabelBegin());
|
||||
if (UseDebugMacroSection)
|
||||
emitMacroHeader(Asm, *this, U);
|
||||
emitMacroHeader(Asm, *this, U, getDwarfVersion());
|
||||
handleMacroNodes(Macros, U);
|
||||
Asm->OutStreamer->AddComment("End Of Macro List Mark");
|
||||
Asm->emitInt8(0);
|
||||
|
50
test/DebugInfo/X86/debug-macro-gnu-dwo.ll
Normal file
50
test/DebugInfo/X86/debug-macro-gnu-dwo.ll
Normal file
@ -0,0 +1,50 @@
|
||||
; It is unclear if the GNU .debug_macro extension is well-specified for split
|
||||
; DWARF. For now, verify that a .debug_macinfo.dwo section is emitted when
|
||||
; -gdwarf-4 -gsplit-dwarf -fdebug-macro is specified, regardless of the GNU
|
||||
; extension being requested.
|
||||
|
||||
; RUN: %llc_dwarf -dwarf-version=4 -O0 -filetype=obj -use-gnu-debug-macro \
|
||||
; RUN: -split-dwarf-file=foo.dwo < %s | llvm-dwarfdump -v - | FileCheck %s
|
||||
|
||||
; CHECK: .debug_info.dwo contents:
|
||||
; CHECK: DW_AT_macro_info [DW_FORM_sec_offset] (0x00000000)
|
||||
|
||||
; CHECK-LABEL: .debug_macinfo.dwo contents:
|
||||
; CHECK-NEXT: 0x00000000:
|
||||
; CHECK-NEXT: DW_MACINFO_start_file - lineno: 0 filenum: 1
|
||||
; CHECK-NEXT: DW_MACINFO_start_file - lineno: 1 filenum: 2
|
||||
; CHECK-NEXT: DW_MACINFO_define - lineno: 1 macro: FOO 5
|
||||
; CHECK-NEXT: DW_MACINFO_end_file
|
||||
; CHECK-NEXT: DW_MACINFO_start_file - lineno: 2 filenum: 3
|
||||
; CHECK-NEXT: DW_MACINFO_undef - lineno: 14 macro: YEA
|
||||
; CHECK-NEXT: DW_MACINFO_end_file
|
||||
; CHECK-NEXT: DW_MACINFO_undef - lineno: 14 macro: YEA
|
||||
; CHECK-NEXT: DW_MACINFO_end_file
|
||||
|
||||
; ModuleID = 'test.c'
|
||||
source_filename = "test.c"
|
||||
target datalayout = "e-m:e-p200:32:32-p201:32:32-p202:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!14, !15, !16}
|
||||
!llvm.ident = !{!17}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, macros: !3, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.c", directory: "/home/")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = !DIMacroFile(file: !1, nodes: !5)
|
||||
!5 = !{!6, !10, !13}
|
||||
!6 = !DIMacroFile(line: 1, file: !7, nodes: !8)
|
||||
!7 = !DIFile(filename: "./foo.h", directory: "/home/")
|
||||
!8 = !{!9}
|
||||
!9 = !DIMacro(type: DW_MACINFO_define, line: 1, name: "FOO", value: "5")
|
||||
!10 = !DIMacroFile(line: 2, file: !11, nodes: !12)
|
||||
!11 = !DIFile(filename: "./bar.h", directory: "/home/")
|
||||
!12 = !{!13}
|
||||
!13 = !DIMacro(type: DW_MACINFO_undef, line: 14, name: "YEA")
|
||||
!14 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!15 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!16 = !{i32 1, !"wchar_size", i32 4}
|
||||
!17 = !{!"clang version 10.0.0"}
|
47
test/DebugInfo/X86/debug-macro-gnu.ll
Normal file
47
test/DebugInfo/X86/debug-macro-gnu.ll
Normal file
@ -0,0 +1,47 @@
|
||||
; This test checks emission of the GNU extension for the .debug_macro section.
|
||||
|
||||
; RUN: %llc_dwarf -dwarf-version=4 -O0 -use-gnu-debug-macro -filetype=obj < %s | llvm-dwarfdump -v - | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: .debug_info contents:
|
||||
; CHECK: DW_AT_GNU_macros [DW_FORM_sec_offset] (0x00000000)
|
||||
|
||||
; CHECK-LABEL: .debug_macro contents:
|
||||
; CHECK-NEXT: 0x00000000:
|
||||
; CHECK-NEXT: macro header: version = 0x0004, flags = 0x02, format = DWARF32, debug_line_offset = 0x0000
|
||||
; CHECK-NEXT: DW_MACRO_GNU_start_file - lineno: 0 filenum: 1
|
||||
; CHECK-NEXT: DW_MACRO_GNU_start_file - lineno: 1 filenum: 2
|
||||
; CHECK-NEXT: DW_MACRO_GNU_define_indirect - lineno: 1 macro: FOO 5
|
||||
; CHECK-NEXT: DW_MACRO_GNU_end_file
|
||||
; CHECK-NEXT: DW_MACRO_GNU_start_file - lineno: 2 filenum: 3
|
||||
; CHECK-NEXT: DW_MACRO_GNU_undef_indirect - lineno: 14 macro: YEA
|
||||
; CHECK-NEXT: DW_MACRO_GNU_end_file
|
||||
; CHECK-NEXT: DW_MACRO_GNU_undef_indirect - lineno: 14 macro: YEA
|
||||
; CHECK-NEXT: DW_MACRO_GNU_end_file
|
||||
|
||||
; ModuleID = 'test.c'
|
||||
source_filename = "test.c"
|
||||
target datalayout = "e-m:e-p200:32:32-p201:32:32-p202:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!14, !15, !16}
|
||||
!llvm.ident = !{!17}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, macros: !3, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.c", directory: "/home/")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = !DIMacroFile(file: !1, nodes: !5)
|
||||
!5 = !{!6, !10, !13}
|
||||
!6 = !DIMacroFile(line: 1, file: !7, nodes: !8)
|
||||
!7 = !DIFile(filename: "./foo.h", directory: "/home/")
|
||||
!8 = !{!9}
|
||||
!9 = !DIMacro(type: DW_MACINFO_define, line: 1, name: "FOO", value: "5")
|
||||
!10 = !DIMacroFile(line: 2, file: !11, nodes: !12)
|
||||
!11 = !DIFile(filename: "./bar.h", directory: "/home/")
|
||||
!12 = !{!13}
|
||||
!13 = !DIMacro(type: DW_MACINFO_undef, line: 14, name: "YEA")
|
||||
!14 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!15 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!16 = !{i32 1, !"wchar_size", i32 4}
|
||||
!17 = !{!"clang version 10.0.0"}
|
Loading…
Reference in New Issue
Block a user