NetBSD Problem Report #57638
From martin@duskware.de Sat Sep 30 17:50:06 2023
Return-Path: <martin@duskware.de>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 430901A9239
for <gnats-bugs@gnats.NetBSD.org>; Sat, 30 Sep 2023 17:50:06 +0000 (UTC)
From: martin@NetBSD.org
Reply-To: martin@NetBSD.org
To: gnats-bugs@NetBSD.org
Subject: thread local storage broken on evbarm (armv5)
X-Send-Pr-Version: 3.95
>Number: 57638
>Category: lib
>Synopsis: thread local storage broken on evbarm (armv5)
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: lib-bug-people
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Sep 30 17:55:00 +0000 2023
>Closed-Date: Sat Oct 10 17:16:51 +0000 2026
>Last-Modified: Sat Oct 10 17:16:51 +0000 2026
>Originator: Martin Husemann
>Release: NetBSD 10.99.9
>Organization:
The NetBSD Foundation, Inc.
>Environment:
System: NetBSD unpluged.duskware.de 10.99.9 NetBSD 10.99.9 (UNPLUGED) #521: Sat Sep 30 13:40:22 CEST 2023 martin@seven-days-to-the-wolves.aprisoft.de:/work/src/sys/arch/evbarm/compile/UNPLUGED evbarm
Architecture: earmv5
Machine: evbarm
>Description:
Many (all?) TLS related tests crash on evbarm, like:
tp-start: 1696095219.51665, t_tls_extern, 21
tc-start: 1696095219.52148, dynamic_abusedef
tc-se:Test program crashed; attempting to get stack trace
Unfortunately gdb is not helpfull (11.0.50 hangs, 13.2 crashes).
Extracting the core and examining with gdb 11.0.50 shows:
Core was generated by `t_tls_extern'.
Program terminated with signal SIGBUS, Bus error.
#0 0xbbed8c78 in _rtld_symlook_list (
name=name@entry=0xbbbc0233 "__aeabi_read_tp", hash=hash@entry=0xbfffe624,
objlist=0xbbef1258 <_rtld_list_main>,
defobj_out=defobj_out@entry=0xbfffe5d8, flags=flags@entry=1,
ventry=ventry@entry=0x0, dlp=dlp@entry=0xbfffe5dc)
at /work/src/libexec/ld.elf_so/symbol.c:88
88 /work/src/libexec/ld.elf_so/symbol.c: No such file or directory.
(gdb) info thread
Id Target Id Frame
* 1 process 9670 0xbbed8c78 in _rtld_symlook_list (
name=name@entry=0xbbbc0233 "__aeabi_read_tp", hash=hash@entry=0xbfffe624,
objlist=0xbbef1258 <_rtld_list_main>,
defobj_out=defobj_out@entry=0xbfffe5d8, flags=flags@entry=1,
ventry=ventry@entry=0x0, dlp=dlp@entry=0xbfffe5dc)
at /work/src/libexec/ld.elf_so/symbol.c:88
(gdb) info locals
symp = <optimized out>
def = 0x0
defobj = 0x0
elm = 0xbbef80e0
(gdb) p *elm
$1 = {link = {sqe_next = 0xbbef8140}, obj = 0xbbefc000}
(gdb) info dll
From To Syms Read Shared Object Library
0xbbea4270 0xbbead1c8 Yes /usr/lib/libatf-c.so.0
0xbbd3df60 0xbbe3f104 Yes /usr/lib/libc.so.12
0xbbbe0320 0xbbbe040c Yes /usr/tests/libexec/ld.elf_so/libh_use_static.so
0xbbbc0328 0xbbbc0414 Yes /usr/tests/libexec/ld.elf_so/libh_def_static.so.1
0xbbed0608 0xbbedd154 Yes /usr/libexec/ld.elf_so
(gdb) info reg
r0 0xbbbc0233 3149660723
r1 0xbfffe624 3221218852
r2 0xbbef1258 3153007192
r3 0xbfffe5d8 3221218776
r4 0xbbef80e0 3153035488
r5 0xbfffe5dc 3221218780
r6 0xbbbc0233 3149660723
r7 0x0 0
r8 0x1 1
r9 0xbfffe5d8 3221218776
r10 0xbfffe624 3221218852
r11 0xbfffe610 3221218832
r12 0x40 64
sp 0xbfffe55c 0xbfffe55c
lr 0xbbed91b8 3152908728
pc 0xbbed8c78 0xbbed8c78 <_rtld_symlook_list+24>
cpsr 0xa0000010 2684354576
(gdb) x/16i _rtld_symlook_list
0xbbed8c60 <_rtld_symlook_list>:
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
0xbbed8c64 <_rtld_symlook_list+4>: ldr r4, [r2]
0xbbed8c68 <_rtld_symlook_list+8>: sub sp, sp, #20
0xbbed8c6c <_rtld_symlook_list+12>: cmp r4, #0
0xbbed8c70 <_rtld_symlook_list+16>: ldr r5, [sp, #64] ; 0x40
0xbbed8c74 <_rtld_symlook_list+20>: str r3, [sp, #12]
=> 0xbbed8c78 <_rtld_symlook_list+24>: ldrd r8, [sp, #56] ; 0x38
0xbbed8c7c <_rtld_symlook_list+28>:
beq 0xbbed8d70 <_rtld_symlook_list+272>
0xbbed8c80 <_rtld_symlook_list+32>: mov r10, #0
0xbbed8c84 <_rtld_symlook_list+36>: mov r7, r0
0xbbed8c88 <_rtld_symlook_list+40>: mov r11, r1
0xbbed8c8c <_rtld_symlook_list+44>: mov r6, r10
0xbbed8c90 <_rtld_symlook_list+48>: ldr r12, [r5, #8]
0xbbed8c94 <_rtld_symlook_list+52>: ldr r2, [r4, #4]
0xbbed8c98 <_rtld_symlook_list+56>: cmp r12, #0
0xbbed8c9c <_rtld_symlook_list+60>:
beq 0xbbed8cf0 <_rtld_symlook_list+144>
... which looks exactly like the crash gdb 13.2 dies with.
>How-To-Repeat:
s/a
>Fix:
n/a
>Release-Note:
>Audit-Trail:
From: Taylor R Campbell <riastradh@NetBSD.org>
To: Martin Husemann <martin@NetBSD.org>, Nick Hudson <skrll@NetBSD.org>,
matthew green <mrg@NetBSD.org>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: lib/57638: thread local storage broken on evbarm (armv5)
Date: Fri, 24 Jul 2026 16:11:31 +0000
This is a multi-part message in MIME format.
--=_zuuYtksK0C8RJaF9J8AwVVP/KZSlw/L+
nick and I tracked this down to gcc generating calls to
__aeabi_read_tp (read thread pointer) -- which it uses only on armv5
(or with -mtp=soft) -- with a misaligned stack pointer:
00000328 <fdef>:
fdef():
328: e52de004 push {lr} @ (str lr, [sp, #-4]!)
32c: ebfffffa bl 31c <__aeabi_read_tp@plt>
330: e59f3008 ldr r3, [pc, #8] @ 340 <fdef+0x18>
334: e79f3003 ldr r3, [pc, r3]
338: e0800003 add r0, r0, r3
33c: e49df004 pop {pc} @ (ldr pc, [sp], #4)
340: 000012a4 .word 0x000012a4
The ABI requires 8-byte stack alignment on entry to procedures, but
this calls __aeabi_read_tp with only 4-byte alignment. And although
__aeabi_read_tp itself doesn't care about stack alignment, if the
symbol is resolved lazily, we'll take a detour through the dynamic
linker, which does care about stack alignment.
I filed an upstream gcc bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
The attached patch works around it when compiling with an ABI that
uses __aeabi_read_tp (instead of, e.g., cp15, as armv>=6 use) by
forcing stack alignment for leaf procedures -- so any procedures that
would have saved 2n+1 registers will instead save 2n+2 registers.
(Leaf procedures that don't use the stack at all are unaffected.)
Shall we commit this?
--=_zuuYtksK0C8RJaF9J8AwVVP/KZSlw/L+
Content-Type: text/plain; charset="ISO-8859-1"; name="pr57638-armv5tls"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr57638-armv5tls.patch"
# HG changeset patch
# User Taylor R Campbell <riastradh@NetBSD.org>
# Date 1784905905 0
# Fri Jul 24 15:11:45 2026 +0000
# Branch trunk
# Node ID e31559a47a90f4fc44d6145177b4fdadb3bad67d
# Parent a8ca1f8a2394ec93dffbe0921ba3fb836fefd4c9
# EXP-Topic riastradh-pr57638-armv5tls
gcc/arm: For -mtp=3Dsoft, ensure stack alignment even in leaves.
The option -mtp=3Dsoft, which is the default on earmv5, makes queries
to the thread pointer, for access to static (`initial-exec')
thread-local storage, go through the C runtime subroutine
__aeabi_read_tp. (For earmv>=3D6, we use the cp15 register via a
single instruction.)
Thus procedures which gcc thinks of as leaf procedures that use
__aeabi_read_tp are not really leaf procedures -- and even though
__aeabi_read_tp itself doesn't use the stack pointer at all,
resolving the symbol may take a detour through the dynamic linker,
which does rely on an aligned stack pointer.
Ideally, we would ensure stack alignment only for `leaf' procedures
that actually use __aeabi_read_tp. But I don't know how to query
that in this context. And in any case, this change only applies to
subroutines that are already saving 2n+1 registers for some n,
picking some arbitrary register to round it up to 2n+2. For example:
int y;
int *
get_y(void)
{
return &y;
}
int *
get_y_with_r4(void)
{
asm volatile("" ::: "r4");
return &y;
}
With this change, we get:
00000018 <get_y>:
get_y():
18: e59f0000 ldr r0, [pc] @ 20 <get_y+0x8>
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
20: R_ARM_ABS32 .bss
00000024 <get_y_with_r4>:
get_y_with_r4():
24: e92d0030 push {r4, r5}
28: e8bd0030 pop {r4, r5}
2c: e59f0000 ldr r0, [pc] @ 34 <get_y_with_r4+0x10>
30: e12fff1e bx lr
34: 00000000 .word 0x00000000
34: R_ARM_ABS32 .bss
In contrast, with earmv>=3D6, get_y would be unchanged, but
get_y_with_r4 would be:
00000020 <get_y_with_r4>:
get_y_with_r4():
20: e52d4004 push {r4} @ (str r4, [sp, #-4]!)
24: e59f0004 ldr r0, [pc, #4] @ 30 <get_y_with_r4+0x10>
28: e49d4004 pop {r4} @ (ldr r4, [sp], #4)
2c: e12fff1e bx lr
30: 00000000 .word 0x00000000
30: R_ARM_ABS32 .bss
Note that the number of instructions hasn't changed; all that has
changed is whether we save and restore one or two registers in the
function prologue and epilogue.
PR lib/57638: thread local storage broken on evbarm (armv5)
diff -r a8ca1f8a2394 -r e31559a47a90 external/gpl3/gcc/dist/gcc/config/arm/=
arm.cc
--- a/external/gpl3/gcc/dist/gcc/config/arm/arm.cc Fri Jul 24 03:41:48 2026=
+0000
+++ b/external/gpl3/gcc/dist/gcc/config/arm/arm.cc Fri Jul 24 15:11:45 2026=
+0000
@@ -23156,7 +23156,16 @@ arm_compute_frame_layout (void)
if (crtl->is_leaf && frame_size =3D=3D 0
/* However if it calls alloca(), we have a dynamically allocated
block of BIGGEST_ALIGNMENT on stack, so still do stack alignment. */
- && ! cfun->calls_alloca)
+ && ! cfun->calls_alloca
+ /* If queries to the thread pointer go through __aeabi_read_tp,
+ we must ensure the stack has correct alignment even though we
+ think of this as a leaf routine. Even if __aeabi_read_tp
+ itself doesn't use the stack, resolving the symbol may take a
+ detour through a procedure call to the dynamic linker. We
+ should really enforce alignment only if the procedure actually
+ uses __aeabi_read_tp (load_tp_soft*) but I don't know how to
+ query that here. */
+ && !TARGET_SOFT_TP)
{
offsets->outgoing_args =3D offsets->soft_frame;
offsets->locals_base =3D offsets->soft_frame;
--=_zuuYtksK0C8RJaF9J8AwVVP/KZSlw/L+--
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/57638 CVS commit: src/external/gpl3/gcc/dist/gcc/config/arm
Date: Sat, 25 Jul 2026 19:01:48 +0000
Module Name: src
Committed By: riastradh
Date: Sat Jul 25 19:01:48 UTC 2026
Modified Files:
src/external/gpl3/gcc/dist/gcc/config/arm: arm.cc
Log Message:
gcc/arm: For -mtp=soft, ensure stack alignment even in leaves.
The option -mtp=soft, which is the default on earmv5, makes queries
to the thread pointer, for access to static (`initial-exec')
thread-local storage, go through the C runtime subroutine
__aeabi_read_tp. (For earmv>=6, we use the cp15 register via a
single instruction.)
Thus procedures which gcc thinks of as leaf procedures that use
__aeabi_read_tp are not really leaf procedures -- and even though
__aeabi_read_tp itself doesn't use the stack pointer at all,
resolving the symbol may take a detour through the dynamic linker,
which does rely on an aligned stack pointer.
Without this change, code like
__thread int x = 0;
int *
get_x(void)
{
return &x;
}
is compiled into:
00000000 <get_x>:
get_x():
0: e52de004 push {lr} @ (str lr, [sp, #-4]!)
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e49df004 pop {pc} @ (ldr pc, [sp], #4)
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
With this change, extend the _existing_ push and pop instructions in
the prologue and epilogue to save and restore r4 arbitrarily (not
that the content is useful for anything; it just keeps the stack
pointer aligned to multiple of 8):
00000000 <get_x>:
get_x():
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e8bd8010 pop {r4, pc}
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
Ideally, we would ensure stack alignment only for `leaf' procedures
that actually use __aeabi_read_tp. But I don't know how to query
that in this context. And in any case, this change only applies to
subroutines that are already saving 2n+1 registers for some n,
picking some arbitrary register to round it up to 2n+2. For example:
int y;
int *
get_y(void)
{
return &y;
}
int *
get_y_with_r4(void)
{
asm volatile("" ::: "r4");
return &y;
}
With this change, we get:
00000018 <get_y>:
get_y():
18: e59f0000 ldr r0, [pc] @ 20 <get_y+0x8>
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
20: R_ARM_ABS32 .bss
00000024 <get_y_with_r4>:
get_y_with_r4():
24: e92d0030 push {r4, r5}
28: e8bd0030 pop {r4, r5}
2c: e59f0000 ldr r0, [pc] @ 34 <get_y_with_r4+0x10>
30: e12fff1e bx lr
34: 00000000 .word 0x00000000
34: R_ARM_ABS32 .bss
In contrast, with earmv>=6, get_y would be unchanged, but
get_y_with_r4 would be:
00000020 <get_y_with_r4>:
get_y_with_r4():
20: e52d4004 push {r4} @ (str r4, [sp, #-4]!)
24: e59f0004 ldr r0, [pc, #4] @ 30 <get_y_with_r4+0x10>
28: e49d4004 pop {r4} @ (ldr r4, [sp], #4)
2c: e12fff1e bx lr
30: 00000000 .word 0x00000000
30: R_ARM_ABS32 .bss
Note that the number of instructions hasn't changed; all that has
changed is whether we save and restore one or two registers in the
function prologue and epilogue (or more generally, 2n+1 vs 2n+2
registers).
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@
To generate a diff of this commit:
cvs rdiff -u -r1.1.1.4 -r1.2 src/external/gpl3/gcc/dist/gcc/config/arm/arm.cc
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: open->needs-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Sat, 25 Jul 2026 19:31:32 +0000
State-Changed-Why:
Workaround has been committed to HEAD.
Probably worth pulling up after we run some tests with it.
From: "Kalvis Duckmanton" <kalvisd@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/57638 CVS commit: src/external/gpl3/gcc/dist/gcc/config/arm
Date: Thu, 6 Aug 2026 04:29:14 +0000
Module Name: src
Committed By: kalvisd
Date: Thu Aug 6 04:29:14 UTC 2026
Modified Files:
src/external/gpl3/gcc/dist/gcc/config/arm: arm.cc arm.h arm.md
Log Message:
gcc/arm: For -mtp=soft, ensure stack alignment in leaf functions using
thread local storage.
For each function compiled, record whether it accesses thread-local
storage. When laying out the stack frame for a leaf function, if the
function needs to use a C runtime subroutine to retrieve the thread
pointer, make sure that the stack pointer is aligned appropriately.
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@ riastradh@
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/external/gpl3/gcc/dist/gcc/config/arm/arm.cc
cvs rdiff -u -r1.26 -r1.27 src/external/gpl3/gcc/dist/gcc/config/arm/arm.h
cvs rdiff -u -r1.23 -r1.24 src/external/gpl3/gcc/dist/gcc/config/arm/arm.md
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: needs-pullups->pending-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Thu, 08 Oct 2026 20:17:29 +0000
State-Changed-Why:
fixed in HEAD, bug submitted upstream
pullup-11 #515
pullup-10 #1356
From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/57638 CVS commit: [netbsd-11] src/external/gpl3/gcc/dist/gcc/config/arm
Date: Fri, 9 Oct 2026 15:25:40 +0000
Module Name: src
Committed By: martin
Date: Fri Oct 9 15:25:40 UTC 2026
Modified Files:
src/external/gpl3/gcc/dist/gcc/config/arm [netbsd-11]: arm.cc arm.h
arm.md
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #515):
external/gpl3/gcc/dist/gcc/config/arm/arm.cc: revision 1.2
external/gpl3/gcc/dist/gcc/config/arm/arm.cc: revision 1.3
external/gpl3/gcc/dist/gcc/config/arm/arm.md: revision 1.24
external/gpl3/gcc/dist/gcc/config/arm/arm.h: revision 1.27
gcc/arm: For -mtp=soft, ensure stack alignment even in leaves.
The option -mtp=soft, which is the default on earmv5, makes queries
to the thread pointer, for access to static (`initial-exec')
thread-local storage, go through the C runtime subroutine
__aeabi_read_tp. (For earmv>=6, we use the cp15 register via a
single instruction.)
Thus procedures which gcc thinks of as leaf procedures that use
__aeabi_read_tp are not really leaf procedures -- and even though
__aeabi_read_tp itself doesn't use the stack pointer at all,
resolving the symbol may take a detour through the dynamic linker,
which does rely on an aligned stack pointer.
Without this change, code like
__thread int x = 0;
int *
get_x(void)
{
return &x;
}
is compiled into:
00000000 <get_x>:
get_x():
0: e52de004 push {lr} @ (str lr, [sp, #-4]!)
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e49df004 pop {pc} @ (ldr pc, [sp], #4)
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
With this change, extend the _existing_ push and pop instructions in
the prologue and epilogue to save and restore r4 arbitrarily (not
that the content is useful for anything; it just keeps the stack
pointer aligned to multiple of 8):
00000000 <get_x>:
get_x():
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e8bd8010 pop {r4, pc}
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
Ideally, we would ensure stack alignment only for `leaf' procedures
that actually use __aeabi_read_tp. But I don't know how to query
that in this context. And in any case, this change only applies to
subroutines that are already saving 2n+1 registers for some n,
picking some arbitrary register to round it up to 2n+2. For example:
int y;
int *
get_y(void)
{
return &y;
}
int *
get_y_with_r4(void)
{
asm volatile("" ::: "r4");
return &y;
}
With this change, we get:
00000018 <get_y>:
get_y():
18: e59f0000 ldr r0, [pc] @ 20 <get_y+0x8>
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
20: R_ARM_ABS32 .bss
00000024 <get_y_with_r4>:
get_y_with_r4():
24: e92d0030 push {r4, r5}
28: e8bd0030 pop {r4, r5}
2c: e59f0000 ldr r0, [pc] @ 34 <get_y_with_r4+0x10>
30: e12fff1e bx lr
34: 00000000 .word 0x00000000
34: R_ARM_ABS32 .bss
In contrast, with earmv>=6, get_y would be unchanged, but
get_y_with_r4 would be:
00000020 <get_y_with_r4>:
get_y_with_r4():
20: e52d4004 push {r4} @ (str r4, [sp, #-4]!)
24: e59f0004 ldr r0, [pc, #4] @ 30 <get_y_with_r4+0x10>
28: e49d4004 pop {r4} @ (ldr r4, [sp], #4)
2c: e12fff1e bx lr
30: 00000000 .word 0x00000000
30: R_ARM_ABS32 .bss
Note that the number of instructions hasn't changed; all that has
changed is whether we save and restore one or two registers in the
function prologue and epilogue (or more generally, 2n+1 vs 2n+2
registers).
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@
gcc/arm: For -mtp=soft, ensure stack alignment in leaf functions using
thread local storage.
For each function compiled, record whether it accesses thread-local
storage. When laying out the stack frame for a leaf function, if the
function needs to use a C runtime subroutine to retrieve the thread
pointer, make sure that the stack pointer is aligned appropriately.
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@ riastradh@
To generate a diff of this commit:
cvs rdiff -u -r1.1.1.3 -r1.1.1.3.2.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.cc
cvs rdiff -u -r1.25 -r1.25.4.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.h
cvs rdiff -u -r1.22 -r1.22.2.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.md
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/57638 CVS commit: [netbsd-10] src/external/gpl3/gcc/dist/gcc/config/arm
Date: Fri, 9 Oct 2026 15:30:51 +0000
Module Name: src
Committed By: martin
Date: Fri Oct 9 15:30:51 UTC 2026
Modified Files:
src/external/gpl3/gcc/dist/gcc/config/arm [netbsd-10]: arm.c arm.h
arm.md
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #515):
external/gpl3/gcc/dist/gcc/config/arm/arm.cc: revision 1.2
external/gpl3/gcc/dist/gcc/config/arm/arm.cc: revision 1.3
(applied to arm.c)
external/gpl3/gcc/dist/gcc/config/arm/arm.md: revision 1.24
external/gpl3/gcc/dist/gcc/config/arm/arm.h: revision 1.27
(all via patch)
gcc/arm: For -mtp=soft, ensure stack alignment even in leaves.
The option -mtp=soft, which is the default on earmv5, makes queries
to the thread pointer, for access to static (`initial-exec')
thread-local storage, go through the C runtime subroutine
__aeabi_read_tp. (For earmv>=6, we use the cp15 register via a
single instruction.)
Thus procedures which gcc thinks of as leaf procedures that use
__aeabi_read_tp are not really leaf procedures -- and even though
__aeabi_read_tp itself doesn't use the stack pointer at all,
resolving the symbol may take a detour through the dynamic linker,
which does rely on an aligned stack pointer.
Without this change, code like
__thread int x = 0;
int *
get_x(void)
{
return &x;
}
is compiled into:
00000000 <get_x>:
get_x():
0: e52de004 push {lr} @ (str lr, [sp, #-4]!)
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e49df004 pop {pc} @ (ldr pc, [sp], #4)
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
With this change, extend the _existing_ push and pop instructions in
the prologue and epilogue to save and restore r4 arbitrarily (not
that the content is useful for anything; it just keeps the stack
pointer aligned to multiple of 8):
00000000 <get_x>:
get_x():
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <__aeabi_read_tp>
4: R_ARM_CALL __aeabi_read_tp
8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14>
c: e0830000 add r0, r3, r0
10: e8bd8010 pop {r4, pc}
14: 00000000 .word 0x00000000
14: R_ARM_TLS_LE32 .LANCHOR0
Ideally, we would ensure stack alignment only for `leaf' procedures
that actually use __aeabi_read_tp. But I don't know how to query
that in this context. And in any case, this change only applies to
subroutines that are already saving 2n+1 registers for some n,
picking some arbitrary register to round it up to 2n+2. For example:
int y;
int *
get_y(void)
{
return &y;
}
int *
get_y_with_r4(void)
{
asm volatile("" ::: "r4");
return &y;
}
With this change, we get:
00000018 <get_y>:
get_y():
18: e59f0000 ldr r0, [pc] @ 20 <get_y+0x8>
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
20: R_ARM_ABS32 .bss
00000024 <get_y_with_r4>:
get_y_with_r4():
24: e92d0030 push {r4, r5}
28: e8bd0030 pop {r4, r5}
2c: e59f0000 ldr r0, [pc] @ 34 <get_y_with_r4+0x10>
30: e12fff1e bx lr
34: 00000000 .word 0x00000000
34: R_ARM_ABS32 .bss
In contrast, with earmv>=6, get_y would be unchanged, but
get_y_with_r4 would be:
00000020 <get_y_with_r4>:
get_y_with_r4():
20: e52d4004 push {r4} @ (str r4, [sp, #-4]!)
24: e59f0004 ldr r0, [pc, #4] @ 30 <get_y_with_r4+0x10>
28: e49d4004 pop {r4} @ (ldr r4, [sp], #4)
2c: e12fff1e bx lr
30: 00000000 .word 0x00000000
30: R_ARM_ABS32 .bss
Note that the number of instructions hasn't changed; all that has
changed is whether we save and restore one or two registers in the
function prologue and epilogue (or more generally, 2n+1 vs 2n+2
registers).
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@
gcc/arm: For -mtp=soft, ensure stack alignment in leaf functions using
thread local storage.
For each function compiled, record whether it accesses thread-local
storage. When laying out the stack frame for a leaf function, if the
function needs to use a C runtime subroutine to retrieve the thread
pointer, make sure that the stack pointer is aligned appropriately.
PR lib/57638: thread local storage broken on evbarm (armv5)
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394
ok skrll@ riastradh@
To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.12.2.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.c
cvs rdiff -u -r1.24 -r1.24.2.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.h
cvs rdiff -u -r1.20 -r1.20.2.1 \
src/external/gpl3/gcc/dist/gcc/config/arm/arm.md
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: pending-pullups->closed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Sat, 10 Oct 2026 17:16:51 +0000
State-Changed-Why:
fixed and pullups completed
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.