From 92aa0c2dbcb723d102c508f6e7559330b637f912 Mon Sep 17 00:00:00 2001 From: David Candler Date: Thu, 31 Oct 2019 08:55:57 +0000 Subject: [PATCH] [cfi] Add flag to always generate .debug_frame This adds a flag to LLVM and clang to always generate a .debug_frame section, even if other debug information is not being generated. In situations where .eh_frame would normally be emitted, both .debug_frame and .eh_frame will be used. Differential Revision: https://reviews.llvm.org/D67216 --- clang/include/clang/Basic/CodeGenOptions.def | 2 ++ clang/include/clang/Driver/Options.td | 4 +++ clang/lib/CodeGen/BackendUtil.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 4 +++ clang/lib/Frontend/CompilerInvocation.cpp | 3 ++ clang/test/Driver/fforce-dwarf-frame.c | 6 ++++ llvm/include/llvm/CodeGen/CommandFlags.inc | 6 ++++ llvm/include/llvm/CodeGen/MachineFunction.h | 3 ++ llvm/include/llvm/Target/TargetOptions.h | 5 ++- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 3 ++ llvm/lib/CodeGen/CFIInstrInserter.cpp | 3 +- llvm/lib/CodeGen/MachineFunction.cpp | 7 +++++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp | 4 +-- llvm/lib/Target/ARC/ARCRegisterInfo.cpp | 2 +- llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp | 3 +- llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 3 +- llvm/lib/Target/X86/X86FrameLowering.cpp | 14 +++------ llvm/lib/Target/X86/X86InstrInfo.cpp | 4 +-- llvm/lib/Target/XCore/XCoreRegisterInfo.cpp | 2 +- llvm/test/CodeGen/ARM/dwarf-frame.ll | 38 +++++++++++++++++++++++ 21 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 clang/test/Driver/fforce-dwarf-frame.c create mode 100644 llvm/test/CodeGen/ARM/dwarf-frame.ll diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index f8d94e3..0a47869 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -97,6 +97,8 @@ CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled. +CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is + ///< enabled. ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 2401a31..07c27eb 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1950,6 +1950,10 @@ def fdebug_prefix_map_EQ : Joined<["-"], "fdebug-prefix-map=">, Group, Flags<[CC1Option,CC1AsOption]>, HelpText<"remap file source paths in debug info">; +def fforce_dwarf_frame : Flag<["-"], "fforce-dwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Always emit a debug frame section">; +def fno_force_dwarf_frame : Flag<["-"], "fno-force-dwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Don't always emit a debug frame section">; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 75a54d8..c15dc0b 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -485,6 +485,7 @@ static void initTargetOptions(llvm::TargetOptions &Options, Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; Options.EmitAddrsig = CodeGenOpts.Addrsig; Options.EnableDebugEntryValues = CodeGenOpts.EnableDebugEntryValues; + Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection; Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c60dc76..81e01ae 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3339,6 +3339,10 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-generate-arange-section"); } + if (Args.hasFlag(options::OPT_fforce_dwarf_frame, + options::OPT_fno_force_dwarf_frame, false)) + CmdArgs.push_back("-fforce-dwarf-frame"); + if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { if (!T.isOSBinFormatELF()) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f197a67..0775d10 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -769,6 +769,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); Opts.EmbedSource = Args.hasArg(OPT_gembed_source); + Opts.ForceDwarfFrameSection = + Args.hasFlag(OPT_fforce_dwarf_frame, OPT_fno_force_dwarf_frame, false); + for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); diff --git a/clang/test/Driver/fforce-dwarf-frame.c b/clang/test/Driver/fforce-dwarf-frame.c new file mode 100644 index 0000000..fb5442c --- /dev/null +++ b/clang/test/Driver/fforce-dwarf-frame.c @@ -0,0 +1,6 @@ +// RUN: %clang -target arm -c -### %s -fforce-dwarf-frame 2>&1 | FileCheck --check-prefix=CHECK-ALWAYS %s +// RUN: %clang -target arm -c -### %s -fno-force-dwarf-frame 2>&1 | FileCheck --check-prefix=CHECK-NO-ALWAYS %s +// RUN: %clang -target arm -c -### %s 2>&1 | FileCheck --check-prefix=CHECK-NO-ALWAYS %s + +// CHECK-ALWAYS: -fforce-dwarf-frame +// CHECK-NO-ALWAYS-NOT: -fforce-dwarf-frame diff --git a/llvm/include/llvm/CodeGen/CommandFlags.inc b/llvm/include/llvm/CodeGen/CommandFlags.inc index cb69e9f..16b7028 100644 --- a/llvm/include/llvm/CodeGen/CommandFlags.inc +++ b/llvm/include/llvm/CodeGen/CommandFlags.inc @@ -276,6 +276,11 @@ static cl::opt cl::desc("Emit debug info about parameter's entry values"), cl::init(false)); +static cl::opt + ForceDwarfFrameSection("force-dwarf-frame-section", + cl::desc("Always emit a debug frame section."), + cl::init(false)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -306,6 +311,7 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.EmitStackSizeSection = EnableStackSizeSection; Options.EmitAddrsig = EnableAddrsig; Options.EnableDebugEntryValues = EnableDebugEntryValues; + Options.ForceDwarfFrameSection = ForceDwarfFrameSection; Options.MCOptions = InitMCTargetOptionsFromFlags(); diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index c67fd27..c5a6a6e 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -560,6 +560,9 @@ public: } void setHasWinCFI(bool v) { HasWinCFI = v; } + /// True if this function needs frame moves for debug or exceptions. + bool needsFrameMoves() const; + /// Get the function properties const MachineFunctionProperties &getProperties() const { return Properties; } MachineFunctionProperties &getProperties() { return Properties; } diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h index 8cc2a60..c395e5b 100644 --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -119,7 +119,7 @@ namespace llvm { ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), SupportsDefaultOutlining(false), EmitAddrsig(false), - EnableDebugEntryValues(false) {} + EnableDebugEntryValues(false), ForceDwarfFrameSection(false) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -256,6 +256,9 @@ namespace llvm { /// Emit debug info about parameter's entry values. unsigned EnableDebugEntryValues : 1; + /// Emit DWARF debug frame section. + unsigned ForceDwarfFrameSection : 1; + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 6bff8de..4cd3031 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -935,7 +935,7 @@ AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { MF->getFunction().needsUnwindTableEntry()) return CFI_M_EH; - if (MMI->hasDebugInfo()) + if (MMI->hasDebugInfo() || MF->getTarget().Options.ForceDwarfFrameSection) return CFI_M_Debug; return CFI_M_None; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 207a728..facbf22 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -133,6 +134,8 @@ void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, if (!hasEmittedCFISections) { if (Asm->needsOnlyDebugCFIMoves()) Asm->OutStreamer->EmitCFISections(false, true); + else if (Asm->TM.Options.ForceDwarfFrameSection) + Asm->OutStreamer->EmitCFISections(true, true); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp index 1a4d542..3129894 100644 --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -48,8 +48,7 @@ class CFIInstrInserter : public MachineFunctionPass { } bool runOnMachineFunction(MachineFunction &MF) override { - if (!MF.getMMI().hasDebugInfo() && - !MF.getFunction().needsUnwindTableEntry()) + if (!MF.needsFrameMoves()) return false; MBBVector.resize(MF.getNumBlockIDs()); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index d75e77d..115aad3 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -520,6 +520,13 @@ void MachineFunction::print(raw_ostream &OS, const SlotIndexes *Indexes) const { OS << "\n# End machine code for function " << getName() << ".\n\n"; } +/// True if this function needs frame moves for debug or exceptions. +bool MachineFunction::needsFrameMoves() const { + return getMMI().hasDebugInfo() || + getTarget().Options.ForceDwarfFrameSection || + F.needsUnwindTableEntry(); +} + namespace llvm { template<> diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 042d8fd..bbd7c51 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -844,8 +844,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineModuleInfo &MMI = MF.getMMI(); AArch64FunctionInfo *AFI = MF.getInfo(); - bool needsFrameMoves = (MMI.hasDebugInfo() || F.needsUnwindTableEntry()) && - !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); + bool needsFrameMoves = + MF.needsFrameMoves() && !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); bool HasFP = hasFP(MF); bool NeedsWinCFI = needsWinCFI(MF); bool HasWinCFI = false; diff --git a/llvm/lib/Target/ARC/ARCRegisterInfo.cpp b/llvm/lib/Target/ARC/ARCRegisterInfo.cpp index a7f89b3..490f089 100644 --- a/llvm/lib/Target/ARC/ARCRegisterInfo.cpp +++ b/llvm/lib/Target/ARC/ARCRegisterInfo.cpp @@ -128,7 +128,7 @@ static void ReplaceFrameIndex(MachineBasicBlock::iterator II, ARCRegisterInfo::ARCRegisterInfo() : ARCGenRegisterInfo(ARC::BLINK) {} bool ARCRegisterInfo::needsFrameMoves(const MachineFunction &MF) { - return MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry(); + return MF.needsFrameMoves(); } const MCPhysReg * diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp index bfa3372..dc114d0 100644 --- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -223,8 +223,7 @@ namespace { bool HexagonCallFrameInformation::runOnMachineFunction(MachineFunction &MF) { auto &HFI = *MF.getSubtarget().getFrameLowering(); - bool NeedCFI = MF.getMMI().hasDebugInfo() || - MF.getFunction().needsUnwindTableEntry(); + bool NeedCFI = MF.needsFrameMoves(); if (!NeedCFI) return false; diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index 06a4d18..b62c2fe 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -782,8 +782,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF, MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); DebugLoc dl; - bool needsCFI = MMI.hasDebugInfo() || - MF.getFunction().needsUnwindTableEntry(); + bool needsCFI = MF.needsFrameMoves(); // Get processor type. bool isPPC64 = Subtarget.isPPC64(); diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 1b469a81..0d4db14 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -993,8 +993,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, bool NeedsWinFPO = !IsFunclet && STI.isTargetWin32() && MMI.getModule()->getCodeViewFlag(); bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO; - bool NeedsDwarfCFI = - !IsWin64Prologue && (MMI.hasDebugInfo() || Fn.needsUnwindTableEntry()); + bool NeedsDwarfCFI = !IsWin64Prologue && MF.needsFrameMoves(); Register FramePtr = TRI->getFrameRegister(MF); const Register MachineFramePtr = STI.isTarget64BitILP32() @@ -1614,10 +1613,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, bool HasFP = hasFP(MF); uint64_t NumBytes = 0; - bool NeedsDwarfCFI = - (!MF.getTarget().getTargetTriple().isOSDarwin() && - !MF.getTarget().getTargetTriple().isOSWindows()) && - (MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry()); + bool NeedsDwarfCFI = (!MF.getTarget().getTargetTriple().isOSDarwin() && + !MF.getTarget().getTargetTriple().isOSWindows()) && + MF.needsFrameMoves(); if (IsFunclet) { assert(HasFP && "EH funclets without FP not yet implemented"); @@ -2812,11 +2810,9 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned StackAlign = getStackAlignment(); Amount = alignTo(Amount, StackAlign); - MachineModuleInfo &MMI = MF.getMMI(); const Function &F = MF.getFunction(); bool WindowsCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool DwarfCFI = !WindowsCFI && - (MMI.hasDebugInfo() || F.needsUnwindTableEntry()); + bool DwarfCFI = !WindowsCFI && MF.needsFrameMoves(); // If we have any exception handlers in this function, and we adjust // the SP before calls, we may need to indicate this to the unwinder diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 8e491c5..8fdcf1e 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -3963,9 +3963,7 @@ static bool ExpandMOVImmSExti8(MachineInstrBuilder &MIB, MachineFunction &MF = *MBB.getParent(); const X86FrameLowering *TFL = Subtarget.getFrameLowering(); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool NeedsDwarfCFI = - !IsWin64Prologue && - (MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry()); + bool NeedsDwarfCFI = !IsWin64Prologue && MF.needsFrameMoves(); bool EmitCFI = !TFL->hasFP(MF) && NeedsDwarfCFI; if (EmitCFI) { TFL->BuildCFI(MBB, I, DL, diff --git a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp b/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp index 86ec7f8..56fed26 100644 --- a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -203,7 +203,7 @@ static void InsertSPConstInst(MachineBasicBlock::iterator II, } bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { - return MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry(); + return MF.needsFrameMoves(); } const MCPhysReg * diff --git a/llvm/test/CodeGen/ARM/dwarf-frame.ll b/llvm/test/CodeGen/ARM/dwarf-frame.ll new file mode 100644 index 0000000..a15c9c5 --- /dev/null +++ b/llvm/test/CodeGen/ARM/dwarf-frame.ll @@ -0,0 +1,38 @@ +; RUN: llc -mtriple armv7-unknown -frame-pointer=all -filetype=asm -o - %s | FileCheck %s --check-prefix=CHECK-NO-CFI +; RUN: llc -mtriple armv7-unknown -frame-pointer=all -filetype=asm -force-dwarf-frame-section -o - %s | FileCheck %s --check-prefix=CHECK-ALWAYS-CFI + +declare void @dummy_use(i32*, i32) + +define void @test_basic() #0 { + %mem = alloca i32, i32 10 + call void @dummy_use (i32* %mem, i32 10) + ret void +} + +; CHECK-NO-CFI-LABEL: test_basic: +; CHECK-NO-CFI: .fnstart +; CHECK-NO-CFI-NOT: .cfi_sections .debug_frame +; CHECK-NO-CFI-NOT: .cfi_startproc +; CHECK-NO-CFI: @ %bb.0: +; CHECK-NO-CFI: push {r11, lr} +; CHECK-NO-CFI-NOT: .cfi_def_cfa_offset 8 +; CHECK-NO-CFI-NOT: .cfi_offset lr, -4 +; CHECK-NO-CFI-NOT: .cfi_offset r11, -8 +; CHECK-NO-CFI: mov r11, sp +; CHECK-NO-CFI-NOT: .cfi_def_cfa_register r11 +; CHECK-NO-CFI-NOT: .cfi_endproc +; CHECK-NO-CFI: .fnend + +; CHECK-ALWAYS-CFI-LABEL: test_basic: +; CHECK-ALWAYS-CFI: .fnstart +; CHECK-ALWAYS-CFI: .cfi_sections .debug_frame +; CHECK-ALWAYS-CFI: .cfi_startproc +; CHECK-ALWAYS-CFI: @ %bb.0: +; CHECK-ALWAYS-CFI: push {r11, lr} +; CHECK-ALWAYS-CFI: .cfi_def_cfa_offset 8 +; CHECK-ALWAYS-CFI: .cfi_offset lr, -4 +; CHECK-ALWAYS-CFI: .cfi_offset r11, -8 +; CHECK-ALWAYS-CFI: mov r11, sp +; CHECK-ALWAYS-CFI: .cfi_def_cfa_register r11 +; CHECK-ALWAYS-CFI: .cfi_endproc +; CHECK-ALWAYS-CFI: .fnend -- 2.7.4