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:

NetBSD Home
NetBSD PR Database Search

(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.