diff options
author | Ming-Yi Lai <ming-yi.lai@mediatek.com> | 2024-09-26 18:30:43 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-26 18:30:43 +0800 |
commit | 9f33eb861a3d17fd92163ee894f7cd9f256d03fb (patch) | |
tree | e81f0cec7a13842d45bc8de1413f3e51398dc55d /clang/lib | |
parent | 497523b695d06c8bf9f3aaf5a5cb4414a5b0625b (diff) | |
download | llvm-9f33eb861a3d17fd92163ee894f7cd9f256d03fb.zip llvm-9f33eb861a3d17fd92163ee894f7cd9f256d03fb.tar.gz llvm-9f33eb861a3d17fd92163ee894f7cd9f256d03fb.tar.bz2 |
[clang][RISCV] Introduce command line options for RISC-V Zicfilp CFI
This patch enables the following command line flags for RISC-V targets:
+ `-fcf-protection=branch` turns on forward-edge control-flow integrity conditioning
+ `-mcf-branch-label-scheme=unlabeled|func-sig` selects the label scheme used in the forward-edge CFI conditioning
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/TargetInfo.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/RISCV.h | 22 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 40 |
5 files changed, 92 insertions, 0 deletions
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 29f5cd1..9219533 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -198,6 +198,22 @@ TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const { return false; } +CFBranchLabelSchemeKind TargetInfo::getDefaultCFBranchLabelScheme() const { + // if this hook is called, the target should override it to return a + // non-default scheme + llvm::report_fatal_error("not implemented"); +} + +bool TargetInfo::checkCFBranchLabelSchemeSupported( + const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const { + if (Scheme != CFBranchLabelSchemeKind::Default) + Diags.Report(diag::err_opt_not_valid_on_target) + << (Twine("mcf-branch-label-scheme=") + + getCFBranchLabelSchemeFlagVal(Scheme)) + .str(); + return false; +} + bool TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const { Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return"; diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index 351ef21..bf40edb 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -134,6 +134,28 @@ public: bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const override; + + bool checkCFProtectionBranchSupported(DiagnosticsEngine &) const override { + // Always generate Zicfilp lpad insns + // Non-zicfilp CPUs would read them as NOP + return true; + } + + CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override { + return CFBranchLabelSchemeKind::FuncSig; + } + + bool + checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme, + DiagnosticsEngine &Diags) const override { + switch (Scheme) { + case CFBranchLabelSchemeKind::Default: + case CFBranchLabelSchemeKind::Unlabeled: + case CFBranchLabelSchemeKind::FuncSig: + return true; + } + return TargetInfo::checkCFBranchLabelSchemeSupported(Scheme, Diags); + } }; class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d53d479..2381fa9 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1164,6 +1164,16 @@ void CodeGenModule::Release() { // Indicate that we want to instrument branch control flow protection. getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch", 1); + + auto Scheme = CodeGenOpts.getCFBranchLabelScheme(); + if (Target.checkCFBranchLabelSchemeSupported(Scheme, getDiags())) { + if (Scheme == CFBranchLabelSchemeKind::Default) + Scheme = Target.getDefaultCFBranchLabelScheme(); + getModule().addModuleFlag( + llvm::Module::Error, "cf-branch-label-scheme", + llvm::MDString::get(getLLVMContext(), + getCFBranchLabelSchemeFlagVal(Scheme))); + } } if (CodeGenOpts.FunctionReturnThunks) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a2e403e..cbcc3b8 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7016,6 +7016,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { CmdArgs.push_back( Args.MakeArgString(Twine("-fcf-protection=") + A->getValue())); + + if (Arg *SA = Args.getLastArg(options::OPT_mcf_branch_label_scheme_EQ)) + CmdArgs.push_back(Args.MakeArgString(Twine("-mcf-branch-label-scheme=") + + SA->getValue())); } if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index efd8525..6c09843 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1688,6 +1688,18 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, else if (Opts.CFProtectionBranch) GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch"); + if (Opts.CFProtectionBranch) { + switch (Opts.getCFBranchLabelScheme()) { + case CFBranchLabelSchemeKind::Default: + break; +#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \ + case CFBranchLabelSchemeKind::Kind: \ + GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal); \ + break; +#include "clang/Basic/CFProtectionOptions.def" + } + } + if (Opts.FunctionReturnThunks) GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern"); @@ -2022,6 +2034,22 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; } + if (Opts.CFProtectionBranch && T.isRISCV()) { + if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) { + const auto Scheme = + llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue()) +#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \ + .Case(#FlagVal, CFBranchLabelSchemeKind::Kind) +#include "clang/Basic/CFProtectionOptions.def" + .Default(CFBranchLabelSchemeKind::Default); + if (Scheme != CFBranchLabelSchemeKind::Default) + Opts.setCFBranchLabelScheme(Scheme); + else + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } + if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) { auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue()) .Case("keep", llvm::FunctionReturnThunksKind::Keep) @@ -3952,6 +3980,18 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, } } + if (Opts.CFProtectionBranch) { + if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) { + const auto Scheme = + llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue()) +#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \ + .Case(#FlagVal, CFBranchLabelSchemeKind::Kind) +#include "clang/Basic/CFProtectionOptions.def" + .Default(CFBranchLabelSchemeKind::Default); + Opts.setCFBranchLabelScheme(Scheme); + } + } + if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) && !Args.hasArg(OPT_sycl_std_EQ)) { // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to |