/* 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 . */ #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 = (struct fbsd_collect_regset_section_cb_data *) cb_data; gdb_assert (regset->collect_regset); buf = (char *) 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); }