Linux: dump the signalled thread first
... like the kernel does. gcore-thread.exp has a check to make sure the signalled thread is the current thread after loading the core back, but that just works by accident, because the signalled thread happened to be the last thread on the thread list, and gdb currently iterates over threads in reverse order. So this fixes gcore-thread.exp once we start walking threads in ascending number. gdb/ChangeLog: 2015-11-24 Pedro Alves <palves@redhat.com> * linux-tdep.c (find_stop_signal): Delete. (struct linux_corefile_thread_data) <pid>: 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.
This commit is contained in:
parent
2cc57ad8d1
commit
050c224b67
|
@ -1,3 +1,15 @@
|
||||||
|
2015-11-24 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* linux-tdep.c (find_stop_signal): Delete.
|
||||||
|
(struct linux_corefile_thread_data) <pid>: 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 <simon.marchi@ericsson.com>
|
2015-11-23 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
* breakpoint.c (tracepoint_print_recreate): Fix logic error
|
* breakpoint.c (tracepoint_print_recreate): Fix logic error
|
||||||
|
|
|
@ -1347,18 +1347,6 @@ find_signalled_thread (struct thread_info *info, void *data)
|
||||||
return 0;
|
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. */
|
/* Generate corefile notes for SPU contexts. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -1661,28 +1649,18 @@ linux_get_siginfo_data (struct gdbarch *gdbarch, LONGEST *size)
|
||||||
struct linux_corefile_thread_data
|
struct linux_corefile_thread_data
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch;
|
struct gdbarch *gdbarch;
|
||||||
int pid;
|
|
||||||
bfd *obfd;
|
bfd *obfd;
|
||||||
char *note_data;
|
char *note_data;
|
||||||
int *note_size;
|
int *note_size;
|
||||||
enum gdb_signal stop_signal;
|
enum gdb_signal stop_signal;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Called by gdbthread.c once per thread. Records the thread's
|
/* Records the thread's register state for the corefile note
|
||||||
register state for the corefile note section. */
|
section. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
linux_corefile_thread_callback (struct thread_info *info, void *data)
|
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;
|
|
||||||
|
|
||||||
/* It can be current thread
|
|
||||||
which cannot be removed by update_thread_list. */
|
|
||||||
if (info->state == THREAD_EXITED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (ptid_get_pid (info->ptid) == args->pid)
|
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
struct regcache *regcache;
|
struct regcache *regcache;
|
||||||
|
@ -1716,9 +1694,6 @@ linux_corefile_thread_callback (struct thread_info *info, void *data)
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !args->note_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill the PRPSINFO structure with information about the process being
|
/* Fill the PRPSINFO structure with information about the process being
|
||||||
debugged. Returns 1 in case of success, 0 for failures. Please note that
|
debugged. Returns 1 in case of success, 0 for failures. Please note that
|
||||||
even if the structure cannot be entirely filled (e.g., GDB was unable to
|
even if the structure cannot be entirely filled (e.g., GDB was unable to
|
||||||
|
@ -1932,6 +1907,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
||||||
char *note_data = NULL;
|
char *note_data = NULL;
|
||||||
gdb_byte *auxv;
|
gdb_byte *auxv;
|
||||||
int auxv_len;
|
int auxv_len;
|
||||||
|
struct thread_info *curr_thr, *signalled_thr, *thr;
|
||||||
|
|
||||||
if (! gdbarch_iterate_over_regset_sections_p (gdbarch))
|
if (! gdbarch_iterate_over_regset_sections_p (gdbarch))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1968,13 +1944,37 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
||||||
}
|
}
|
||||||
END_CATCH
|
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.gdbarch = gdbarch;
|
||||||
thread_args.pid = ptid_get_pid (inferior_ptid);
|
|
||||||
thread_args.obfd = obfd;
|
thread_args.obfd = obfd;
|
||||||
thread_args.note_data = note_data;
|
thread_args.note_data = note_data;
|
||||||
thread_args.note_size = note_size;
|
thread_args.note_size = note_size;
|
||||||
thread_args.stop_signal = find_stop_signal ();
|
thread_args.stop_signal = signalled_thr->suspend.stop_signal;
|
||||||
iterate_over_threads (linux_corefile_thread_callback, &thread_args);
|
|
||||||
|
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;
|
note_data = thread_args.note_data;
|
||||||
if (!note_data)
|
if (!note_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue