1
0
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:
David Stenberg 2020-08-11 13:48:30 +02:00
parent 9a1cd64d35
commit 9857b3e63f
3 changed files with 145 additions and 20 deletions

View File

@ -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,6 +3036,7 @@ void DwarfDebug::emitMacro(DIMacro &M) {
std::string Str = Value.empty() ? Name.str() : (Name + " " + Value).str();
if (UseDebugMacroSection) {
if (getDwarfVersion() >= 5) {
unsigned Type = M.getMacinfoType() == dwarf::DW_MACINFO_define
? dwarf::DW_MACRO_define_strx
: dwarf::DW_MACRO_undef_strx;
@ -3034,6 +3047,20 @@ void DwarfDebug::emitMacro(DIMacro &M) {
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);

View 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"}

View 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"}