diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bc1a29ef01..9a79b05691 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2015-11-24 Pedro Alves + + * linux-tdep.c (find_stop_signal): Delete. + (struct linux_corefile_thread_data) : Remove field. + (linux_corefile_thread_callback): Rename to ... + (linux_corefile_thread): ... this. Now takes a struct + linux_corefile_thread_data pointer rather than a void pointer. + Remove thread state and thread pid checks. + (linux_make_corefile_notes): Prefer dumping the signalled thread + first. Use ALL_NON_EXITED_THREADS instead of + iterate_over_threads. + 2015-11-23 Simon Marchi * breakpoint.c (tracepoint_print_recreate): Fix logic error diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 30740c0391..000efc806b 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1347,18 +1347,6 @@ find_signalled_thread (struct thread_info *info, void *data) return 0; } -static enum gdb_signal -find_stop_signal (void) -{ - struct thread_info *info = - iterate_over_threads (find_signalled_thread, NULL); - - if (info) - return info->suspend.stop_signal; - else - return GDB_SIGNAL_0; -} - /* Generate corefile notes for SPU contexts. */ static char * @@ -1661,62 +1649,49 @@ linux_get_siginfo_data (struct gdbarch *gdbarch, LONGEST *size) struct linux_corefile_thread_data { struct gdbarch *gdbarch; - int pid; bfd *obfd; char *note_data; int *note_size; enum gdb_signal stop_signal; }; -/* Called by gdbthread.c once per thread. Records the thread's - register state for the corefile note section. */ +/* Records the thread's register state for the corefile note + section. */ -static int -linux_corefile_thread_callback (struct thread_info *info, void *data) +static void +linux_corefile_thread (struct thread_info *info, + struct linux_corefile_thread_data *args) { - struct linux_corefile_thread_data *args - = (struct linux_corefile_thread_data *) data; + struct cleanup *old_chain; + struct regcache *regcache; + gdb_byte *siginfo_data; + LONGEST siginfo_size = 0; - /* It can be current thread - which cannot be removed by update_thread_list. */ - if (info->state == THREAD_EXITED) - return 0; + regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); - if (ptid_get_pid (info->ptid) == args->pid) - { - struct cleanup *old_chain; - struct regcache *regcache; - gdb_byte *siginfo_data; - LONGEST siginfo_size = 0; + old_chain = save_inferior_ptid (); + inferior_ptid = info->ptid; + target_fetch_registers (regcache, -1); + siginfo_data = linux_get_siginfo_data (args->gdbarch, &siginfo_size); + do_cleanups (old_chain); - regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); + old_chain = make_cleanup (xfree, siginfo_data); - old_chain = save_inferior_ptid (); - inferior_ptid = info->ptid; - target_fetch_registers (regcache, -1); - siginfo_data = linux_get_siginfo_data (args->gdbarch, &siginfo_size); - do_cleanups (old_chain); + args->note_data = linux_collect_thread_registers + (regcache, info->ptid, args->obfd, args->note_data, + args->note_size, args->stop_signal); - old_chain = make_cleanup (xfree, siginfo_data); + /* Don't return anything if we got no register information above, + such a core file is useless. */ + if (args->note_data != NULL) + if (siginfo_data != NULL) + args->note_data = elfcore_write_note (args->obfd, + args->note_data, + args->note_size, + "CORE", NT_SIGINFO, + siginfo_data, siginfo_size); - args->note_data = linux_collect_thread_registers - (regcache, info->ptid, args->obfd, args->note_data, - args->note_size, args->stop_signal); - - /* Don't return anything if we got no register information above, - such a core file is useless. */ - if (args->note_data != NULL) - if (siginfo_data != NULL) - args->note_data = elfcore_write_note (args->obfd, - args->note_data, - args->note_size, - "CORE", NT_SIGINFO, - siginfo_data, siginfo_size); - - do_cleanups (old_chain); - } - - return !args->note_data; + do_cleanups (old_chain); } /* Fill the PRPSINFO structure with information about the process being @@ -1932,6 +1907,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) char *note_data = NULL; gdb_byte *auxv; int auxv_len; + struct thread_info *curr_thr, *signalled_thr, *thr; if (! gdbarch_iterate_over_regset_sections_p (gdbarch)) return NULL; @@ -1968,13 +1944,37 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) } END_CATCH + /* Like the kernel, prefer dumping the signalled thread first. + "First thread" is what tools use to infer the signalled thread. + In case there's more than one signalled thread, prefer the + current thread, if it is signalled. */ + curr_thr = inferior_thread (); + if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) + signalled_thr = curr_thr; + else + { + signalled_thr = iterate_over_threads (find_signalled_thread, NULL); + if (signalled_thr == NULL) + signalled_thr = curr_thr; + } + thread_args.gdbarch = gdbarch; - thread_args.pid = ptid_get_pid (inferior_ptid); thread_args.obfd = obfd; thread_args.note_data = note_data; thread_args.note_size = note_size; - thread_args.stop_signal = find_stop_signal (); - iterate_over_threads (linux_corefile_thread_callback, &thread_args); + thread_args.stop_signal = signalled_thr->suspend.stop_signal; + + linux_corefile_thread (signalled_thr, &thread_args); + ALL_NON_EXITED_THREADS (thr) + { + if (thr == signalled_thr) + continue; + if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid)) + continue; + + linux_corefile_thread (thr, &thread_args); + } + note_data = thread_args.note_data; if (!note_data) return NULL;