llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-x86 Author: Daniel Paoliello (dpaoliello) <details> <summary>Changes</summary> Adds a new Clang and CC1 flag to control the Control Flow Guard mechanism on Windows: `-fwin-cfg-mechanism`. This can be set to `automatic` (use the targat arch default), `force-dispatch` or `force-check`. Also adds the support for the equivalent MSVC flag `/d2guardcfgdispatch`. NOTE: Arm64EC only supports the check mechanism. It should be noted that MSVC emits the "dispatch" name for the call checker (for legacy reasons) but uses the check mechanism. --- Patch is 30.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/176276.diff 23 Files Affected: - (modified) clang/include/clang/Basic/CodeGenOptions.def (+4) - (modified) clang/include/clang/Basic/CodeGenOptions.h (+1) - (modified) clang/include/clang/Options/Options.td (+12) - (modified) clang/lib/CodeGen/CodeGenModule.cpp (+13-2) - (modified) clang/lib/Driver/ToolChains/Clang.cpp (+9) - (added) clang/test/CodeGen/cfguard-mechanism.c (+11) - (modified) clang/test/Driver/cl-options.c (+6) - (modified) llvm/include/llvm/IR/Module.h (+3) - (modified) llvm/include/llvm/Support/CodeGen.h (+17) - (modified) llvm/include/llvm/Transforms/CFGuard.h (+2-5) - (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+2-2) - (modified) llvm/lib/CodeGen/CFGuardLongjmp.cpp (+2-1) - (modified) llvm/lib/IR/Module.cpp (+7) - (modified) llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp (+4-5) - (modified) llvm/lib/Target/AArch64/AArch64TargetMachine.cpp (+1-1) - (modified) llvm/lib/Target/ARM/ARMTargetMachine.cpp (+1-1) - (modified) llvm/lib/Target/X86/X86CallingConv.td (+3-1) - (modified) llvm/lib/Target/X86/X86RegisterInfo.cpp (+7-3) - (modified) llvm/lib/Target/X86/X86TargetMachine.cpp (+1-5) - (modified) llvm/lib/Transforms/CFGuard/CFGuard.cpp (+32-31) - (modified) llvm/test/CodeGen/AArch64/cfguard-module-flag.ll (+26-10) - (modified) llvm/test/CodeGen/ARM/cfguard-module-flag.ll (+26-10) - (modified) llvm/test/CodeGen/X86/cfguard-module-flag.ll (+32-11) ``````````diff diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index baf8b093c10e6..3dad7dd1d551f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -505,6 +505,10 @@ CODEGENOPT(AllResourcesBound, 1, 0, Benign) ENUM_CODEGENOPT(WinX64EHUnwindV2, WinX64EHUnwindV2Mode, 2, WinX64EHUnwindV2Mode::Disabled, Benign) +/// Controls the mechanism used for Control Flow Guard (CFG) on Windows. +ENUM_CODEGENOPT(WinControlFlowGuardMechanism, ControlFlowGuardMechanism, + 2, ControlFlowGuardMechanism::Automatic, Benign) + /// FIXME: Make DebugOptions its own top-level .def file. #include "DebugOptions.def" diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index c60ca507ff917..365dd4fe2eac3 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -66,6 +66,7 @@ class CodeGenOptionsBase { using VectorLibrary = llvm::driver::VectorLibrary; using ZeroCallUsedRegsKind = llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind; using WinX64EHUnwindV2Mode = llvm::WinX64EHUnwindV2Mode; + using ControlFlowGuardMechanism = llvm::ControlFlowGuardMechanism; using DebugCompressionType = llvm::DebugCompressionType; using EmitDwarfUnwindType = llvm::EmitDwarfUnwindType; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index d4dd71b9d1bea..b74cac8cb44f8 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2257,6 +2257,14 @@ def winx64_eh_unwindv2 NormalizedValues<["Disabled", "BestEffort", "Required"]>, NormalizedValuesScope<"llvm::WinX64EHUnwindV2Mode">, MarshallingInfoEnum<CodeGenOpts<"WinX64EHUnwindV2">, "Disabled">; +def win_cfg_mechanism + : Joined<["-"], "fwin-cfg-mechanism=">, Group<f_Group>, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Sets the mechanism to use for Control Flow Guard on Windows">, + Values<"automatic,force-dispatch,force-check">, + NormalizedValues<["Automatic", "ForceDispatch", "ForceCheck"]>, + NormalizedValuesScope<"llvm::ControlFlowGuardMechanism">, + MarshallingInfoEnum<CodeGenOpts<"WinControlFlowGuardMechanism">, "Automatic">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group<f_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -9382,6 +9390,10 @@ def _SLASH_d2epilogunwind : CLFlag<"d2epilogunwind">, HelpText<"Best effort generate unwind v2 (epilog) information for x64 Windows">; def _SLASH_d2epilogunwindrequirev2 : CLFlag<"d2epilogunwindrequirev2">, HelpText<"Require generation of unwind v2 (epilog) information for x64 Windows">; +def _SLASH_d2guardcfgdispatch : CLFlag<"d2guardcfgdispatch">, + HelpText<"Force Control Flow Guard to use the dispatch pattern">; +def _SLASH_d2guardcfgdispatch_ : CLFlag<"d2guardcfgdispatch-">, + HelpText<"Force Control Flow Guard to use the check pattern">; def _SLASH_EH : CLJoined<"EH">, HelpText<"Set exception handling model">; def _SLASH_EP : CLFlag<"EP">, HelpText<"Disable linemarker output and preprocess to stdout">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 614bca627e03c..99242afd1c2b8 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1123,10 +1123,21 @@ void CodeGenModule::Release() { } if (CodeGenOpts.ControlFlowGuard) { // Function ID tables and checks for Control Flow Guard (cfguard=2). - getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 2); + getModule().addModuleFlag( + llvm::Module::Warning, "cfguard", + static_cast<unsigned>(llvm::ControlFlowGuardMode::Enabled)); } else if (CodeGenOpts.ControlFlowGuardNoChecks) { // Function ID tables for Control Flow Guard (cfguard=1). - getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1); + getModule().addModuleFlag( + llvm::Module::Warning, "cfguard", + static_cast<unsigned>(llvm::ControlFlowGuardMode::TableOnly)); + } + if (CodeGenOpts.getWinControlFlowGuardMechanism() != + llvm::ControlFlowGuardMechanism::Automatic) { + // Specify the Control Flow Guard mechanism to use on Windows. + getModule().addModuleFlag( + llvm::Module::Warning, "cfguard-mechanism", + static_cast<unsigned>(CodeGenOpts.getWinControlFlowGuardMechanism())); } if (CodeGenOpts.EHContGuard) { // Function ID tables for EH Continuation Guard. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4ca98600d6e93..706910d4bc02c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7393,6 +7393,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Unwind v2 (epilog) information for x64 Windows. Args.AddLastArg(CmdArgs, options::OPT_winx64_eh_unwindv2); + // Control Flow Guard mechanism for Windows. + Args.AddLastArg(CmdArgs, options::OPT_win_cfg_mechanism); + // C++ "sane" operator new. Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new); @@ -8522,6 +8525,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, A->claim(); } + // Unwind v2 (epilog) information for x64 Windows. + if (Args.hasArg(options::OPT__SLASH_d2guardcfgdispatch_)) + CmdArgs.push_back("-fwin-cfg-mechanism=force-check"); + else if (Args.hasArg(options::OPT__SLASH_d2guardcfgdispatch)) + CmdArgs.push_back("-fwin-cfg-mechanism=force-dispatch"); + for (const auto &FuncOverride : Args.getAllArgValues(options::OPT__SLASH_funcoverride)) { CmdArgs.push_back(Args.MakeArgString( diff --git a/clang/test/CodeGen/cfguard-mechanism.c b/clang/test/CodeGen/cfguard-mechanism.c new file mode 100644 index 0000000000000..c6db8ff5135b1 --- /dev/null +++ b/clang/test/CodeGen/cfguard-mechanism.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix=AUTOMATIC +// RUN: %clang_cc1 -fwin-cfg-mechanism=automatic -emit-llvm %s -o - | FileCheck %s -check-prefix=AUTOMATIC +// RUN: %clang_cc1 -fwin-cfg-mechanism=force-dispatch -emit-llvm %s -o - | FileCheck %s -check-prefix=FORCEDISPATCH +// RUN: %clang_cc1 -fwin-cfg-mechanism=force-check -emit-llvm %s -o - | FileCheck %s -check-prefix=FORCECHECK +// RUN: %clang -fwin-cfg-mechanism=force-dispatch -S -emit-llvm %s -o - | FileCheck %s -check-prefix=FORCEDISPATCH + +void f(void) {} + +// FORCECHECK: !"cfguard-mechanism", i32 1} +// FORCEDISPATCH: !"cfguard-mechanism", i32 2} +// AUTOMATIC-NOT: "cfguard-mechanism" diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 1b1169b71554a..bd25184fb9240 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -845,4 +845,10 @@ // FUNCOVERRIDE: -loader-replaceable-function=override_me1 // FUNCOVERRIDE-SAME: -loader-replaceable-function=override_me2 +// RUN: %clang_cl /d2guardcfgdispatch /c -### -- %s 2>&1 | FileCheck %s --check-prefix=GUARDCFGDISPATCH +// GUARDCFGDISPATCH: -fwin-cfg-mechanism=force-dispatch + +// RUN: %clang_cl /d2guardcfgdispatch- /c -### -- %s 2>&1 | FileCheck %s --check-prefix=GUARDCFGDISPATCHNEG +// GUARDCFGDISPATCHNEG: -fwin-cfg-mechanism=force-check + void f(void) { } diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index ac6c20b81d68c..7156a83c9f3cc 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -1056,6 +1056,9 @@ class LLVM_ABI Module { /// Get how unwind v2 (epilog) information should be generated for x64 /// Windows. WinX64EHUnwindV2Mode getWinX64EHUnwindV2Mode() const; + + /// Gets the Control Flow Guard mode. + ControlFlowGuardMode getControlFlowGuardMode() const; }; /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h index 848796ef574f8..9626782729f3c 100644 --- a/llvm/include/llvm/Support/CodeGen.h +++ b/llvm/include/llvm/Support/CodeGen.h @@ -173,6 +173,23 @@ namespace llvm { Required = 2, }; + enum class ControlFlowGuardMode { + // Don't enable Control Flow Guard. + Disabled = 0, + // Emit the Control Flow Guard tables in the binary, but don't emit any + // checks. + TableOnly = 1, + // Enable Control Flow Guard checks and emit the tables. + Enabled = 2, + }; + + enum class ControlFlowGuardMechanism { + // Choose the mechanism automatically based on the target. + Automatic = 0, + ForceCheck = 1, + ForceDispatch = 2, + }; + } // namespace llvm #endif diff --git a/llvm/include/llvm/Transforms/CFGuard.h b/llvm/include/llvm/Transforms/CFGuard.h index b81db8f487965..6af0f351b75d0 100644 --- a/llvm/include/llvm/Transforms/CFGuard.h +++ b/llvm/include/llvm/Transforms/CFGuard.h @@ -29,11 +29,8 @@ class CFGuardPass : public PassInfoMixin<CFGuardPass> { Mechanism GuardMechanism; }; -/// Insert Control FLow Guard checks on indirect function calls. -FunctionPass *createCFGuardCheckPass(); - -/// Insert Control FLow Guard dispatches on indirect function calls. -FunctionPass *createCFGuardDispatchPass(); +/// Insert Control Flow Guard checks on indirect function calls. +FunctionPass *createCFGuardPass(); bool isCFGuardFunction(const GlobalValue *GV); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d96294e06d579..5990c2a2ba26a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -665,7 +665,7 @@ bool AsmPrinter::doInitialization(Module &M) { Handlers.push_back(std::unique_ptr<EHStreamer>(ES)); // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2). - if (mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) + if (M.getControlFlowGuardMode() != ControlFlowGuardMode::Disabled) EHHandlers.push_back(std::make_unique<WinCFGuard>(this)); for (auto &Handler : Handlers) @@ -5088,7 +5088,7 @@ void AsmPrinter::emitCOFFFeatureSymbol(Module &M) { Feat00Value |= COFF::Feat00Flags::SafeSEH; } - if (M.getModuleFlag("cfguard")) { + if (M.getControlFlowGuardMode() != ControlFlowGuardMode::Disabled) { // Object is CFG-aware. Feat00Value |= COFF::Feat00Flags::GuardCF; } diff --git a/llvm/lib/CodeGen/CFGuardLongjmp.cpp b/llvm/lib/CodeGen/CFGuardLongjmp.cpp index 04de011400568..639d0537c2cc1 100644 --- a/llvm/lib/CodeGen/CFGuardLongjmp.cpp +++ b/llvm/lib/CodeGen/CFGuardLongjmp.cpp @@ -62,7 +62,8 @@ FunctionPass *llvm::createCFGuardLongjmpPass() { return new CFGuardLongjmp(); } bool CFGuardLongjmp::runOnMachineFunction(MachineFunction &MF) { // Skip modules for which the cfguard flag is not set. - if (!MF.getFunction().getParent()->getModuleFlag("cfguard")) + if (MF.getFunction().getParent()->getControlFlowGuardMode() == + ControlFlowGuardMode::Disabled) return false; // Skip functions that do not have calls to _setjmp. diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 7360d0fa1f86a..11dc68e0e4751 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -940,3 +940,10 @@ WinX64EHUnwindV2Mode Module::getWinX64EHUnwindV2Mode() const { return static_cast<WinX64EHUnwindV2Mode>(CI->getZExtValue()); return WinX64EHUnwindV2Mode::Disabled; } + +ControlFlowGuardMode Module::getControlFlowGuardMode() const { + Metadata *MD = getModuleFlag("cfguard"); + if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD)) + return static_cast<ControlFlowGuardMode>(CI->getZExtValue()); + return ControlFlowGuardMode::Disabled; +} diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp index d0c4b1b9f83fd..c27a693ceecc1 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -75,7 +75,7 @@ class AArch64Arm64ECCallLowering : public ModulePass { bool runOnModule(Module &M) override; private: - int cfguard_module_flag = 0; + ControlFlowGuardMode CFGuardModuleFlag = ControlFlowGuardMode::Disabled; FunctionType *GuardFnType = nullptr; FunctionType *DispatchFnType = nullptr; Constant *GuardFnCFGlobal = nullptr; @@ -758,7 +758,8 @@ void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) { // Load the global symbol as a pointer to the check function. Value *GuardFn; - if (cfguard_module_flag == 2 && !CB->hasFnAttr("guard_nocf")) + if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) && + !CB->hasFnAttr("guard_nocf")) GuardFn = GuardFnCFGlobal; else GuardFn = GuardFnGlobal; @@ -794,9 +795,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { M = &Mod; // Check if this module has the cfguard flag and read its value. - if (auto *MD = - mdconst::extract_or_null<ConstantInt>(M->getModuleFlag("cfguard"))) - cfguard_module_flag = MD->getZExtValue(); + CFGuardModuleFlag = M->getControlFlowGuardMode(); PtrTy = PointerType::getUnqual(M->getContext()); I64Ty = Type::getInt64Ty(M->getContext()); diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 3aba866458830..09795672da1cf 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -674,7 +674,7 @@ void AArch64PassConfig::addIRPasses() { if (TM->getTargetTriple().isWindowsArm64EC()) addPass(createAArch64Arm64ECCallLoweringPass()); else - addPass(createCFGuardCheckPass()); + addPass(createCFGuardPass()); } if (TM->Options.JMCInstrument) diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp index 590d4c70592f8..aadf8624c7c8c 100644 --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -384,7 +384,7 @@ void ARMPassConfig::addIRPasses() { // Add Control Flow Guard checks. if (TM->getTargetTriple().isOSWindows()) - addPass(createCFGuardCheckPass()); + addPass(createCFGuardPass()); if (TM->Options.JMCInstrument) addPass(createJMCInstrumenterPass()); diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index f020e0b55141c..7d24126f820f8 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -1217,8 +1217,10 @@ def CSR_Win32_CFGuard_Check_NoSSE : CalleeSavedRegs<(add CSR_32_RegCall_NoSSE, E def CSR_Win32_CFGuard_Check : CalleeSavedRegs<(add CSR_32_RegCall, ECX)>; def CSR_Win64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, (sequence "R%u", 10, 15))>; -def CSR_Win64_RegCall : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE, +def CSR_Win64_RegCall : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE, (sequence "XMM%u", 8, 15))>; +def CSR_Win64_CFGuard_Check_NoSSE : CalleeSavedRegs<(add CSR_Win64_RegCall_NoSSE, RCX)>; +def CSR_Win64_CFGuard_Check : CalleeSavedRegs<(add CSR_Win64_RegCall, RCX)>; def CSR_SysV64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP, (sequence "R%u", 12, 15))>; def CSR_SysV64_RegCall : CalleeSavedRegs<(add CSR_SysV64_RegCall_NoSSE, diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 72f38133e21ff..635c06440c873 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -434,9 +434,13 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF, CSR_32_RegCall_NoSSE_RegMask); } case CallingConv::CFGuard_Check: - assert(!Is64Bit && "CFGuard check mechanism only used on 32-bit X86"); - return (HasSSE ? CSR_Win32_CFGuard_Check_RegMask - : CSR_Win32_CFGuard_Check_NoSSE_RegMask); + if (Is64Bit) { + return (HasSSE ? CSR_Win64_CFGuard_Check_RegMask + : CSR_Win64_CFGuard_Check_NoSSE_RegMask); + } else { + return (HasSSE ? CSR_Win32_CFGuard_Check_RegMask + : CSR_Win32_CFGuard_Check_NoSSE_RegMask); + } case CallingConv::Cold: if (Is64Bit) return CSR_64_MostRegs_RegMask; diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index d5907d55998b5..bf9ec458acf27 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -441,11 +441,7 @@ void X86PassConfig::addIRPasses() { // Add Control Flow Guard checks. const Triple &TT = TM->getTargetTriple(); if (TT.isOSWindows()) { - if (TT.isX86_64()) { - addPass(createCFGuardDispatchPass()); - } else { - addPass(createCFGuardCheckPass()); - } + addPass(createCFGuardPass()); } if (TM->Options.JMCInstrument) diff --git a/llvm/lib/Transforms/CFGuard/CFGuard.cpp b/llvm/lib/Transforms/CFGuard/CFGuard.cpp index 46456706d46a1..b648b4f862c65 100644 --- a/llvm/lib/Transforms/CFGuard/CFGuard.cpp +++ b/llvm/lib/Transforms/CFGuard/CFGuard.cpp @@ -38,24 +38,11 @@ namespace { /// Adds Control Flow Guard (CFG) checks on indirect function calls/invokes. /// These checks ensure that the target address corresponds to the start of an -/// address-taken function. X86_64 targets use the Mechanism::Dispatch -/// mechanism. X86, ARM, and AArch64 targets use the Mechanism::Check machanism. +/// address-taken function. class CFGuardImpl { public: using Mechanism = CFGuardPass::Mechanism; - CFGuardImpl(Mechanism M) : GuardMechanism(M) { - // Get or insert the guard check or dispatch global symbols. - switch (GuardMechanism) { - case Mechanism::Check: - GuardFnName = GuardCheckFunctionName; - break; - case Mechanism::Dispatch: - GuardFnName = GuardDispatchFunctionName; - break; - } - } - /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG /// check mechanism. When the image is loaded, the loader puts the appropriate /// guard check function pointer in the __guard_check_icall_fptr global @@ -147,8 +134,7 @@ class CFGuardImpl { private: // Only add checks if the module has the cfguard=2 flag. - int CFGuardModuleFlag = 0; - StringRef GuardFnName; + ControlFlowGuardMode CFGuardModuleFlag = ControlFlowGuardMode::Disabled; Mechanism GuardMechanism = Mechanism::Check; FunctionType *GuardFnType = nullptr; PointerType *GuardFnPtrType = nullptr; @@ -162,7 +148,7 @@ class CFGuard : public FunctionPass { static char ID; // Default constructor required for the INITIALIZE_PASS macro. - CFGuard(CFGuardImpl::Mechanism M) : FunctionPass(ID), Impl(M) {} + CFGuard() : FunctionPass(ID) {} bool doInitialization(Module &M) override { return Impl.doInitialization(M); } bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); } @@ -233,20 +219,42 @@ void CFGuardImpl::insertCFGuardDispatch(CallBase *CB) { bool CFGuardImpl::doInitialization(Module &M) { // Check if this module has the cfguard flag and read its value. - if (auto *MD = - mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) - CFGuardModuleFlag = MD->getZExtValue(); + CFGuardModuleFlag = M.getControlFlowGuardMode(); // Skip modules for which CFGuard checks have been disabled. - if (CFGuardModuleFlag != 2) + if (CFGuardModuleFlag != ControlFlowGuardMode::Enabled) return false; + // Determine the guard mechanism to use. + ControlFlowGuardMechanism MechanismOverride = + ControlFlowGuardMechanism::Automatic; + if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>( + M.getModuleFlag("cfguard-mechanism"))) + MechanismOverride = + static_cast<ControlFlowGuardMechanism>(CI->getZExtValue()); + switch (MechanismOverride) { + case ControlFlowGuardMechanism::ForceCheck: + GuardMechanism = Mechanism::Check; + break; + case ControlFlowGuardMechanism::ForceDispatch: + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/176276 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
