Commit | Line | Data |
---|---|---|
a904c024 AA |
1 | /* Target-dependent code for FreeBSD, architecture-independent. |
2 | ||
32d0add0 | 3 | Copyright (C) 2002-2015 Free Software Foundation, Inc. |
a904c024 AA |
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 | ||
a904c024 AA |
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 | { | |
3ce5b6e2 | 92 | struct regcache *regcache = get_current_regcache (); |
a904c024 AA |
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; | |
3ce5b6e2 | 107 | target_fetch_registers (regcache, -1); |
a904c024 AA |
108 | gdbarch_iterate_over_regset_sections (gdbarch, |
109 | fbsd_collect_regset_section_cb, | |
110 | &data, regcache); | |
111 | note_data = data.note_data; | |
112 | ||
113 | if (get_exec_file (0)) | |
114 | { | |
115 | const char *fname = lbasename (get_exec_file (0)); | |
116 | char *psargs = xstrdup (fname); | |
117 | ||
118 | if (get_inferior_args ()) | |
119 | psargs = reconcat (psargs, psargs, " ", get_inferior_args (), | |
120 | (char *) NULL); | |
121 | ||
122 | note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, | |
123 | fname, psargs); | |
124 | } | |
125 | ||
126 | return note_data; | |
127 | } | |
128 | ||
129 | /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */ | |
130 | ||
131 | void | |
132 | fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
133 | { | |
134 | set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); | |
135 | } |