Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3600,13 +3600,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
/// adrp x0, :tlsdesc_auth:var
/// ldr x16, [x0, #:tlsdesc_auth_lo12:var]
/// add x0, x0, #:tlsdesc_auth_lo12:var
/// .tlsauthdesccall var
/// blraa x16, x0
/// (TPIDR_EL0 offset now in x0)
const MachineOperand &MO_Sym = MI->getOperand(0);
MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
MCOperand SymTLSDescLo12, SymTLSDesc;
MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
MCInstLowering.lowerOperand(MO_Sym, Sym);
MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);

Expand All @@ -3632,8 +3634,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
EmitToStreamer(*OutStreamer, Add);

// Authenticated TLSDESC accesses are not relaxed.
// Thus, do not emit .tlsdesccall for AUTH TLSDESC.
// Emit a relocation-annotation. This expands to no code, but requests
// the following instruction gets an R_AARCH64_AUTH_TLSDESC_CALL.
MCInst TLSAuthDescCall;
TLSAuthDescCall.setOpcode(AArch64::TLSAUTHDESCCALL);
TLSAuthDescCall.addOperand(Sym);
EmitToStreamer(*OutStreamer, TLSAuthDescCall);
#ifndef NDEBUG
--InstsEmitted; // no code emitted
#endif

MCInst Blraa;
Blraa.setOpcode(AArch64::BLRAA);
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -3773,6 +3773,14 @@ def TLSDESCCALL : Pseudo<(outs), (ins i64imm:$sym), []>, Sched<[]> {
let AsmString = ".tlsdesccall $sym";
}

// This is a directive-like pseudo-instruction. The purpose is to insert an
// R_AARCH64_AUTH_TLSDESC_CALL relocation at the offset of the following instruction
// (which in the usual case is a BLRAA).
let hasSideEffects = 1 in
def TLSAUTHDESCCALL : Pseudo<(outs), (ins i64imm:$sym), []>, Sched<[]> {
let AsmString = ".tlsauthdesccall $sym";
}

// Pseudo instruction to tell the streamer to emit a 'B' character into the
// augmentation string.
def EMITBKEY : Pseudo<(outs), (ins), []>, Sched<[]> {}
Expand Down
17 changes: 11 additions & 6 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool parseDirectiveCPU(SMLoc L);
bool parseDirectiveInst(SMLoc L);

bool parseDirectiveTLSDescCall(SMLoc L);
bool parseDirectiveTLSDescCall(SMLoc L, bool IsAuth);

bool parseDirectiveLOH(StringRef LOH, SMLoc L);
bool parseDirectiveLtorg(SMLoc L);
Expand Down Expand Up @@ -7074,7 +7074,9 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
else if (IDVal == ".cpu")
parseDirectiveCPU(Loc);
else if (IDVal == ".tlsdesccall")
parseDirectiveTLSDescCall(Loc);
parseDirectiveTLSDescCall(Loc, /*IsAuth=*/false);
else if (IDVal == ".tlsauthdesccall")
parseDirectiveTLSDescCall(Loc, /*IsAuth=*/true);
else if (IDVal == ".ltorg" || IDVal == ".pool")
parseDirectiveLtorg(Loc);
else if (IDVal == ".unreq")
Expand Down Expand Up @@ -7399,19 +7401,22 @@ bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
}

// parseDirectiveTLSDescCall:
// ::= .tlsdesccall symbol
bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
// ::= .tlsdesccall symbol (if IsAuth is false)
// ::= .tlsauthdesccall symbol (if IsAuth is true)
bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L, bool IsAuth) {
StringRef Name;
if (check(getParser().parseIdentifier(Name), L, "expected symbol") ||
parseToken(AsmToken::EndOfStatement))
return true;

MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
Expr = MCSpecifierExpr::create(Expr, AArch64::S_TLSDESC, getContext());
Expr = MCSpecifierExpr::create(
Expr, IsAuth ? AArch64::S_TLSDESC_AUTH : AArch64::S_TLSDESC,
getContext());

MCInst Inst;
Inst.setOpcode(AArch64::TLSDESCCALL);
Inst.setOpcode(IsAuth ? AArch64::TLSAUTHDESCCALL : AArch64::TLSDESCCALL);
Inst.addOperand(MCOperand::createExpr(Expr));

getParser().getStreamer().emitInstruction(Inst, getSTI());
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,15 @@ void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI,
return;
}

if (MI.getOpcode() == AArch64::TLSAUTHDESCCALL) {
// This is a directive which applies an R_AARCH64_AUTH_TLSDESC_CALL to the
// following (BLRAA) instruction. It doesn't emit any code itself so it
// doesn't go through the normal TableGenerated channels.
addFixup(Fixups, 0, MI.getOperand(0).getExpr(),
ELF::R_AARCH64_AUTH_TLSDESC_CALL);
return;
}

if (MI.getOpcode() == AArch64::SPACE) {
// SPACE just increases basic block size, in both cases no actual code.
return;
Expand Down
15 changes: 10 additions & 5 deletions llvm/test/CodeGen/AArch64/ptrauth-arm64-tls-dynamics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ define i32 @test_generaldynamic() {
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var]
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var
; CHECK-NEXT: .tlsauthdesccall general_dynamic_var
; CHECK-NEXT: blraa x16, x0
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]

; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_CALL
}

define ptr @test_generaldynamic_addr() {
Expand All @@ -36,14 +37,15 @@ define ptr @test_generaldynamic_addr() {
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var]
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var
; CHECK-NEXT: .tlsauthdesccall general_dynamic_var
; CHECK-NEXT: blraa x16, x0
; CHECK-NEXT: mrs [[TP:x[0-9]+]], TPIDR_EL0
; CHECK-NEXT: add x0, [[TP]], x0

; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_CALL
}

;; Note: with signed TLSDESC, general dynamic model is always used,
Expand All @@ -60,14 +62,15 @@ define i32 @test_localdynamic() {
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
; CHECK-NEXT: .tlsauthdesccall local_dynamic_var
; CHECK-NEXT: blraa x16, x0
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]

; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_CALL
}

define ptr @test_localdynamic_addr() {
Expand All @@ -78,14 +81,15 @@ define ptr @test_localdynamic_addr() {
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var]
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var
; CHECK-NEXT: .tlsauthdesccall local_dynamic_var
; CHECK-NEXT: blraa x16, x0
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
; CHECK-NEXT: add x0, x[[TPIDR]], x0

; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_CALL
}

@extern_weak_var = extern_weak thread_local global i32
Expand All @@ -99,14 +103,15 @@ define i32 @test_extern_weak() {
; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:extern_weak_var
; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var]
; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:extern_weak_var
; CHECK-NEXT: .tlsauthdesccall extern_weak_var
; CHECK-NEXT: blraa x16, x0
; CHECK-NEXT: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
; CHECK-NEXT: ldr w0, [x[[TPIDR]], x0]

; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_LD64_LO12
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_ADD_LO12
; CHECK-OBJ-NOT: R_AARCH64_TLSDESC_CALL
; CHECK-OBJ: R_AARCH64_AUTH_TLSDESC_CALL
; CHECK-OBJ: 0000000000000000 0 TLS WEAK DEFAULT UND extern_weak_var
}

Expand Down
3 changes: 3 additions & 0 deletions llvm/test/MC/AArch64/directives-case_insensitive.s
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@ fred .REQ x5
.TLSDESCCALL var
// CHECK: .tlsdesccall var

.TLSAUTHDESCCALL var
// CHECK: .tlsauthdesccall var

.LTORG
.POOL
32 changes: 32 additions & 0 deletions llvm/test/MC/AArch64/tls-auth-relocs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: llvm-mc -triple=aarch64-none-linux-gnu -mattr=+pauth -show-encoding %s | FileCheck %s
// RUN: llvm-mc -triple=aarch64-none-linux-gnu -mattr=+pauth -filetype=obj %s -o - | \
// RUN: llvm-readelf -r -s - | FileCheck --check-prefix=CHECK-ELF %s

adrp x8, :tlsdesc_auth:var
ldr x7, [x6, :tlsdesc_auth_lo12:var]
add x5, x4, #:tlsdesc_auth_lo12:var
.tlsauthdesccall var
blraa x3, x2

// CHECK: adrp x8, :tlsdesc_auth:var // encoding: [0x08'A',A,A,0x90'A']
// CHECK-NEXT: // fixup A - offset: 0, value: :tlsdesc_auth:var, kind: fixup_aarch64_pcrel_adrp_imm21
// CHECK: ldr x7, [x6, :tlsdesc_auth_lo12:var] // encoding: [0xc7,0bAAAAAA00,0b01AAAAAA,0xf9]
// CHECK-NEXT: // fixup A - offset: 0, value: :tlsdesc_auth_lo12:var, kind: fixup_aarch64_ldst_imm12_scale8
// CHECK: add x5, x4, :tlsdesc_auth_lo12:var // encoding: [0x85,0bAAAAAA00,0b00AAAAAA,0x91]
// CHECK-NEXT: // fixup A - offset: 0, value: :tlsdesc_auth_lo12:var, kind: fixup_aarch64_add_imm12
// CHECK: .tlsauthdesccall var // encoding: []
// CHECK-NEXT: // fixup A - offset: 0, value: var, relocation type: 598
// CHECK: blraa x3, x2 // encoding: [0x62,0x08,0x3f,0xd7]

// CHECK-ELF: Relocation section '.rela.text' at offset 0x98 contains 4 entries:
// CHECK-ELF-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
// CHECK-ELF-NEXT: 0000000000000000 0000000200000253 R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 0000000000000000 var + 0
// CHECK-ELF-NEXT: 0000000000000004 0000000200000254 R_AARCH64_AUTH_TLSDESC_LD64_LO12 0000000000000000 var + 0
// CHECK-ELF-NEXT: 0000000000000008 0000000200000255 R_AARCH64_AUTH_TLSDESC_ADD_LO12 0000000000000000 var + 0
// CHECK-ELF-NEXT: 000000000000000c 0000000200000256 R_AARCH64_AUTH_TLSDESC_CALL 0000000000000000 var + 0

// Make sure symbol has type STT_TLS:

// CHECK-ELF: Symbol table '.symtab' contains [[#]] entries:
// CHECK-ELF-NEXT: Num: Value Size Type Bind Vis Ndx Name
// CHECK-ELF: [[#]]: 0000000000000000 0 TLS GLOBAL DEFAULT UND var
Loading