diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 0b257340cf8e25f287c35c3c084356c7e23e0cbc..764f6835bb0d556389cdf28cef2b93e22307aba6 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -105,6 +105,10 @@ FEATURE(gwp_asan, LangOpts.Sanitize.hasOneOf(SanitizerKind::GWPAsan)) FEATURE(swiftasynccc, PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) == clang::TargetInfo::CCCR_OK) +FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT) +// OHOS_LOCAL begin +FEATURE(ptrauth_elf_got_func, LangOpts.PointerAuthFuncELFGOT) +// OHOS_LOCAL end // Objective-C features FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 5d7fd36723e20ff18a0417ddd28abf8ef3149298..f6632b0bd4a0732afdd403bdf0cc4757e607886e 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -157,6 +157,11 @@ LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods" LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments") LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features") +LANGOPT(PointerAuthELFGOT, 1, 0, "authenticate pointers from GOT") +// OHOS_LOCAL begin +LANGOPT(PointerAuthFuncELFGOT, 1, 0, "authenticate function pointers from GOT") +// OHOS_LOCAL end + LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 6f3a3cb8d6d989105ff9fc0bb58c0e43f3c18a63..9d6b0545887c9f4dc0be9f2c5566a6b8700920f9 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3073,6 +3073,11 @@ defm strict_return : BoolFOption<"strict-return", " of a non-void function as unreachable">, PosFlag>; +defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">; +// OHOS_LOCAL begin +defm ptrauth_elf_got_func : OptInCC1FFlag<"ptrauth-elf-got-func", "Enable authentication of function pointers from GOT (ELF only)">; +// OHOS_LOCAL end + def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, Flags<[CC1Option]>, HelpText<"Enable matrix data type and related builtin functions">, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4a5115078270b84c8bcbc1013dee28fab1687539..04fe1e2cb42d28674eaf82003c3f1f7e30caad7d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -824,6 +824,12 @@ void CodeGenModule::Release() { if (!LangOpts.isSignReturnAddressWithAKey()) getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", 1); + if (LangOpts.PointerAuthELFGOT) + getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1); + // OHOS_LOCAL begin + if (LangOpts.PointerAuthFuncELFGOT) + getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got-func", 1); + // OHOS_LOCAL end } if (!CodeGenOpts.MemoryProfileOutput.empty()) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 21699557075ad77e1b12be96464e0e4fe5bbecec..49af5907a506178702335f9fd6c98ed0f33903cc 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1975,6 +1975,13 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back(A->getValue()); } + if (Args.hasArg(options::OPT_fptrauth_elf_got)) + CmdArgs.push_back("-fptrauth-elf-got"); + // OHOS_LOCAL begin + if (Args.hasArg(options::OPT_fptrauth_elf_got_func)) + CmdArgs.push_back("-fptrauth-elf-got-func"); + // OHOS_LOCAL end + AddUnalignedAccessWarning(CmdArgs); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 17c8951ebd65d4e2c53b8cb72db88994d6681bc9..5b8bdd947ee1a25f3df9ef03747b36e69db721d4 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3211,6 +3211,25 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } +static void GeneratePointerAuthArgs(const LangOptions &Opts, + SmallVectorImpl &Args, + CompilerInvocation::StringAllocator SA) { + if (Opts.PointerAuthELFGOT) + GenerateArg(Args, OPT_fptrauth_elf_got, SA); + // OHOS_LOCAL begin + if (Opts.PointerAuthFuncELFGOT) + GenerateArg(Args, OPT_fptrauth_elf_got_func, SA); + // OHOS_LOCAL end +} + +static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags) { + Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); + // OHOS_LOCAL begin + Opts.PointerAuthFuncELFGOT = Args.hasArg(OPT_fptrauth_elf_got_func); + // OHOS_LOCAL end +} + /// Check if input file kind and language standard are compatible. static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S) { @@ -4486,6 +4505,7 @@ bool CompilerInvocation::CreateFromArgsImpl( llvm::Triple T(Res.getTargetOpts().Triple); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags, Res.getFileSystemOpts().WorkingDir); + ParsePointerAuthArgs(LangOpts, Args, Diags); ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes, Diags); @@ -4682,6 +4702,7 @@ void CompilerInvocation::generateCC1CommandLine( GeneratePreprocessorOutputArgs(PreprocessorOutputOpts, Args, SA, FrontendOpts.ProgramAction); GenerateDependencyOutputArgs(DependencyOutputOpts, Args, SA); + GeneratePointerAuthArgs(*LangOpts, Args, SA); } IntrusiveRefCntPtr diff --git a/clang/test/CodeGen/ptrauth-module-flags.c b/clang/test/CodeGen/ptrauth-module-flags.c new file mode 100644 index 0000000000000000000000000000000000000000..5a7e9a7c2a36fe923fd901b758a9f1a0a520766e --- /dev/null +++ b/clang/test/CodeGen/ptrauth-module-flags.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT + +// ELFGOT: !llvm.module.flags = !{ +// ELFGOT-SAME: !1 +// ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1} + +// OFF-NOT: "ptrauth- diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index b23684819a23967127a1cf2e3f5fea57d9733731..76d7e01c108f8f04a0cf9e1721f86d4560e0f01d 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -145,11 +145,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_LD64_GOT_LO12_NC: + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: + return RE_AARCH64_AUTH_GOT; + case R_AARCH64_AUTH_GOT_LD_PREL19: + case R_AARCH64_AUTH_GOT_ADR_PREL_LO21: + return RE_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 RE_AARCH64_AUTH_GOT_PAGE_PC; case R_AARCH64_NONE: return R_NONE; default: @@ -197,6 +205,7 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const { case R_AARCH64_TLSDESC: return read64(buf + 8); case R_AARCH64_NONE: + case R_AARCH64_AUTH_GLOB_DAT: return 0; case R_AARCH64_PREL32: return SignExtend64<32>(read32(buf)); @@ -315,6 +324,14 @@ static void or32AArch64Imm(uint8_t *l, uint64_t imm) { or32le(l, (imm & 0xFFF) << 10); } +static void writeMaskedBits32le(uint8_t *p, int32_t v, uint32_t mask) { + write32le(p, (read32le(p) & ~mask) | v); +} + +static void write32Imm12(uint8_t *l, uint64_t imm) { + writeMaskedBits32le(l, (imm & 0xFFF) << 10, 0XFFF << 10); +} + // Update the immediate field in an AArch64 movk, movn or movz instruction // for a signed relocation, and update the opcode of a movn or movz instruction // to match the sign of the operand. @@ -359,7 +376,11 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_ADD_ABS_LO12_NC: or32AArch64Imm(loc, val); break; + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: + write32Imm12(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: @@ -369,6 +390,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_PREL_LO21: checkInt(loc, val, 21, rel); write32AArch64Addr(loc, val); break; @@ -392,6 +414,11 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkInt(loc, val, 21, rel); or32le(loc, (val & 0x1FFFFC) << 3); break; + case R_AARCH64_AUTH_GOT_LD_PREL19: + checkAlignment(loc, val, 4, rel); + checkInt(loc, val, 21, rel); + writeMaskedBits32le(loc, (val & 0x1FFFFC) << 3, 0x1FFFFC << 3); + break; case R_AARCH64_LDST8_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: or32AArch64Imm(loc, getBits(val, 0, 11)); @@ -414,6 +441,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkAlignment(loc, val, 8, rel); or32AArch64Imm(loc, getBits(val, 3, 11)); break; + case R_AARCH64_AUTH_LD64_GOT_LO12_NC: + checkAlignment(loc, val, 8, rel); + write32Imm12(loc, getBits(val, 3, 11)); + break; case R_AARCH64_LDST128_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: checkAlignment(loc, val, 16, rel); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1420d8ce4e58ad9cfcc1b1689cf4cf717a62e53f..a10a7da6935b6a7bf4c337c63441ab46c3a2e153 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -629,6 +629,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_ARM_SBREL: return sym.getVA(a) - getARMStaticBase(sym); case R_GOT: + case RE_AARCH64_AUTH_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return sym.getGotVA() + a; case R_LOONGARCH_GOT: @@ -656,11 +657,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 RE_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 RE_AARCH64_AUTH_GOT_PC: case R_RELAX_TLS_GD_TO_IE: return sym.getGotVA() + a - p; case R_LOONGARCH_GOT_PAGE_PC: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index a617d55bfe000a08884d58b288f9e724111e6119..8d6e3f822ba124e136b964408f5683056dba6d6b 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -198,8 +198,10 @@ static bool needsPlt(RelExpr expr) { // returns false for TLS variables even though they need GOT, because // TLS variables uses GOT differently than the regular variables. static bool needsGot(RelExpr expr) { - return oneof( expr); } @@ -918,6 +920,25 @@ static void addGotEntry(Symbol &sym) { addRelativeReloc(*in.got, off, sym, 0, R_ABS, target->symbolicRel); } +static void addGotAuthEntry(Symbol &sym) { + in.got->addEntry(sym); + in.got->addAuthEntry(sym); + uint64_t off = sym.getGotOffset(); + + // If preemptible, emit a GLOB_DAT relocation. + if (sym.isPreemptible) { + mainPart->relaDyn->addReloc({R_AARCH64_AUTH_GLOB_DAT, in.got.get(), + off, DynamicReloc::AgainstSymbol, sym, 0, + R_ABS}); + return; + } + + // Signed GOT requires dynamic relocation. + in.got->getPartition().relaDyn->addReloc( + {R_AARCH64_AUTH_RELATIVE, in.got.get(), off, + DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS}); +} + static void addTpOffsetGotEntry(Symbol &sym) { in.got->addEntry(sym); uint64_t off = sym.getGotOffset(); @@ -965,9 +986,10 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, // These expressions always compute a constant if (oneof( e)) return true; @@ -1445,6 +1467,11 @@ template void RelocationScanner::scanOne(RelTy *&i) { // Many LoongArch TLS relocs reuse the R_LOONGARCH_GOT type, in which // case the `needsGot` flag shouldn't get set. sym.needsGot = true; + if (expr == RE_AARCH64_AUTH_GOT || expr == RE_AARCH64_AUTH_GOT_PAGE_PC || + expr == RE_AARCH64_AUTH_GOT_PC) + sym.needsGotAuth = true; + else + sym.needsGotNoAuth = true; } } else if (needsPlt(expr)) { sym.needsPlt = true; @@ -1625,8 +1652,11 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { // don't try to call the PLT as if it were an ifunc resolver. d.type = STT_FUNC; - if (sym.needsGot) + if (sym.needsGot) { + assert(!(sym.needsGotAuth) && + "R_AARCH64_AUTH_IRELATIVE is not supported yet"); addGotEntry(sym); + } } else if (sym.needsGot) { // Redirect GOT accesses to point to the Igot. sym.gotInIgot = true; @@ -1642,8 +1672,18 @@ void elf::postScanRelocations() { return; sym.allocateAux(); - if (sym.needsGot) - addGotEntry(sym); + if (sym.needsGot) { + if (sym.needsGotAuth && sym.needsGotNoAuth) { + errorOrWarn("both AUTH and non-AUTH GOT entries for '" + sym.getName() + + "' requested, but only one type of GOT entry per symbol is " + + "supported"); + return; + } + if (sym.needsGotAuth) + addGotAuthEntry(sym); + else + addGotEntry(sym); + } if (sym.needsPlt) addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); if (sym.needsCopy) { diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index f512047802ef1271bfa60b2f55d814159c7b01f7..feb425553da178a77ba0faa879acb86775c8e415 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -81,7 +81,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, + RE_AARCH64_AUTH_GOT_PAGE_PC, R_AARCH64_GOT_PAGE, + RE_AARCH64_AUTH_GOT, + RE_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 657c19a00ba364cf3bd429141fe53d097f3decc2..dd55ef03077e095824b78a8cd15b2c13a36e35cc 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -253,7 +253,7 @@ protected: scriptDefined(false), needsCopy(false), needsGot(false), needsPlt(false), needsTlsDesc(false), needsTlsGd(false), needsTlsGdToIe(false), needsGotDtprel(false), needsTlsIe(false), - hasDirectReloc(false) {} + hasDirectReloc(false), needsGotAuth(false), needsGotNoAuth(false) {} public: // True if this symbol is in the Iplt sub-section of the Plt and the Igot @@ -291,6 +291,8 @@ public: uint8_t needsGotDtprel : 1; uint8_t needsTlsIe : 1; uint8_t hasDirectReloc : 1; + uint8_t needsGotAuth : 1; + uint8_t needsGotNoAuth : 1; // A symAux index used to access GOT/PLT entry indexes. This is allocated in // postScanRelocations(). diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f298b83bda0e4f00b253c28a201d7a1b69a759a0..2d73481c417f6704f1edf48d632782db327fa06f 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -713,6 +713,10 @@ void GotSection::addEntry(Symbol &sym) { symAux.back().gotIdx = numEntries++; } +void GotSection::addAuthEntry(const Symbol &sym) { + authEntries.push_back({(numEntries - 1) * config->wordsize, sym.isFunc()}); +} + bool GotSection::addTlsDescEntry(Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().tlsDescIdx = numEntries; @@ -774,6 +778,21 @@ void GotSection::writeTo(uint8_t *buf) { return; target->writeGotHeader(buf); relocateAlloc(buf, buf + size); + for (const AuthEntryInfo &authEntry : authEntries) { + // https://github.com/ARM-software/abi-aa/blob/2024Q3/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/2024Q3/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 83a2bd7d34dfd0efd99cb12b442793d340dcfec8..953833abf2e188e25a0b64136e1d2331a585a1ae 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -128,6 +128,7 @@ public: void writeTo(uint8_t *buf) override; void addEntry(Symbol &sym); + void addAuthEntry(const Symbol &sym); bool addTlsDescEntry(Symbol &sym); bool addDynTlsEntry(Symbol &sym); bool addTlsIndex(); @@ -147,6 +148,11 @@ protected: 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-got-relocations-pauth.s b/lld/test/ELF/aarch64-got-relocations-pauth.s new file mode 100644 index 0000000000000000000000000000000000000000..ded9572b92c91635f3ad6b5e31f8cc1e21585ee9 --- /dev/null +++ b/lld/test/ELF/aarch64-got-relocations-pauth.s @@ -0,0 +1,144 @@ +# REQUIRES: aarch64 + +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -filetype=obj -triple=aarch64 %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 ok.s -o ok.o + +# RUN: ld.lld ok.o a.so -pie -o ok1 +# RUN: llvm-readelf -r -S -x .got ok1 | FileCheck %s --check-prefix=OK1 + +# RUN: ld.lld ok.o a.o -pie -o ok2 +# RUN: llvm-readelf -r -S -x .got -s ok2 | FileCheck %s --check-prefix=OK2 + +# OK1: Offset Info Type Symbol's Value Symbol's Name + Addend +# OK1-NEXT: 0000000000020380 0000000100000412 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0 +# OK1-NEXT: 0000000000020388 0000000200000412 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) +# OK2: Offset Info Type Symbol's Value Symbol's Name + Addend +# OK2-NEXT: 0000000000020320 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 +# OK2-NEXT: 0000000000020328 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260 + +# OK1: Hex dump of section '.got': +# OK1-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 + +# OK2: Symbol table '.symtab' contains {{.*}} entries: +# OK2: Num: Value Size Type Bind Vis Ndx Name +# OK2: 0000000000010260 0 FUNC GLOBAL DEFAULT 6 bar +# OK2: 0000000000010260 0 NOTYPE GLOBAL DEFAULT 6 zed + +# OK2: Hex dump of section '.got': +# OK2-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 ok1 | FileCheck %s --check-prefix=OK1-ASM + +# OK1-ASM: <_start>: +# OK1-ASM-NEXT: adrp x0, 0x20000 +# OK1-ASM-NEXT: ldr x0, [x0, #896] +# OK1-ASM-NEXT: adrp x1, 0x20000 +# OK1-ASM-NEXT: add x1, x1, #896 +# OK1-ASM-NEXT: adrp x0, 0x20000 +# OK1-ASM-NEXT: ldr x0, [x0, #904] +# OK1-ASM-NEXT: adrp x1, 0x20000 +# OK1-ASM-NEXT: add x1, x1, #904 + +# RUN: llvm-objdump -d ok2 | FileCheck %s --check-prefix=OK2-ASM + +# OK2-ASM: <_start>: +# OK2-ASM-NEXT: adrp x0, 0x20000 +# OK2-ASM-NEXT: ldr x0, [x0, #800] +# OK2-ASM-NEXT: adrp x1, 0x20000 +# OK2-ASM-NEXT: add x1, x1, #800 +# OK2-ASM-NEXT: adrp x0, 0x20000 +# OK2-ASM-NEXT: ldr x0, [x0, #808] +# OK2-ASM-NEXT: adrp x1, 0x20000 +# OK2-ASM-NEXT: add x1, x1, #808 + +.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 ok-tiny.s -o ok-tiny.o + +# RUN: ld.lld ok-tiny.o a.so -pie -o tiny1 +# RUN: llvm-readelf -r -S -x .got tiny1 | FileCheck %s --check-prefix=TINY1 + +# RUN: ld.lld ok-tiny.o a.o -pie -o tiny2 +# RUN: llvm-readelf -r -S -x .got -s tiny2 | FileCheck %s --check-prefix=TINY2 + +# TINY1: Offset Info Type Symbol's Value Symbol's Name + Addend +# TINY1-NEXT: 0000000000020368 0000000100000412 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0 +# TINY1-NEXT: 0000000000020370 0000000200000412 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) +# TINY2: Offset Info Type Symbol's Value Symbol's Name + Addend +# TINY2-NEXT: 0000000000020308 0000000000000411 R_AARCH64_AUTH_RELATIVE 10248 +# TINY2-NEXT: 0000000000020310 0000000000000411 R_AARCH64_AUTH_RELATIVE 10248 + +# TINY1: Hex dump of section '.got': +# TINY1-NEXT: 0x00020368 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 + +# TINY2: Symbol table '.symtab' contains {{.*}} entries: +# TINY2: Num: Value Size Type Bind Vis Ndx Name +# TINY2: 0000000000010248 0 FUNC GLOBAL DEFAULT 6 bar +# TINY2: 0000000000010248 0 NOTYPE GLOBAL DEFAULT 6 zed + +# TINY2: Hex dump of section '.got': +# TINY2-NEXT: 0x00020308 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 tiny1 | FileCheck %s --check-prefix=TINY1-ASM + +# TINY1-ASM: <_start>: +# TINY1-ASM-NEXT: adr x0, #65752 +# TINY1-ASM-NEXT: ldr x1, 0x20370 + +# RUN: llvm-objdump -d tiny2 | FileCheck %s --check-prefix=TINY2-ASM + +# TINY2-ASM: <_start>: +# TINY2-ASM-NEXT: adr x0, #65736 +# TINY2-ASM-NEXT: ldr x1, 0x20310 + +.globl _start +_start: + adr x0, :got_auth:bar + ldr x1, :got_auth:zed + +#--- err.s +# RUN: llvm-mc -filetype=obj -triple=aarch64 err.s -o err.o +# RUN: not ld.lld err.o a.so -pie 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error: +# 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/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def index 96a4efe82560438aa508e61dfe228c1e80ec9dbb..025fa9b349dbad613f2ef18566d057de45da18a5 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def @@ -121,6 +121,11 @@ ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a) ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b) ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c) ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d) +ELF_RELOC(R_AARCH64_AUTH_GOT_LD_PREL19, 0x24c) +ELF_RELOC(R_AARCH64_AUTH_ADR_GOT_PAGE, 0x24e) +ELF_RELOC(R_AARCH64_AUTH_LD64_GOT_LO12_NC, 0x24f) +ELF_RELOC(R_AARCH64_AUTH_GOT_ADD_LO12_NC, 0x251) +ELF_RELOC(R_AARCH64_AUTH_GOT_ADR_PREL_LO21, 0x252) // Dynamic relocations start ELF_RELOC(R_AARCH64_COPY, 0x400) ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401) @@ -134,6 +139,8 @@ ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x405) ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406) ELF_RELOC(R_AARCH64_TLSDESC, 0x407) ELF_RELOC(R_AARCH64_IRELATIVE, 0x408) +ELF_RELOC(R_AARCH64_AUTH_RELATIVE, 0x411) +ELF_RELOC(R_AARCH64_AUTH_GLOB_DAT, 0x412) // ELF_RELOC(R_AARCH64_P32_NONE, 0) ELF_RELOC(R_AARCH64_P32_ABS32, 0x001) diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 87f3982208fb9a9176048c3a948d6fb0a29ea1d5..1dd0dd97617b387354ca78c752aa05ac15697359 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -158,6 +158,10 @@ public: // We didn't modify anything. return false; } + // Emit the sequence for LOADgotAUTH (load signed pointer from signed ELF GOT + // and authenticate it with, if FPAC bit is not set, check+trap sequence after + // authenticating) + void LowerLOADgotAUTH(const MachineInstr &MI); private: void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O); @@ -579,7 +583,28 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) { // generates code that does this, it is always safe to set. OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols); } - + if (TT.isOSBinFormatELF()) { + // With signed ELF GOT enabled, the linker looks at the symbol type to + // choose between keys IA (for STT_FUNC) and DA (for other types). Symbols + // for functions not defined in the module have STT_NOTYPE type by default. + // This makes linker to emit signing schema with DA key (instead of IA) for + // corresponding R_AARCH64_AUTH_GLOB_DAT dynamic reloc. To avoid that, force + // all function symbols used in the module to have STT_FUNC type. See + // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema + const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null( + M.getModuleFlag("ptrauth-elf-got")); + // OHOS_LOCAL begin + const auto *PtrAuthFuncELFGOTFlag = mdconst::extract_or_null( + M.getModuleFlag("ptrauth-elf-got-func")); + if ((PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1) || + (PtrAuthFuncELFGOTFlag && PtrAuthFuncELFGOTFlag->getZExtValue() == 1)) + // OHOS_LOCAL end + for (const GlobalValue &GV : M.global_values()) + if (!GV.use_empty() && isa(GV) && + !GV.getName().startswith("llvm.")) + OutStreamer->emitSymbolAttribute(getSymbol(&GV), + MCSA_ELF_TypeFunction); + } // Emit stack and fault map information. emitStackMaps(SM); FM.serializeToFaultMapSection(); @@ -1168,6 +1193,69 @@ void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) { } } +void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) { + Register DstReg = MI.getOperand(0).getReg(); + Register AuthResultReg = DstReg; + const MachineOperand &GAMO = MI.getOperand(1); + assert(GAMO.getOffset() == 0); + + if (MI.getMF()->getTarget().getCodeModel() == CodeModel::Tiny) { + MCOperand GAMC; + MCInstLowering.lowerOperand(GAMO, GAMC); + EmitToStreamer( + *OutStreamer, MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addOperand(GAMC)); + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui) + .addReg(AuthResultReg) + .addReg(AArch64::X17) + .addImm(0)); + } else { + MachineOperand GAHiOp(GAMO); + MachineOperand GALoOp(GAMO); + GAHiOp.addTargetFlag(AArch64II::MO_PAGE); + GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + + MCOperand GAMCHi, GAMCLo; + MCInstLowering.lowerOperand(GAHiOp, GAMCHi); + MCInstLowering.lowerOperand(GALoOp, GAMCLo); + + EmitToStreamer( + *OutStreamer, MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi)); + + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri) + .addReg(AArch64::X17) + .addReg(AArch64::X17) + .addOperand(GAMCLo) + .addImm(0)); + + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui) + .addReg(AuthResultReg) + .addReg(AArch64::X17) + .addImm(0)); + } + + assert(GAMO.isGlobal()); + MCSymbol *UndefWeakSym; + if (GAMO.getGlobal()->hasExternalWeakLinkage()) { + UndefWeakSym = createTempSymbol("undef_weak"); + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::CBZX) + .addReg(AuthResultReg) + .addExpr(MCSymbolRefExpr::create(UndefWeakSym, OutContext))); + } + + assert(GAMO.getGlobal()->getValueType() != nullptr); + unsigned AuthOpcode = GAMO.getGlobal()->getValueType()->isFunctionTy() + ? AArch64::AUTIA + : AArch64::AUTDA; + EmitToStreamer(*OutStreamer, MCInstBuilder(AuthOpcode) + .addReg(AuthResultReg) + .addReg(AuthResultReg) + .addReg(AArch64::X17)); + + if (GAMO.getGlobal()->hasExternalWeakLinkage()) + OutStreamer->emitLabel(UndefWeakSym); +} + // Simple pseudo-instructions have their lowering (with expansion to real // instructions) auto-generated. #include "AArch64GenMCPseudoLowering.inc" @@ -1297,6 +1385,9 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { OutStreamer->emitCFIMTETaggedFrame(); return; } + case AArch64::LOADgotAUTH: + LowerLOADgotAUTH(*MI); + return; // Tail calls use pseudo instructions so they have the proper code-gen // attributes (isCall, isReturn, etc.). We lower them to the real diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 9b4ddd03b9a09a05eceb7bc21d723645992de1b9..901d35aeef55168ed7c270f76f33db22e2c2c860 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -448,7 +448,13 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) { // movz/movk sequences, which FastISel doesn't handle yet. if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO()) return 0; - + // OHOS_LOCAL begin + if (FuncInfo.MF->getInfo()->hasELFSignedGOT() || + (FuncInfo.MF->getInfo()->hasELFSignedGOTFunc() && + GV->getValueType()->isFunctionTy())) + // OHOS_LOCAL end + 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 fa0dd4421823ae5b033960d716f6f916d4181c22..69fbc7b9317c50c99980fbf813b9602c66e4d5c4 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -7191,6 +7191,28 @@ SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG, return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr); } +// OHOS_LOCAL begin +// (loadGOT sym) +template +SDValue AArch64TargetLowering::getGOTAuth(NodeTy *N, SelectionDAG &DAG, + unsigned Flags) const { + LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getGOTAuth\n"); + SDLoc DL(N); + EVT Ty = getPointerTy(DAG.getDataLayout()); + SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags); + bool IsGotAuth = + DAG.getMachineFunction() + .getInfo()->hasELFSignedGOT() || + (DAG.getMachineFunction() + .getInfo()->hasELFSignedGOTFunc() && + N->getGlobal()->getValueType()->isFunctionTy()); + if (IsGotAuth) + return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr), + 0); + return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr); +} +// OHOS_LOCAL end + // (wrapper %highest(sym), %higher(sym), %hi(sym), %lo(sym)) template SDValue AArch64TargetLowering::getAddrLarge(NodeTy *N, SelectionDAG &DAG, @@ -7245,7 +7267,7 @@ SDValue AArch64TargetLowering::LowerGlobalAddress(SDValue Op, // This also catches the large code model case for Darwin, and tiny code // model with got relocations. if ((OpFlags & AArch64II::MO_GOT) != 0) { - return getGOT(GN, DAG, OpFlags); + return getGOTAuth(GN, DAG, OpFlags); } SDValue Result; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index ff3bfe89786918ab0459a1bec40a833a2c04aec1..f8926cd8b009c5f5a225b985ba30bac006fd4d14 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -946,6 +946,10 @@ private: unsigned Flag) const; template SDValue getGOT(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; + // OHOS_LOCAL begin + template + SDValue getGOTAuth(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; + // OHOS_LOCAL end template SDValue getAddrLarge(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; template diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 3c2a1f24d67945236042d05c3e8bc5c32b4a0385..a7fe45472a428721ac3cafe4fddda0fce42ef34e 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -1387,7 +1387,11 @@ 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,X17,NZCV]; + let Size = 44; + } } // v8.3a floating point conversion for javascript diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp index 450c270fcc9b5c7d28f219b5d863f68b1e6f9ac1..5ffd29b5139c7026f942f7fbbcee805edd10f8d3 100644 --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "AArch64MCInstLower.h" +#include "AArch64MachineFunctionInfo.h" #include "MCTargetDesc/AArch64MCExpr.h" #include "Utils/AArch64BaseInfo.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -115,9 +116,17 @@ 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) { + const MachineFunction *MF = MO.getParent()->getParent()->getParent(); + // OHOS_LOCAL begin + bool IsGotAuth = MF->getInfo()->hasELFSignedGOT() || + (MF->getInfo()->hasELFSignedGOTFunc() && + MO.getGlobal()->getValueType()->isFunctionTy()); + RefFlags |= (IsGotAuth + ? AArch64MCExpr::VK_GOT_AUTH + : AArch64MCExpr::VK_GOT); + // OHOS_LOCAL end + } 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/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp index a2ab2b855d80e14d2b9798f81c1d595fe04b8e06..2e7aa00df644a1b038b0318ac3e7f2b1d1270a2b 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -80,6 +80,24 @@ static bool ShouldSignWithBKey(const Function &F) { return Key.equals_insensitive("b_key"); } +// OHOS_LOCAL begin +static std::pair hasELFSignedGOTHelper(const Function &F, + const AArch64Subtarget &STI) { + if (!Triple(STI.getTargetTriple()).isOSBinFormatELF()) + return {false, false}; + const Module *M = F.getParent(); + const auto *Flag = mdconst::extract_or_null( + M->getModuleFlag("ptrauth-elf-got")); + if (Flag && Flag->getZExtValue() == 1) + return {true, false}; + const auto *FlagFunc = mdconst::extract_or_null( + M->getModuleFlag("ptrauth-elf-got-func")); + if (FlagFunc && FlagFunc->getZExtValue() == 1) + return {false, true}; + return {false, false}; +} +// OHOS_LOCAL end + AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF_) : MF(&MF_) { // If we already know that the function doesn't have a redzone, set // HasRedZone here. @@ -89,6 +107,9 @@ AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF_) : MF(&MF_) { const Function &F = MF->getFunction(); std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F); SignWithBKey = ShouldSignWithBKey(F); + // OHOS_LOCAL begin + std::tie(HasELFSignedGOT, HasELFSignedGOTFunc) = hasELFSignedGOTHelper(F, MF->getSubtarget()); + // OHOS_LOCAL end // TODO: skip functions that have no instrumented allocas for optimization IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag); diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index 707c542685db0c6e91dfb612b6cd9b45b38e90a3..7121e986746868a8e8db3447bf03af506bdacc7d 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -193,6 +193,11 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { #ifdef ARK_GC_SUPPORT SmallVector ArkArgInfos; // OHOS_LOCAL #endif + /// HasELFSignedGOT is true if the target binary format is ELF and the IR + /// module containing the corresponding function has "ptrauth-elf-got" flag + /// set to 1. + bool HasELFSignedGOT = false; + bool HasELFSignedGOTFunc = false; // OHOS_LOCAL public: explicit AArch64FunctionInfo(MachineFunction &MF); @@ -453,7 +458,9 @@ public: } #endif - // OHOS_LOCAL end + // OHOS_LOCAL end + bool hasELFSignedGOT() const { return HasELFSignedGOT; } + bool hasELFSignedGOTFunc() const { return HasELFSignedGOTFunc; } // OHOS_LOCAL private: // Hold the lists of LOHs. MILOHContainer LOHContainerSet; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index ade23f64353843b7d8378085f8b1d6cef3fc05d7..6715ae699660412cb0c0ad5805e5a38c58562950 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -805,6 +805,7 @@ public: 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 || @@ -918,6 +919,7 @@ public: || 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 @@ -2860,6 +2862,7 @@ 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) { @@ -2904,7 +2907,13 @@ 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? Error(S, "unexpected adr label"); return MatchOperand_ParseFail; } @@ -3832,6 +3841,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) @@ -5085,6 +5096,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 6d29504c7ce3ef494ee7f583eeedc5577bb73169..b8cc907d69bc5d2f6ac36fa48a30994c0ed0a954 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2747,7 +2747,14 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } if (OpFlags & AArch64II::MO_GOT) { - I.setDesc(TII.get(AArch64::LOADgot)); + // OHOS_LOCAL begin + bool IsGotAuth = MF.getInfo()->hasELFSignedGOT() || + (MF.getInfo()->hasELFSignedGOTFunc() && + GV->getValueType()->isFunctionTy()); + // OHOS_LOCAL end + I.setDesc(TII.get(IsGotAuth + ? AArch64::LOADgotAUTH + : AArch64::LOADgot)); I.getOperand(1).setTargetFlags(OpFlags); } else if (TM.getCodeModel() == CodeModel::Large) { // Materialize the global using movz/movk instructions. diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 2f9c17245b5f6de3dd04edf3e052df6f3e5700ac..9988b959cebe54ee72ff6d433686a2ea06e51fe7 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -144,6 +144,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_PREL_LO21)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_GOT_ADR_PREL_LO21; + } if (SymLoc != AArch64MCExpr::VK_ABS) Ctx.reportError(Fixup.getLoc(), "invalid symbol kind for ADR relocation"); @@ -163,6 +172,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) @@ -179,6 +197,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); @@ -222,6 +249,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); @@ -321,17 +357,23 @@ 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; + return (IsAuth ? ELF::R_AARCH64_AUTH_LD64_GOT_LO12_NC + : 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)"); + 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; } } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp index cb39c2a114872bbb926baed9816a66486b47e02e..91a11d926c376c1a5947293401da6ff2d37a6a8a 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -82,6 +82,9 @@ 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"); } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index d3e834a140b2142d7b4837aec83e7dc3c8a941d0..57b85fbb8dd3e397d63af68b98a9d6666bd676f5 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -34,6 +34,7 @@ public: VK_TPREL = 0x007, VK_TLSDESC = 0x008, VK_SECREL = 0x009, + VK_GOT_AUTH = 0x00c, VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is @@ -84,6 +85,8 @@ public: 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, diff --git a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..7409175120af780e8d13377dbd82722ff86ec9fc --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll @@ -0,0 +1,76 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK + +;; Note: for FastISel, we fall back to SelectionDAG + +@var = global i32 0 + +define i32 @get_globalvar() { +; CHECK-LABEL: get_globalvar: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret i32 %val +} + +define ptr @get_globalvaraddr() { +; CHECK-LABEL: get_globalvaraddr: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autda x0, x17 +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret ptr @var +} + +declare i32 @foo() + +define ptr @resign_globalfunc() { +; CHECK-LABEL: resign_globalfunc: +; CHECK: adrp x17, :got_auth:foo +; CHECK-NEXT: add x17, x17, :got_auth_lo12:foo +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: ret + + ret ptr @foo +} + +define ptr @resign_globalvar() { +; CHECK-LABEL: resign_globalvar: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autda x0, x17 +; CHECK-NEXT: ret + + ret ptr @var +} + +define ptr @resign_globalvar_offset() { +; CHECK-LABEL: resign_globalvar_offset: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: add x0, x8, #16 +; CHECK-NEXT: ret + + ret ptr getelementptr (i8, ptr @var, i64 16) +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..bebf8d2cb820b0973eb593e6b1d10b071632847d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0 -relocation-model=pic -o - %s \ +; RUN: -mcpu=cyclone -mattr=+pauth | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1 -relocation-model=pic -o - %s \ +; RUN: -mcpu=cyclone -mattr=+pauth | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=arm64 -global-isel=1 -global-isel-abort=1 -relocation-model=pic -o - %s \ +; RUN: -mcpu=cyclone -mattr=+pauth | FileCheck --check-prefixes=CHECK %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-LABEL: test_i8: +; CHECK: adrp x17, :got_auth:var8 +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var8 +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: ldrb w8, [x9] +; CHECK-NEXT: strb w0, [x9] +; CHECK-NEXT: mov x0, x8 +; CHECK-NEXT: ret +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll new file mode 100644 index 0000000000000000000000000000000000000000..c57e86e9b75668332374c27eccc974cd7d144b6e --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-got-function-symbols.ll @@ -0,0 +1,34 @@ +; RUN: llc -mtriple aarch64-linux-pauthtest -mattr +pauth -filetype=asm %s -o - | \ +; RUN: FileCheck %s --check-prefix=ASM +; RUN: llc -mtriple aarch64-linux-pauthtest -mattr +pauth -filetype=obj %s -o - | \ +; RUN: llvm-readelf -s - | FileCheck %s --check-prefix=OBJ + +; ASM: .type foo,@function +; ASM-LABEL: foo: +; ASM: adrp x17, :got_auth:bar +; ASM-NEXT: add x17, x17, :got_auth_lo12:bar +; ASM-NEXT: ldr x9, [x17] +; ASM-NEXT: autia x9, x17 +; ASM-NEXT: str x9, [x8, :lo12:.Lfptr] +; ASM-NEXT: ret +; ASM: .type .Lfptr,@object +; ASM-NEXT: .local .Lfptr +; ASM-NEXT: .comm .Lfptr,8,8 +; ASM: .type bar,@function + +; OBJ: Symbol table '.symtab' contains [[#]] entries: +; OBJ-NEXT: Num: Value Size Type Bind Vis Ndx Name +; OBJ: 0000000000000000 0 FUNC GLOBAL DEFAULT UND bar + +@fptr = private global ptr null + +define void @foo() { + store ptr @bar, ptr @fptr + ret void +} + +declare i32 @bar() + +!llvm.module.flags = !{!0} + +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll new file mode 100644 index 0000000000000000000000000000000000000000..9dbe0c7ae80e7d5f54908e55183ea0d255f21454 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll @@ -0,0 +1,68 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0 -relocation-model=pic \ +; RUN: -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1 -relocation-model=pic \ +; RUN: -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \ +; RUN: -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -o - %s | \ +; RUN: FileCheck --check-prefixes=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-LABEL: foo: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: cbz x0, .Lundef_weak0 +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: .Lundef_weak0: +; CHECK-NEXT: ret + +; CHECK-TINY-LABEL: foo: +; CHECK-TINY: adr x17, :got_auth:var +; CHECK-TINY-NEXT: ldr x0, [x17] +; CHECK-TINY-NEXT: cbz x0, .Lundef_weak0 +; CHECK-TINY-NEXT: autia x0, x17 +; CHECK-TINY-NEXT: .Lundef_weak0: +; CHECK-TINY-NEXT: ret +} + +@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-LABEL: bar: +; CHECK: adrp x17, :got_auth:arr_var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:arr_var +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: cbz x8, .Lundef_weak1 +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: .Lundef_weak1: +; CHECK-NEXT: add x0, x8, #20 +; CHECK-NEXT: ret + +; CHECK-TINY-LABEL: bar: +; CHECK-TINY: adr x17, :got_auth:arr_var +; CHECK-TINY-NEXT: ldr x8, [x17] +; CHECK-TINY-NEXT: cbz x8, .Lundef_weak1 +; CHECK-TINY-NEXT: autda x8, x17 +; CHECK-TINY-NEXT: .Lundef_weak1: +; CHECK-TINY-NEXT: add x0, x8, #20 +; CHECK-TINY-NEXT: ret +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll new file mode 100644 index 0000000000000000000000000000000000000000..0af6185f30568d98d759abfcef86a83b7ccfe2f5 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll @@ -0,0 +1,57 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0 \ +; RUN: -relocation-model=pic -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1 \ +; RUN: -relocation-model=pic -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \ +; RUN: -relocation-model=pic -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0 \ +; RUN: -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1 \ +; RUN: -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 \ +; RUN: -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 x17, :got_auth:func +; CHECK-NEXT: add x17, x17, :got_auth_lo12:func +; CHECK-NEXT: ldr x[[TMP0:[0-9]+]], [x17] +; CHECK-NEXT: autia x[[TMP0]], x17 + + + call void @consume(i32 ptrtoint (ptr @alias_func to i32)) +; CHECK: adrp x17, :got_auth:alias_func +; CHECK-NEXT: add x17, x17, :got_auth_lo12:alias_func +; CHECK-NEXT: ldr x[[TMP1:[0-9]+]], [x17] +; CHECK-NEXT: autia x[[TMP1]], x17 + + + call void @consume(i32 ptrtoint (ptr @alias_global to i32)) +; CHECK: adrp x17, :got_auth:alias_global +; CHECK-NEXT: add x17, x17, :got_auth_lo12:alias_global +; CHECK-NEXT: ldr x[[TMP2:[0-9]+]], [x17] +; CHECK-NEXT: autda x[[TMP2]], x17 + + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..858709310da3c305d060680153f34543b4ef57f6 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll @@ -0,0 +1,72 @@ +; RUN: llc -global-isel=0 -fast-isel=0 -O0 --relocation-model=pic < %s \ +; RUN: -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL + +; RUN: llc -global-isel=0 -fast-isel=1 -O0 --relocation-model=pic < %s \ +; RUN: -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL + +; RUN: llc -global-isel=1 -global-isel-abort=1 -O0 --relocation-model=pic < %s \ +; RUN: -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-LABEL: global_addr: +; CHECK: adrp x17, :got_auth:global +; CHECK-NEXT: add x17, x17, :got_auth_lo12:global +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autda x0, x17 +; CHECK-NEXT: ret + + ret ptr @global +} + +define i32 @global_load() #0 { +; CHECK-LABEL: global_load: +; CHECK: adrp x17, :got_auth:global +; CHECK-NEXT: add x17, x17, :got_auth_lo12:global +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: ret + + %load = load i32, ptr @global + ret i32 %load +} + +define void @global_store() #0 { +; CHECK-LABEL: global_store: +; CHECK: adrp x17, :got_auth:global +; CHECK-NEXT: add x17, x17, :got_auth_lo12:global +; GISEL-NEXT: ldr x8, [x17] +; GISEL-NEXT: autda x8, x17 +; DAGISEL-NEXT: ldr x9, [x17] +; DAGISEL-NEXT: autda x9, x17 +; GISEL-NEXT: str wzr, [x8] +; DAGISEL-NEXT: mov w8, wzr +; DAGISEL-NEXT: str w8, [x9] +; CHECK-NEXT: ret + store i32 0, ptr @global + ret void +} + +define ptr @func_addr() #0 { +; CHECK-LABEL: func_addr: +; CHECK: adrp x17, :got_auth:func +; CHECK-NEXT: add x17, x17, :got_auth_lo12:func +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: ret + + ret ptr @func +} + +attributes #0 = { "target-features"="+tagged-globals" } + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..967b0b233ad13ce360603cce16f9ac305967512f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll @@ -0,0 +1,104 @@ +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \ +; RUN: -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \ +; RUN: -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \ +; RUN: -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK %s + +; 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-LABEL: foo1: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:src +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: adr x17, :got_auth:dst +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: strb w8, [x9] +; CHECK-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-LABEL: foo2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:ptr +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: adr x17, :got_auth:dst +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: str x9, [x8] +; CHECK-NEXT: ret + +entry: + store ptr @dst, ptr @ptr, align 8 + ret void +} + +define dso_preemptable void @foo3() { +; CHECK-LABEL: foo3: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:src +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: adr x17, :got_auth:ptr +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: ldr x9, [x9] +; CHECK-NEXT: strb w8, [x9] +; CHECK-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-LABEL: externfuncaddr: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:func +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: ret + +entry: + ret ptr @func +} + +define dso_preemptable ptr @localfuncaddr() { +; CHECK-LABEL: localfuncaddr: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:externfuncaddr +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: ret + +entry: + ret ptr @externfuncaddr +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll new file mode 100644 index 0000000000000000000000000000000000000000..8bf364b5b429109fb7a15878a581130b93ddff9f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll @@ -0,0 +1,88 @@ +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \ +; RUN: -code-model=tiny < %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \ +; RUN: -code-model=tiny -fast-isel < %s | FileCheck --check-prefixes=CHECK %s + +; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \ +; RUN: -code-model=tiny -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK %s + +; 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 x17, :got_auth:src +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: adr x17, :got_auth:dst +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: strb w8, [x9] +; CHECK-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 x17, :got_auth:ptr +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: adr x17, :got_auth:dst +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: str x9, [x8] +; CHECK-NEXT: ret + +entry: + store ptr @dst, ptr @ptr, align 8 + ret void +} + +define dso_local void @foo3() { +; CHECK-LABEL: foo3: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adr x17, :got_auth:src +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: autda x8, x17 +; CHECK-NEXT: ldrb w8, [x8] +; CHECK-NEXT: adr x17, :got_auth:ptr +; CHECK-NEXT: ldr x9, [x17] +; CHECK-NEXT: autda x9, x17 +; CHECK-NEXT: ldr x9, [x9] +; CHECK-NEXT: strb w8, [x9] +; CHECK-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 x17, :got_auth:func +; CHECK-NEXT: ldr x0, [x17] +; CHECK-NEXT: autia x0, x17 +; CHECK-NEXT: ret + +entry: + ret ptr @func +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} 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 0000000000000000000000000000000000000000..57021c71632ff37daecea6080d71bcc268906475 --- /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 e958f300b47ab6f1936b0b810b0839a34a40a2c5..6fdf8af19f6a91530c1b31672e5463d60eba043f 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_LD64_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym+0x7 + ldr x24, [x23, #:gotpage_lo15:sym] ldr d22, [x21, :gotpage_lo15:sym] ldr d22, [x23, :gotpage_lo15:sym+7] @@ -316,3 +330,16 @@ trickQuestion: // CHECK: ldr d22, :got:sym // 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_PREL_LO21 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_ADR_PREL_LO21 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s index 65c9e4ea5a1c56a255642df8c22c39d0085235a7..b637c66d7b3da0b6bab080e0d7a1393d8455fffa 100644 --- a/llvm/test/MC/AArch64/ilp32-diagnostics.s +++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s @@ -79,6 +79,12 @@ // 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] +// ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: AUTH_GOT_LO12_NC) + + add x24, x23, #:got_auth_lo12:sym +// ERROR: [[#@LINE-1]]:1: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADD_LO12_NC) + 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: ^ @@ -95,3 +101,9 @@ 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 +// ERROR: [[#@LINE-1]]:1: error: ILP32 LDR AUTH relocation not supported (LP64 eqv: AUTH_GOT_LD_PREL19) + +adr x24, :got_auth:sym +// ERROR: [[#@LINE-1]]:1: error: ILP32 ADR AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADR_PREL_LO21) 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 7291282811048fad225b07130f11750137d302ab..6b57bc0cae2c7376e8bc7f77e2cb19962e1db652 100644 --- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test +++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test @@ -119,6 +119,11 @@ # CHECK: Type: R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC (571) # CHECK: Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12 (572) # CHECK: Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC (573) +# CHECK: Type: R_AARCH64_AUTH_GOT_LD_PREL19 (588) +# CHECK: Type: R_AARCH64_AUTH_ADR_GOT_PAGE (590) +# CHECK: Type: R_AARCH64_AUTH_LD64_GOT_LO12_NC (591) +# CHECK: Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC (593) +# CHECK: Type: R_AARCH64_AUTH_GOT_ADR_PREL_LO21 (594) # CHECK: Type: R_AARCH64_COPY (1024) # CHECK: Type: R_AARCH64_GLOB_DAT (1025) # CHECK: Type: R_AARCH64_JUMP_SLOT (1026) @@ -128,7 +133,8 @@ # CHECK: Type: R_AARCH64_TLS_TPREL64 (1030) # CHECK: Type: R_AARCH64_TLSDESC (1031) # CHECK: Type: R_AARCH64_IRELATIVE (1032) - +# CHECK: Type: R_AARCH64_AUTH_RELATIVE (1041) +# CHECK: Type: R_AARCH64_AUTH_GLOB_DAT (1042) --- !ELF FileHeader: Class: ELFCLASS64 @@ -254,6 +260,11 @@ Sections: - Type: R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC - Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12 - Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC + - Type: R_AARCH64_AUTH_GOT_LD_PREL19 + - Type: R_AARCH64_AUTH_ADR_GOT_PAGE + - Type: R_AARCH64_AUTH_LD64_GOT_LO12_NC + - Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC + - Type: R_AARCH64_AUTH_GOT_ADR_PREL_LO21 - Type: R_AARCH64_COPY - Type: R_AARCH64_GLOB_DAT - Type: R_AARCH64_JUMP_SLOT @@ -263,3 +274,5 @@ Sections: - Type: R_AARCH64_TLS_TPREL64 - Type: R_AARCH64_TLSDESC - Type: R_AARCH64_IRELATIVE + - Type: R_AARCH64_AUTH_RELATIVE + - Type: R_AARCH64_AUTH_GLOB_DAT