Skip to content

[PAC][clang] Handle pauthtest environment and ABI in Linux-specific code #113151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/kovdan01/pauthtest-new-features
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
StringRef AArch64TargetInfo::getABI() const { return ABI; }

bool AArch64TargetInfo::setABI(const std::string &Name) {
if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs" &&
Name != "pauthtest")
if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs")
return false;

ABI = Name;
Expand All @@ -221,12 +220,6 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
Diags.Report(diag::err_target_unsupported_abi_with_fpu) << ABI;
return false;
}
if (getTriple().getEnvironment() == llvm::Triple::PAuthTest &&
getTriple().getOS() != llvm::Triple::Linux) {
Diags.Report(diag::err_target_unsupported_abi_for_triple)
<< getTriple().getEnvironmentName() << getTriple().getTriple();
return false;
}
return true;
}

Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {

const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A;

protected:
std::string ABI;

public:
Expand Down Expand Up @@ -258,6 +259,16 @@ class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
void setDataLayout() override;
};

template <>
inline bool
LinuxTargetInfo<AArch64leTargetInfo>::setABI(const std::string &Name) {
if (Name == "pauthtest") {
ABI = Name;
return true;
}
return AArch64leTargetInfo::setABI(Name);
}

class LLVM_LIBRARY_VISIBILITY WindowsARM64TargetInfo
: public WindowsTargetInfo<AArch64leTargetInfo> {
const llvm::Triple Triple;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/OSTargets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//

#include "OSTargets.h"
#include "AArch64.h"
#include "clang/Basic/MacroBuilder.h"
#include "llvm/ADT/StringRef.h"

Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/OSTargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,12 @@ class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
const char *getStaticInitSectionSpecifier() const override {
return ".text.startup";
}

// This allows template specializations, see
// LinuxTargetInfo<AArch64leTargetInfo>::setABI
bool setABI(const std::string &Name) override {
return OSTargetInfo<Target>::setABI(Name);
}
};

// NetBSD Target
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64);
else if (Target.getABI() == "aapcs-soft")
Kind = AArch64ABIKind::AAPCSSoft;
else if (Target.getABI() == "pauthtest")
Kind = AArch64ABIKind::PAuthTest;

return createAArch64TargetCodeGenInfo(CGM, Kind);
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,6 @@ enum class AArch64ABIKind {
DarwinPCS,
Win64,
AAPCSSoft,
PAuthTest,
};

std::unique_ptr<TargetCodeGenInfo>
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,6 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
}
case llvm::Triple::aarch64: {
llvm::Triple Triple = getTriple();
tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple);
if (!Triple.isOSBinFormatMachO())
return Triple.getTriple();

Expand Down
21 changes: 0 additions & 21 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,24 +455,3 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
Features.push_back("+no-bti-at-return-twice");
}

void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
llvm::Triple &Triple) {
Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ);
bool HasPAuthABI =
ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false;

switch (Triple.getEnvironment()) {
case llvm::Triple::UnknownEnvironment:
if (HasPAuthABI)
Triple.setEnvironment(llvm::Triple::PAuthTest);
break;
case llvm::Triple::PAuthTest:
break;
default:
if (HasPAuthABI)
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< ABIArg->getAsString(Args) << Triple.getTriple();
break;
}
}
3 changes: 0 additions & 3 deletions clang/lib/Driver/ToolChains/Arch/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, llvm::opt::Arg *&A);

void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
llvm::Triple &triple);

} // end namespace aarch64
} // end namespace target
} // end namespace driver
Expand Down
60 changes: 3 additions & 57 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1501,59 +1501,6 @@ void AddUnalignedAccessWarning(ArgStringList &CmdArgs) {
}
}

// Each combination of options here forms a signing schema, and in most cases
// each signing schema is its own incompatible ABI. The default values of the
// options represent the default signing schema.
static void handlePAuthABI(const ArgList &DriverArgs, ArgStringList &CC1Args) {
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
options::OPT_fno_ptrauth_intrinsics))
CC1Args.push_back("-fptrauth-intrinsics");

if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
options::OPT_fno_ptrauth_calls))
CC1Args.push_back("-fptrauth-calls");

if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
options::OPT_fno_ptrauth_returns))
CC1Args.push_back("-fptrauth-returns");

if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
options::OPT_fno_ptrauth_auth_traps))
CC1Args.push_back("-fptrauth-auth-traps");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_address_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_type_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_type_info_vtable_pointer_discrimination,
options::OPT_fno_ptrauth_type_info_vtable_pointer_discrimination))
CC1Args.push_back("-fptrauth-type-info-vtable-pointer-discrimination");

