3ce5b6e25c
Without this, not all registers were present in the core generated by gcore. For example, running 'gcore' on a program without examining the vector registers (SSE or AVX) would store all the vector registers as zeros because they were not pulled into the regcache. Running 'info vector' before 'gcore' would store the correct values in the core since it populated the regcache. For Linux processes, a similar operation is achieved by having the thread iterator callback invoke target_fetch_registers on each thread before its corresponding register notes are dumped. gdb/ChangeLog: * fbsd-tdep.c (fbsd_make_corefile_notes): Fetch all target registers before writing core register notes.
136 lines
3.7 KiB
C
136 lines
3.7 KiB
C
/* Target-dependent code for FreeBSD, architecture-independent.
|
|
|
|
Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "gdbcore.h"
|
|
#include "inferior.h"
|
|
#include "regcache.h"
|
|
#include "regset.h"
|
|
#include "gdbthread.h"
|
|
|
|
#include "elf-bfd.h"
|
|
#include "fbsd-tdep.h"
|
|
|
|
|
|
static int
|
|
find_signalled_thread (struct thread_info *info, void *data)
|
|
{
|
|
if (info->suspend.stop_signal != GDB_SIGNAL_0
|
|
&& ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
|
|
return 1;
|
|
|
|
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;
|
|
}
|
|
|
|
struct fbsd_collect_regset_section_cb_data
|
|
{
|
|
const struct regcache *regcache;
|
|
bfd *obfd;
|
|
char *note_data;
|
|
int *note_size;
|
|
};
|
|
|
|
static void
|
|
fbsd_collect_regset_section_cb (const char *sect_name, int size,
|
|
const struct regset *regset,
|
|
const char *human_name, void *cb_data)
|
|
{
|
|
char *buf;
|
|
struct fbsd_collect_regset_section_cb_data *data = cb_data;
|
|
|
|
gdb_assert (regset->collect_regset);
|
|
|
|
buf = xmalloc (size);
|
|
regset->collect_regset (regset, data->regcache, -1, buf, 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);
|
|
else
|
|
data->note_data = (char *) elfcore_write_register_note
|
|
(data->obfd, data->note_data, data->note_size,
|
|
sect_name, buf, size);
|
|
xfree (buf);
|
|
}
|
|
|
|
/* Create appropriate note sections for a corefile, returning them in
|
|
allocated memory. */
|
|
|
|
static char *
|
|
fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
|
{
|
|
struct regcache *regcache = get_current_regcache ();
|
|
char *note_data;
|
|
Elf_Internal_Ehdr *i_ehdrp;
|
|
struct fbsd_collect_regset_section_cb_data data;
|
|
|
|
/* Put a "FreeBSD" label in the ELF header. */
|
|
i_ehdrp = elf_elfheader (obfd);
|
|
i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
|
|
|
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));
|
|
char *psargs = xstrdup (fname);
|
|
|
|
if (get_inferior_args ())
|
|
psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
|
|
(char *) NULL);
|
|
|
|
note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
|
|
fname, psargs);
|
|
}
|
|
|
|
return note_data;
|
|
}
|
|
|
|
/* To be called from GDB_OSABI_FREEBSD_ELF handlers. */
|
|
|
|
void
|
|
fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
|
|
}
|