https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128364
Bug ID: 128364
Summary: aarch64: -mharden-sls=blr leaves a raw BLR in TLS
descriptor sequences
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: aarch64*-*-*
Reproducer
----------
$ cat trigger.c
__thread int tls_var;
void *tls_addr (void)
{
return &tls_var; /* TLS descriptor call: raw blr */
}
int indirect (int (*f) (int), int a)
{
return f (a) + 1; /* ordinary indirect call: hardened */
}
Compile flag: aarch64-linux-gnu-gcc -O2 -fPIC -mtls-dialect=desc
-mharden-sls=blr -S trigger.c
tls_addr:
adrp x0, :tlsdesc:tls_var
ldr x1, [x0, #:tlsdesc_lo12:tls_var]
add x0, x0, :tlsdesc_lo12:tls_var
.tlsdesccall tls_var
blr x1 # raw BLR, not hardened
...
indirect:
bl .L6 # ordinary indirect call: hardened via stub
...
.L6:
mov x16, x2
br x16
dsb sy
isb
# with -march=armv8.2-a+sve -mharden-sls=all: tlsdesc_small_sve emits a raw
`blr x30`
Root cause
----------
aarch64_indirect_call_asm (gcc/config/aarch64/aarch64.cc:31788) rewrites
BLR into BL to a per-register stub, but it is only reached from the 'Ucr'
alternatives of *call_insn / *call_value_insn. The TLS descriptor patterns
emit the call from a fixed template:
tlsdesc_small_advsimd_<mode>: "...;.tlsdesccall\t%0;blr\t%1"
(aarch64.md:8146)
tlsdesc_small_sve_<mode>: "...;.tlsdesccall\t%0;blr\tx30"
(aarch64.md:8162)
so they bypass the hardening. (Clang 23.1.2 emits the same raw blr for
TLS descriptors under -mharden-sls=all.)
Suggested Fix
-------------
When aarch64_harden_sls_blr_p (), emit the descriptor call as
"bl <stub for %1>" (aarch64_sls_create_blr_label) in both tlsdesc templates,
or document that TLS descriptor calls are excluded from -mharden-sls=blr.