if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
options::OPT_fno_ptrauth_indirect_gotos))
CC1Args.push_back("-fptrauth-indirect-gotos");

if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini,
options::OPT_fno_ptrauth_init_fini))
CC1Args.push_back("-fptrauth-init-fini");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_init_fini_address_discrimination,
options::OPT_fno_ptrauth_init_fini_address_discrimination))
CC1Args.push_back("-fptrauth-init-fini-address-discrimination");

if (!DriverArgs.hasArg(options::OPT_faarch64_jump_table_hardening,
options::OPT_fno_aarch64_jump_table_hardening))
CC1Args.push_back("-faarch64-jump-table-hardening");
}

static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, bool isAArch64) {
const Arg *A = isAArch64
Expand Down Expand Up @@ -1783,7 +1730,9 @@ void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
ABIName = A->getValue();
else if (Triple.isOSDarwin())
ABIName = "darwinpcs";
else if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
// TODO: we probably want to have some target hook here.
else if (Triple.isOSLinux() &&
Triple.getEnvironment() == llvm::Triple::PAuthTest)
ABIName = "pauthtest";
else
ABIName = "aapcs";
Expand Down Expand Up @@ -1821,9 +1770,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
// Enable/disable return address signing and indirect branch targets.
CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/);

if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
handlePAuthABI(Args, CmdArgs);

// Handle -msve_vector_bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
StringRef Val = A->getValue();
Expand Down
96 changes: 96 additions & 0 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,102 @@ std::string Linux::computeSysRoot() const {
return std::string();
}

static void setPAuthABIInTriple(const Driver &D, const ArgList &Args,
llvm::Triple &Triple) {
Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ);
bool HasPAuthABI =
ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false;

switch (Triple.getEnvironment()) {
case llvm::Triple::UnknownEnvironment:
if (HasPAuthABI)
Triple.setEnvironment(llvm::Triple::PAuthTest);
break;
case llvm::Triple::PAuthTest:
break;
default:
if (HasPAuthABI)
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< ABIArg->getAsString(Args) << Triple.getTriple();
break;
}
}

std::string Linux::ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const {
std::string TripleString =
Generic_ELF::ComputeEffectiveClangTriple(Args, InputType);
if (getTriple().isAArch64()) {
llvm::Triple Triple(TripleString);
setPAuthABIInTriple(getDriver(), Args, Triple);
return Triple.getTriple();
}
return TripleString;
}

// Each combination of options here forms a signing schema, and in most cases
// each signing schema is its own incompatible ABI. The default values of the
// options represent the default signing schema.
static void handlePAuthABI(const Driver &D, const ArgList &DriverArgs,
ArgStringList &CC1Args) {
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
options::OPT_fno_ptrauth_intrinsics))
CC1Args.push_back("-fptrauth-intrinsics");

if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
options::OPT_fno_ptrauth_calls))
CC1Args.push_back("-fptrauth-calls");

if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
options::OPT_fno_ptrauth_returns))
CC1Args.push_back("-fptrauth-returns");

if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
options::OPT_fno_ptrauth_auth_traps))
CC1Args.push_back("-fptrauth-auth-traps");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_address_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_vtable_pointer_type_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_type_info_vtable_pointer_discrimination,
options::OPT_fno_ptrauth_type_info_vtable_pointer_discrimination))
CC1Args.push_back("-fptrauth-type-info-vtable-pointer-discrimination");

if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
options::OPT_fno_ptrauth_indirect_gotos))
CC1Args.push_back("-fptrauth-indirect-gotos");

if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini,
options::OPT_fno_ptrauth_init_fini))
CC1Args.push_back("-fptrauth-init-fini");

if (!DriverArgs.hasArg(
options::OPT_fptrauth_init_fini_address_discrimination,
options::OPT_fno_ptrauth_init_fini_address_discrimination))
CC1Args.push_back("-fptrauth-init-fini-address-discrimination");

if (!DriverArgs.hasArg(options::OPT_faarch64_jump_table_hardening,
options::OPT_fno_aarch64_jump_table_hardening))
CC1Args.push_back("-faarch64-jump-table-hardening");
}

void Linux::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
llvm::Triple Triple(ComputeEffectiveClangTriple(DriverArgs));
if (Triple.isAArch64() && Triple.getEnvironment() == llvm::Triple::PAuthTest)
handlePAuthABI(getDriver(), DriverArgs, CC1Args);
Generic_ELF::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
}

