From: Tom de Vries Date: Fri, 21 Nov 2025 13:38:01 +0000 (+0100) Subject: [gdb/corefiles] Fix segfault in add_thread_silent X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af7fe6fff91a61f30f9adddc7ff2f8852dc6482a;p=thirdparty%2Fbinutils-gdb.git [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 PR corefiles/33560 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33560 [1] https://bugzilla.suse.com/show_bug.cgi?id=1251213 --- 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); }