Skip to content

Commit

Permalink
[Clang] Introduce -fcf-branch-label-scheme=unlabeled|func-sig
Browse files Browse the repository at this point in the history
This flag controls the scheme of the labels of landing pad insns. Landing pad
insns are special insns that mark the targets of indirect jumps. In RISC-V
Zicfilp extension, its landing pad insn further encodes a field of `label',
which can be used to limit the sources of indirect jumps to those that set up a
matching label according to a `scheme' selected at compile time. This flag
controls the selection of that `scheme'. It's named `-fcf-branch-label-scheme`
since the generation of landing pad insns is turned on by
`-fcf-protection=branch`.
  • Loading branch information
mylai-mtk committed Sep 23, 2024
1 parent 40ecff6 commit 71de8dc
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 0 deletions.
22 changes: 22 additions & 0 deletions clang/include/clang/Basic/CFProtectionOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===--- CFProtectionOptions.h ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines constants for -fcf-protection and other related flags.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
#define LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H

namespace clang {

enum class CFBranchLabelSchemeKind { Default, Unlabeled, FuncSig };

} // namespace clang

#endif // #ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-protection is
///< set to full or return.
CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
///< set to full or branch.
ENUM_CODEGENOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2,
CFBranchLabelSchemeKind::Default) ///< if -fcf-branch-label-scheme is set.
CODEGENOPT(FunctionReturnThunks, 1, 0) ///< -mfunction-return={keep|thunk-extern}
CODEGENOPT(IndirectBranchCSPrefix, 1, 0) ///< if -mindirect-branch-cs-prefix
///< is set.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H

#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/XRayInstr.h"
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,9 @@ def err_drv_experimental_crel : Error<
"-Wa,--allow-experimental-crel must be specified to use -Wa,--crel. "
"CREL is experimental and uses a non-standard section type code">;

def warn_drv_opt_ignored_by_other : Warning<"ignoring option '%0' due to '%1'">,
InGroup<OptionIgnored>;

def warn_android_unversioned_fallback : Warning<
"using unversioned Android target directory %0 for target %1; unversioned "
"directories will not be used in Clang 19 -- provide a versioned directory "
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0,
LANGOPT(ObjCDisableDirectMethodsForTesting, 1, 0,
"Disable recognition of objc_direct methods")
LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
ENUM_LANGOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2, CFBranchLabelSchemeKind::Default,
"Control-Flow Branch Protection Label Scheme")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
#define LLVM_CLANG_BASIC_LANGOPTIONS_H

#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangStandard.h"
Expand Down Expand Up @@ -73,6 +74,7 @@ class LangOptionsBase {
public:
using Visibility = clang::Visibility;
using RoundingMode = llvm::RoundingMode;
using CFBranchLabelSchemeKind = clang::CFBranchLabelSchemeKind;

enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/BitmaskEnum.h"
#include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
Expand Down Expand Up @@ -1727,6 +1728,9 @@ class TargetInfo : public TransferrableTargetInfo,
virtual bool
checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const;

/// Get the target default CFBranchLabelScheme scheme
virtual CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const;

/// Check if the target supports CFProtection return.
virtual bool
checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2841,6 +2841,10 @@ def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>,
Visibility<[ClangOption, CLOption, CC1Option]>,
Alias<fcf_protection_EQ>, AliasArgs<["full"]>,
HelpText<"Enable cf-protection in 'full' mode">;
def fcf_branch_label_scheme_EQ : Joined<["-"], "fcf-branch-label-scheme=">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Select label scheme for branch control-flow architecture protection">,
Values<"unlabeled,func-sig">;
def mfunction_return_EQ : Joined<["-"], "mfunction-return=">,
Group<m_Group>, Visibility<[ClangOption, CLOption, CC1Option]>,
HelpText<"Replace returns with jumps to ``__x86_return_thunk`` (x86 only, error otherwise)">,
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ void TargetInfo::resetDataLayout(StringRef DL, const char *ULP) {
UserLabelPrefix = ULP;
}

CFBranchLabelSchemeKind TargetInfo::getDefaultCFBranchLabelScheme() const {
// if this hook is called, the target should override it
llvm::report_fatal_error("not implemented");
}

bool
TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ class RISCVTargetInfo : public TargetInfo {
return true;
return TargetInfo::checkCFProtectionBranchSupported(Diags);
}

CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override {
return CFBranchLabelSchemeKind::FuncSig;
};
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
return TargetInfo::checkCFProtectionBranchSupported(Diags);
};

CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override {
return CFBranchLabelSchemeKind::Unlabeled;
};

virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap,
StringRef Constraint, unsigned Size) const;

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7012,6 +7012,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_fcf_branch_label_scheme_EQ))
CmdArgs.push_back(Args.MakeArgString(Twine("-fcf-branch-label-scheme=") +
SA->getValue()));
}

if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ))
Expand Down
39 changes: 39 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,19 @@ 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;
case CFBranchLabelSchemeKind::Unlabeled:
GenerateArg(Consumer, OPT_fcf_branch_label_scheme_EQ, "unlabeled");
break;
case CFBranchLabelSchemeKind::FuncSig:
GenerateArg(Consumer, OPT_fcf_branch_label_scheme_EQ, "func-sig");
break;
}
}

if (Opts.FunctionReturnThunks)
GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");

Expand Down Expand Up @@ -2022,6 +2035,22 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
}

if (const Arg *const A = Args.getLastArg(OPT_fcf_branch_label_scheme_EQ)) {
if (Opts.CFProtectionBranch) {
const StringRef Scheme = A->getValue();
if (Scheme == "unlabeled")
Opts.setCFBranchLabelScheme(CFBranchLabelSchemeKind::Unlabeled);
else if (Scheme == "func-sig")
Opts.setCFBranchLabelScheme(CFBranchLabelSchemeKind::FuncSig);
else
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Scheme;
} else
Diags.Report(diag::warn_drv_opt_ignored_by_other)
<< A->getAsString(Args)
<< Args.getLastArg(OPT_fcf_protection_EQ)->getAsString(Args);
}

if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
.Case("keep", llvm::FunctionReturnThunksKind::Keep)
Expand Down Expand Up @@ -3952,6 +3981,16 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}

if (const Arg *const A = Args.getLastArg(OPT_fcf_branch_label_scheme_EQ)) {
if (Opts.CFProtectionBranch) {
const StringRef Scheme = A->getValue();
if (Scheme == "unlabeled")
Opts.setCFBranchLabelScheme(CFBranchLabelSchemeKind::Unlabeled);
else if (Scheme == "func-sig")
Opts.setCFBranchLabelScheme(CFBranchLabelSchemeKind::FuncSig);
}
}

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
Expand Down

0 comments on commit 71de8dc

Please sign in to comment.