diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -114,6 +114,9 @@ CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is ///< enabled. +CODEGENOPT(ForceDwarfUnwindInfo , 1, 0) ///< Set when -fforce-dwarf-unwind-info + ///< 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 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2986,6 +2986,9 @@ defm force_dwarf_frame : BoolFOption<"force-dwarf-frame", CodeGenOpts<"ForceDwarfFrameSection">, DefaultFalse, PosFlag, NegFlag>; +defm force_dwarf_unwind_info : BoolFOption<"force-dwarf-unwind-info", + CodeGenOpts<"ForceDwarfUnwindInfo">, DefaultFalse, + PosFlag, NegFlag>; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -136,6 +136,8 @@ bool getForceDwarfFrameSection(); +bool getForceDwarfUnwindInfo(); + bool getXRayOmitFunctionIndex(); bool getDebugStrictDwarf(); diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -199,6 +199,10 @@ /// Generate dwarf debugging info for assembly source files. bool GenDwarfForAssembly = false; + /// Always generate dwarf unwind info even if a compact unwind entry is + /// available. + bool GenDwarfUnwindInfo = false; + /// The current dwarf file number when generate dwarf debugging info for /// assembly source files. unsigned GenDwarfFileNumber = 0; @@ -765,6 +769,8 @@ bool getGenDwarfForAssembly() { return GenDwarfForAssembly; } void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; } + bool getGenDwarfUnwindInfo() { return GenDwarfUnwindInfo; } + void setGenDwarfUnwindInfo(bool Value) { GenDwarfUnwindInfo = Value; } unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; } void setGenDwarfFileNumber(unsigned FileNumber) { diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -142,8 +142,9 @@ EmitAddrsig(false), EmitCallSiteInfo(false), SupportsDebugEntryValues(false), EnableDebugEntryValues(false), ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false), - XRayOmitFunctionIndex(false), DebugStrictDwarf(false), - Hotpatch(false), PPCGenScalarMASSEntries(false), JMCInstrument(false), + ForceDwarfUnwindInfo(false), XRayOmitFunctionIndex(false), + DebugStrictDwarf(false), Hotpatch(false), + PPCGenScalarMASSEntries(false), JMCInstrument(false), EnableCFIFixup(false), FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {} @@ -341,6 +342,9 @@ /// Emit DWARF debug frame section. unsigned ForceDwarfFrameSection : 1; + /// Emit DWARF unwind info (EH frames) for all functions. + unsigned ForceDwarfUnwindInfo : 1; + /// Emit XRay Function Index section unsigned XRayOmitFunctionIndex : 1; diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -98,6 +98,7 @@ CGOPT(bool, EnableMachineFunctionSplitter) CGOPT(bool, EnableDebugEntryValues) CGOPT(bool, ForceDwarfFrameSection) +CGOPT(bool, ForceDwarfUnwindInfo) CGOPT(bool, XRayOmitFunctionIndex) CGOPT(bool, DebugStrictDwarf) CGOPT(unsigned, AlignLoops) @@ -464,6 +465,11 @@ cl::desc("Always emit a debug frame section."), cl::init(false)); CGBINDOPT(ForceDwarfFrameSection); + static cl::opt ForceDwarfUnwindInfo( + "force-dwarf-unwind-info", + cl::desc("Always emit a DWARF EH frame section."), cl::init(false)); + CGBINDOPT(ForceDwarfUnwindInfo); + static cl::opt XRayOmitFunctionIndex( "no-xray-index", cl::desc("Don't emit xray_fn_idx section"), cl::init(false)); @@ -556,6 +562,7 @@ Options.EmitCallSiteInfo = getEmitCallSiteInfo(); Options.EnableDebugEntryValues = getEnableDebugEntryValues(); Options.ForceDwarfFrameSection = getForceDwarfFrameSection(); + Options.ForceDwarfUnwindInfo = getForceDwarfUnwindInfo(); Options.XRayOmitFunctionIndex = getXRayOmitFunctionIndex(); Options.DebugStrictDwarf = getDebugStrictDwarf(); Options.LoopAlignment = getAlignLoops(); diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -251,6 +251,9 @@ "Cannot emit MC with limited codegen pipeline"); Ctx = &MMIWP->getMMI().getContext(); + // libunwind is unable to load compact unwind dynamically, so we must generate + // DWARF unwind info for the JIT. + Ctx->setGenDwarfUnwindInfo(true); if (Options.MCOptions.MCSaveTempLabels) Ctx->setAllowTemporaryLabels(false); diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DynamicLibrary.h" diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp --- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp @@ -12,6 +12,7 @@ #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -95,18 +95,16 @@ // and projects/libunwind/src/UnwindLevel1-gcc-ext.c. const char *P = (const char *)Addr; const char *End = P + Size; - do { + while (P != End) P = processFDE(P, false); - } while(P != End); } void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr, size_t Size) { const char *P = (const char *)Addr; const char *End = P + Size; - do { + while (P != End) P = processFDE(P, true); - } while(P != End); } #else diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1834,8 +1834,6 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, bool IsEH) { - Streamer.generateCompactUnwindEncodings(MAB); - MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); const MCAsmInfo *AsmInfo = Context.getAsmInfo(); @@ -1845,6 +1843,7 @@ // Emit the compact unwind info if available. bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); if (IsEH && MOFI->getCompactUnwindSection()) { + Streamer.generateCompactUnwindEncodings(MAB); bool SectionEmitted = false; for (const MCDwarfFrameInfo &Frame : FrameArray) { if (Frame.CompactUnwindEncoding == 0) continue; diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -63,8 +63,7 @@ (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32)) SupportsCompactUnwindWithoutEHFrame = true; - if (T.isWatchABI()) - OmitDwarfIfHaveCompactUnwind = true; + OmitDwarfIfHaveCompactUnwind = !Ctx->getGenDwarfUnwindInfo(); FDECFIEncoding = dwarf::DW_EH_PE_pcrel; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1377,7 +1377,7 @@ default: // Any other CFI directives indicate a frame that we aren't prepared // to represent via compact unwind, so just bail out. - return 0; + return CU::UNWIND_MODE_DWARF; case MCCFIInstruction::OpDefCfaRegister: { // Defines a frame pointer. E.g. // @@ -1391,7 +1391,7 @@ // generate a compact unwinding representation, so bail out. if (*MRI.getLLVMRegNum(Inst.getRegister(), true) != (Is64Bit ? X86::RBP : X86::EBP)) - return 0; + return CU::UNWIND_MODE_DWARF; // Reset the counts. memset(SavedRegs, 0, sizeof(SavedRegs)); diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s b/llvm/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s --- a/llvm/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s +++ b/llvm/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s @@ -1,5 +1,5 @@ # RUN: rm -rf %t && mkdir -p %t -# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/test_x86-64.o %s +# RUN: llvm-mc --generate-dwarf-unwind-info -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/test_x86-64.o %s # RUN: llvm-rtdyld -triple=x86_64-apple-macosx10.9 -dummy-extern ds1=0xfffffffffffffffe -dummy-extern ds2=0xffffffffffffffff -verify -check=%s %t/test_x86-64.o .section __TEXT,__text,regular,pure_instructions diff --git a/llvm/test/MC/ELF/cfi-version.ll b/llvm/test/MC/ELF/cfi-version.ll --- a/llvm/test/MC/ELF/cfi-version.ll +++ b/llvm/test/MC/ELF/cfi-version.ll @@ -1,7 +1,7 @@ -; RUN: %llc_dwarf %s -o - -dwarf-version 2 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF2 -; RUN: %llc_dwarf %s -o - -dwarf-version 3 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF3 -; RUN: %llc_dwarf %s -o - -dwarf-version 4 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF4 -; RUN: %llc_dwarf %s -o - -dwarf-version 5 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF4 +; RUN: %llc_dwarf --force-dwarf-unwind-info %s -o - -dwarf-version 2 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF2 +; RUN: %llc_dwarf --force-dwarf-unwind-info %s -o - -dwarf-version 3 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF3 +; RUN: %llc_dwarf --force-dwarf-unwind-info %s -o - -dwarf-version 4 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF4 +; RUN: %llc_dwarf --force-dwarf-unwind-info %s -o - -dwarf-version 5 -filetype=obj | llvm-dwarfdump -v - | FileCheck %s --check-prefix=DWARF4 ; PR46647 ; XFAIL: arm64-apple diff --git a/llvm/test/MC/MachO/gen-dwarf64.s b/llvm/test/MC/MachO/gen-dwarf64.s --- a/llvm/test/MC/MachO/gen-dwarf64.s +++ b/llvm/test/MC/MachO/gen-dwarf64.s @@ -1,6 +1,6 @@ // This checks that llvm-mc is able to produce 64-bit debug info. -// RUN: llvm-mc -g -dwarf64 -triple x86_64-apple-darwin10 %s -filetype=obj -o %t +// RUN: llvm-mc -g --generate-dwarf-unwind-info -dwarf64 -triple x86_64-apple-darwin10 %s -filetype=obj -o %t // RUN: llvm-dwarfdump -v %t | FileCheck %s // CHECK: .debug_info contents: diff --git a/llvm/test/MC/X86/compact-unwind-mode-dwarf.s b/llvm/test/MC/X86/compact-unwind-mode-dwarf.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/compact-unwind-mode-dwarf.s @@ -0,0 +1,50 @@ +// RUN: llvm-mc -triple x86_64-apple-macos10.6 -filetype=obj %s -o %t.o +// RUN: llvm-objdump --macho --unwind-info --dwarf=frames %t.o | FileCheck %s + +/// For functions whose unwind info cannot be encoded with compact unwind, make +/// sure that we encode them using DWARF unwind, and make sure we emit a compact +/// unwind entry that indicates that a DWARF encoding is being used. + +_f: + .cfi_startproc + ## This encodes DW_CFA_GNU_args_size which cannot be expressed using compact + ## unwind, so we must use DWARF unwind instead. + .cfi_escape 0x2e, 0x10 + ret + .cfi_endproc + +_g: + .cfi_startproc + ## This encodes DW_CFA_GNU_args_size which cannot be expressed using compact + ## unwind, so we must use DWARF unwind instead. + .cfi_escape 0x2e, 0x10 + ret + .cfi_endproc + +// CHECK: Contents of __compact_unwind section: +// CHECK: Entry at offset 0x0: +// CHECK: start: 0x[[#%x,F:]] _f +// CHECK: length: 0x1 +// CHECK: compact encoding: 0x04000000 +// CHECK: Entry at offset 0x20: +// CHECK: start: 0x[[#%x,G:]] _g +// CHECK: length: 0x1 +// CHECK: compact encoding: 0x04000000 + +// CHECK: .eh_frame contents: +// CHECK: 00000000 00000014 00000000 CIE +// CHECK: Format: DWARF32 +// CHECK: Version: 1 +// CHECK: Augmentation: "zR" +// CHECK: Code alignment factor: 1 +// CHECK: Data alignment factor: -8 +// CHECK: Return address column: 16 +// CHECK: Augmentation data: 10 + +// CHECK: FDE cie=00000000 pc=[[#%.8x,F]]... +// CHECK: Format: DWARF32 +// CHECK: DW_CFA_GNU_args_size: +16 + +// CHECK: FDE cie=00000000 pc=[[#%.8x,G]]... +// CHECK: Format: DWARF32 +// CHECK: DW_CFA_GNU_args_size: +16 diff --git a/llvm/test/MC/X86/i386-darwin-frame-register.ll b/llvm/test/MC/X86/i386-darwin-frame-register.ll --- a/llvm/test/MC/X86/i386-darwin-frame-register.ll +++ b/llvm/test/MC/X86/i386-darwin-frame-register.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump -debug-frame - | FileCheck %s +; RUN: llc --force-dwarf-unwind-info -filetype=obj %s -o - | llvm-dwarfdump -debug-frame - | FileCheck %s ; IR reduced from a dummy: ; void foo() {} diff --git a/llvm/test/tools/dsymutil/X86/frame-1.test b/llvm/test/tools/dsymutil/X86/frame-1.test --- a/llvm/test/tools/dsymutil/X86/frame-1.test +++ b/llvm/test/tools/dsymutil/X86/frame-1.test @@ -1,6 +1,6 @@ # RUN: rm -rf %t # RUN: mkdir -p %t -# RUN: llc -filetype=obj %p/../Inputs/frame-dw2.ll -o %t/frame-dw2.o +# RUN: llc --force-dwarf-unwind-info -filetype=obj %p/../Inputs/frame-dw2.ll -o %t/frame-dw2.o # RUN: dsymutil -f -oso-prepend-path=%t -y %s -o - | llvm-dwarfdump -debug-frame - | FileCheck %s # This test is meant to verify that identical CIEs will get reused diff --git a/llvm/test/tools/dsymutil/X86/frame-2.test b/llvm/test/tools/dsymutil/X86/frame-2.test --- a/llvm/test/tools/dsymutil/X86/frame-2.test +++ b/llvm/test/tools/dsymutil/X86/frame-2.test @@ -1,7 +1,7 @@ # RUN: rm -rf %t # RUN: mkdir -p %t -# RUN: llc -filetype=obj %p/../Inputs/frame-dw2.ll -o %t/frame-dw2.o -# RUN: llc -filetype=obj %p/../Inputs/frame-dw4.ll -o %t/frame-dw4.o +# RUN: llc --force-dwarf-unwind-info -filetype=obj %p/../Inputs/frame-dw2.ll -o %t/frame-dw2.o +# RUN: llc --force-dwarf-unwind-info -filetype=obj %p/../Inputs/frame-dw4.ll -o %t/frame-dw4.o # RUN: dsymutil -f -oso-prepend-path=%t -y %s -o - | llvm-dwarfdump -debug-frame - | FileCheck %s # Check the handling of multiple different CIEs. To have CIEs that diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test @@ -1,4 +1,4 @@ -RUN: llc -filetype=obj %p/../../dsymutil/Inputs/frame-dw2.ll -o - \ +RUN: llc --force-dwarf-unwind-info -filetype=obj %p/../../dsymutil/Inputs/frame-dw2.ll -o - \ RUN: | llvm-dwarfdump -debug-frame=0x00000014 - | FileCheck %s CHECK: .debug_frame contents: CHECK-NEXT: 00000014 00000014 00000000 FDE cie=00000000 pc=00000000...0000001d diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -694,9 +694,10 @@ codegen::getFileType(), NoVerify, MMIWP)) { reportError("target does not support generation of this file type"); } - + auto &Ctx = MMIWP->getMMI().getContext(); + Ctx.setGenDwarfUnwindInfo(Target->Options.ForceDwarfUnwindInfo); const_cast(LLVMTM.getObjFileLowering()) - ->Initialize(MMIWP->getMMI().getContext(), *Target); + ->Initialize(Ctx, *Target); if (MIR) { assert(MMIWP && "Forgot to create MMIWP?"); if (MIR->parseMachineFunctions(*M, MMIWP->getMMI())) diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -176,6 +176,12 @@ "source files"), cl::cat(MCCategory)); +static cl::opt + GenDwarfUnwindInfo("generate-dwarf-unwind-info", + cl::desc("Generate dwarf unwind info regardless of " + "whether compact unwind also generated"), + cl::cat(MCCategory)); + static cl::opt DebugCompilationDir("fdebug-compilation-dir", cl::desc("Specifies the debug info's compilation dir"), @@ -429,6 +435,7 @@ // MCObjectFileInfo needs a MCContext reference in order to initialize itself. MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, &MCOptions); + Ctx.setGenDwarfUnwindInfo(GenDwarfUnwindInfo); std::unique_ptr MOFI( TheTarget->createMCObjectFileInfo(Ctx, PIC, LargeCodeModel)); Ctx.setObjectFileInfo(MOFI.get());