[binutils-gdb] [gdb/corefiles] Fix segfault in add_thread_silent

Tom de Vries vries@sourceware.org
Fri Nov 21 13:38:06 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=af7fe6fff91a61f30f9adddc7ff2f8852dc6482a

commit af7fe6fff91a61f30f9adddc7ff2f8852dc6482a
Author: Tom de Vries <tdevries@suse.de>
Date:   Fri Nov 21 14:38:01 2025 +0100

    [gdb/corefiles] Fix segfault in add_thread_silent
    
    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

Diff:
---
 gdb/corelow.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/corelow.c b/gdb/corelow.c
index a9098e6e00e..ec1e4de6f6f 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -1107,7 +1107,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);
     }


More information about the Gdb-cvs mailing list