1 /* Target-dependent code for FreeBSD, architecture-independent. 2 3 Copyright (C) 2002-2015 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "gdbcore.h" 22 #include "inferior.h" 23 #include "regcache.h" 24 #include "regset.h" 25 #include "gdbthread.h" 26 27 #include "elf-bfd.h" 28 #include "fbsd-tdep.h" 29 30 31 static int 32 find_signalled_thread (struct thread_info *info, void *data) 33 { 34 if (info->suspend.stop_signal != GDB_SIGNAL_0 35 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) 36 return 1; 37 38 return 0; 39 } 40 41 static enum gdb_signal 42 find_stop_signal (void) 43 { 44 struct thread_info *info = 45 iterate_over_threads (find_signalled_thread, NULL); 46 47 if (info) 48 return info->suspend.stop_signal; 49 else 50 return GDB_SIGNAL_0; 51 } 52 53 struct fbsd_collect_regset_section_cb_data 54 { 55 const struct regcache *regcache; 56 bfd *obfd; 57 char *note_data; 58 int *note_size; 59 }; 60 61 static void 62 fbsd_collect_regset_section_cb (const char *sect_name, int size, 63 const struct regset *regset, 64 const char *human_name, void *cb_data) 65 { 66 char *buf; 67 struct fbsd_collect_regset_section_cb_data *data = cb_data; 68 69 gdb_assert (regset->collect_regset); 70 71 buf = xmalloc (size); 72 regset->collect_regset (regset, data->regcache, -1, buf, size); 73 74 /* PRSTATUS still needs to be treated specially. */ 75 if (strcmp (sect_name, ".reg") == 0) 76 data->note_data = (char *) elfcore_write_prstatus 77 (data->obfd, data->note_data, data->note_size, 78 ptid_get_pid (inferior_ptid), find_stop_signal (), buf); 79 else 80 data->note_data = (char *) elfcore_write_register_note 81 (data->obfd, data->note_data, data->note_size, 82 sect_name, buf, size); 83 xfree (buf); 84 } 85 86 /* Create appropriate note sections for a corefile, returning them in 87 allocated memory. */ 88 89 static char * 90 fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) 91 { 92 const struct regcache *regcache = get_current_regcache (); 93 char *note_data; 94 Elf_Internal_Ehdr *i_ehdrp; 95 struct fbsd_collect_regset_section_cb_data data; 96 97 /* Put a "FreeBSD" label in the ELF header. */ 98 i_ehdrp = elf_elfheader (obfd); 99 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 100 101 gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); 102 103 data.regcache = regcache; 104 data.obfd = obfd; 105 data.note_data = NULL; 106 data.note_size = note_size; 107 gdbarch_iterate_over_regset_sections (gdbarch, 108 fbsd_collect_regset_section_cb, 109 &data, regcache); 110 note_data = data.note_data; 111 112 if (get_exec_file (0)) 113 { 114 const char *fname = lbasename (get_exec_file (0)); 115 char *psargs = xstrdup (fname); 116 117 if (get_inferior_args ()) 118 psargs = reconcat (psargs, psargs, " ", get_inferior_args (), 119 (char *) NULL); 120 121 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, 122 fname, psargs); 123 } 124 125 return note_data; 126 } 127 128 /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */ 129 130 void 131 fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 132 { 133 set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); 134 } 135