std::string Linux::getDynamicLinker(const ArgList &Args) const {
const llvm::Triple::ArchType Arch = getArch();
const llvm::Triple &Triple = getTriple();
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChains/Linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
std::string ComputeEffectiveClangTriple(
const llvm::opt::ArgList &Args,
types::ID InputType = types::TY_INVALID) const override;
std::string computeSysRoot() const override;
void
addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;

std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;

Expand Down
34 changes: 25 additions & 9 deletions clang/test/Driver/aarch64-ptrauth.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,39 @@
// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1
// RUN: %clang -### -c --target=aarch64-linux-pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1
// PAUTHABI1: "-cc1"{{.*}} "-triple" "aarch64-unknown-linux-pauthtest"
// PAUTHABI1-SAME: "-target-abi" "pauthtest"
// PAUTHABI1-SAME: "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-type-info-vtable-pointer-discrimination" "-fptrauth-indirect-gotos" "-fptrauth-init-fini" "-fptrauth-init-fini-address-discrimination" "-faarch64-jump-table-hardening"
// PAUTHABI1-SAME: "-target-abi" "pauthtest"
// PAUTHABI1-NOT: "-fptrauth-function-pointer-type-discrimination"

// RUN: %clang -### -c --target=aarch64 -mabi=pauthtest -fno-ptrauth-intrinsics \
// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest -fno-ptrauth-intrinsics \
// RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \
// RUN: -fno-ptrauth-vtable-pointer-address-discrimination -fno-ptrauth-vtable-pointer-type-discrimination \
// RUN: -fno-ptrauth-type-info-vtable-pointer-discrimination -fno-ptrauth-indirect-gotos \
// RUN: -fno-ptrauth-init-fini -fno-ptrauth-init-fini-address-discrimination \
// RUN: -fno-aarch64-jump-table-hardening %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2
// RUN: %clang -### -c --target=aarch64-pauthtest -fno-ptrauth-intrinsics \
// RUN: %clang -### -c --target=aarch64-linux-pauthtest -fno-ptrauth-intrinsics \
// RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \
// RUN: -fno-ptrauth-vtable-pointer-address-discrimination -fno-ptrauth-vtable-pointer-type-discrimination \
// RUN: -fno-ptrauth-type-info-vtable-pointer-discrimination -fno-ptrauth-indirect-gotos \
// RUN: -fno-ptrauth-init-fini -fno-ptrauth-init-fini-address-discrimination \
// RUN: -fno-aarch64-jump-table-hardening %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2
// PAUTHABI2: "-cc1"
// PAUTHABI2-NOT: "-fptrauth-

//// Non-linux OS: pauthtest ABI has no effect in terms of passing ptrauth cc1 flags.
//// An error about unsupported ABI will be emitted later in pipeline (see ERR2 below)
// RUN: %clang -### -c --target=aarch64 -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2

// PAUTHABI2: "-cc1"
// PAUTHABI2-SAME: "-target-abi" "pauthtest"
// PAUTHABI2-NOT: "-fptrauth-
// PAUTHABI2-NOT: "-faarch64-jump-table-hardening"

//// Non-linux OS: pauthtest environment does not correspond to pauthtest ABI; aapcs is the default.
// RUN: %clang -### -c --target=aarch64-pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI3
// PAUTHABI3: "-cc1"
// PAUTHABI3-SAME: "-target-abi" "aapcs"
// PAUTHABI3-NOT: "-fptrauth-
// PAUTHABI3-NOT: "-faarch64-jump-table-hardening"

// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps \
// RUN: -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-type-info-vtable-pointer-discrimination -fptrauth-indirect-gotos -fptrauth-init-fini \
Expand All @@ -57,10 +71,12 @@
// ERR1-NEXT: error: unsupported option '-fptrauth-init-fini-address-discrimination' for target '{{.*}}'
// ERR1-NEXT: error: unsupported option '-faarch64-jump-table-hardening' for target '{{.*}}'

//// Only support PAuth ABI for Linux as for now.
// RUN: not %clang -o /dev/null -c --target=aarch64-unknown -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2
// RUN: not %clang -o /dev/null -c --target=aarch64-unknown-pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2
// ERR2: error: ABI 'pauthtest' is not supported for 'aarch64-unknown-unknown-pauthtest'

// RUN: not %clang -c --target=aarch64 -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2
//// The ABI is not specified explicitly, and for non-Linux pauthtest environment does not correspond
//// to pauthtest ABI (each OS target defines this behavior separately). Do not emit an error.
// RUN: %clang -c --target=aarch64-pauthtest %s -o /dev/null
// ERR2: error: unknown target ABI 'pauthtest'

//// PAuth ABI is encoded as environment part of the triple, so don't allow to explicitly set other environments.
// RUN: not %clang -### -c --target=aarch64-linux-gnu -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR3
Expand Down
Loading