diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ed3fd9b1c4a5..0b440f9860ae 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -748,6 +748,10 @@ def warn_drv_fjmc_for_elf_only : Warning< "-fjmc works only for ELF; option ignored">, InGroup; +def warn_drv_ptrauth_elf_got_for_elf_only : Warning< + "-fptrauth-elf-got works only for ELF; option ignored">, + InGroup; + def warn_target_override_arm64ec : Warning< "/arm64EC has been overridden by specified target: %0; option ignored">, InGroup; diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index fe4d1c4afcca..2f2f1af8dc28 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -103,6 +103,13 @@ FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics) +FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls) +FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns) +FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination) +FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) +FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls) +FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) +FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT) EXTENSION(swiftcc, PP.getTargetInfo().checkCallingConvention(CC_Swift) == clang::TargetInfo::CCCR_OK) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 8ef6700ecdc7..e2016aab850e 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -162,6 +162,13 @@ LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template t LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features") LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics") +LANGOPT(PointerAuthCalls , 1, 0, "function pointer authentication") +LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication") +LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps") +LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers") +LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers") +LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays") +LANGOPT(PointerAuthELFGOT, 1, 0, "authenticate pointers from GOT") LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 52d161703f96..e62e2d0bfd4a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4148,6 +4148,15 @@ defm strict_return : BoolFOption<"strict-return", let Flags = [TargetSpecific] in { defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">; +defm ptrauth_calls : OptInCC1FFlag<"ptrauth-calls", "Enable signing and authentication of all indirect calls">; +defm ptrauth_returns : OptInCC1FFlag<"ptrauth-returns", "Enable signing and authentication of return addresses">; +defm ptrauth_auth_traps : OptInCC1FFlag<"ptrauth-auth-traps", "Enable traps on authentication failures">; +defm ptrauth_vtable_pointer_address_discrimination : + OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable address discrimination of vtable pointers">; +defm ptrauth_vtable_pointer_type_discrimination : + OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">; +defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">; +defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0c447b20cef4..ee88bd04104b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -53,6 +53,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/CallingConv.h" @@ -1189,6 +1190,38 @@ void CodeGenModule::Release() { if (!LangOpts.isSignReturnAddressWithAKey()) getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", 1); + + if (getTriple().isOSLinux() && getTriple().isOSBinFormatELF()) { + using namespace llvm::ELF; + uint64_t PAuthABIVersion = + (LangOpts.PointerAuthIntrinsics + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS) | + (LangOpts.PointerAuthCalls + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS) | + (LangOpts.PointerAuthReturns + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS) | + (LangOpts.PointerAuthAuthTraps + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS) | + (LangOpts.PointerAuthVTPtrAddressDiscrimination + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR) | + (LangOpts.PointerAuthVTPtrTypeDiscrimination + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR) | + (LangOpts.PointerAuthInitFini + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI) | + (LangOpts.PointerAuthELFGOT + << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT); + static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT == + AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, + "Update when new enum items are defined"); + if (PAuthABIVersion != 0) { + getModule().addModuleFlag(llvm::Module::Error, + "aarch64-elf-pauthabi-platform", + AARCH64_PAUTH_PLATFORM_LLVM_LINUX); + getModule().addModuleFlag(llvm::Module::Error, + "aarch64-elf-pauthabi-version", + PAuthABIVersion); + } + } } if (CodeGenOpts.StackClashProtector) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 97b4aa1c9b1d..b6ad28b7736c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1782,6 +1782,33 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_intrinsics, options::OPT_fno_ptrauth_intrinsics); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_calls, + options::OPT_fno_ptrauth_calls); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_returns, + options::OPT_fno_ptrauth_returns); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_auth_traps, + options::OPT_fno_ptrauth_auth_traps); + + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_vtable_pointer_address_discrimination, + options::OPT_fno_ptrauth_vtable_pointer_address_discrimination); + + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_vtable_pointer_type_discrimination, + options::OPT_fno_ptrauth_vtable_pointer_type_discrimination); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_init_fini, + options::OPT_fno_ptrauth_init_fini); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_elf_got, + options::OPT_fno_ptrauth_elf_got); + + if (Args.hasArg(options::OPT_fptrauth_elf_got)) + getToolChain().getDriver().Diag( + diag::warn_drv_ptrauth_elf_got_for_elf_only); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 8236051e30c4..2539e7a35bf9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3319,11 +3319,34 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, ArgumentConsumer Consumer) { if (Opts.PointerAuthIntrinsics) GenerateArg(Consumer, OPT_fptrauth_intrinsics); + if (Opts.PointerAuthCalls) + GenerateArg(Consumer, OPT_fptrauth_calls); + if (Opts.PointerAuthReturns) + GenerateArg(Consumer, OPT_fptrauth_returns); + if (Opts.PointerAuthAuthTraps) + GenerateArg(Consumer, OPT_fptrauth_auth_traps); + if (Opts.PointerAuthVTPtrAddressDiscrimination) + GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination); + if (Opts.PointerAuthVTPtrTypeDiscrimination) + GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination); + if (Opts.PointerAuthInitFini) + GenerateArg(Consumer, OPT_fptrauth_init_fini); + if (Opts.PointerAuthELFGOT) + GenerateArg(Consumer, OPT_fptrauth_elf_got); } static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics); + Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls); + Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns); + Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps); + Opts.PointerAuthVTPtrAddressDiscrimination = + Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination); + Opts.PointerAuthVTPtrTypeDiscrimination = + Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination); + Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); + Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); } /// Check if input file kind and language standard are compatible. @@ -4677,6 +4700,7 @@ bool CompilerInvocation::CreateFromArgsImpl( ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags); ParsePointerAuthArgs(LangOpts, Args, Diags); + LangOpts.PointerAuthELFGOT &= T.isOSBinFormatELF(); ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes, Diags); diff --git a/clang/test/CodeGen/aarch64-elf-pauthabi.c b/clang/test/CodeGen/aarch64-elf-pauthabi.c new file mode 100644 index 000000000000..c1b7b9e7ee60 --- /dev/null +++ b/clang/test/CodeGen/aarch64-elf-pauthabi.c @@ -0,0 +1,66 @@ +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-auth-traps \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got %s | \ +// RUN: FileCheck %s --check-prefix=ALL + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-intrinsics %s | FileCheck %s --check-prefix=INTRIN + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-calls %s | FileCheck %s --check-prefix=CALL + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-returns %s | FileCheck %s --check-prefix=RET + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-auth-traps %s | FileCheck %s --check-prefix=TRAP + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination %s | \ +// RUN: FileCheck %s --check-prefix=VPTRADDR + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination %s | \ +// RUN: FileCheck %s --check-prefix=VPTRTYPE + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-calls -fptrauth-init-fini %s | \ +// RUN: FileCheck %s --check-prefix=INITFINI + +// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \ +// RUN: -fptrauth-elf-got %s | FileCheck %s --check-prefix=ELFGOT + +// ALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 255} + +// INTRIN: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// INTRIN: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1} + +// CALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// CALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 2} + +// RET: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// RET: !{i32 1, !"aarch64-elf-pauthabi-version", i32 4} + +// TRAP: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// TRAP: !{i32 1, !"aarch64-elf-pauthabi-version", i32 8} + +// VPTRADDR: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// VPTRADDR: !{i32 1, !"aarch64-elf-pauthabi-version", i32 18} + +// VPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// VPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-version", i32 34} + +// INITFINI: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// INITFINI: !{i32 1, !"aarch64-elf-pauthabi-version", i32 66} + +// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} + +void foo() {} diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c index 1a69b2c6edfb..027ed3a5d9ef 100644 --- a/clang/test/Driver/aarch64-ptrauth.c +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -1,5 +1,44 @@ +// RUN: %clang -### -c --target=aarch64 %s 2>&1 | FileCheck %s --check-prefix NONE +// NONE: "-cc1" +// NONE-NOT: "-fptrauth- + // RUN: %clang -### -c --target=aarch64 -fno-ptrauth-intrinsics -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=INTRIN // INTRIN: "-cc1"{{.*}} "-fptrauth-intrinsics" -// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=ERR -// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-calls -fptrauth-calls %s 2>&1 | FileCheck %s --check-prefix=CALL +// CALL: "-cc1"{{.*}} "-fptrauth-calls" + +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-returns -fptrauth-returns %s 2>&1 | FileCheck %s --check-prefix=RETURN +// RETURN: "-cc1"{{.*}} "-fptrauth-returns" + +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-auth-traps -fptrauth-auth-traps %s 2>&1 | FileCheck %s --check-prefix=TRAP +// TRAP: "-cc1"{{.*}} "-fptrauth-auth-traps" + +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-address-discrimination %s 2>&1 | FileCheck %s --check-prefix=VPTRADDR +// VPTRADDR: "-cc1"{{.*}} "-fptrauth-vtable-pointer-address-discrimination" + +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination %s 2>&1 | FileCheck %s --check-prefix=VPTRTYPE +// VPTRTYPE: "-cc1"{{.*}} "-fptrauth-vtable-pointer-type-discrimination" + +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-init-fini -fptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=INITFINI +// INITFINI: "-cc1"{{.*}} "-fptrauth-init-fini" + +// RUN: %clang -### -c --target=aarch64-elf -fno-ptrauth-elf-got -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=ELFGOT +// ELFGOT: "-cc1"{{.*}} "-fptrauth-elf-got" + +// RUN: %clang -### -c --target=aarch64-darwin -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=NOELFGOT +// NOELFGOT: warning: -fptrauth-elf-got works only for ELF; option ignored [-Woption-ignored] + +// 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-init-fini -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-auth-traps' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-address-discrimination' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-type-discrimination' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-init-fini' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-elf-got' for target '{{.*}}' diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index e45c6ea90fd1..ba256384199f 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -1,5 +1,75 @@ -// RUN: %clang_cc1 %s -E -triple=arm64-- | FileCheck %s --check-prefixes=NOINTRIN -// RUN: %clang_cc1 %s -E -triple=arm64-- -fptrauth-intrinsics | FileCheck %s --check-prefixes=INTRIN +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=NOINTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,NOCALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,NORETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-init-fini \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,INITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-elf-got | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,ELFGOT + +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-init-fini | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOELFGOT #if __has_feature(ptrauth_intrinsics) // INTRIN: has_ptrauth_intrinsics @@ -8,3 +78,60 @@ void has_ptrauth_intrinsics() {} // NOINTRIN: no_ptrauth_intrinsics void no_ptrauth_intrinsics() {} #endif + +#if __has_feature(ptrauth_calls) +// CALLS: has_ptrauth_calls +void has_ptrauth_calls() {} +#else +// NOCALLS: no_ptrauth_calls +void no_ptrauth_calls() {} +#endif + +// This is always enabled when ptrauth_calls is enabled +#if __has_feature(ptrauth_member_function_pointer_type_discrimination) +// CALLS: has_ptrauth_member_function_pointer_type_discrimination +void has_ptrauth_member_function_pointer_type_discrimination() {} +#else +// NOCALLS: no_ptrauth_member_function_pointer_type_discrimination +void no_ptrauth_member_function_pointer_type_discrimination() {} +#endif + +#if __has_feature(ptrauth_returns) +// RETS: has_ptrauth_returns +void has_ptrauth_returns() {} +#else +// NORETS: no_ptrauth_returns +void no_ptrauth_returns() {} +#endif + +#if __has_feature(ptrauth_vtable_pointer_address_discrimination) +// VPTR_ADDR_DISCR: has_ptrauth_vtable_pointer_address_discrimination +void has_ptrauth_vtable_pointer_address_discrimination() {} +#else +// NOVPTR_ADDR_DISCR: no_ptrauth_vtable_pointer_address_discrimination +void no_ptrauth_vtable_pointer_address_discrimination() {} +#endif + +#if __has_feature(ptrauth_vtable_pointer_type_discrimination) +// VPTR_TYPE_DISCR: has_ptrauth_vtable_pointer_type_discrimination +void has_ptrauth_vtable_pointer_type_discrimination() {} +#else +// NOVPTR_TYPE_DISCR: no_ptrauth_vtable_pointer_type_discrimination +void no_ptrauth_vtable_pointer_type_discrimination() {} +#endif + +#if __has_feature(ptrauth_init_fini) +// INITFINI: has_ptrauth_init_fini +void has_ptrauth_init_fini() {} +#else +// NOINITFINI: no_ptrauth_init_fini +void no_ptrauth_init_fini() {} +#endif + +#if __has_feature(ptrauth_elf_got) +// ELFGOT: has_ptrauth_elf_got +void has_ptrauth_elf_got() {} +#else +// NOELFGOT: no_ptrauth_elf_got +void no_ptrauth_elf_got() {} +#endif diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 2bf6e2c6c851..d10f8177c60d 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -169,11 +169,19 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: return R_GOT; + case R_AARCH64_AUTH_GOT_LO12_NC: + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: + return R_AARCH64_AUTH_GOT; + case R_AARCH64_AUTH_GOT_LD_PREL19: + case R_AARCH64_AUTH_GOT_ADR_PREL21: + return R_AARCH64_AUTH_GOT_PC; case R_AARCH64_LD64_GOTPAGE_LO15: return R_AARCH64_GOT_PAGE; case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: return R_AARCH64_GOT_PAGE_PC; + case R_AARCH64_AUTH_ADR_GOT_PAGE: + return R_AARCH64_AUTH_GOT_PAGE_PC; case R_AARCH64_GOTPCREL32: return R_GOT_PC; case R_AARCH64_NONE: @@ -224,6 +232,7 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const { return read64(buf + 8); case R_AARCH64_NONE: case R_AARCH64_GLOB_DAT: + case R_AARCH64_AUTH_GLOB_DAT: case R_AARCH64_JUMP_SLOT: return 0; case R_AARCH64_ABS16: @@ -429,9 +438,11 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write64(loc, val); break; case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: or32AArch64Imm(loc, val); break; case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_AUTH_ADR_GOT_PAGE: case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case R_AARCH64_TLSDESC_ADR_PAGE21: @@ -441,6 +452,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write32AArch64Addr(loc, val >> 12); break; case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_AUTH_GOT_ADR_PREL21: checkInt(loc, val, 21, rel); write32AArch64Addr(loc, val); break; @@ -460,6 +472,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, break; case R_AARCH64_CONDBR19: case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_AUTH_GOT_LD_PREL19: checkAlignment(loc, val, 4, rel); checkInt(loc, val, 21, rel); or32le(loc, (val & 0x1FFFFC) << 3); @@ -480,6 +493,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, break; case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_AUTH_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: case R_AARCH64_TLSDESC_LD64_LO12: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index fa48552b8f7a..0ecbc928bff8 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -691,6 +691,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_ARM_SBREL: return sym.getVA(a) - getARMStaticBase(sym); case R_GOT: + case R_AARCH64_AUTH_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return sym.getGotVA() + a; case R_LOONGARCH_GOT: @@ -718,11 +719,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_RELAX_TLS_GD_TO_IE_GOT_OFF: return sym.getGotOffset() + a; case R_AARCH64_GOT_PAGE_PC: + case R_AARCH64_AUTH_GOT_PAGE_PC: case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(sym.getGotVA() + a) - getAArch64Page(p); case R_AARCH64_GOT_PAGE: return sym.getGotVA() + a - getAArch64Page(in.got->getVA()); case R_GOT_PC: + case R_AARCH64_AUTH_GOT_PC: case R_RELAX_TLS_GD_TO_IE: return sym.getGotVA() + a - p; case R_GOTPLT_GOTREL: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 04db413a6609..550d1a538281 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -209,10 +209,11 @@ static bool needsPlt(RelExpr expr) { } bool lld::elf::needsGot(RelExpr expr) { - return oneof( - expr); + return oneof(expr); } // True if this expression is of the form Sym - X, where X is a position in the @@ -924,13 +925,25 @@ void elf::addGotEntry(Symbol &sym) { // If preemptible, emit a GLOB_DAT relocation. if (sym.isPreemptible) { - mainPart->relaDyn->addReloc({target->gotRel, in.got.get(), off, + RelType gotRel = target->gotRel; + if (sym.hasFlag(NEEDS_GOT_AUTH)) { + assert(config->emachine == EM_AARCH64); + gotRel = R_AARCH64_AUTH_GLOB_DAT; + } + mainPart->relaDyn->addReloc({gotRel, in.got.get(), off, DynamicReloc::AgainstSymbol, sym, 0, R_ABS}); return; } // Otherwise, the value is either a link-time constant or the load base - // plus a constant. + // plus a constant. Signed GOT requires dynamic relocation. + if (sym.hasFlag(NEEDS_GOT_AUTH)) { + in.got->getPartition().relaDyn->addReloc( + {R_AARCH64_AUTH_RELATIVE, in.got.get(), off, + DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS}); + return; + } + if (!config->isPic || isAbsolute(sym)) in.got->addConstant({R_ABS, target->symbolicRel, off, 0, &sym}); else @@ -983,11 +996,12 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, // These expressions always compute a constant if (oneof(e)) + R_AARCH64_GOT_PAGE_PC, R_AARCH64_AUTH_GOT_PAGE_PC, R_GOT_PC, + R_GOTONLY_PC, R_GOTPLTONLY_PC, R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT, + R_GOTPLT_GOTREL, R_GOTPLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT, + R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE, + R_AARCH64_AUTH_GOT, R_AARCH64_AUTH_GOT_PC, R_LOONGARCH_PLT_PAGE_PC, + R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>(e)) return true; // These never do, except if the entire file is position dependent or if @@ -1099,7 +1113,18 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, } else if (!sym.isTls() || config->emachine != EM_LOONGARCH) { // Many LoongArch TLS relocs reuse the R_LOONGARCH_GOT type, in which // case the NEEDS_GOT flag shouldn't get set. - sym.setFlags(NEEDS_GOT); + bool needsGotAuth = + (expr == R_AARCH64_AUTH_GOT || expr == R_AARCH64_AUTH_GOT_PC || + expr == R_AARCH64_AUTH_GOT_PAGE_PC); + if (!sym.hasFlag(NEEDS_GOT)) { + sym.setFlags(NEEDS_GOT); + if (needsGotAuth) + sym.setFlags(NEEDS_GOT_AUTH); + } else if (needsGotAuth != sym.hasFlag(NEEDS_GOT_AUTH)) { + fatal("both AUTH and non-AUTH GOT entries for '" + sym.getName() + + "' requested, but only one type of GOT entry per symbol is " + "supported"); + } } } else if (needsPlt(expr)) { sym.setFlags(NEEDS_PLT); diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index b7b9c09e1b89..692476a98d78 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -83,7 +83,10 @@ enum RelExpr { // of a relocation type, there are some relocations whose semantics are // unique to a target. Such relocation are marked with R_. R_AARCH64_GOT_PAGE_PC, + R_AARCH64_AUTH_GOT_PAGE_PC, R_AARCH64_GOT_PAGE, + R_AARCH64_AUTH_GOT, + R_AARCH64_AUTH_GOT_PC, R_AARCH64_PAGE_PC, R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, R_AARCH64_TLSDESC_PAGE, diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c65c5d6cd0dc..c8aa3d937af0 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -54,6 +54,7 @@ enum { NEEDS_TLSGD_TO_IE = 1 << 6, NEEDS_GOT_DTPREL = 1 << 7, NEEDS_TLSIE = 1 << 8, + NEEDS_GOT_AUTH = 1 << 9, }; // Some index properties of a symbol are stored separately in this auxiliary diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 7b9ada40c0f6..2b4219344081 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -655,6 +655,10 @@ void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); } void GotSection::addEntry(const Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().gotIdx = numEntries++; + if (sym.hasFlag(NEEDS_GOT_AUTH)) { + assert(config->emachine == EM_AARCH64); + authEntries.push_back({(numEntries - 1) * config->wordsize, sym.isFunc()}); + } } bool GotSection::addTlsDescEntry(const Symbol &sym) { @@ -718,6 +722,21 @@ void GotSection::writeTo(uint8_t *buf) { return; target->writeGotHeader(buf); target->relocateAlloc(*this, buf); + for (const AuthEntryInfo &authEntry : authEntries) { + // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema + // Signed GOT entries use the IA key for symbols of type STT_FUNC and the + // DA key for all other symbol types, with the address of the GOT entry as + // the modifier. The static linker must encode the signing schema into the + // GOT slot. + // + // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#encoding-the-signing-schema + // If address diversity is set and the discriminator + // is 0 then modifier = Place + uint8_t *dest = buf + authEntry.offset; + uint64_t key = authEntry.isSymbolFunc ? /*IA*/ 0b00 : /*DA*/ 0b10; + uint64_t addrDiversity = 1; + write64(dest, (addrDiversity << 63) | (key << 60)); + } } static uint64_t getMipsPageAddr(uint64_t addr) { diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 995fd4b344b0..6a217cd9af45 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -131,6 +131,11 @@ class GotSection final : public SyntheticSection { size_t numEntries = 0; uint32_t tlsIndexOff = -1; uint64_t size = 0; + struct AuthEntryInfo { + size_t offset; + bool isSymbolFunc; + }; + SmallVector authEntries; }; // .note.GNU-stack section. diff --git a/lld/test/ELF/aarch64-auth-got-relocations.s b/lld/test/ELF/aarch64-auth-got-relocations.s new file mode 100644 index 000000000000..c43f1ca251a9 --- /dev/null +++ b/lld/test/ELF/aarch64-auth-got-relocations.s @@ -0,0 +1,167 @@ +# REQUIRES: aarch64 + +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o a.o +# RUN: ld.lld -shared a.o -o a.so + +#--- ok.s + +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux ok.s -o ok.o + +# RUN: ld.lld ok.o a.so -pie -o external +# RUN: llvm-readelf -r -S -x .got external | FileCheck %s --check-prefix=EXTERNAL + +# RUN: ld.lld ok.o a.o -pie -o local +# RUN: llvm-readelf -r -S -x .got -s local | FileCheck %s --check-prefix=LOCAL + +# EXTERNAL: Offset Info Type Symbol's Value Symbol's Name + Addend +# EXTERNAL-NEXT: 0000000000020380 000000010000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0 +# EXTERNAL-NEXT: 0000000000020388 000000020000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 zed + 0 + +## Symbol's values for bar and zed are equal since they contain no content (see Inputs/shared.s) +# LOCAL: Offset Info Type Symbol's Value Symbol's Name + Addend +# LOCAL-NEXT: 0000000000020320 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 +# LOCAL-NEXT: 0000000000020328 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 + +# EXTERNAL: Hex dump of section '.got': +# EXTERNAL-NEXT: 0x00020380 00000000 00000080 00000000 000000a0 +# ^^ +# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA +# ^^ +# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA + +# LOCAL: Symbol table '.symtab' contains {{.*}} entries: +# LOCAL: Num: Value Size Type Bind Vis Ndx Name +# LOCAL: 0000000000010260 0 FUNC GLOBAL DEFAULT 6 bar +# LOCAL: 0000000000010260 0 NOTYPE GLOBAL DEFAULT 6 zed + +# LOCAL: Hex dump of section '.got': +# LOCAL-NEXT: 0x00020320 00000000 00000080 00000000 000000a0 +# ^^ +# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA +# ^^ +# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA + +# RUN: llvm-objdump -d external | FileCheck %s --check-prefix=EXTERNAL-ASM + +# EXTERNAL-ASM: <_start>: +# EXTERNAL-ASM-NEXT: adrp x0, 0x20000 +# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x380] +# EXTERNAL-ASM-NEXT: adrp x1, 0x20000 +# EXTERNAL-ASM-NEXT: add x1, x1, #0x380 +# EXTERNAL-ASM-NEXT: adrp x0, 0x20000 +# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x388] +# EXTERNAL-ASM-NEXT: adrp x1, 0x20000 +# EXTERNAL-ASM-NEXT: add x1, x1, #0x388 + +# RUN: llvm-objdump -d local | FileCheck %s --check-prefix=LOCAL-ASM + +# LOCAL-ASM: <_start>: +# LOCAL-ASM-NEXT: adrp x0, 0x20000 +# LOCAL-ASM-NEXT: ldr x0, [x0, #0x320] +# LOCAL-ASM-NEXT: adrp x1, 0x20000 +# LOCAL-ASM-NEXT: add x1, x1, #0x320 +# LOCAL-ASM-NEXT: adrp x0, 0x20000 +# LOCAL-ASM-NEXT: ldr x0, [x0, #0x328] +# LOCAL-ASM-NEXT: adrp x1, 0x20000 +# LOCAL-ASM-NEXT: add x1, x1, #0x328 + +.globl _start +_start: + adrp x0, :got_auth:bar + ldr x0, [x0, :got_auth_lo12:bar] + adrp x1, :got_auth:bar + add x1, x1, :got_auth_lo12:bar + adrp x0, :got_auth:zed + ldr x0, [x0, :got_auth_lo12:zed] + adrp x1, :got_auth:zed + add x1, x1, :got_auth_lo12:zed + +#--- ok-tiny.s + +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux ok-tiny.s -o ok-tiny.o + +# RUN: ld.lld ok-tiny.o a.so -pie -o external-tiny +# RUN: llvm-readelf -r -S -x .got external-tiny | FileCheck %s --check-prefix=EXTERNAL-TINY + +# RUN: ld.lld ok-tiny.o a.o -pie -o local-tiny +# RUN: llvm-readelf -r -S -x .got -s local-tiny | FileCheck %s --check-prefix=LOCAL-TINY + +# EXTERNAL-TINY: Offset Info Type Symbol's Value Symbol's Name + Addend +# EXTERNAL-TINY-NEXT: 0000000000020380 000000010000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0 +# EXTERNAL-TINY-NEXT: 0000000000020388 000000020000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 zed + 0 + +## Symbol's values for bar and zed are equal since they contain no content (see Inputs/shared.s) +# LOCAL-TINY: Offset Info Type Symbol's Value Symbol's Name + Addend +# LOCAL-TINY-NEXT: 0000000000020320 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 +# LOCAL-TINY-NEXT: 0000000000020328 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 + +# EXTERNAL-TINY: Hex dump of section '.got': +# EXTERNAL-TINY-NEXT: 0x00020380 00000000 00000080 00000000 000000a0 +# ^^ +# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA +# ^^ +# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA + +# LOCAL-TINY: Symbol table '.symtab' contains {{.*}} entries: +# LOCAL-TINY: Num: Value Size Type Bind Vis Ndx Name +# LOCAL-TINY: 0000000000010260 0 FUNC GLOBAL DEFAULT 6 bar +# LOCAL-TINY: 0000000000010260 0 NOTYPE GLOBAL DEFAULT 6 zed + +# LOCAL-TINY: Hex dump of section '.got': +# LOCAL-TINY-NEXT: 0x00020320 00000000 00000080 00000000 000000a0 +# ^^ +# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA +# ^^ +# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA + +# RUN: llvm-objdump -d external-tiny | FileCheck %s --check-prefix=EXTERNAL-TINY-ASM + +# EXTERNAL-TINY-ASM: <_start>: +# EXTERNAL-TINY-ASM-NEXT: adr x0, 0x20380 +# EXTERNAL-TINY-ASM-NEXT: ldr x1, [x0] +# EXTERNAL-TINY-ASM-NEXT: adr x0, 0x20380 +# EXTERNAL-TINY-ASM-NEXT: ldr x1, 0x20380 +# EXTERNAL-TINY-ASM-NEXT: adr x0, 0x20388 +# EXTERNAL-TINY-ASM-NEXT: ldr x1, [x0] +# EXTERNAL-TINY-ASM-NEXT: adr x0, 0x20388 +# EXTERNAL-TINY-ASM-NEXT: ldr x1, 0x20388 + +# RUN: llvm-objdump -d local-tiny | FileCheck %s --check-prefix=LOCAL-TINY-ASM + +# LOCAL-TINY-ASM: <_start>: +# LOCAL-TINY-ASM-NEXT: adr x0, 0x20320 +# LOCAL-TINY-ASM-NEXT: ldr x1, [x0] +# LOCAL-TINY-ASM-NEXT: adr x0, 0x20320 +# LOCAL-TINY-ASM-NEXT: ldr x1, 0x20320 +# LOCAL-TINY-ASM-NEXT: adr x0, 0x20328 +# LOCAL-TINY-ASM-NEXT: ldr x1, [x0] +# LOCAL-TINY-ASM-NEXT: adr x0, 0x20328 +# LOCAL-TINY-ASM-NEXT: ldr x1, 0x20328 + +.globl _start +_start: + adr x0, :got_auth:bar + ldr x1, [x0] + adr x0, :got_auth:bar + ldr x1, :got_auth:bar + adr x0, :got_auth:zed + ldr x1, [x0] + adr x0, :got_auth:zed + ldr x1, :got_auth:zed + +#--- err.s + +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux err.s -o err.o + +# RUN: not ld.lld err.o a.so -pie -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: both AUTH and non-AUTH GOT entries for 'bar' requested, but only one type of GOT entry per symbol is supported + +.globl _start +_start: + adrp x0, :got_auth:bar + ldr x0, [x0, :got_auth_lo12:bar] + adrp x0, :got:bar + ldr x0, [x0, :got_lo12:bar] diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 56b5d4e399c6..8eb7a93c24ea 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1770,8 +1770,9 @@ enum : unsigned { AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR = 4, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR = 5, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI = 6, + AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT = 7, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST = - AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI, + AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT, }; // x86 processor feature bits. diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def index cb05db85e2b5..ece8577fe219 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def @@ -144,6 +144,23 @@ ELF_RELOC(R_AARCH64_IRELATIVE, 0x408) // https://github.com/ARM-software/abi-aa ELF_RELOC(R_AARCH64_AUTH_ABS64, 0x244) ELF_RELOC(R_AARCH64_AUTH_RELATIVE, 0x411) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G0, 0x8110) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G0_NC, 0x8111) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G1, 0x8112) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G1_NC, 0x8113) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G2, 0x8114) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G2_NC, 0x8115) +ELF_RELOC(R_AARCH64_AUTH_MOVW_GOTOFF_G3, 0x8116) +ELF_RELOC(R_AARCH64_AUTH_GOT_LD_PREL19, 0x8117) +ELF_RELOC(R_AARCH64_AUTH_LD64_GOTOFF_LO15, 0x8118) +ELF_RELOC(R_AARCH64_AUTH_ADR_GOT_PAGE, 0x8119) +ELF_RELOC(R_AARCH64_AUTH_GOT_LO12_NC, 0x811a) +ELF_RELOC(R_AARCH64_AUTH_LD64_GOTPAGE_LO15, 0x811b) +ELF_RELOC(R_AARCH64_AUTH_GOT_ADD_LO12_NC, 0x811c) +ELF_RELOC(R_AARCH64_AUTH_GOT_ADR_PREL21, 0x811d) +ELF_RELOC(R_AARCH64_AUTH_GLOB_DAT, 0xe201) +ELF_RELOC(R_AARCH64_AUTH_TLSDESC, 0xe202) +ELF_RELOC(R_AARCH64_AUTH_IRELATIVE, 0xe203) // ELF32 // ELF_RELOC(R_AARCH64_P32_NONE, 0) diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 6135e15fd030..694149cc85cf 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -1062,6 +1062,12 @@ class LLVM_EXTERNAL_VISIBILITY Module { /// Set the target variant version build SDK version metadata. void setDarwinTargetVariantSDKVersion(VersionTuple Version); + + /// Check if the module is compiled with signed GOT. + /// @returns true if and only if aarch64-elf-pauthabi-platform module flag + /// equals AARCH64_PAUTH_PLATFORM_LLVM_LINUX and aarch64-elf-pauthabi-version + /// module flag has AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT bit set. + bool hasELFSignedGOT() const; }; /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index a8696ed9e3ce..33f173188680 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/Constants.h" @@ -44,6 +45,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -893,3 +895,20 @@ VersionTuple Module::getDarwinTargetVariantSDKVersion() const { void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) { addSDKVersionMD(Version, *this, "darwin.target_variant.SDK Version"); } + +bool Module::hasELFSignedGOT() const { + if (!Triple(TargetTriple).isOSBinFormatELF()) + return false; + uint64_t PAuthABIPlatform = -1; + if (const auto *PAP = mdconst::extract_or_null( + getModuleFlag("aarch64-elf-pauthabi-platform"))) + PAuthABIPlatform = PAP->getZExtValue(); + if (PAuthABIPlatform != ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX) + return false; + uint64_t PAuthABIVersion = -1; + if (const auto *PAV = mdconst::extract_or_null( + getModuleFlag("aarch64-elf-pauthabi-version"))) + PAuthABIVersion = PAV->getZExtValue(); + return (PAuthABIVersion & + (1 << ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT)) != 0; +} diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 03f0778bae59..09431e4cde40 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -1246,7 +1246,47 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case AArch64::LOADgotAUTH: { + const MachineFunction *MF = MBB.getParent(); + Register DstReg = MI.getOperand(0).getReg(); + const MachineOperand &MO1 = MI.getOperand(1); + DebugLoc DL = MI.getDebugLoc(); + + if (MF->getTarget().getCodeModel() == CodeModel::Tiny) { + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADR), AArch64::X16).add(MO1); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), DstReg) + .addReg(AArch64::X16) + .addImm(0); + } else { + MachineOperand GAHiOp(MO1); + MachineOperand GALoOp(MO1); + GAHiOp.addTargetFlag(AArch64II::MO_PAGE); + GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADRP), AArch64::X16).add(GAHiOp); + + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X16) + .addReg(AArch64::X16) + .add(GALoOp) + .addImm(0); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), DstReg) + .addReg(AArch64::X16) + .addImm(0); + } + + assert(MO1.isGlobal()); + assert(MO1.getGlobal()->getValueType() != nullptr); + unsigned AuthOpcode = MO1.getGlobal()->getValueType()->isFunctionTy() + ? AArch64::AUTIA + : AArch64::AUTDA; + BuildMI(MBB, MBBI, DL, TII->get(AuthOpcode), DstReg) + .addReg(DstReg) + .addReg(AArch64::X16); + + MI.eraseFromParent(); + return true; + } case AArch64::LOADgot: { MachineFunction *MF = MBB.getParent(); Register DstReg = MI.getOperand(0).getReg(); diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 62cf6a2c47ac..b1f846a84c96 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -452,6 +452,9 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) { if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO()) return 0; + if (GV->getParent()->hasELFSignedGOT()) + return 0; + unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM); EVT DestEVT = TLI.getValueType(DL, GV->getType(), true); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 3d1453e3beb9..04e5e84e1f19 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -8709,6 +8709,9 @@ SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG, SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags); // FIXME: Once remat is capable of dealing with instructions with register // operands, expand this into two nodes instead of using a wrapper node. + if (DAG.getMachineFunction().getFunction().getParent()->hasELFSignedGOT()) + return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr), + 0); return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr); } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index be53be782077..25bf85ffbc14 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -1689,6 +1689,10 @@ let Predicates = [HasPAuth] in { defm LDRAA : AuthLoad<0, "ldraa", simm10Scaled>; defm LDRAB : AuthLoad<1, "ldrab", simm10Scaled>; + def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>, + Sched<[WriteI, ReadI]> { + let Defs = [X16]; + } } // v9.5-A pointer authentication extensions diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp index 37d621cd2f65..5870696c7219 100644 --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -184,9 +184,16 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, MCSymbol *Sym) const { uint32_t RefFlags = 0; - if (MO.getTargetFlags() & AArch64II::MO_GOT) - RefFlags |= AArch64MCExpr::VK_GOT; - else if (MO.getTargetFlags() & AArch64II::MO_TLS) { + if (MO.getTargetFlags() & AArch64II::MO_GOT) { + // TODO: it's probably better to introduce MO_GOT_AUTH or smth and avoid + // running M->hasELFSignedGOT() every time, but existing flags already cover + // all 12 bits of SubReg_TargetFlags field in MachineOperand, and making the + // field wider breaks static assertions. + const Module *M = + MO.getParent()->getParent()->getParent()->getFunction().getParent(); + RefFlags |= (M->hasELFSignedGOT() ? AArch64MCExpr::VK_GOT_AUTH + : AArch64MCExpr::VK_GOT); + } else if (MO.getTargetFlags() & AArch64II::MO_TLS) { TLSModel::Model Model; if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index a3b966aa6155..fd4b98526711 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -873,6 +873,7 @@ class AArch64Operand : public MCParsedAsmOperand { if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || ELFRefKind == AArch64MCExpr::VK_LO12 || ELFRefKind == AArch64MCExpr::VK_GOT_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || @@ -984,19 +985,20 @@ class AArch64Operand : public MCParsedAsmOperand { int64_t Addend; if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) { - return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF - || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF - || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) - || ELFRefKind == AArch64MCExpr::VK_LO12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC - || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 - || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC - || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 - || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; + return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || + DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF || + (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) || + ELFRefKind == AArch64MCExpr::VK_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || + ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || + ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; } // If it's a constant, it should be a real immediate in range. @@ -3248,6 +3250,7 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE && ELFRefKind != AArch64MCExpr::VK_ABS_PAGE_NC && ELFRefKind != AArch64MCExpr::VK_GOT_PAGE && + ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE && ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 && ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE && ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) { @@ -3290,7 +3293,13 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) { // No modifier was specified at all; this is the syntax for an ELF basic // ADR relocation (unfortunately). Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext()); - } else { + } else if (ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE) { + // For tiny code model, we use :got_auth: operator to fill 21-bit imm of + // adr. It's not actually GOT entry page address but the GOT address + // itself - we just share the same variant kind with :got_auth: operator + // applied for adrp. + // TODO: can we somehow get current TargetMachine object to call + // getCodeModel() on it to ensure we are using tiny code model? return Error(S, "unexpected adr label"); } } @@ -4333,6 +4342,8 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { .Case("got", AArch64MCExpr::VK_GOT_PAGE) .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15) .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12) + .Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE) + .Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12) .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE) .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC) .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1) @@ -5682,6 +5693,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc, // Only allow these with ADDXri/ADDWri if ((ELFRefKind == AArch64MCExpr::VK_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 61f5bc2464ee..aacba7afbeb1 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2819,7 +2819,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } if (OpFlags & AArch64II::MO_GOT) { - I.setDesc(TII.get(AArch64::LOADgot)); + I.setDesc(TII.get(MF.getFunction().getParent()->hasELFSignedGOT() + ? AArch64::LOADgotAUTH + : AArch64::LOADgot)); I.getOperand(1).setTargetFlags(OpFlags); } else if (TM.getCodeModel() == CodeModel::Large && !TM.isPositionIndependent()) { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 6e074b6a63c4..6a583681e7a8 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -149,6 +149,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, } else return ELF::R_AARCH64_PREL64; case AArch64::fixup_aarch64_pcrel_adr_imm21: + if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADR AUTH relocation not supported " + "(LP64 eqv: AUTH_GOT_ADR_PREL21)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_GOT_ADR_PREL21; + } if (SymLoc != AArch64MCExpr::VK_ABS) Ctx.reportError(Fixup.getLoc(), "invalid symbol kind for ADR relocation"); @@ -168,6 +177,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, } if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) return R_CLS(ADR_GOT_PAGE); + if (SymLoc == AArch64MCExpr::VK_GOT_AUTH && !IsNC) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADRP AUTH relocation not supported " + "(LP64 eqv: AUTH_ADR_GOT_PAGE)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_ADR_GOT_PAGE; + } if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC) return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21); if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) @@ -184,6 +202,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return R_CLS(TLSIE_LD_GOTTPREL_PREL19); if (SymLoc == AArch64MCExpr::VK_GOT) return R_CLS(GOT_LD_PREL19); + if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 LDR AUTH relocation not supported " + "(LP64 eqv: AUTH_GOT_LD_PREL19)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_GOT_LD_PREL19; + } return R_CLS(LD_PREL_LO19); case AArch64::fixup_aarch64_pcrel_branch14: return R_CLS(TSTBR14); @@ -211,18 +238,18 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, Target.getAccessVariant() == MCSymbolRefExpr::VK_GOTPCREL) ? ELF::R_AARCH64_GOTPCREL32 : R_CLS(ABS32); - case FK_Data_8: + case FK_Data_8: { + bool IsAuth = (RefKind == AArch64MCExpr::VK_AUTH || + RefKind == AArch64MCExpr::VK_AUTHADDR); if (IsILP32) { Ctx.reportError(Fixup.getLoc(), - "ILP32 8 byte absolute data " - "relocation not supported (LP64 eqv: ABS64)"); + Twine("ILP32 8 byte absolute data " + "relocation not supported (LP64 eqv: ") + + (IsAuth ? "AUTH_ABS64" : "ABS64") + Twine(')')); return ELF::R_AARCH64_NONE; - } else { - if (RefKind == AArch64MCExpr::VK_AUTH || - RefKind == AArch64MCExpr::VK_AUTHADDR) - return ELF::R_AARCH64_AUTH_ABS64; - return ELF::R_AARCH64_ABS64; } + return (IsAuth ? ELF::R_AARCH64_AUTH_ABS64 : ELF::R_AARCH64_ABS64); + } case AArch64::fixup_aarch64_add_imm12: if (RefKind == AArch64MCExpr::VK_DTPREL_HI12) return R_CLS(TLSLD_ADD_DTPREL_HI12); @@ -238,6 +265,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return R_CLS(TLSLE_ADD_TPREL_LO12); if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12) return R_CLS(TLSDESC_ADD_LO12); + if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADD AUTH relocation not supported " + "(LP64 eqv: AUTH_GOT_ADD_LO12_NC)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_GOT_ADD_LO12_NC; + } if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) return R_CLS(ADD_ABS_LO12_NC); @@ -337,19 +373,24 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, case AArch64::fixup_aarch64_ldst_imm12_scale8: if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) return R_CLS(LDST64_ABS_LO12_NC); - if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) { + if ((SymLoc == AArch64MCExpr::VK_GOT || + SymLoc == AArch64MCExpr::VK_GOT_AUTH) && + IsNC) { AArch64MCExpr::VariantKind AddressLoc = AArch64MCExpr::getAddressFrag(RefKind); + bool IsAuth = (SymLoc == AArch64MCExpr::VK_GOT_AUTH); if (!IsILP32) { if (AddressLoc == AArch64MCExpr::VK_LO15) return ELF::R_AARCH64_LD64_GOTPAGE_LO15; - return ELF::R_AARCH64_LD64_GOT_LO12_NC; - } else { - Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store " - "relocation not supported (LP64 eqv: " - "LD64_GOT_LO12_NC)"); - return ELF::R_AARCH64_NONE; + return (IsAuth ? ELF::R_AARCH64_AUTH_GOT_LO12_NC + : ELF::R_AARCH64_LD64_GOT_LO12_NC); } + Ctx.reportError(Fixup.getLoc(), + Twine("ILP32 64-bit load/store " + "relocation not supported (LP64 eqv: ") + + (IsAuth ? "AUTH_GOT_LO12_NC" : "LD64_GOT_LO12_NC") + + Twine(')')); + return ELF::R_AARCH64_NONE; } if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) return R_CLS(TLSLD_LDST64_DTPREL_LO12); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp index 0c5a9d79f6cb..768170281a05 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -30,6 +30,7 @@ const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind, } StringRef AArch64MCExpr::getVariantKindName() const { + // clang-format off switch (static_cast(getKind())) { case VK_CALL: return ""; case VK_LO12: return ":lo12:"; @@ -82,9 +83,13 @@ StringRef AArch64MCExpr::getVariantKindName() const { case VK_TLSDESC_PAGE: return ":tlsdesc:"; case VK_SECREL_LO12: return ":secrel_lo12:"; case VK_SECREL_HI12: return ":secrel_hi12:"; + case VK_GOT_AUTH: return ":got_auth:"; + case VK_GOT_AUTH_PAGE: return ":got_auth:"; + case VK_GOT_AUTH_LO12: return ":got_auth_lo12:"; default: llvm_unreachable("Invalid ELF symbol kind"); } + // clang-format on } void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index 48235988869c..780ae39c15a7 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -24,6 +24,7 @@ namespace llvm { class AArch64MCExpr : public MCTargetExpr { public: enum VariantKind { + // clang-format off // Symbol locations specifying (roughly speaking) what calculation should be // performed to construct the final address for the relocated // symbol. E.g. direct, via the GOT, ... @@ -38,6 +39,7 @@ class AArch64MCExpr : public MCTargetExpr { VK_SECREL = 0x009, VK_AUTH = 0x00a, VK_AUTHADDR = 0x00b, + VK_GOT_AUTH = 0x00c, VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is @@ -88,6 +90,8 @@ class AArch64MCExpr : public MCTargetExpr { VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC, VK_GOT_PAGE = VK_GOT | VK_PAGE, VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC, + VK_GOT_AUTH_LO12 = VK_GOT_AUTH | VK_PAGEOFF | VK_NC, + VK_GOT_AUTH_PAGE = VK_GOT_AUTH | VK_PAGE, VK_DTPREL_G2 = VK_DTPREL | VK_G2, VK_DTPREL_G1 = VK_DTPREL | VK_G1, VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC, @@ -114,6 +118,7 @@ class AArch64MCExpr : public MCTargetExpr { VK_SECREL_HI12 = VK_SECREL | VK_HI12, VK_INVALID = 0xfff + // clang-format on }; private: diff --git a/llvm/test/CodeGen/AArch64/basic-pic-auth.ll b/llvm/test/CodeGen/AArch64/basic-pic-auth.ll new file mode 100644 index 000000000000..32d2098ee63c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/basic-pic-auth.ll @@ -0,0 +1,39 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s + +;; Note: for FastISel, we fall back to SelectionDAG + +@var = global i32 0 + +define i32 @get_globalvar() { +; CHECK-LABEL: get_globalvar: + + %val = load i32, ptr @var + +; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var +; CHECK: add x[[GOT]], x[[GOT]], :got_auth_lo12:var +; CHECK: ldr x[[SYM:[0-9]+]], [x[[GOT]]] +; CHECK: autda x[[SYM]], x[[GOT]] +; CHECK: ldr w0, [x[[SYM]]] + ret i32 %val +} + +define ptr @get_globalvaraddr() { +; CHECK-LABEL: get_globalvaraddr: + + %val = load i32, ptr @var + +; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var +; CHECK: add x[[GOT]], x[[GOT]], :got_auth_lo12:var +; CHECK: ldr x0, [x[[GOT]]] +; CHECK: autda x0, x[[GOT]] + ret ptr @var +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/elf-globals-pic-auth.ll b/llvm/test/CodeGen/AArch64/elf-globals-pic-auth.ll new file mode 100644 index 000000000000..0bf76aeebd2c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/elf-globals-pic-auth.ll @@ -0,0 +1,23 @@ +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s +; RUN: llc -mtriple=arm64 -global-isel=1 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s + +;; Note: for FastISel, we fall back to SelectionDAG + +@var8 = external global i8, align 1 + +define i8 @test_i8(i8 %new) { + %val = load i8, ptr @var8, align 1 + store i8 %new, ptr @var8 + ret i8 %val + +; CHECK: adrp x[[HIREG:[0-9]+]], :got_auth:var8 +; CHECK: add x[[HIREG]], x[[HIREG]], :got_auth_lo12:var8 +; CHECK: ldr x[[VAR_ADDR:[0-9]+]], [x[[HIREG]]] +; CHECK: autda x[[VAR_ADDR]], x[[HIREG]] +; CHECK: ldrb {{w[0-9]+}}, [x[[VAR_ADDR]]] +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/extern-weak-auth.ll b/llvm/test/CodeGen/AArch64/extern-weak-auth.ll new file mode 100644 index 000000000000..605630be4d53 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/extern-weak-auth.ll @@ -0,0 +1,47 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s + +; RUN: llc -mtriple=aarch64-none-elf -code-model=tiny -mattr=+pauth -o - %s | FileCheck --check-prefix=CHECK-TINY %s + +;; Note: for FastISel, we fall back to SelectionDAG + +declare extern_weak dso_local i32 @var() + +define ptr @foo() { +; The usual ADRP/ADD pair can't be used for a weak reference because it must +; evaluate to 0 if the symbol is undefined. We use a GOT entry for PIC +; otherwise a litpool entry. + ret ptr @var + +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:var +; CHECK: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:var +; CHECK: ldr x0, [x[[ADDRHI]]] +; CHECK: autia x0, x[[ADDRHI]] + +; CHECK-TINY: adr x16, :got_auth:var +; CHECK-TINY: ldr x0, [x16] +; CHECK-TINY: autia x0, x16 +} + +@arr_var = extern_weak global [10 x i32] + +define ptr @bar() { + %addr = getelementptr [10 x i32], ptr @arr_var, i32 0, i32 5 + ret ptr %addr + +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:arr_var +; CHECK: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:arr_var +; CHECK: ldr [[BASE:x[0-9]+]], [x[[ADDRHI]]] +; CHECK: autda [[BASE]], x[[ADDRHI]] +; CHECK: add x0, [[BASE]], #20 + +; CHECK-TINY: adr x16, :got_auth:arr_var +; CHECK-TINY: ldr [[BASE:x[0-9]+]], [x16] +; CHECK-TINY: autda [[BASE]], x16 +; CHECK-TINY: add x0, [[BASE]], #20 +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/got-abuse-auth.ll b/llvm/test/CodeGen/AArch64/got-abuse-auth.ll new file mode 100644 index 000000000000..da0aa19ea6bb --- /dev/null +++ b/llvm/test/CodeGen/AArch64/got-abuse-auth.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s + +;; Note: for FastISel, we fall back to SelectionDAG + +declare void @consume(i32) +declare void @func() + +define void @aliasee_func() { + ret void +} +@alias_func = alias void (), ptr @aliasee_func + +@aliasee_global = global i32 42 +@alias_global = alias i32, ptr @aliasee_global + +define void @foo() nounwind { +; CHECK-LABEL: foo: +entry: + call void @consume(i32 ptrtoint (ptr @func to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:func +; CHECK: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:func +; CHECK: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK: autia x[[SYM:[0-9]+]], x[[ADDRHI]] + call void @consume(i32 ptrtoint (ptr @alias_func to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:alias_func +; CHECK: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:alias_func +; CHECK: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK: autia x[[SYM:[0-9]+]], x[[ADDRHI]] + call void @consume(i32 ptrtoint (ptr @alias_global to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:alias_global +; CHECK: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:alias_global +; CHECK: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK: autda x[[SYM:[0-9]+]], x[[ADDRHI]] + ret void +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll index 728cffeba02a..fb69a12b2f90 100644 --- a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll +++ b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll @@ -27,7 +27,7 @@ ; OBJ: Displaying notes found in: .note.gnu.property ; OBJ-NEXT: Owner Data size Description ; OBJ-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note) -; OBJ-NEXT: AArch64 PAuth ABI core info: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini) +; OBJ-NEXT: AArch64 PAuth ABI core info: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini, !PointerAuthELFGOT) ; ERR: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present diff --git a/llvm/test/CodeGen/AArch64/tagged-globals-pic-auth.ll b/llvm/test/CodeGen/AArch64/tagged-globals-pic-auth.ll new file mode 100644 index 000000000000..d0ba1c2bb9e2 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/tagged-globals-pic-auth.ll @@ -0,0 +1,66 @@ +; RUN: llc --relocation-model=pic -mattr=+pauth < %s | FileCheck %s + +; RUN: llc -global-isel=0 -fast-isel=0 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL +; RUN: llc -global-isel=0 -fast-isel=1 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL +; RUN: llc -global-isel=1 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,GISEL + +;; Note: for FastISel, we fall back to SelectionDAG + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-android" + +@global = external global i32 +declare void @func() + +define ptr @global_addr() #0 { + ; CHECK: global_addr: + ; CHECK: adrp [[REG:x[0-9]+]], :got_auth:global + ; CHECK: add [[REG]], [[REG]], :got_auth_lo12:global + ; CHECK: ldr x0, [[[REG]]] + ; CHECK: autda x0, [[REG]] + ; CHECK: ret + + ret ptr @global +} + +define i32 @global_load() #0 { + ; CHECK: global_load: + ; CHECK: adrp [[REG0:x[0-9]+]], :got_auth:global + ; CHECK: add [[REG0]], [[REG0]], :got_auth_lo12:global + ; CHECK: ldr [[REG1:x[0-9]+]], [[[REG0]]] + ; CHECK: autda [[REG1]], [[REG0]] + ; CHECK: ldr w0, [[[REG1]]] + ; CHECK: ret + %load = load i32, ptr @global + ret i32 %load +} + +define void @global_store() #0 { + ; CHECK: global_store: + ; CHECK: adrp [[REG0:x[0-9]+]], :got_auth:global + ; CHECK: add [[REG0]], [[REG0]], :got_auth_lo12:global + ; CHECK: ldr [[REG1:x[0-9]+]], [[[REG0]]] + ; CHECK: autda [[REG1]], [[REG0]] + ; GISEL: str wzr, [[[REG1]]] + ; DAGISEL: mov w8, wzr + ; DAGISEL: str w8, [[[REG1]]] + ; CHECK: ret + store i32 0, ptr @global + ret void +} + +define ptr @func_addr() #0 { + ; CHECK: func_addr: + ; CHECK: adrp [[REG:x[0-9]+]], :got_auth:func + ; CHECK: add [[REG]], [[REG]], :got_auth_lo12:func + ; CHECK: ldr x0, [[[REG]]] + ; CHECK: autia x0, [[REG]] + ; CHECK: ret + ret ptr @func +} + +attributes #0 = { "target-features"="+tagged-globals" } + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/tiny-model-pic-auth.ll b/llvm/test/CodeGen/AArch64/tiny-model-pic-auth.ll new file mode 100644 index 000000000000..6d602afc53ef --- /dev/null +++ b/llvm/test/CodeGen/AArch64/tiny-model-pic-auth.ll @@ -0,0 +1,148 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK-PIC +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny -relocation-model=pic -fast-isel < %s | FileCheck %s --check-prefix=CHECK-PIC +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny -relocation-model=pic -global-isel < %s | FileCheck %s --check-prefix=CHECK-PIC-GLOBISEL + +; TODO Note fast-isel tests here will fall back to isel + +@src = external local_unnamed_addr global [65536 x i8], align 1 +@dst = external global [65536 x i8], align 1 +@ptr = external local_unnamed_addr global ptr, align 8 + +define dso_preemptable void @foo1() { +; CHECK-PIC-LABEL: foo1: +; CHECK-PIC: // %bb.0: // %entry +; CHECK-PIC-NEXT: adr x16, :got_auth:src +; CHECK-PIC-NEXT: ldr x8, [x16] +; CHECK-PIC-NEXT: autda x8, x16 +; CHECK-PIC-NEXT: adr x16, :got_auth:dst +; CHECK-PIC-NEXT: ldrb w8, [x8] +; CHECK-PIC-NEXT: ldr x9, [x16] +; CHECK-PIC-NEXT: autda x9, x16 +; CHECK-PIC-NEXT: strb w8, [x9] +; CHECK-PIC-NEXT: ret +; +; CHECK-PIC-GLOBISEL-LABEL: foo1: +; CHECK-PIC-GLOBISEL: // %bb.0: // %entry +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:src +; CHECK-PIC-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x8, x16 +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:dst +; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8] +; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x9, x16 +; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9] +; CHECK-PIC-GLOBISEL-NEXT: ret +entry: + %0 = load i8, ptr @src, align 1 + store i8 %0, ptr @dst, align 1 + ret void +} + +define dso_preemptable void @foo2() { +; CHECK-PIC-LABEL: foo2: +; CHECK-PIC: // %bb.0: // %entry +; CHECK-PIC-NEXT: adr x16, :got_auth:ptr +; CHECK-PIC-NEXT: ldr x8, [x16] +; CHECK-PIC-NEXT: autda x8, x16 +; CHECK-PIC-NEXT: adr x16, :got_auth:dst +; CHECK-PIC-NEXT: ldr x9, [x16] +; CHECK-PIC-NEXT: autda x9, x16 +; CHECK-PIC-NEXT: str x9, [x8] +; CHECK-PIC-NEXT: ret +; +; CHECK-PIC-GLOBISEL-LABEL: foo2: +; CHECK-PIC-GLOBISEL: // %bb.0: // %entry +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:ptr +; CHECK-PIC-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x8, x16 +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:dst +; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x9, x16 +; CHECK-PIC-GLOBISEL-NEXT: str x9, [x8] +; CHECK-PIC-GLOBISEL-NEXT: ret +entry: + store ptr @dst, ptr @ptr, align 8 + ret void +} + +define dso_preemptable void @foo3() { +; FIXME: Needn't adr ptr +; +; CHECK-PIC-LABEL: foo3: +; CHECK-PIC: // %bb.0: // %entry +; CHECK-PIC-NEXT: adr x16, :got_auth:src +; CHECK-PIC-NEXT: ldr x8, [x16] +; CHECK-PIC-NEXT: autda x8, x16 +; CHECK-PIC-NEXT: adr x16, :got_auth:ptr +; CHECK-PIC-NEXT: ldrb w8, [x8] +; CHECK-PIC-NEXT: ldr x9, [x16] +; CHECK-PIC-NEXT: autda x9, x16 +; CHECK-PIC-NEXT: ldr x9, [x9] +; CHECK-PIC-NEXT: strb w8, [x9] +; CHECK-PIC-NEXT: ret +; +; CHECK-PIC-GLOBISEL-LABEL: foo3: +; CHECK-PIC-GLOBISEL: // %bb.0: // %entry +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:src +; CHECK-PIC-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x8, x16 +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:ptr +; CHECK-PIC-GLOBISEL-NEXT: ldrb w8, [x8] +; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autda x9, x16 +; CHECK-PIC-GLOBISEL-NEXT: ldr x9, [x9] +; CHECK-PIC-GLOBISEL-NEXT: strb w8, [x9] +; CHECK-PIC-GLOBISEL-NEXT: ret +entry: + %0 = load i8, ptr @src, align 1 + %1 = load ptr, ptr @ptr, align 8 + store i8 %0, ptr %1, align 1 + ret void +} + +@lsrc = internal global i8 0, align 4 +@ldst = internal global i8 0, align 4 +@lptr = internal global ptr null, align 8 + +declare void @func(...) + +define dso_preemptable ptr @externfuncaddr() { +; CHECK-PIC-LABEL: externfuncaddr: +; CHECK-PIC: // %bb.0: // %entry +; CHECK-PIC-NEXT: adr x16, :got_auth:func +; CHECK-PIC-NEXT: ldr x0, [x16] +; CHECK-PIC-NEXT: autia x0, x16 +; CHECK-PIC-NEXT: ret +; +; CHECK-PIC-GLOBISEL-LABEL: externfuncaddr: +; CHECK-PIC-GLOBISEL: // %bb.0: // %entry +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:func +; CHECK-PIC-GLOBISEL-NEXT: ldr x0, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autia x0, x16 +; CHECK-PIC-GLOBISEL-NEXT: ret +entry: + ret ptr @func +} + +define dso_preemptable ptr @localfuncaddr() { +; CHECK-PIC-LABEL: localfuncaddr: +; CHECK-PIC: // %bb.0: // %entry +; CHECK-PIC-NEXT: adr x16, :got_auth:externfuncaddr +; CHECK-PIC-NEXT: ldr x0, [x16] +; CHECK-PIC-NEXT: autia x0, x16 +; CHECK-PIC-NEXT: ret +; +; CHECK-PIC-GLOBISEL-LABEL: localfuncaddr: +; CHECK-PIC-GLOBISEL: // %bb.0: // %entry +; CHECK-PIC-GLOBISEL-NEXT: adr x16, :got_auth:externfuncaddr +; CHECK-PIC-GLOBISEL-NEXT: ldr x0, [x16] +; CHECK-PIC-GLOBISEL-NEXT: autia x0, x16 +; CHECK-PIC-GLOBISEL-NEXT: ret +entry: + ret ptr @externfuncaddr +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/CodeGen/AArch64/tiny-model-static-auth.ll b/llvm/test/CodeGen/AArch64/tiny-model-static-auth.ll new file mode 100644 index 000000000000..4e8b1bedfb51 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/tiny-model-static-auth.ll @@ -0,0 +1,126 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -code-model=tiny < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -code-model=tiny -fast-isel < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -code-model=tiny -global-isel < %s | FileCheck %s --check-prefix=CHECK-GLOBISEL + +; Note fast-isel tests here will fall back to isel + +@src = external local_unnamed_addr global [65536 x i8], align 1 +@dst = external global [65536 x i8], align 1 +@ptr = external local_unnamed_addr global ptr, align 8 + +define dso_local void @foo1() { +; CHECK-LABEL: foo1: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x16, :got_auth:src +; CHECK-NEXT: ldr x8, [x16] +; CHECK-NEXT: autda x8, x16 +; CHECK-NEXT: adr x16, :got_auth:dst +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: ldr x9, [x16] +; CHECK-NEXT: autda x9, x16 +; CHECK-NEXT: strb w8, [x9] +; CHECK-NEXT: ret +; +; CHECK-GLOBISEL-LABEL: foo1: +; CHECK-GLOBISEL: // %bb.0: // %entry +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:src +; CHECK-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-GLOBISEL-NEXT: autda x8, x16 +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:dst +; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] +; CHECK-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-GLOBISEL-NEXT: autda x9, x16 +; CHECK-GLOBISEL-NEXT: strb w8, [x9] +; CHECK-GLOBISEL-NEXT: ret +entry: + %0 = load i8, ptr @src, align 1 + store i8 %0, ptr @dst, align 1 + ret void +} + +define dso_local void @foo2() { +; CHECK-LABEL: foo2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x16, :got_auth:ptr +; CHECK-NEXT: ldr x8, [x16] +; CHECK-NEXT: autda x8, x16 +; CHECK-NEXT: adr x16, :got_auth:dst +; CHECK-NEXT: ldr x9, [x16] +; CHECK-NEXT: autda x9, x16 +; CHECK-NEXT: str x9, [x8] +; CHECK-NEXT: ret +; +; CHECK-GLOBISEL-LABEL: foo2: +; CHECK-GLOBISEL: // %bb.0: // %entry +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:ptr +; CHECK-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-GLOBISEL-NEXT: autda x8, x16 +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:dst +; CHECK-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-GLOBISEL-NEXT: autda x9, x16 +; CHECK-GLOBISEL-NEXT: str x9, [x8] +; CHECK-GLOBISEL-NEXT: ret +entry: + store ptr @dst, ptr @ptr, align 8 + ret void +} + +define dso_local void @foo3() { +; FIXME: Needn't adr ptr +; +; CHECK-LABEL: foo3: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x16, :got_auth:src +; CHECK-NEXT: ldr x8, [x16] +; CHECK-NEXT: autda x8, x16 +; CHECK-NEXT: adr x16, :got_auth:ptr +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: ldr x9, [x16] +; CHECK-NEXT: autda x9, x16 +; CHECK-NEXT: ldr x9, [x9] +; CHECK-NEXT: strb w8, [x9] +; CHECK-NEXT: ret +; +; CHECK-GLOBISEL-LABEL: foo3: +; CHECK-GLOBISEL: // %bb.0: // %entry +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:src +; CHECK-GLOBISEL-NEXT: ldr x8, [x16] +; CHECK-GLOBISEL-NEXT: autda x8, x16 +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:ptr +; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] +; CHECK-GLOBISEL-NEXT: ldr x9, [x16] +; CHECK-GLOBISEL-NEXT: autda x9, x16 +; CHECK-GLOBISEL-NEXT: ldr x9, [x9] +; CHECK-GLOBISEL-NEXT: strb w8, [x9] +; CHECK-GLOBISEL-NEXT: ret +entry: + %0 = load i8, ptr @src, align 1 + %1 = load ptr, ptr @ptr, align 8 + store i8 %0, ptr %1, align 1 + ret void +} + +declare void @func(...) + +define dso_local ptr @externfuncaddr() { +; CHECK-LABEL: externfuncaddr: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x16, :got_auth:func +; CHECK-NEXT: ldr x0, [x16] +; CHECK-NEXT: autia x0, x16 +; CHECK-NEXT: ret +; +; CHECK-GLOBISEL-LABEL: externfuncaddr: +; CHECK-GLOBISEL: // %bb.0: // %entry +; CHECK-GLOBISEL-NEXT: adr x16, :got_auth:func +; CHECK-GLOBISEL-NEXT: ldr x0, [x16] +; CHECK-GLOBISEL-NEXT: autia x0, x16 +; CHECK-GLOBISEL-NEXT: ret +entry: + ret ptr @func +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/MC/AArch64/adrp-auth-relocation.s b/llvm/test/MC/AArch64/adrp-auth-relocation.s new file mode 100644 index 000000000000..57021c71632f --- /dev/null +++ b/llvm/test/MC/AArch64/adrp-auth-relocation.s @@ -0,0 +1,12 @@ +// RUN: llvm-mc -triple=aarch64-linux-gnu -filetype=obj -o - %s | llvm-readobj -r - | FileCheck %s +// RUN: not llvm-mc -triple=aarch64-linux-gnu_ilp32 -filetype=obj \ +// RUN: -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-ILP32 %s + +.text +adrp x0, :got_auth:sym + +.global sym +sym: + +// CHECK: R_AARCH64_AUTH_ADR_GOT_PAGE sym +// CHECK-ILP32: error: ILP32 ADRP AUTH relocation not supported (LP64 eqv: AUTH_ADR_GOT_PAGE) diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s index 8813c4bd7d1a..3e7bd1492016 100644 --- a/llvm/test/MC/AArch64/arm64-elf-relocs.s +++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s @@ -81,13 +81,17 @@ // CHECK: adrp x15, :got:sym // CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym + adrp x15, :got_auth:sym +// CHECK: adrp x15, :got_auth:sym +// CHECK-OBJ-LP64: 5c R_AARCH64_AUTH_ADR_GOT_PAGE sym + adrp x29, :gottprel:sym // CHECK: adrp x29, :gottprel:sym -// CHECK-OBJ-LP64: 5c R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym +// CHECK-OBJ-LP64: 60 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym adrp x2, :tlsdesc:sym // CHECK: adrp x2, :tlsdesc:sym -// CHECK-OBJ-LP64: 60 R_AARCH64_TLSDESC_ADR_PAGE21 sym +// CHECK-OBJ-LP64: 64 R_AARCH64_TLSDESC_ADR_PAGE21 sym // LLVM is not competent enough to do this relocation because the // page boundary could occur anywhere after linking. A relocation @@ -96,7 +100,7 @@ .global trickQuestion trickQuestion: // CHECK: adrp x3, trickQuestion -// CHECK-OBJ-LP64: 64 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion +// CHECK-OBJ-LP64: 68 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion ldrb w2, [x3, :lo12:sym] ldrsb w5, [x7, #:lo12:sym] @@ -245,6 +249,16 @@ trickQuestion: // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym+0x7 + ldr x24, [x23, #:got_auth_lo12:sym] + ldr d22, [x21, :got_auth_lo12:sym] + ldr x24, [x23, :got_auth_lo12:sym+7] +// CHECK: ldr x24, [x23, :got_auth_lo12:sym] +// CHECK: ldr d22, [x21, :got_auth_lo12:sym] +// CHECK: ldr x24, [x23, :got_auth_lo12:sym+7] +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LO12_NC sym+0x7 + ldr x24, [x23, #:gotpage_lo15:sym] ldr d22, [x21, :gotpage_lo15:sym] ldr d22, [x23, :gotpage_lo15:sym+7] @@ -317,6 +331,19 @@ trickQuestion: // CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym // CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym + adr x24, #:got_auth:sym + adr x24, :got_auth:sym + ldr x24, #:got_auth:sym + ldr x24, :got_auth:sym +// CHECK: adr x24, :got_auth:sym +// CHECK: adr x24, :got_auth:sym +// CHECK: ldr x24, :got_auth:sym +// CHECK: ldr x24, :got_auth:sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_ADR_PREL21 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_ADR_PREL21 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym + // GOT relocations referencing local symbols are not converted to reference // STT_SECTION symbols. https://github.com/llvm/llvm-project/issues/63418 ldr x0, [x0, :got_lo12:local0] diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s index 65c9e4ea5a1c..472c140ea36a 100644 --- a/llvm/test/MC/AArch64/ilp32-diagnostics.s +++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s @@ -8,6 +8,14 @@ .xword sym+16 // CHECK-ERROR: error: ILP32 8 byte absolute data relocation not supported (LP64 eqv: ABS64) +// CHECK-ERROR: ^ + + .xword sym@AUTH(da,42) +// CHECK-ERROR: error: ILP32 8 byte absolute data relocation not supported (LP64 eqv: AUTH_ABS64) +// CHECK-ERROR: ^ + + .xword sym@AUTH(da,42,addr) +// CHECK-ERROR: error: ILP32 8 byte absolute data relocation not supported (LP64 eqv: AUTH_ABS64) // CHECK-ERROR: ^ movz x7, #:abs_g3:some_label @@ -77,6 +85,14 @@ ldr x24, [x23, #:got_lo12:sym] // CHECK-ERROR: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: LD64_GOT_LO12_NC) +// CHECK-ERROR: ^ + + ldr x24, [x23, #:got_auth_lo12:sym] +// CHECK-ERROR: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: AUTH_GOT_LO12_NC) +// CHECK-ERROR: ^ + + add x24, x23, #:got_auth_lo12:sym +// CHECK-ERROR: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADD_LO12_NC) // CHECK-ERROR: ^ ldr x24, [x23, :gottprel_lo12:sym] @@ -94,4 +110,12 @@ ldr x24, [x23, :gottprel_lo12:sym] // CHECK-ERROR: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: TLSIE_LD64_GOTTPREL_LO12_NC) +// CHECK-ERROR: ^ + + ldr x24, :got_auth:sym +// CHECK-ERROR: error: ILP32 LDR AUTH relocation not supported (LP64 eqv: AUTH_GOT_LD_PREL19) +// CHECK-ERROR: ^ + + adr x24, :got_auth:sym +// CHECK-ERROR: error: ILP32 ADR AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADR_PREL21) // CHECK-ERROR: ^ diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s index 512531748cd2..65e9b818729e 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s @@ -106,12 +106,12 @@ end: # RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0x10000002-85.s -o gnu-0x10000002-85.o # RUN: llvm-readelf --notes gnu-0x10000002-85.o | \ # RUN: FileCheck --check-prefix=ELF -DPLATFORM="0x10000002 (llvm_linux)" \ -# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s +# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini, !PointerAuthELFGOT)" %s # RUN: llvm-readobj --notes gnu-0x10000002-85.o | \ # RUN: FileCheck --check-prefix=OBJ -DPLATFORM="0x10000002 (llvm_linux)" \ -# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s +# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini, !PointerAuthELFGOT)" %s -#--- gnu-0x10000002-128.s +#--- gnu-0x10000002-256.s .section ".note.gnu.property", "a" .long 4 // Name length is always 4 ("GNU") .long end - begin // Data length @@ -123,15 +123,15 @@ begin: .long 0xc0000001 // Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH .long 16 // Data size .quad 0x10000002 // PAuth ABI platform - .quad 128 // PAuth ABI version + .quad 256 // PAuth ABI version .p2align 3 // Align to 8 byte for 64 bit end: -# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0x10000002-128.s -o gnu-0x10000002-128.o -# RUN: llvm-readelf --notes gnu-0x10000002-128.o | \ -# RUN: FileCheck --check-prefix=ELF -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x80 (unknown)" %s -# RUN: llvm-readobj --notes gnu-0x10000002-128.o | \ -# RUN: FileCheck --check-prefix=OBJ -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x80 (unknown)" %s +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0x10000002-256.s -o gnu-0x10000002-256.o +# RUN: llvm-readelf --notes gnu-0x10000002-256.o | \ +# RUN: FileCheck --check-prefix=ELF -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x100 (unknown)" %s +# RUN: llvm-readobj --notes gnu-0x10000002-256.o | \ +# RUN: FileCheck --check-prefix=OBJ -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x100 (unknown)" %s #--- gnu-short.s .section ".note.gnu.property", "a" diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test index cf95b5170026..8111bfe71c10 100644 --- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test +++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test @@ -130,6 +130,23 @@ # CHECK: Type: R_AARCH64_TLSDESC (1031) # CHECK: Type: R_AARCH64_IRELATIVE (1032) # CHECK: Type: R_AARCH64_AUTH_RELATIVE (1041) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G0 (33040) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G0_NC (33041) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G1 (33042) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G1_NC (33043) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G2 (33044) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G2_NC (33045) +# CHECK: Type: R_AARCH64_AUTH_MOVW_GOTOFF_G3 (33046) +# CHECK: Type: R_AARCH64_AUTH_GOT_LD_PREL19 (33047) +# CHECK: Type: R_AARCH64_AUTH_LD64_GOTOFF_LO15 (33048) +# CHECK: Type: R_AARCH64_AUTH_ADR_GOT_PAGE (33049) +# CHECK: Type: R_AARCH64_AUTH_GOT_LO12_NC (33050) +# CHECK: Type: R_AARCH64_AUTH_LD64_GOTPAGE_LO15 (33051) +# CHECK: Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC (33052) +# CHECK: Type: R_AARCH64_AUTH_GOT_ADR_PREL21 (33053) +# CHECK: Type: R_AARCH64_AUTH_GLOB_DAT (57857) +# CHECK: Type: R_AARCH64_AUTH_TLSDESC (57858) +# CHECK: Type: R_AARCH64_AUTH_IRELATIVE (57859) --- !ELF FileHeader: @@ -267,3 +284,20 @@ Sections: - Type: R_AARCH64_TLSDESC - Type: R_AARCH64_IRELATIVE - Type: R_AARCH64_AUTH_RELATIVE + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G0 + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G0_NC + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G1 + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G1_NC + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G2 + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G2_NC + - Type: R_AARCH64_AUTH_MOVW_GOTOFF_G3 + - Type: R_AARCH64_AUTH_GOT_LD_PREL19 + - Type: R_AARCH64_AUTH_LD64_GOTOFF_LO15 + - Type: R_AARCH64_AUTH_ADR_GOT_PAGE + - Type: R_AARCH64_AUTH_GOT_LO12_NC + - Type: R_AARCH64_AUTH_LD64_GOTPAGE_LO15 + - Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC + - Type: R_AARCH64_AUTH_GOT_ADR_PREL21 + - Type: R_AARCH64_AUTH_GLOB_DAT + - Type: R_AARCH64_AUTH_TLSDESC + - Type: R_AARCH64_AUTH_IRELATIVE diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index f145653ac743..38cfa1fc0a5f 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -5236,8 +5236,9 @@ static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize, Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] = "VTPtrTypeDiscrimination"; Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini"; + Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT] = "ELFGOT"; - static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI == + static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT == AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, "Update when new enum items are defined");