4284f3809b41ed65f15de41f221481b61aeea90a
[binutils-gdb.git] / gdb / fbsd-tdep.c
1 /* Target-dependent code for FreeBSD, architecture-independent.
2
3 Copyright (C) 2002-2016 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 /* This is how we want PTIDs from core files to be printed. */
32
33 static char *
34 fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
35 {
36 static char buf[80];
37
38 if (ptid_get_lwp (ptid) != 0)
39 {
40 xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid));
41 return buf;
42 }
43
44 return normal_pid_to_str (ptid);
45 }
46
47 /* Extract the name assigned to a thread from a core. Returns the
48 string in a static buffer. */
49
50 static const char *
51 fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
52 {
53 static char buf[80];
54 struct bfd_section *section;
55 bfd_size_type size;
56 char sectionstr[32];
57
58 if (ptid_get_lwp (thr->ptid) != 0)
59 {
60 /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread
61 whose contents are defined by a "struct thrmisc" declared in
62 <sys/procfs.h> on FreeBSD. The per-thread name is stored as
63 a null-terminated string as the first member of the
64 structure. Rather than define the full structure here, just
65 extract the null-terminated name from the start of the
66 note. */
67 xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
68 ptid_get_lwp (thr->ptid));
69 section = bfd_get_section_by_name (core_bfd, sectionstr);
70 if (section != NULL && bfd_section_size (core_bfd, section) > 0)
71 {
72 /* Truncate the name if it is longer than "buf". */
73 size = bfd_section_size (core_bfd, section);
74 if (size > sizeof buf - 1)
75 size = sizeof buf - 1;
76 if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0,
77 size)
78 && buf[0] != '\0')
79 {
80 buf[size] = '\0';
81
82 /* Note that each thread will report the process command
83 as its thread name instead of an empty name if a name
84 has not been set explicitly. Return a NULL name in
85 that case. */
86 if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0)
87 return buf;
88 }
89 }
90 }
91
92 return NULL;
93 }
94
95 static int
96 find_signalled_thread (struct thread_info *info, void *data)
97 {
98 if (info->suspend.stop_signal != GDB_SIGNAL_0
99 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
100 return 1;
101
102 return 0;
103 }
104
105 static enum gdb_signal
106 find_stop_signal (void)
107 {
108 struct thread_info *info =
109 iterate_over_threads (find_signalled_thread, NULL);
110
111 if (info)
112 return info->suspend.stop_signal;
113 else
114 return GDB_SIGNAL_0;
115 }
116
117 struct fbsd_collect_regset_section_cb_data
118 {
119 const struct regcache *regcache;
120 bfd *obfd;
121 char *note_data;
122 int *note_size;
123 };
124
125 static void
126 fbsd_collect_regset_section_cb (const char *sect_name, int size,
127 const struct regset *regset,
128 const char *human_name, void *cb_data)
129 {
130 char *buf;
131 struct fbsd_collect_regset_section_cb_data *data
132 = (struct fbsd_collect_regset_section_cb_data *) cb_data;
133
134 gdb_assert (regset->collect_regset);
135
136 buf = (char *) xmalloc (size);
137 regset->collect_regset (regset, data->regcache, -1, buf, size);
138
139 /* PRSTATUS still needs to be treated specially. */
140 if (strcmp (sect_name, ".reg") == 0)
141 data->note_data = (char *) elfcore_write_prstatus
142 (data->obfd, data->note_data, data->note_size,
143 ptid_get_pid (inferior_ptid), find_stop_signal (), buf);
144 else
145 data->note_data = (char *) elfcore_write_register_note
146 (data->obfd, data->note_data, data->note_size,
147 sect_name, buf, size);
148 xfree (buf);
149 }
150
151 /* Create appropriate note sections for a corefile, returning them in
152 allocated memory. */
153
154 static char *
155 fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
156 {
157 struct regcache *regcache = get_current_regcache ();
158 char *note_data;
159 Elf_Internal_Ehdr *i_ehdrp;
160 struct fbsd_collect_regset_section_cb_data data;
161
162 /* Put a "FreeBSD" label in the ELF header. */
163 i_ehdrp = elf_elfheader (obfd);
164 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
165
166 gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch));
167
168 data.regcache = regcache;
169 data.obfd = obfd;
170 data.note_data = NULL;
171 data.note_size = note_size;
172 target_fetch_registers (regcache, -1);
173 gdbarch_iterate_over_regset_sections (gdbarch,
174 fbsd_collect_regset_section_cb,
175 &data, regcache);
176 note_data = data.note_data;
177
178 if (get_exec_file (0))
179 {
180 const char *fname = lbasename (get_exec_file (0));
181 char *psargs = xstrdup (fname);
182
183 if (get_inferior_args ())
184 psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
185 (char *) NULL);
186
187 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
188 fname, psargs);
189 }
190
191 return note_data;
192 }
193
194 /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */
195
196 void
197 fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
198 {
199 set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str);
200 set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
201 set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
202 }