NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-mips/59064 (jemalloc switch to 5.3 broke userland)
[+cc another mips wizard]
At this point I am well and truly baffled.
Running the attached test program (same name as the other program but
rather inaptly named now) under gdb, it works fine every time, with:
(gdb) set environment LD_LIBRARY_PATH = /var/tmp/20250413/lib
(/var/tmp/20250413/lib/libc.so.12 is built with jemalloc using
initial-exec tls, while /lib/libc.so.12 is not -- this way programs
generally work, including gdb, but I can test the broken libc with a
target program.)
If I set a breakpoint on malloc_default, and single-step through, I
get to:
(gdb) disas
Dump of assembler code for function malloc_default:
0x7853be08 <+0>: addiu sp,sp,-144
0x7853be0c <+4>: sd gp,120(sp)
0x7853be10 <+8>: lui gp,0x16
0x7853be14 <+12>: addu gp,gp,t9
0x7853be18 <+16>: addiu gp,gp,-31640
=> 0x7853be1c <+20>: lw v0,-23368(gp)
0x7853be20 <+24>: .word 0x7c03e83b /* rdhwr v1,$29 */
...
(gdb) print (void *)$gp
$4 = (void *) 0x78694270 <path+752>
(gdb) x/xw $gp - 23368
0x7868e728: 0xffff9008
That looks fine (0xffff9008 = -28664, a plausible tls offset from
$v1), and $v0 and $v1 hold reasonable values when I single-step
through to
0x7853be50 <+72>: lbu v1,600(a2)
and it all works:
(gdb) print (void *)$v0
$8 = (void *) 0xffff9008
(gdb) print (void *)$v1
$9 = (void *) 0x786b9008
But for some runs of
$ LD_LIBRARY_PATH=/var/tmp/20250413/lib ./rdhwr
it crashes at the lbu instruction, and gdb on the core dump shows:
(gdb) disas
Dump of assembler code for function malloc_default:
0x7853be08 <+0>: addiu sp,sp,-144
0x7853be0c <+4>: sd gp,120(sp)
0x7853be10 <+8>: lui gp,0x16
0x7853be14 <+12>: addu gp,gp,t9
0x7853be18 <+16>: addiu gp,gp,-31640
0x7853be1c <+20>: lw v0,-23368(gp)
0x7853be20 <+24>: .word 0x7c03e83b /* rdhwr v1,$29 */
...
=> 0x7853be50 <+72>: lbu v1,600(a2)
...
(gdb) print (void *)$gp
$4 = (void *) 0x78694270 <path+752>
(gdb) print (void *)$v0
$14 = (void *) 0x7853be20 <malloc_default+24>
(gdb) x/xw $gp - 23368
0x7868e728: 0xffff9008
But:
(gdb) print (void *)$v0
$15 = (void *) 0x7853be20 <malloc_default+24>
(gdb) print (void *)$v1
$16 = (void *) 0x786b9008
$v1 is right, but $v0 is completely bonkers -- and doesn't match what
is at -23368(gp), which surely lw v0,-23368(gp) should have loaded!
How does $v0 wind up with the address of the _rdhwr instruction_ when
I run this _not_ under gdb??? Are we dumping core dumps wrong, hiding
some underlying problem?
#include <machine/lwp_private.h>
#include <link_elf.h>
#include <lwp.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__thread int foo = 123;
struct tls_tcb tcb_storage[0x8000];
__noinline __used
static struct tls_tcb *
gettcb_rdhwr(void)
{
struct tls_tcb *tcb;
asm(".set push\n\t"
".set mips32r2\n\t"
"rdhwr $3,$29\n\t"
"move %[tcb],$3\n\t"
".set pop"
: [tcb]"=r"(tcb)
:
: "$3");
return tcb - (TLS_TP_OFFSET/sizeof(*tcb) + 1);
}
static int
dlitercb(struct dl_phdr_info *dlpi, size_t size, void *cookie)
{
char buf[1024];
snprintf(buf, sizeof(buf),
"dlpi_addr=0x%lx\n"
"dlpi_name=%s\n"
"dlpi_phdr=%p\n"
"dlpi_phnum=%d\n"
"dlpi_adds=%lld\n"
"dlpi_subs=%lld\n"
"dlpi_tls_modid=0x%zx\n"
"dlpi_tls_data=%p\n"
"\n",
(long)dlpi->dlpi_addr,
dlpi->dlpi_name,
dlpi->dlpi_phdr,
dlpi->dlpi_phnum,
dlpi->dlpi_adds,
dlpi->dlpi_subs,
dlpi->dlpi_tls_modid,
dlpi->dlpi_tls_data);
(void)write(STDOUT_FILENO, buf, strlen(buf));
return 0;
}
int
main(void)
{
char buf[1024];
struct tls_tcb *tcb_rdhwr, *tcb_syscall;
(void)dl_iterate_phdr(&dlitercb, NULL);
tcb_syscall = __lwp_gettcb_fast();
snprintf_ss(buf, sizeof(buf), "tcb_syscall %p\n", tcb_syscall);
(void)write(STDOUT_FILENO, buf, strlen(buf));
tcb_rdhwr = gettcb_rdhwr();
snprintf_ss(buf, sizeof(buf), "tcb_rdhwr %p\n", tcb_rdhwr);
(void)write(STDOUT_FILENO, buf, strlen(buf));
printf("%p\n", malloc(1));
fflush(stdout);
#if 1
__USE(tcb_storage);
__USE(tcb_syscall);
__USE(tcb_rdhwr);
__USE(buf);
#else
__lwp_settcb(tcb_storage);
tcb_syscall = __lwp_gettcb_fast();
snprintf_ss(buf, sizeof(buf), "tcb_syscall %p\n", tcb_syscall);
(void)write(STDOUT_FILENO, buf, strlen(buf));
tcb_rdhwr = gettcb_rdhwr();
snprintf_ss(buf, sizeof(buf), "tcb_rdhwr %p\n", tcb_rdhwr);
(void)write(STDOUT_FILENO, buf, strlen(buf));
#endif
return 0;
}
Home |
Main Index |
Thread Index |
Old Index