File gdb-corefiles-fix-segfault-in-add_thread_silent.patch of Package gdb
From 01a9516fcbec4ac8d4cafab711d22d4396094694 Mon Sep 17 00:00:00 2001
From: Tom de Vries <tdevries@suse.de>
Date: Fri, 21 Nov 2025 14:38:01 +0100
Subject: [PATCH 15/25] [gdb/corefiles] Fix segfault in add_thread_silent
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
A user reported a segfault when loading a core file [1].
The core file is from arm-linux, but I reproduced the segfault on
x86_64-linux:
...
$ gdb -q --core core
warning: Can't open file /usr/bin/rs_scope during file-backed mapping note processing
warning: Can't open file /lib/libc-2.26.so during file-backed mapping note processing
warning: File /lib/libgcc_s.so.1 doesn't match build-id from core-file during file-backed mapping processing
warning: Can't open file /lib/libm-2.26.so during file-backed mapping note processing
warning: Can't open file /usr/lib/libstdc++.so.6.0.28 during file-backed mapping note processing
warning: Can't open file /lib/libpthread-2.26.so during file-backed mapping note processing
warning: Can't open file /lib/ld-2.26.so during file-backed mapping note processing
Fatal signal: Segmentation fault
----- Backtrace -----
0x64a4ff gdb_internal_backtrace_1
gdb/bt-utils.c:122
0x64a59d _Z22gdb_internal_backtracev
gdb/bt-utils.c:175
0x9429e7 handle_fatal_signal
gdb/event-top.c:1013
0x942b96 handle_sigsegv
gdb/event-top.c:1090
0x7fbf6a64708f ???
/usr/src/debug/glibc-2.40/signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x5eb453 _ZN9__gnu_cxx17__normal_iteratorIPKSt4pairI6ptid_tP11thread_infoESt6vectorIS5_SaIS5_EEEC4ERKS7_
/usr/include/c++/15/bits/stl_iterator.h:1059
0x5eb453 _ZNKSt6vectorISt4pairI6ptid_tP11thread_infoESaIS4_EE3endEv
/usr/include/c++/15/bits/stl_vector.h:1029
0x5eae9e _ZNKSt6vectorISt4pairI6ptid_tP11thread_infoESaIS4_EE5emptyEv
/usr/include/c++/15/bits/stl_vector.h:1224
0xa77588 _ZNK6ankerl15unordered_dense6v4_4_06detail5tableI6ptid_tP11thread_infoNS1_4hashIS4_vEESt8equal_toIS4_ESaISt4pairIS4_S6_EENS1_11bucket_type8standardELb0EE5emptyEv
gdb/../gdbsupport/unordered_dense.h:1351
0xa76533 _ZN6ankerl15unordered_dense6v4_4_06detail5tableI6ptid_tP11thread_infoNS1_4hashIS4_vEESt8equal_toIS4_ESaISt4pairIS4_S6_EENS1_11bucket_type8standardELb0EE7do_findIS4_EEN9__gnu_cxx17__normal_iteratorIPSC_St6vectorISC_SD_EEERKT_
gdb/../gdbsupport/unordered_dense.h:1119
0xa74fef _ZN6ankerl15unordered_dense6v4_4_06detail5tableI6ptid_tP11thread_infoNS1_4hashIS4_vEESt8equal_toIS4_ESaISt4pairIS4_S6_EENS1_11bucket_type8standardELb0EE4findERKS4_
gdb/../gdbsupport/unordered_dense.h:1773
0xa6f787 _ZN8inferior11find_threadE6ptid_t
gdb/inferior.c:253
0xfc852a _Z17add_thread_silentP22process_stratum_target6ptid_t
gdb/thread.c:310
0x73b995 core_target_open
gdb/corelow.c:1111
0x73a095 _Z17core_file_commandPKci
gdb/corelow.c:708
0xb6cb38 catch_command_errors
gdb/main.c:510
0xb6e354 captured_main_1
gdb/main.c:1279
0xb6e9a2 captured_main
gdb/main.c:1372
0xb6eaa3 _Z8gdb_mainP18captured_main_args
gdb/main.c:1401
0x419704 main
gdb/gdb.c:38
...
The problem happens as follows. In core_target_open, we do:
...
if (thread == NULL)
thread = add_thread_silent (target, ptid_t (CORELOW_PID));
...
and then in add_thread_silent:
...
struct thread_info *
add_thread_silent (process_stratum_target *targ, ptid_t ptid)
{
gdb_assert (targ != nullptr);
inferior *inf = find_inferior_ptid (targ, ptid);
...
find_inferior_ptid returns nullptr, which eventually causes the segfault.
So, why can't we find an inferior with CORELOW_PID?
A bit earlier in core_target_open, we do:
...
/* Find (or fake) the pid for the process in this core file, and
initialise the current inferior with that pid. */
bool fake_pid_p = false;
int pid = bfd_core_file_pid (target->core_bfd ());
if (pid == 0)
{
fake_pid_p = true;
pid = CORELOW_PID;
}
inferior *inf = current_inferior ();
gdb_assert (inf->pid == 0);
inferior_appeared (inf, pid);
inf->fake_pid_p = fake_pid_p;
...
The problem is that looking for an inferior using CORELOW_PID is correct in
case fake_pid_p == true, but otherwise not.
Fix this by using inf->pid instead:
...
- thread = add_thread_silent (target, ptid_t (CORELOW_PID));
+ thread = add_thread_silent (target, ptid_t (inf->pid));
...
Doing so enables us to continue to a gdb prompt:
...
Core was generated by `/usr/bin/rs_scope -d'.
⚠️ warning: Couldn't find general-purpose registers in core file.
(gdb)
...
The warning is emitted because the pseudo-section .reg is missing, because
elf32_arm_nabi_grok_prstatus expects the PRSTATUS note to have size 148, but
instead we have:
...
$ eu-readelf -n core | grep -i prstatus
CORE 156 PRSTATUS
CORE 156 PRSTATUS
CORE 156 PRSTATUS
CORE 156 PRSTATUS
...
I'm assuming this is a bug for CONFIG_BINFMT_ELF_FDPIC=y configurations, fixed
by v5.9 linux kernel commit 16aead81018c ("take fdpic-related parts of
elf_prstatus out").
The core was generated using a kernel with CONFIG_BINFMT_ELF_FDPIC=y and
v5.3.18.
We can try to work around this bug in elf32_arm_nabi_grok_prstatus, but
that's out of scope for this commit, which focuses on fixing the segfault.
Tested on x86_64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
PR corefiles/33560
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33560
[1] https://bugzilla.suse.com/show_bug.cgi?id=1251213
---
gdb/corelow.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 59c16677109..69bb7e4f163 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -1120,7 +1120,7 @@ core_target_open (const char *arg, int from_tty)
thread_info *thread = first_thread_of_inferior (inf);
if (thread == NULL)
- thread = add_thread_silent (target, ptid_t (CORELOW_PID));
+ thread = add_thread_silent (target, ptid_t (inf->pid));
switch_to_thread (thread);
}
--
2.51.0