From 9f33eb861a3d17fd92163ee894f7cd9f256d03fb Mon Sep 17 00:00:00 2001 From: Ming-Yi Lai Date: Thu, 26 Sep 2024 18:30:43 +0800 Subject: [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 --- clang/lib/Frontend/CompilerInvocation.cpp | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'clang/lib/Frontend/CompilerInvocation.cpp') 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(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(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(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 -- cgit v1.1