diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 45875667027..4621ecbb510 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -76,6 +76,17 @@ static cl::opt GenerateARangeSection("generate-arange-section", cl::desc("Generate dwarf aranges"), cl::init(false)); +static cl::opt +DebuggerTuningOpt("debugger-tune", + cl::desc("Tune debug info for a particular debugger"), + cl::init(DebuggerKind::Default), + cl::values( + clEnumValN(DebuggerKind::GDB, "gdb", "gdb"), + clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"), + clEnumValN(DebuggerKind::SCE, "sce", + "SCE targets (e.g. PS4)"), + clEnumValEnd)); + namespace { enum DefaultOnOff { Default, Enable, Disable }; } @@ -197,32 +208,44 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) UsedNonDefaultText(false), SkeletonHolder(A, "skel_string", DIEValueAllocator), IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), - IsPS4(Triple(A->getTargetTriple()).isPS4()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), - AccelTypes(TypeAtoms) { + AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) { CurFn = nullptr; CurMI = nullptr; + Triple TT(Asm->getTargetTriple()); - // Turn on accelerator tables for Darwin by default, pubnames by - // default for non-Darwin/PS4, and handle split dwarf. + // Make sure we know our "debugger tuning." The command-line option takes + // precedence; fall back to triple-based defaults. + if (DebuggerTuningOpt != DebuggerKind::Default) + DebuggerTuning = DebuggerTuningOpt; + else if (IsDarwin || TT.isOSFreeBSD()) + DebuggerTuning = DebuggerKind::LLDB; + else if (TT.isPS4CPU()) + DebuggerTuning = DebuggerKind::SCE; + else + DebuggerTuning = DebuggerKind::GDB; + + // Turn on accelerator tables for LLDB by default. if (DwarfAccelTables == Default) - HasDwarfAccelTables = IsDarwin; + HasDwarfAccelTables = tuneForLLDB(); else HasDwarfAccelTables = DwarfAccelTables == Enable; + // Handle split DWARF. Off by default for now. if (SplitDwarf == Default) HasSplitDwarf = false; else HasSplitDwarf = SplitDwarf == Enable; + // Pubnames/pubtypes on by default for GDB. if (DwarfPubSections == Default) - HasDwarfPubSections = !IsDarwin && !IsPS4; + HasDwarfPubSections = tuneForGDB(); else HasDwarfPubSections = DwarfPubSections == Enable; @@ -230,9 +253,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber : MMI->getModule()->getDwarfVersion(); - // Darwin and PS4 use the standard TLS opcode (defined in DWARF 3). - // Everybody else uses GNU's. - UseGNUTLSOpcode = !(IsDarwin || IsPS4) || DwarfVersion < 3; + // Work around a GDB bug. GDB doesn't support the standard opcode; + // SCE doesn't support GNU's; LLDB prefers the standard opcode, which + // is defined as of DWARF 3. + // See GDB bug 11616 - DW_OP_form_tls_address is unimplemented + // https://sourceware.org/bugzilla/show_bug.cgi?id=11616 + UseGNUTLSOpcode = tuneForGDB() || DwarfVersion < 3; Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 36502225c29..57bb8d0229d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -203,6 +203,30 @@ struct SymbolCU { DwarfCompileUnit *CU; }; +/// Identify a debugger for "tuning" the debug info. +/// +/// The "debugger tuning" concept allows us to present a more intuitive +/// interface that unpacks into different sets of defaults for the various +/// individual feature-flag settings, that suit the preferences of the +/// various debuggers. However, it's worth remembering that debuggers are +/// not the only consumers of debug info, and some variations in DWARF might +/// better be treated as target/platform issues. Fundamentally, +/// o if the feature is useful (or not) to a particular debugger, regardless +/// of the target, that's a tuning decision; +/// o if the feature is useful (or not) on a particular platform, regardless +/// of the debugger, that's a target decision. +/// It's not impossible to see both factors in some specific case. +/// +/// The "tuning" should be used to set defaults for individual feature flags +/// in DwarfDebug; if a given feature has a more specific command-line option, +/// that option should take precedence over the tuning. +enum class DebuggerKind { + Default, // No specific tuning requested. + GDB, // Tune debug info for gdb. + LLDB, // Tune debug info for lldb. + SCE // Tune debug info for SCE targets (e.g. PS4). +}; + /// Collects and handles dwarf debug information. class DwarfDebug : public AsmPrinterHandler { /// Target of Dwarf emission. @@ -338,7 +362,6 @@ class DwarfDebug : public AsmPrinterHandler { /// True iff there are multiple CUs in this module. bool SingleCU; bool IsDarwin; - bool IsPS4; AddressPool AddrPool; @@ -349,6 +372,9 @@ class DwarfDebug : public AsmPrinterHandler { DenseMap FunctionDIs; + // Identify a debugger for "tuning" the debug info. + DebuggerKind DebuggerTuning; + MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &); const SmallVectorImpl> &getUnits() { @@ -565,6 +591,15 @@ public: /// standard DW_OP_form_tls_address opcode bool useGNUTLSOpcode() const { return UseGNUTLSOpcode; } + /// \defgroup DebuggerTuning Predicates to tune DWARF for a given debugger. + /// + /// Returns whether we are "tuning" for a given debugger. + /// @{ + bool tuneForGDB() const { return DebuggerTuning == DebuggerKind::GDB; } + bool tuneForLLDB() const { return DebuggerTuning == DebuggerKind::LLDB; } + bool tuneForSCE() const { return DebuggerTuning == DebuggerKind::SCE; } + /// @} + // Experimental DWARF5 features. /// Returns whether or not to emit tables that dwarf consumers can diff --git a/test/DebugInfo/X86/debugger-tune.ll b/test/DebugInfo/X86/debugger-tune.ll new file mode 100644 index 00000000000..7d862e31517 --- /dev/null +++ b/test/DebugInfo/X86/debugger-tune.ll @@ -0,0 +1,44 @@ +; Verify target-based defaults for "debugger tuning," and the ability to +; override defaults. +; We use existence of the debug_pubnames section to distinguish the GDB case, +; and the apple_names section to distinguish the LLDB case. SCE has neither. + +; Verify defaults for various targets. +; RUN: llc -mtriple=x86_64-scei-ps4 -filetype=obj < %s | llvm-readobj -sections - | FileCheck --check-prefix=SCE %s +; RUN: llc -mtriple=x86_64-apple-darwin12 -filetype=obj < %s | llvm-readobj -sections - | FileCheck --check-prefix=LLDB %s +; RUN: llc -mtriple=x86_64-pc-freebsd -filetype=obj < %s | llvm-readobj -sections - | FileCheck --check-prefix=LLDB %s +; RUN: llc -mtriple=x86_64-pc-linux -filetype=obj < %s | llvm-readobj -sections - | FileCheck --check-prefix=GDB %s + +; We can override defaults. +; RUN: llc -mtriple=x86_64-scei-ps4 -filetype=obj -debugger-tune=gdb < %s | llvm-readobj -sections - | FileCheck --check-prefix=GDB %s +; RUN: llc -mtriple=x86_64-pc-linux -filetype=obj -debugger-tune=lldb < %s | llvm-readobj -sections - | FileCheck --check-prefix=LLDB %s +; RUN: llc -mtriple=x86_64-apple-darwin12 -filetype=obj -debugger-tune=sce < %s | llvm-readobj -sections - | FileCheck --check-prefix=SCE %s + + +; GDB-NOT: apple_names +; GDB: debug_pubnames +; GDB-NOT: apple_names + +; LLDB-NOT: debug_pubnames +; LLDB: apple_names +; LLDB-NOT: debug_pubnames + +; SCE-NOT: debug_pubnames +; SCE-NOT: apple_names + + +@globalvar = global i32 0, align 4 + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 238808)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !2, globals: !3, imports: !2) +!1 = !DIFile(filename: "debugger-tune.cpp", directory: "/home/probinson/projects/scratch") +!2 = !{} +!3 = !{!4} +!4 = !DIGlobalVariable(name: "globalvar", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, variable: i32* @globalvar) +!5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"clang version 3.7.0 (trunk 238808)"} diff --git a/test/DebugInfo/X86/tls.ll b/test/DebugInfo/X86/tls.ll index 55930f0bacf..e54d925f68b 100644 --- a/test/DebugInfo/X86/tls.ll +++ b/test/DebugInfo/X86/tls.ll @@ -14,7 +14,7 @@ ; RUN: | FileCheck --check-prefix=DARWIN --check-prefix=STDOP %s ; RUN: llc %s -o - -filetype=asm -O0 -mtriple=x86_64-unknown-freebsd \ -; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-64 --check-prefix=GNUOP %s +; RUN: | FileCheck --check-prefix=SINGLE --check-prefix=SINGLE-64 --check-prefix=STDOP %s ; FIXME: add relocation and DWARF expression support to llvm-dwarfdump & use ; that here instead of raw assembly printing