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

openSUSE Build Service is sponsored by