From patchwork Wed Jan 13 21:45:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 10370 Received: (qmail 51770 invoked by alias); 13 Jan 2016 21:46:35 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 51681 invoked by uid 89); 13 Jan 2016 21:46:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.6 required=5.0 tests=AWL, BAYES_50, SPF_HELO_PASS, SPF_SOFTFAIL autolearn=no version=3.3.2 spammy=dumping, sk:iterate, sk:datast, 1646 X-Spam-User: qpsmtpd, 2 recipients X-HELO: bigwig.baldwin.cx Received: from bigwig.baldwin.cx (HELO bigwig.baldwin.cx) (96.47.65.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Wed, 13 Jan 2016 21:46:33 +0000 Received: from ralph.com (c-73-231-226-104.hsd1.ca.comcast.net [73.231.226.104]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id C95FFB9C7; Wed, 13 Jan 2016 16:46:30 -0500 (EST) From: John Baldwin To: gdb-patches@sourceware.org, binutils@sourceware.org Subject: [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core. Date: Wed, 13 Jan 2016 13:45:51 -0800 Message-Id: <1452721551-657-7-git-send-email-jhb@FreeBSD.org> In-Reply-To: <1452721551-657-1-git-send-email-jhb@FreeBSD.org> References: <1452721551-657-1-git-send-email-jhb@FreeBSD.org> X-IsSubscribed: yes gdb/ChangeLog: * fbsd-tdep.c (find_stop_signal): Remove. (struct fbsd_collect_regset_section_cb) : New field. : New field. : New field. (fbsd_collect_regset_section_cb): Use new fields. (fbsd_collect_thread_registers): New function. (struct fbsd_corefile_thread_data): New structure. (fbsd_corefile_thread): New function. (fbsd_make_corefile_notes): Use new function to dump notes for each non-exited thread in a process. --- gdb/ChangeLog | 13 +++++ gdb/fbsd-tdep.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 131 insertions(+), 26 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fdf35b0..178046d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2016-01-10 John Baldwin + * fbsd-tdep.c (find_stop_signal): Remove. + (struct fbsd_collect_regset_section_cb) : New field. + : New field. + : New field. + (fbsd_collect_regset_section_cb): Use new fields. + (fbsd_collect_thread_registers): New function. + (struct fbsd_corefile_thread_data): New structure. + (fbsd_corefile_thread): New function. + (fbsd_make_corefile_notes): Use new function to dump notes for each + non-exited thread in a process. + +2016-01-10 John Baldwin + * configure.ac: Check for support for LWP names on FreeBSD. * fbsd-nat.c [PT_LWPINFO] New variable debug_fbsd_lwp. [TDP_RFPPWAIT || HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME] diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index 6851cc1..be3350e 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -78,17 +78,9 @@ 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; -} +/* Structure for passing information from + fbsd_collect_thread_registers via an iterator to + fbsd_collect_regset_section_cb. */ struct fbsd_collect_regset_section_cb_data { @@ -96,6 +88,9 @@ struct fbsd_collect_regset_section_cb_data bfd *obfd; char *note_data; int *note_size; + unsigned long lwp; + enum gdb_signal stop_signal; + int abort_iteration; }; static void @@ -107,6 +102,9 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, struct fbsd_collect_regset_section_cb_data *data = (struct fbsd_collect_regset_section_cb_data *) cb_data; + if (data->abort_iteration) + return; + gdb_assert (regset->collect_regset); buf = (char *) xmalloc (size); @@ -115,13 +113,73 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, /* PRSTATUS still needs to be treated specially. */ if (strcmp (sect_name, ".reg") == 0) data->note_data = (char *) elfcore_write_prstatus - (data->obfd, data->note_data, data->note_size, - ptid_get_pid (inferior_ptid), find_stop_signal (), buf); + (data->obfd, data->note_data, data->note_size, data->lwp, + gdb_signal_to_host (data->stop_signal), buf); else data->note_data = (char *) elfcore_write_register_note (data->obfd, data->note_data, data->note_size, sect_name, buf, size); xfree (buf); + + if (data->note_data == NULL) + data->abort_iteration = 1; +} + +/* Records the thread's register state for the corefile note + section. */ + +static char * +fbsd_collect_thread_registers (const struct regcache *regcache, + ptid_t ptid, bfd *obfd, + char *note_data, int *note_size, + enum gdb_signal stop_signal) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct fbsd_collect_regset_section_cb_data data; + + data.regcache = regcache; + data.obfd = obfd; + data.note_data = note_data; + data.note_size = note_size; + data.stop_signal = stop_signal; + data.abort_iteration = 0; + data.lwp = ptid_get_lwp (ptid); + + gdbarch_iterate_over_regset_sections (gdbarch, + fbsd_collect_regset_section_cb, + &data, regcache); + return data.note_data; +} + +struct fbsd_corefile_thread_data +{ + struct gdbarch *gdbarch; + bfd *obfd; + char *note_data; + int *note_size; + enum gdb_signal stop_signal; +}; + +/* Records the thread's register state for the corefile note + section. */ + +static void +fbsd_corefile_thread (struct thread_info *info, + struct fbsd_corefile_thread_data *args) +{ + struct cleanup *old_chain; + struct regcache *regcache; + + regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); + + old_chain = save_inferior_ptid (); + inferior_ptid = info->ptid; + target_fetch_registers (regcache, -1); + do_cleanups (old_chain); + + args->note_data = fbsd_collect_thread_registers + (regcache, info->ptid, args->obfd, args->note_data, + args->note_size, args->stop_signal); } /* Create appropriate note sections for a corefile, returning them in @@ -130,10 +188,10 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, static char * fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) { - struct regcache *regcache = get_current_regcache (); - char *note_data; + struct fbsd_corefile_thread_data thread_args; + char *note_data = NULL; Elf_Internal_Ehdr *i_ehdrp; - struct fbsd_collect_regset_section_cb_data data; + struct thread_info *curr_thr, *signalled_thr, *thr; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); @@ -141,16 +199,6 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); - data.regcache = regcache; - data.obfd = obfd; - data.note_data = NULL; - data.note_size = note_size; - target_fetch_registers (regcache, -1); - gdbarch_iterate_over_regset_sections (gdbarch, - fbsd_collect_regset_section_cb, - &data, regcache); - note_data = data.note_data; - if (get_exec_file (0)) { const char *fname = lbasename (get_exec_file (0)); @@ -164,6 +212,50 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) fname, psargs); } + /* Thread register information. */ + TRY + { + update_thread_list (); + } + CATCH (e, RETURN_MASK_ERROR) + { + exception_print (gdb_stderr, e); + } + 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.obfd = obfd; + thread_args.note_data = note_data; + thread_args.note_size = note_size; + thread_args.stop_signal = signalled_thr->suspend.stop_signal; + + fbsd_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; + + fbsd_corefile_thread (thr, &thread_args); + } + + note_data = thread_args.note_data; + return note_data; }