Skip to content

Commit f990bf5

Browse files
committed
[AArch64] Reject ptrauth global refs. as GOT-equivalent candidates.
AsmPrinter has the ability to recognize "GOT equivalents", which are symbols that just point to another symbol and are used in 32-bit relative-offset references. When possible, we form GOTPCREL relocations to the pointed-to symbol, which lets us avoid a global needing a bind in its initializer symbol relocation at load-time. If the GOTPCREL relocation isn't possible, we can fallback to the global we emitted as a GOT equivalent placeholder. The reference to it can still be a 32-bit link-time relative offset, and we still need to pay for an additional bind at load-time, but it's just one more rather than one for each use. ptrauth puts a wrench in all that: if the symbol reference is intended to be signed, we need a way to express "a GOTPCREL reference to a symbol but also sign the symbol's address in this funky way". We don't have the bits to encode all that. Concretely, this means we don't have a way to encode ptrauth GOT-equivalents today. We may have that in the future: rdar://84309968. So far, we have gotten lucky and these ptrauth GOT-equivalents have been silently rejected as ineligible for GOTPCREL, thanks to the weird struct type the ptrauth wrapper references have. This hid the ptrauth wrappers from the `isa<GlobalValue>` isGOTEquivalentCandidate does, since the ptrauth wrappers always needed a pointer bitcast. However, with opaque pointers, we don't need the pointer bitcast anymore, and the direct use of the wrapper global as a `ptr` passes the `isa<GlobalValue>` check. We end up trying to turn that into a GOTPCREL reference, but we're still pointing to the fake ptrauth wrapper symbol. The GOTPCREL reference is done using raw MCSymbols and MCExprs. But the ptrauth wrapper symbol lowering (to MCAuthExprs and __auth_ptr symbols) is done when lowering the ConstantExpr initializer. So it never happens for GOT equivalents, and we end up with missing symbols. Reject ptrauth wrapper globals outright as GOT equivalent candidates. We can somehow support the combination separately. rdar://101041228 rdar://103610908
1 parent 4422a08 commit f990bf5

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,30 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
18751875
!isa<GlobalValue>(GV->getOperand(0)))
18761876
return false;
18771877

1878+
// ptrauth globals are themselves an indirection pointing at another global.
1879+
// We currently can't express authentication when referencing PC-relative GOT
1880+
// entries, because the main GOT has no authentication.
1881+
//
1882+
// FIXME: the linker uses a special __auth_got (accessed by symbol stubs), and
1883+
// we could extend that to know about the compiler's __auth_ptr section.
1884+
// This would let us use the PC relative GOT trickery here.
1885+
// However, the __auth_got has a known signing scheme, and __auth_ptr doesn't,
1886+
// so we'd still need a way to express "an offset to the GOT entry that is
1887+
// signed this particular way". The trick is that this would happen using
1888+
// the existing @AUTH relocations, and the __auth_ptr entries themselves.
1889+
// So the ptrauth equivalent of:
1890+
// .long foo@GOTPCREL
1891+
//
1892+
// would be:
1893+
// .long l_foo$auth$ia$42
1894+
//
1895+
// l_foo$auth$ia$42:
1896+
// .quad _foo@AUTH(ia,42)
1897+
//
1898+
// where the the latter being in the __auth_ptr section makes it coalescable.
1899+
if (cast<GlobalValue>(GV->getOperand(0))->getSection() == "llvm.ptrauth")
1900+
return false;
1901+
18781902
// To be a got equivalent, at least one of its users need to be a constant
18791903
// expression used by another global variable.
18801904
for (const auto *U : GV->users())
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; RUN: llc %s -o - -mtriple=arm64e-apple-ios | FileCheck %s
2+
3+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4+
5+
@foo = external global i64, align 8
6+
@foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @foo, i32 2, i64 0, i64 12345 }, section "llvm.ptrauth", align 8
7+
8+
; CHECK-LABEL: l_got.foo:
9+
; CHECK-NEXT: .quad _foo@AUTH(da,12345)
10+
11+
; CHECK-LABEL: _foo_ref:
12+
; CHECK-NEXT: .long l_got.foo-_foo_ref
13+
14+
@got.foo = private unnamed_addr constant ptr @foo.ptrauth
15+
@foo_ref = constant i32 trunc (i64 sub (i64 ptrtoint (ptr @got.foo to i64), i64 ptrtoint (ptr @foo_ref to i64)) to i32), align 8

0 commit comments

Comments
 (0)