NetBSD Problem Report #59567
From www@netbsd.org Thu Jul 31 13:39:09 2025
Return-Path: <www@netbsd.org>
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)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id B785C1A923C
for <gnats-bugs@gnats.NetBSD.org>; Thu, 31 Jul 2025 13:39:09 +0000 (UTC)
Message-Id: <20250731133908.7914C1A923E@mollari.NetBSD.org>
Date: Thu, 31 Jul 2025 13:39:08 +0000 (UTC)
From: sagawa.aki+nbsd@gmail.com
Reply-To: sagawa.aki+nbsd@gmail.com
To: gnats-bugs@NetBSD.org
Subject: dladdr(3) doesn't work properly especially when main executable is loaded at high memory address
X-Send-Pr-Version: www-1.0
>Number: 59567
>Category: lib
>Synopsis: dladdr(3) doesn't work properly especially when main executable is loaded at high memory address
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: riastradh
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 31 13:40:01 +0000 2025
>Closed-Date: Sat Jun 27 20:05:53 +0000 2026
>Last-Modified: Sat Jun 27 20:05:53 +0000 2026
>Originator: Akihiro Sagawa
>Release: NetBSD 10.1
>Organization:
>Environment:
NetBSD xiaolan.local 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/i386/compile/GENERIC i386
>Description:
I'm trying to run Wine on NetBSD/i386. When using ALSA lib (alisa-lib
and alsa-plugins-oss) to play a wav audio file, wine complains with the
following message and no sound is output.
> ALSA lib conf.c:4029:(snd_config_hooks_call) Cannot open shared library (null) (mmap of executable at correct address failed)
> ALSA lib conf.c:4658:(snd_config_update_r) hooks failed, removing configuration
Upon investigating the issue, I found that dladdr(3) appears to be the
source of the problem.
My Investigation:
_rtld_obj_from_addr function, called from dladdr(3), traverses
_rtld_objlist and returns the Obj_Entry object which satisfies
mapbase < addr < (mapbase + mapsize). However, the main executable's
mapsize is currently broken and has too large value. Thus, its result is
the main executable object. As a result, given addr is incorrectly
interpreted as belonging to the main executable rather than another shared library.
>How-To-Repeat:
As the compilation procedure for Wine is highly involved, a simplified
example is presented below.
[demo.c]----------------------------------------------------------------
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char* argv[])
{
Dl_info dlinfo;
int ret;
ret = dladdr(printf, &dlinfo);
printf("ret=%d, name=%s\n", ret, dlinfo.dli_fname);
return 0;
}
------------------------------------------------------------------------
To compile the file, run:
% gcc -fno-plt -g -O -Wl,-Ttext-segment=0x78000000 -o demo demo.c
Expected Result:
% $PWD/demo
ret=1, name=/usr/lib/libc.so.12
Actual Result:
% $PWD/demo
ret=1, name=/home/sagawa/dladdr/demo
Debug procedure:
% gdb ./demo
(gdb) b dladdr
Function "dladdr" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (dladdr) pending.
(gdb) run
Starting program: /home/sagawa/dladdr/demo
Breakpoint 1, dladdr (addr=0xb138a557 <printf>, info=0xbfb4753c)
at /usr/src/libexec/ld.elf_so/rtld.c:1339
1339 {
(gdb) info proc mappings
process 7029
Mapped address spaces:
Start Addr End Addr Size Offset Flags File
0x78000000 0x78001000 0x1000 0x0 r-x C-PD /home/sagawa/dladdr/demo
0x78001000 0x78002000 0x1000 0x0 rw- C-PD
(*snip*)
(gdb) p/x _rtld_objlist->mapsize
$1 = 0x78001000
mapsize should be 0x1000 at this point as shown in gdb's "info proc mapping" Size column.
>Fix:
Here is the proposed patch for NetBSD-current which fixes the main executable's mapsize in _rtld_objlist.
Otherwise, the value of obj->vaddrbase is zero when the line "size =
roundup(vaddr + ph->p_memsz) - obj->vaddrbase;" is executed at the first time.
Index: ld.elf_so/headers.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/headers.c,v
retrieving revision 1.75
diff -u -r1.75 headers.c
--- ld.elf_so/headers.c 2 May 2025 23:03:16 -0000 1.75
+++ ld.elf_so/headers.c 31 Jul 2025 12:33:07 -0000
@@ -551,14 +551,15 @@
break;
case PT_LOAD:
- size = round_up(vaddr + ph->p_memsz) - obj->vaddrbase;
if (first_seg) { /* First load segment */
obj->vaddrbase = round_down(vaddr);
obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
+ size = round_up(vaddr + ph->p_memsz) - obj->vaddrbase;
obj->textsize = size;
obj->mapsize = size;
first_seg = false;
} else { /* Last load segment */
+ size = round_up(vaddr + ph->p_memsz) - obj->vaddrbase;
obj->mapsize = MAX(obj->mapsize, size);
}
dbg(("headers: %s %p phsize %" PRImemsz,
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Sun, 03 Aug 2025 19:58:28 +0000
State-Changed-Why:
Problem has been analyzed. Patch has been provided.
Need:
[x] automatic test to exercise the bug
[x] fix in HEAD once testbed confirms test xfails
[ ] pullup-9, [ ] pullup-10, [ ] pullup-11
We appear to have absolutely no direct tests of dladdr(3). Closest
we have is tests of libexecinfo's backtrace_symbols_fmt, which calls
dladdr(3), in tests/lib/libexecinfo. We could add a variant
libexecinfo test with -fno-plt -Ttext-segment=<high> to trigger this,
but we should also have some direct tests of dladdr(3).
Rather than relying on -fno-plt -Ttext-segment=<high> and using
dladdr's search as a proxy, I wonder if obj->mapsize or obj->textsize
is exposed more directly anywhere else like dlinfo(3) RTLD_DI_LINKMAP
which we could compare to the PT_LOAD segment obtained by
dl_iterate_phdr(3).
(Writing down all the analogous linker arguments for each
architecture, and verifying they exercise the bug, sounds like a
pain!)
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59567 CVS commit: src
Date: Sun, 14 Dec 2025 23:26:12 +0000
Module Name: src
Committed By: riastradh
Date: Sun Dec 14 23:26:12 UTC 2025
Modified Files:
src/distrib/sets/lists/debug: mi
src/distrib/sets/lists/tests: mi
src/tests/libexec/ld.elf_so: Makefile
Added Files:
src/tests/libexec/ld.elf_so: t_dladdr.c
Log Message:
dl_addr(3): Add some automatic tests.
XXX Should also test the libc stubs, maybe move this into
tests/lib/libc/dlfcn and test both static and (for MKPIC=yes)
dynamic, but this'll do for now.
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
To generate a diff of this commit:
cvs rdiff -u -r1.492 -r1.493 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1403 -r1.1404 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.30 -r1.31 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/t_dladdr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Responsible-Changed-From-To: lib-bug-people->riastradh
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Sun, 14 Dec 2025 23:44:24 +0000
Responsible-Changed-Why:
I'll take it
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59567 CVS commit: src
Date: Mon, 15 Dec 2025 02:36:47 +0000
Module Name: src
Committed By: riastradh
Date: Mon Dec 15 02:36:47 UTC 2025
Modified Files:
src/libexec/ld.elf_so: headers.c
src/tests/libexec/ld.elf_so: t_dladdr.c
Log Message:
dladdr(3): Fix determination of object address intervals.
This appears to have been broken in rev. 1.62 back in 2017 with a
change to compute the largest distance from the first LOAD segment's
starting address to the maximum address of any LOAD segment -- we
started by finding the distance from _zero_ to the maximum address of
the first LOAD segment because we subtracted obj->vaddrbase which
wasn't initialized yet, so we would overshoot obj->mapsize and
obj->textsize by whatever the value of obj->vaddrbase turned out to
be.
XXX The commit message for 1.62 suggests we are dropping the
assumption that the LOAD segments appear in order. But it looks to
me like we still assume the _first_ load segment has the lowest
virtual address, because we keep it as obj->vaddrbase/obj->mapbase
and use it as a reference point for measuring the size of an object
by subtracting it from each load segment's maximum address. Is the
original assumption that LOAD segments appear in order valid after
all, or do we need to do extra work here to handle objects whose LOAD
segments are so much out of order that the first LOAD segment isn't
lowest in virtual address space? Unclear!
Might help with wine.
Based on a patch by Akihiro Sagawa, thanks!
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.1 -r1.2 src/tests/libexec/ld.elf_so/t_dladdr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: analyzed->needs-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Mon, 15 Dec 2025 02:41:35 +0000
State-Changed-Why:
needs pullup-9, pullup-10, pullup-11
From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59567 CVS commit: [netbsd-11] src
Date: Thu, 18 Dec 2025 18:17:32 +0000
Module Name: src
Committed By: martin
Date: Thu Dec 18 18:17:32 UTC 2025
Modified Files:
src/distrib/sets/lists/debug [netbsd-11]: mi
src/distrib/sets/lists/tests [netbsd-11]: mi
src/libexec/ld.elf_so [netbsd-11]: headers.c
src/tests/libexec/ld.elf_so [netbsd-11]: Makefile
Added Files:
src/tests/libexec/ld.elf_so [netbsd-11]: t_dladdr.c
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #129):
distrib/sets/lists/tests/mi: revision 1.1404
libexec/ld.elf_so/headers.c: revision 1.76
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.1
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.2
tests/libexec/ld.elf_so/Makefile: revision 1.31
distrib/sets/lists/debug/mi: revision 1.493
dl_addr(3): Add some automatic tests.
XXX Should also test the libc stubs, maybe move this into
tests/lib/libc/dlfcn and test both static and (for MKPIC=yes)
dynamic, but this'll do for now.
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
dladdr(3): Fix determination of object address intervals.
This appears to have been broken in rev. 1.62 back in 2017 with a
change to compute the largest distance from the first LOAD segment's
starting address to the maximum address of any LOAD segment -- we
started by finding the distance from _zero_ to the maximum address of
the first LOAD segment because we subtracted obj->vaddrbase which
wasn't initialized yet, so we would overshoot obj->mapsize and
obj->textsize by whatever the value of obj->vaddrbase turned out to
be.
XXX The commit message for 1.62 suggests we are dropping the
assumption that the LOAD segments appear in order. But it looks to
me like we still assume the _first_ load segment has the lowest
virtual address, because we keep it as obj->vaddrbase/obj->mapbase
and use it as a reference point for measuring the size of an object
by subtracting it from each load segment's maximum address. Is the
original assumption that LOAD segments appear in order valid after
all, or do we need to do extra work here to handle objects whose LOAD
segments are so much out of order that the first LOAD segment isn't
lowest in virtual address space? Unclear!
Might help with wine.
Based on a patch by Akihiro Sagawa, thanks!
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
To generate a diff of this commit:
cvs rdiff -u -r1.485.2.5 -r1.485.2.6 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1387.2.4 -r1.1387.2.5 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.75 -r1.75.2.1 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.28.2.2 -r1.28.2.3 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.2.2.2 src/tests/libexec/ld.elf_so/t_dladdr.c
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: Fri, 26 Jun 2026 18:41:58 +0000
State-Changed-Why:
fixed in HEAD
pullup-11 #129 https://releng.netbsd.org/cgi-bin/req-11.cgi?show=129
pullup-10 #1291 https://releng.netbsd.org/cgi-bin/req-10.cgi?show=1291
pullup-9 #2021 https://releng.netbsd.org/cgi-bin/req-9.cgi?show=2021
From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59567 CVS commit: [netbsd-10] src
Date: Sat, 27 Jun 2026 19:55:35 +0000
Module Name: src
Committed By: martin
Date: Sat Jun 27 19:55:35 UTC 2026
Modified Files:
src/distrib/sets/lists/debug [netbsd-10]: mi
src/distrib/sets/lists/tests [netbsd-10]: mi
src/libexec/ld.elf_so [netbsd-10]: headers.c
src/tests/libexec/ld.elf_so [netbsd-10]: Makefile
Added Files:
src/tests/libexec/ld.elf_so [netbsd-10]: t_dladdr.c
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #1291):
distrib/sets/lists/tests/mi: revision 1.1404
libexec/ld.elf_so/headers.c: revision 1.76
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.1
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.2
tests/libexec/ld.elf_so/Makefile: revision 1.31
distrib/sets/lists/debug/mi: revision 1.493
dl_addr(3): Add some automatic tests.
XXX Should also test the libc stubs, maybe move this into
tests/lib/libc/dlfcn and test both static and (for MKPIC=yes)
dynamic, but this'll do for now.
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
dladdr(3): Fix determination of object address intervals.
This appears to have been broken in rev. 1.62 back in 2017 with a
change to compute the largest distance from the first LOAD segment's
starting address to the maximum address of any LOAD segment -- we
started by finding the distance from _zero_ to the maximum address of
the first LOAD segment because we subtracted obj->vaddrbase which
wasn't initialized yet, so we would overshoot obj->mapsize and
obj->textsize by whatever the value of obj->vaddrbase turned out to
be.
XXX The commit message for 1.62 suggests we are dropping the
assumption that the LOAD segments appear in order. But it looks to
me like we still assume the _first_ load segment has the lowest
virtual address, because we keep it as obj->vaddrbase/obj->mapbase
and use it as a reference point for measuring the size of an object
by subtracting it from each load segment's maximum address. Is the
original assumption that LOAD segments appear in order valid after
all, or do we need to do extra work here to handle objects whose LOAD
segments are so much out of order that the first LOAD segment isn't
lowest in virtual address space? Unclear!
Might help with wine.
Based on a patch by Akihiro Sagawa, thanks!
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
To generate a diff of this commit:
cvs rdiff -u -r1.394.2.17 -r1.394.2.18 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1238.2.21 -r1.1238.2.22 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.70.2.1 -r1.70.2.2 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.12.4.2 -r1.12.4.3 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.2.4.2 src/tests/libexec/ld.elf_so/t_dladdr.c
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/59567 CVS commit: [netbsd-9] src
Date: Sat, 27 Jun 2026 20:01:09 +0000
Module Name: src
Committed By: martin
Date: Sat Jun 27 20:01:09 UTC 2026
Modified Files:
src/distrib/sets/lists/debug [netbsd-9]: mi
src/distrib/sets/lists/tests [netbsd-9]: mi
src/libexec/ld.elf_so [netbsd-9]: headers.c
src/tests/libexec/ld.elf_so [netbsd-9]: Makefile
Added Files:
src/tests/libexec/ld.elf_so [netbsd-9]: t_dladdr.c
Log Message:
Pull up following revision(s) (requested by riastradh in ticket #2021):
distrib/sets/lists/tests/mi: revision 1.1404
libexec/ld.elf_so/headers.c: revision 1.76
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.1
tests/libexec/ld.elf_so/t_dladdr.c: revision 1.2
tests/libexec/ld.elf_so/Makefile: revision 1.31
distrib/sets/lists/debug/mi: revision 1.493
dl_addr(3): Add some automatic tests.
XXX Should also test the libc stubs, maybe move this into
tests/lib/libc/dlfcn and test both static and (for MKPIC=yes)
dynamic, but this'll do for now.
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
dladdr(3): Fix determination of object address intervals.
This appears to have been broken in rev. 1.62 back in 2017 with a
change to compute the largest distance from the first LOAD segment's
starting address to the maximum address of any LOAD segment -- we
started by finding the distance from _zero_ to the maximum address of
the first LOAD segment because we subtracted obj->vaddrbase which
wasn't initialized yet, so we would overshoot obj->mapsize and
obj->textsize by whatever the value of obj->vaddrbase turned out to
be.
XXX The commit message for 1.62 suggests we are dropping the
assumption that the LOAD segments appear in order. But it looks to
me like we still assume the _first_ load segment has the lowest
virtual address, because we keep it as obj->vaddrbase/obj->mapbase
and use it as a reference point for measuring the size of an object
by subtracting it from each load segment's maximum address. Is the
original assumption that LOAD segments appear in order valid after
all, or do we need to do extra work here to handle objects whose LOAD
segments are so much out of order that the first LOAD segment isn't
lowest in virtual address space? Unclear!
Might help with wine.
Based on a patch by Akihiro Sagawa, thanks!
PR lib/59567: dladdr(3) doesn't work properly especially when main
executable is loaded at high memory address
To generate a diff of this commit:
cvs rdiff -u -r1.285.2.11 -r1.285.2.12 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.818.2.9 -r1.818.2.10 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.65.2.2 -r1.65.2.3 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.10.2.2 -r1.10.2.3 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.2.6.2 src/tests/libexec/ld.elf_so/t_dladdr.c
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, 27 Jun 2026 20:05:53 +0000
State-Changed-Why:
fixed in HEAD, pulled up to 11, 10, and 9
>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.