Skip to content

Conversation

@jrtc27
Copy link
Collaborator

@jrtc27 jrtc27 commented Dec 8, 2025

This allows R_AARCH64_AUTH_ABS64 to follow R_AARCH64_ABS64's flow rather
than being implemented in the side in the place that is normally for
symbolic relocations.

Note that this has one implementation change: the RelExpr passed to
relaDyn is now RE_AARCH64_AUTH rather than R_ABS, but the two are
handled identically by InputSectionbase::getRelocTargetVA, and it was
inconsistent with relrAuthDyn which was passed RE_AARCH64_AUTH.

Created using spr 1.3.5
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-elf

Author: Jessica Clarke (jrtc27)

Changes

This allows R_AARCH64_AUTH_ABS64 to follow R_AARCH64_ABS64's flow rather
than being implemented in the side in the place that is normally for
symbolic relocations.

Note that this has one implementation change: the RelExpr passed to
relaDyn is now RE_AARCH64_AUTH rather than R_ABS, but the two are
handled identically by InputSectionbase::getRelocTargetVA, and it was
inconsistent with relrAuthDyn which was passed RE_AARCH64_AUTH.


Full diff: https://github.com/llvm/llvm-project/pull/171180.diff

1 Files Affected:

  • (modified) lld/ELF/Relocations.cpp (+20-24)
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index ce7ed5a413beb..e3bb2e8b6e805 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -704,8 +704,10 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
                              uint64_t offsetInSec, Symbol &sym, int64_t addend,
                              RelExpr expr, RelType type) {
   Partition &part = isec.getPartition(ctx);
+  bool isAArch64Auth =
+      ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64;
 
-  if (sym.isTagged()) {
+  if (sym.isTagged() && !isAArch64Auth) {
     part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
                                           offsetInSec, sym, addend, type, expr);
     // With MTE globals, we always want to derive the address tag by `ldg`-ing
@@ -727,13 +729,22 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
   // relrDyn sections don't support odd offsets. Also, relrDyn sections
   // don't store the addend values, so we must write it to the relocated
   // address.
-  if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
-    part.relrDyn->addRelativeReloc<shard>(isec, offsetInSec, sym, addend, type,
-                                          expr);
+  //
+  // When symbol values are determined in finalizeAddressDependentContent,
+  // some .relr.auth.dyn relocations may be moved to .rela.dyn.
+  RelrBaseSection *relrDyn = part.relrDyn.get();
+  if (isAArch64Auth)
+    relrDyn = part.relrAuthDyn.get();
+  if (relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
+    relrDyn->addRelativeReloc<shard>(isec, offsetInSec, sym, addend, type,
+                                     expr);
     return;
   }
-  part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
-                                        offsetInSec, sym, addend, type, expr);
+  RelType relativeType = ctx.target->relativeRel;
+  if (isAArch64Auth)
+    relativeType = R_AARCH64_AUTH_RELATIVE;
+  part.relaDyn->addRelativeReloc<shard>(relativeType, isec, offsetInSec, sym,
+                                        addend, type, expr);
 }
 
 template <class PltSection, class GotPltSection>
@@ -992,7 +1003,9 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
   if (canWrite) {
     RelType rel = ctx.target->getDynRel(type);
     if (oneof<R_GOT, RE_LOONGARCH_GOT>(expr) ||
-        (rel == ctx.target->symbolicRel && !sym.isPreemptible)) {
+        ((rel == ctx.target->symbolicRel ||
+          (ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64)) &&
+         !sym.isPreemptible)) {
       addRelativeReloc<true>(ctx, *sec, offset, sym, addend, expr, type);
       return;
     }
@@ -1001,23 +1014,6 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
         rel = ctx.target->relativeRel;
       std::lock_guard<std::mutex> lock(ctx.relocMutex);
       Partition &part = sec->getPartition(ctx);
-      // For a preemptible symbol, we can't use a relative relocation. For an
-      // undefined symbol, we can't compute offset at link-time and use a
-      // relative relocation. Use a symbolic relocation instead.
-      if (ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64 &&
-          !sym.isPreemptible) {
-        if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0) {
-          // When symbol values are determined in
-          // finalizeAddressDependentContent, some .relr.auth.dyn relocations
-          // may be moved to .rela.dyn.
-          part.relrAuthDyn->addRelativeReloc(*sec, offset, sym, addend, type,
-                                             expr);
-        } else {
-          part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, false,
-                                  sym, addend, R_ABS});
-        }
-        return;
-      }
       if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
         if (sym.isPreemptible) {
           auto diag = Err(ctx);

ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64;

if (sym.isTagged()) {
if (sym.isTagged() && !isAArch64Auth) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've preserved the fact that sym.isTagged() is ignored for R_AARCH64_AUTH_ABS64, but suspect that the ptrauth and memtag ABIs are currently mutually-exclusive? If so I can drop this diff from this and later PRs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but suspect that the ptrauth and memtag ABIs are currently mutually-exclusive?

@smithp35 Could you please clarify what is the correct answer for the question above? I was only working on ptrauth and do not feel confident enough to reason about memtag with ptrauth combination :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TL;DR is that in theory they could be combined. In practice no-one has tried combining or expressed an interest in combining them. One opinion is that it could be removed for now, and when someone does try it, they'll need to put something similar back. Perhaps leave a comment.

From a user group perspective the PAuthABI and the MemtagABI communities are separate. As I understand the PAuthABI is an ABI break for the group using Memtag and the group intending to use PAuthABI is targeting hardware that doesn't have MTE so can't use the Memtag ABI anyway.

Re-reading the specifications I don't think that there's anything fundamental at the specification level that would prevent the two being used together. The PAuthABI adds new relocations, the MemtagABI alters the behaviour of existing non PAuth ABI relocations. This means that global signed pointers can't be tagged, but as tagging does not have to be complete, anything that isn't signed could be tagged.

I expect that the memtag ABI could be extended to cover signed pointers. It would need to encode the tag offset for relative relocations for R_AARCH64_AUTH_RELATIVE in a compatible way to the signing schema.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmayer is I think the lead for the Memtag ABI. Tagging him here just in case there are any plans for combining hte Memtag ABI with PAuthABI.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With PAuth2 XORing rather than replacing the upper bits you might even be able to do both for a given pointer? I haven’t properly thought it through and it may be a terrible idea, but on the surface it seemed plausible to me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When both MTE and PAC are enabled the amount of bits avaible to PAC is reduced so they don't overlap with the bits used for MTE. They can be used together, although fewer bits available to PAC makes it statistically weaker.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, MTE and PAuth ABI are not mutually exclusive, as they can use different bits.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the existing implementation that uses .relr.auth.dyn and/or no offset to the start of the symbol for AUTH_RELATIVE relocations against tagged symbols correct? I am assuming not, and that it should be doing the "obvious" composition of the two. Which would also simplify this patch.

@asl asl requested review from MaskRay and kovdan01 December 8, 2025 21:40
@jrtc27 jrtc27 changed the title [NFCI][ELF][AArch64] Teach addRelativeReloc to emit R_AARCH64_AUTH_RELATIVE [NFCI][ELF][AArch64][PAC] Teach addRelativeReloc to emit R_AARCH64_AUTH_RELATIVE Dec 8, 2025
Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I like that we now remove one ... && sec->addralign >= 2 && offset % 2 == 0 condition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants