* [PATCH v2] [gdb] Detect corrupt link map with zero l_ld and l_addr
@ 2026-09-27 6:30 Tom de Vries
2026-09-28 14:54 ` Simon Marchi
0 siblings, 1 reply; 3+ messages in thread
From: Tom de Vries @ 2026-09-27 6:30 UTC (permalink / raw)
To: gdb-patches
On ppc64le-linux (AlmaLinux 9.8), I run into:
...
FAIL: gdb.mi/mi-dlmopen.exp: still-in-use fields were all correct
...
While investigating this, I stumbled on this warning emitted during the
calculation of allow_dlmopen_tests:
...
(gdb) run ^M
Starting program: allow_dlmopen_tests.x ^M
[Thread debugging using libthread_db enabled]^M
Using host libthread_db library "/lib64/libthread_db.so.1".^M
warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
address (wrong library or version mismatch?)^M
dlmopen debug supported.^M
...
The warning is mentioned in this glibc commit 88361b408b:
...
elf: Copy l_addr/l_ld when adding ld.so to a new namespace
When add ld.so to a new namespace, we don't actually load ld.so. We
create a new link map and refers the real one for almost everything.
Copy l_addr and l_ld from the real ld.so link map to avoid GDB warning:
warning: .dynamic section for ".../elf/ld-linux-x86-64.so.2" is not at \
the expected address (wrong library or version mismatch?)
when handling shared library loaded by dlmopen.
...
So, AFAICT the setup is:
- the glibc package is based on v2.34
- it contains a backport of commit a93d9e03a3 ("Extend struct r_debug to
support multiple namespaces [BZ #15971]")
- it doesn't contain a backport of commit 88361b408b ("elf: Copy l_addr/l_ld
when adding ld.so to a new namespace") [1]
- both commits are part of v2.35
What happens is:
- when probing for l_addr and l_ld in svr4_solib_ops::read_lm_info, both get
the value 0
- in svr4_solib_ops::lm_addr_check, the 0 value propagates to l_dynaddr, and
"l_addr = l_dynaddr - dynaddr" then underflows, and things go downhill from
there, resulting in the warning and eventually the FAIL.
Fix this by detecting the situation in svr4_solib_ops::read_so_list, and
bailing out with a warning.
Add detection of this and other "corruption" warnings in allow_dlmopen_tests
to make sure the related test-cases are skipped.
In more detail, before this patch we have:
...
$ gdb -q -batch outputs/gdb.base/dlmopen/dlmopen -ex start -ex next \
-ex "pipe info shared | ld64"
...
warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
address (wrong library or version mismatch?)
...
0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
0x0000000000000160 0xffffffffffff0000 1 Yes /lib64/ld64.so.2
...
and after:
...
warning: Corrupted shared library entry: zero l_addr and l_ld
warning: Corrupted shared library entry: zero l_addr and l_ld
...
0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
...
Alternatively, we could prevent the underflow in svr4_solib_ops::lm_addr_check:
...
bool l_addr_updated = false;
if (l_dynaddr >= dynaddr)
{
l_addr = l_dynaddr - dynaddr;
l_addr_updated = true;
}
if (l_addr_updated
&& (l_addr & (minpagesize - 1)) == 0
&& (l_addr & align) == ((l_dynaddr - dynaddr) & align))
...
but we'd still get an incorrect range:
...
warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
address (wrong library or version mismatch?)
...
0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
0x0000000000060000 0x0000000000080000 1 Yes /lib64/ld64.so.2
...
FTR, in an earlier attempt I proposed to deal with the FAIL using an
xfail [2]. And in an another attempt I proposed to deal with it by
replicating the glibc fix in gdb [3].
Changed in v2:
- fixed incorrect footnote reference
- made comment more precise
- use "AlmaLinux" consistently
Versions:
- v1 https://sourceware.org/pipermail/gdb-patches/2026-September/230275.html
Tested on ppc64le-linux and x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33662
[1] https://bugs.almalinux.org/view.php?id=667
[2] https://sourceware.org/pipermail/gdb-patches/2026-July/229073.html
[3] https://sourceware.org/pipermail/gdb-patches/2026-August/229549.html
---
gdb/solib-svr4.c | 23 +++++++++++++++++++++++
gdb/testsuite/lib/gdb.exp | 3 +++
2 files changed, 26 insertions(+)
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index c4af1b11a4d..810b0fae7a3 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1333,6 +1333,29 @@ svr4_solib_ops::read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
if (*name == '\0' || match_main (name.get ()))
continue;
+ gdb_byte dummy;
+ if (li->l_addr_inferior == 0 && li->l_ld == 0
+ && target_read_memory (0, &dummy, 1) != 0)
+ {
+ /* We have l_addr_inferior == 0 and l_ld == 0 (corresponding to link
+ map entries l_addr and l_ld). This can happen with a glibc that:
+ - has commit a93d9e03a3 ("Extend struct r_debug to support
+ multiple namespaces [BZ #15971]"), but
+ - misses commit 88361b408b ("elf: Copy l_addr/l_ld when adding
+ ld.so to a new namespace").
+ This seems to be the case at least for the AlmaLinux 9.8 BaseOS
+ version, which uses glibc v2.34 and backports only the first
+ commit ( https://bugs.almalinux.org/view.php?id=667 ).
+ Detect this here and bail out. Otherwise, we'll present
+ the user with incorrect info for "info shared".
+
+ The target_read_memory is there to detect the improbable
+ situation that address 0 is mapped, in which case it might be the
+ address of the dynamic section. */
+ warning (_("Corrupted shared library entry: zero l_addr and l_ld"));
+ return 0;
+ }
+
sos.emplace_back (name.get (), std::move (li));
}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 9ade9a16818..bfb0e8e9273 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -3193,6 +3193,9 @@ gdb_caching_proc allow_dlmopen_tests {} {
return 0
}
gdb_expect {
+ -re "warning: Corrupted.*$gdb_prompt $" {
+ set allow_dlmopen_tests 0
+ }
-re "$inferior_exited_re normally.*${gdb_prompt} $" {
set allow_dlmopen_tests 1
}
base-commit: 196286d25ccc652dc086ae173d1cfa836bed0618
--
2.51.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] [gdb] Detect corrupt link map with zero l_ld and l_addr
2026-09-27 6:30 [PATCH v2] [gdb] Detect corrupt link map with zero l_ld and l_addr Tom de Vries
@ 2026-09-28 14:54 ` Simon Marchi
2026-09-28 15:30 ` Tom de Vries
0 siblings, 1 reply; 3+ messages in thread
From: Simon Marchi @ 2026-09-28 14:54 UTC (permalink / raw)
To: Tom de Vries, gdb-patches
On 9/27/26 2:30 AM, Tom de Vries wrote:
> On ppc64le-linux (AlmaLinux 9.8), I run into:
> ...
> FAIL: gdb.mi/mi-dlmopen.exp: still-in-use fields were all correct
> ...
>
> While investigating this, I stumbled on this warning emitted during the
> calculation of allow_dlmopen_tests:
> ...
> (gdb) run ^M
> Starting program: allow_dlmopen_tests.x ^M
> [Thread debugging using libthread_db enabled]^M
> Using host libthread_db library "/lib64/libthread_db.so.1".^M
> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
> address (wrong library or version mismatch?)^M
> dlmopen debug supported.^M
> ...
>
> The warning is mentioned in this glibc commit 88361b408b:
> ...
> elf: Copy l_addr/l_ld when adding ld.so to a new namespace
>
> When add ld.so to a new namespace, we don't actually load ld.so. We
> create a new link map and refers the real one for almost everything.
> Copy l_addr and l_ld from the real ld.so link map to avoid GDB warning:
>
> warning: .dynamic section for ".../elf/ld-linux-x86-64.so.2" is not at \
> the expected address (wrong library or version mismatch?)
>
> when handling shared library loaded by dlmopen.
> ...
>
> So, AFAICT the setup is:
> - the glibc package is based on v2.34
> - it contains a backport of commit a93d9e03a3 ("Extend struct r_debug to
> support multiple namespaces [BZ #15971]")
> - it doesn't contain a backport of commit 88361b408b ("elf: Copy l_addr/l_ld
> when adding ld.so to a new namespace") [1]
> - both commits are part of v2.35
>
> What happens is:
> - when probing for l_addr and l_ld in svr4_solib_ops::read_lm_info, both get
> the value 0
> - in svr4_solib_ops::lm_addr_check, the 0 value propagates to l_dynaddr, and
> "l_addr = l_dynaddr - dynaddr" then underflows, and things go downhill from
> there, resulting in the warning and eventually the FAIL.
>
> Fix this by detecting the situation in svr4_solib_ops::read_so_list, and
> bailing out with a warning.
>
> Add detection of this and other "corruption" warnings in allow_dlmopen_tests
> to make sure the related test-cases are skipped.
>
> In more detail, before this patch we have:
> ...
> $ gdb -q -batch outputs/gdb.base/dlmopen/dlmopen -ex start -ex next \
> -ex "pipe info shared | ld64"
> ...
> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
> address (wrong library or version mismatch?)
> ...
> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
> 0x0000000000000160 0xffffffffffff0000 1 Yes /lib64/ld64.so.2
> ...
> and after:
> ...
> warning: Corrupted shared library entry: zero l_addr and l_ld
> warning: Corrupted shared library entry: zero l_addr and l_ld
> ...
> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
> ...
>
> Alternatively, we could prevent the underflow in svr4_solib_ops::lm_addr_check:
> ...
> bool l_addr_updated = false;
> if (l_dynaddr >= dynaddr)
> {
> l_addr = l_dynaddr - dynaddr;
> l_addr_updated = true;
> }
>
> if (l_addr_updated
> && (l_addr & (minpagesize - 1)) == 0
> && (l_addr & align) == ((l_dynaddr - dynaddr) & align))
> ...
> but we'd still get an incorrect range:
> ...
> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
> address (wrong library or version mismatch?)
> ...
> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
> 0x0000000000060000 0x0000000000080000 1 Yes /lib64/ld64.so.2
> ...
>
> FTR, in an earlier attempt I proposed to deal with the FAIL using an
> xfail [2]. And in an another attempt I proposed to deal with it by
> replicating the glibc fix in gdb [3].
>
> Changed in v2:
> - fixed incorrect footnote reference
> - made comment more precise
> - use "AlmaLinux" consistently
>
> Versions:
> - v1 https://sourceware.org/pipermail/gdb-patches/2026-September/230275.html
>
> Tested on ppc64le-linux and x86_64-linux.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33662
>
> [1] https://bugs.almalinux.org/view.php?id=667
> [2] https://sourceware.org/pipermail/gdb-patches/2026-July/229073.html
> [3] https://sourceware.org/pipermail/gdb-patches/2026-August/229549.html
> ---
> gdb/solib-svr4.c | 23 +++++++++++++++++++++++
> gdb/testsuite/lib/gdb.exp | 3 +++
> 2 files changed, 26 insertions(+)
>
> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
> index c4af1b11a4d..810b0fae7a3 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -1333,6 +1333,29 @@ svr4_solib_ops::read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
> if (*name == '\0' || match_main (name.get ()))
> continue;
>
> + gdb_byte dummy;
> + if (li->l_addr_inferior == 0 && li->l_ld == 0
> + && target_read_memory (0, &dummy, 1) != 0)
> + {
> + /* We have l_addr_inferior == 0 and l_ld == 0 (corresponding to link
> + map entries l_addr and l_ld). This can happen with a glibc that:
> + - has commit a93d9e03a3 ("Extend struct r_debug to support
> + multiple namespaces [BZ #15971]"), but
> + - misses commit 88361b408b ("elf: Copy l_addr/l_ld when adding
> + ld.so to a new namespace").
> + This seems to be the case at least for the AlmaLinux 9.8 BaseOS
> + version, which uses glibc v2.34 and backports only the first
> + commit ( https://bugs.almalinux.org/view.php?id=667 ).
> + Detect this here and bail out. Otherwise, we'll present
> + the user with incorrect info for "info shared".
> +
> + The target_read_memory is there to detect the improbable
> + situation that address 0 is mapped, in which case it might be the
> + address of the dynamic section. */
> + warning (_("Corrupted shared library entry: zero l_addr and l_ld"));
> + return 0;
> + }
Returning 0 means we stop reading the shared library list, is that
expected? The known case of this isn't really that the shared library
list is corrupted, just that this entry is incomplete. We could maybe
skip over this entry and keep reading the list, to be able to present
all the loaded shared libraries to the user?
Is the warning printed every time the library list is read (like at each
stop)? Does that become annoying for the user?
In the end maybe we don't care too much about these concerns, because
it's for one specific version of one specific distro, and only when
debugging programs that use multiple namespaces (which are quite rare I
think).
Simon
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] [gdb] Detect corrupt link map with zero l_ld and l_addr
2026-09-28 14:54 ` Simon Marchi
@ 2026-09-28 15:30 ` Tom de Vries
0 siblings, 0 replies; 3+ messages in thread
From: Tom de Vries @ 2026-09-28 15:30 UTC (permalink / raw)
To: Simon Marchi, gdb-patches
On 9/28/26 4:54 PM, Simon Marchi wrote:
> On 9/27/26 2:30 AM, Tom de Vries wrote:
>> On ppc64le-linux (AlmaLinux 9.8), I run into:
>> ...
>> FAIL: gdb.mi/mi-dlmopen.exp: still-in-use fields were all correct
>> ...
>>
>> While investigating this, I stumbled on this warning emitted during the
>> calculation of allow_dlmopen_tests:
>> ...
>> (gdb) run ^M
>> Starting program: allow_dlmopen_tests.x ^M
>> [Thread debugging using libthread_db enabled]^M
>> Using host libthread_db library "/lib64/libthread_db.so.1".^M
>> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
>> address (wrong library or version mismatch?)^M
>> dlmopen debug supported.^M
>> ...
>>
>> The warning is mentioned in this glibc commit 88361b408b:
>> ...
>> elf: Copy l_addr/l_ld when adding ld.so to a new namespace
>>
>> When add ld.so to a new namespace, we don't actually load ld.so. We
>> create a new link map and refers the real one for almost everything.
>> Copy l_addr and l_ld from the real ld.so link map to avoid GDB warning:
>>
>> warning: .dynamic section for ".../elf/ld-linux-x86-64.so.2" is not at \
>> the expected address (wrong library or version mismatch?)
>>
>> when handling shared library loaded by dlmopen.
>> ...
>>
>> So, AFAICT the setup is:
>> - the glibc package is based on v2.34
>> - it contains a backport of commit a93d9e03a3 ("Extend struct r_debug to
>> support multiple namespaces [BZ #15971]")
>> - it doesn't contain a backport of commit 88361b408b ("elf: Copy l_addr/l_ld
>> when adding ld.so to a new namespace") [1]
>> - both commits are part of v2.35
>>
>> What happens is:
>> - when probing for l_addr and l_ld in svr4_solib_ops::read_lm_info, both get
>> the value 0
>> - in svr4_solib_ops::lm_addr_check, the 0 value propagates to l_dynaddr, and
>> "l_addr = l_dynaddr - dynaddr" then underflows, and things go downhill from
>> there, resulting in the warning and eventually the FAIL.
>>
>> Fix this by detecting the situation in svr4_solib_ops::read_so_list, and
>> bailing out with a warning.
>>
>> Add detection of this and other "corruption" warnings in allow_dlmopen_tests
>> to make sure the related test-cases are skipped.
>>
>> In more detail, before this patch we have:
>> ...
>> $ gdb -q -batch outputs/gdb.base/dlmopen/dlmopen -ex start -ex next \
>> -ex "pipe info shared | ld64"
>> ...
>> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
>> address (wrong library or version mismatch?)
>> ...
>> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
>> 0x0000000000000160 0xffffffffffff0000 1 Yes /lib64/ld64.so.2
>> ...
>> and after:
>> ...
>> warning: Corrupted shared library entry: zero l_addr and l_ld
>> warning: Corrupted shared library entry: zero l_addr and l_ld
>> ...
>> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
>> ...
>>
>> Alternatively, we could prevent the underflow in svr4_solib_ops::lm_addr_check:
>> ...
>> bool l_addr_updated = false;
>> if (l_dynaddr >= dynaddr)
>> {
>> l_addr = l_dynaddr - dynaddr;
>> l_addr_updated = true;
>> }
>>
>> if (l_addr_updated
>> && (l_addr & (minpagesize - 1)) == 0
>> && (l_addr & align) == ((l_dynaddr - dynaddr) & align))
>> ...
>> but we'd still get an incorrect range:
>> ...
>> warning: .dynamic section for "/lib64/ld64.so.2" is not at the expected \
>> address (wrong library or version mismatch?)
>> ...
>> 0x00007ffff7f80000 0x00007ffff8000000 0 Yes /lib64/ld64.so.2
>> 0x0000000000060000 0x0000000000080000 1 Yes /lib64/ld64.so.2
>> ...
>>
>> FTR, in an earlier attempt I proposed to deal with the FAIL using an
>> xfail [2]. And in an another attempt I proposed to deal with it by
>> replicating the glibc fix in gdb [3].
>>
>> Changed in v2:
>> - fixed incorrect footnote reference
>> - made comment more precise
>> - use "AlmaLinux" consistently
>>
>> Versions:
>> - v1 https://sourceware.org/pipermail/gdb-patches/2026-September/230275.html
>>
>> Tested on ppc64le-linux and x86_64-linux.
>>
>> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33662
>>
>> [1] https://bugs.almalinux.org/view.php?id=667
>> [2] https://sourceware.org/pipermail/gdb-patches/2026-July/229073.html
>> [3] https://sourceware.org/pipermail/gdb-patches/2026-August/229549.html
>> ---
>> gdb/solib-svr4.c | 23 +++++++++++++++++++++++
>> gdb/testsuite/lib/gdb.exp | 3 +++
>> 2 files changed, 26 insertions(+)
>>
>> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
>> index c4af1b11a4d..810b0fae7a3 100644
>> --- a/gdb/solib-svr4.c
>> +++ b/gdb/solib-svr4.c
>> @@ -1333,6 +1333,29 @@ svr4_solib_ops::read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
>> if (*name == '\0' || match_main (name.get ()))
>> continue;
>>
>> + gdb_byte dummy;
>> + if (li->l_addr_inferior == 0 && li->l_ld == 0
>> + && target_read_memory (0, &dummy, 1) != 0)
>> + {
>> + /* We have l_addr_inferior == 0 and l_ld == 0 (corresponding to link
>> + map entries l_addr and l_ld). This can happen with a glibc that:
>> + - has commit a93d9e03a3 ("Extend struct r_debug to support
>> + multiple namespaces [BZ #15971]"), but
>> + - misses commit 88361b408b ("elf: Copy l_addr/l_ld when adding
>> + ld.so to a new namespace").
>> + This seems to be the case at least for the AlmaLinux 9.8 BaseOS
>> + version, which uses glibc v2.34 and backports only the first
>> + commit ( https://bugs.almalinux.org/view.php?id=667 ).
>> + Detect this here and bail out. Otherwise, we'll present
>> + the user with incorrect info for "info shared".
>> +
>> + The target_read_memory is there to detect the improbable
>> + situation that address 0 is mapped, in which case it might be the
>> + address of the dynamic section. */
>> + warning (_("Corrupted shared library entry: zero l_addr and l_ld"));
>> + return 0;
>> + }
>
> Returning 0 means we stop reading the shared library list, is that
> expected? The known case of this isn't really that the shared library
> list is corrupted, just that this entry is incomplete. We could maybe
> skip over this entry and keep reading the list, to be able to present
> all the loaded shared libraries to the user?
>
Hi Simon,
thanks for the review.
I think you're right, using continue instead of return 0 is more
appropriate.
> Is the warning printed every time the library list is read (like at each
> stop)? Does that become annoying for the user?
>
> In the end maybe we don't care too much about these concerns, because
> it's for one specific version of one specific distro, and only when
> debugging programs that use multiple namespaces (which are quite rare I
> think).
>
It could be annoying, agreed.
I'm treating this though as a corruption that is triggered by one
specific version of one specific distro, but might happen otherwise.
So I think there is information in how many times the warning triggers.
We could keep track for which shared libs the warning triggers, and emit
a summary instead. But I don't think it's worth the bother at this point.
Thanks,
- Tom
> Simon
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-28 15:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-27 6:30 [PATCH v2] [gdb] Detect corrupt link map with zero l_ld and l_addr Tom de Vries
2026-09-28 14:54 ` Simon Marchi
2026-09-28 15:30 ` Tom de Vries
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox