Removed
Link Here
|
1 |
diff --git bfd/elf.c bfd/elf.c |
2 |
index a031b9e..41fb023 100644 |
3 |
--- bfd/elf.c |
4 |
+++ bfd/elf.c |
5 |
@@ -8737,6 +8737,9 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) |
6 |
if (note->namesz == 6 |
7 |
&& strcmp (note->namedata, "LINUX") == 0) |
8 |
return elfcore_grok_xstatereg (abfd, note); |
9 |
+ else if (note->namesz == 8 |
10 |
+ && strcmp (note->namedata, "FreeBSD") == 0) |
11 |
+ return elfcore_grok_xstatereg (abfd, note); |
12 |
else |
13 |
return TRUE; |
14 |
|
15 |
@@ -9556,7 +9559,11 @@ char * |
16 |
elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz, |
17 |
const void *xfpregs, int size) |
18 |
{ |
19 |
- char *note_name = "LINUX"; |
20 |
+ char *note_name; |
21 |
+ if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD) |
22 |
+ note_name = "FreeBSD"; |
23 |
+ else |
24 |
+ note_name = "LINUX"; |
25 |
return elfcore_write_note (abfd, buf, bufsiz, |
26 |
note_name, NT_X86_XSTATE, xfpregs, size); |
27 |
} |
28 |
diff --git gdb/amd64-tdep.c gdb/amd64-tdep.c |
29 |
index 3e5d1bd..461b701 100644 |
30 |
--- gdb/amd64-tdep.c |
31 |
+++ gdb/amd64-tdep.c |
32 |
@@ -39,6 +39,7 @@ |
33 |
#include "disasm.h" |
34 |
#include "amd64-tdep.h" |
35 |
#include "i387-tdep.h" |
36 |
+#include "x86-xstate.h" |
37 |
|
38 |
#include "features/i386/amd64.c" |
39 |
#include "features/i386/amd64-avx.c" |
40 |
@@ -3118,6 +3119,25 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
41 |
set_gdbarch_ptr_bit (gdbarch, 32); |
42 |
} |
43 |
|
44 |
+/* Return the target description for a specified XSAVE feature mask. */ |
45 |
+ |
46 |
+const struct target_desc * |
47 |
+amd64_target_description (uint64_t xcr0) |
48 |
+{ |
49 |
+ switch (xcr0 & X86_XSTATE_ALL_MASK) |
50 |
+ { |
51 |
+ case X86_XSTATE_MPX_AVX512_MASK: |
52 |
+ case X86_XSTATE_AVX512_MASK: |
53 |
+ return tdesc_amd64_avx512; |
54 |
+ case X86_XSTATE_MPX_MASK: |
55 |
+ return tdesc_amd64_mpx; |
56 |
+ case X86_XSTATE_AVX_MASK: |
57 |
+ return tdesc_amd64_avx; |
58 |
+ default: |
59 |
+ return tdesc_amd64; |
60 |
+ } |
61 |
+} |
62 |
+ |
63 |
/* Provide a prototype to silence -Wmissing-prototypes. */ |
64 |
void _initialize_amd64_tdep (void); |
65 |
|
66 |
diff --git gdb/amd64-tdep.h gdb/amd64-tdep.h |
67 |
index 318fd43..704225e 100644 |
68 |
--- gdb/amd64-tdep.h |
69 |
+++ gdb/amd64-tdep.h |
70 |
@@ -84,6 +84,8 @@ enum amd64_regnum |
71 |
|
72 |
#define AMD64_NUM_REGS (AMD64_ZMM31H_REGNUM + 1) |
73 |
|
74 |
+extern struct target_desc *tdesc_amd64; |
75 |
+ |
76 |
extern struct displaced_step_closure *amd64_displaced_step_copy_insn |
77 |
(struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, |
78 |
struct regcache *regs); |
79 |
@@ -95,6 +97,7 @@ extern void amd64_displaced_step_fixup (struct gdbarch *gdbarch, |
80 |
extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); |
81 |
extern void amd64_x32_init_abi (struct gdbarch_info info, |
82 |
struct gdbarch *gdbarch); |
83 |
+extern const struct target_desc *amd64_target_description (uint64_t xcr0); |
84 |
|
85 |
/* Fill register REGNUM in REGCACHE with the appropriate |
86 |
floating-point or SSE register value from *FXSAVE. If REGNUM is |
87 |
diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c |
88 |
index 31060a123..66d4289 100644 |
89 |
--- gdb/amd64bsd-nat.c |
90 |
+++ gdb/amd64bsd-nat.c |
91 |
@@ -35,6 +35,10 @@ |
92 |
#include "inf-ptrace.h" |
93 |
|
94 |
|
95 |
+#ifdef PT_GETXSTATE_INFO |
96 |
+size_t amd64bsd_xsave_len; |
97 |
+#endif |
98 |
+ |
99 |
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this |
100 |
for all registers (including the floating-point registers). */ |
101 |
|
102 |
@@ -60,6 +64,20 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, |
103 |
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) |
104 |
{ |
105 |
struct fpreg fpregs; |
106 |
+#ifdef PT_GETXSTATE_INFO |
107 |
+ char *xstateregs; |
108 |
+ |
109 |
+ if (amd64bsd_xsave_len != 0) |
110 |
+ { |
111 |
+ xstateregs = alloca (amd64bsd_xsave_len); |
112 |
+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), |
113 |
+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) |
114 |
+ perror_with_name (_("Couldn't get extended state status")); |
115 |
+ |
116 |
+ amd64_supply_xsave (regcache, -1, xstateregs); |
117 |
+ return; |
118 |
+ } |
119 |
+#endif |
120 |
|
121 |
if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), |
122 |
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1) |
123 |
@@ -99,6 +117,24 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, |
124 |
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) |
125 |
{ |
126 |
struct fpreg fpregs; |
127 |
+#ifdef PT_GETXSTATE_INFO |
128 |
+ char *xstateregs; |
129 |
+ |
130 |
+ if (amd64bsd_xsave_len != 0) |
131 |
+ { |
132 |
+ xstateregs = alloca (amd64bsd_xsave_len); |
133 |
+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), |
134 |
+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) |
135 |
+ perror_with_name (_("Couldn't get extended state status")); |
136 |
+ |
137 |
+ amd64_collect_xsave (regcache, regnum, xstateregs, 0); |
138 |
+ |
139 |
+ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), |
140 |
+ (PTRACE_TYPE_ARG3) xstateregs, amd64bsd_xsave_len) == -1) |
141 |
+ perror_with_name (_("Couldn't write extended state status")); |
142 |
+ return; |
143 |
+ } |
144 |
+#endif |
145 |
|
146 |
if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), |
147 |
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1) |
148 |
diff --git gdb/amd64bsd-nat.h gdb/amd64bsd-nat.h |
149 |
index 167eb56..09776ee 100644 |
150 |
--- gdb/amd64bsd-nat.h |
151 |
+++ gdb/amd64bsd-nat.h |
152 |
@@ -20,6 +20,9 @@ |
153 |
#ifndef AMD64BSD_NAT_H |
154 |
#define AMD64BSD_NAT_H |
155 |
|
156 |
+/* Low level amd64 XSAVE info. */ |
157 |
+extern size_t amd64bsd_xsave_len; |
158 |
+ |
159 |
/* Low level amd64 debug register functions. */ |
160 |
|
161 |
extern void amd64bsd_dr_set_control (unsigned long control); |
162 |
diff --git gdb/amd64fbsd-nat.c gdb/amd64fbsd-nat.c |
163 |
index b1b261c..a721f48 100644 |
164 |
--- gdb/amd64fbsd-nat.c |
165 |
+++ gdb/amd64fbsd-nat.c |
166 |
@@ -151,6 +151,50 @@ amd64fbsd_mourn_inferior (struct target_ops *ops) |
167 |
super_mourn_inferior (ops); |
168 |
} |
169 |
|
170 |
+/* Implement the to_read_description method. */ |
171 |
+ |
172 |
+static const struct target_desc * |
173 |
+amd64fbsd_read_description (struct target_ops *ops) |
174 |
+{ |
175 |
+#ifdef PT_GETXSTATE_INFO |
176 |
+ static int xsave_probed; |
177 |
+ static uint64_t xcr0; |
178 |
+#endif |
179 |
+ struct reg regs; |
180 |
+ int is64; |
181 |
+ |
182 |
+ if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), |
183 |
+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) |
184 |
+ perror_with_name (_("Couldn't get registers")); |
185 |
+ is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); |
186 |
+#ifdef PT_GETXSTATE_INFO |
187 |
+ if (!xsave_probed) |
188 |
+ { |
189 |
+ struct ptrace_xstate_info info; |
190 |
+ |
191 |
+ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), |
192 |
+ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) |
193 |
+ { |
194 |
+ amd64bsd_xsave_len = info.xsave_len; |
195 |
+ xcr0 = info.xsave_mask; |
196 |
+ } |
197 |
+ xsave_probed = 1; |
198 |
+ } |
199 |
+ |
200 |
+ if (amd64bsd_xsave_len != 0) |
201 |
+ { |
202 |
+ if (is64) |
203 |
+ return amd64_target_description (xcr0); |
204 |
+ else |
205 |
+ return i386_target_description (xcr0); |
206 |
+ } |
207 |
+#endif |
208 |
+ if (is64) |
209 |
+ return tdesc_amd64; |
210 |
+ else |
211 |
+ return tdesc_i386; |
212 |
+} |
213 |
+ |
214 |
/* Provide a prototype to silence -Wmissing-prototypes. */ |
215 |
void _initialize_amd64fbsd_nat (void); |
216 |
|
217 |
@@ -181,6 +225,7 @@ _initialize_amd64fbsd_nat (void) |
218 |
|
219 |
super_mourn_inferior = t->to_mourn_inferior; |
220 |
t->to_mourn_inferior = amd64fbsd_mourn_inferior; |
221 |
+ t->to_read_description = amd64fbsd_read_description; |
222 |
|
223 |
t->to_pid_to_exec_file = fbsd_pid_to_exec_file; |
224 |
t->to_find_memory_regions = fbsd_find_memory_regions; |
225 |
diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c |
226 |
index 62dcb83..52705d9 100644 |
227 |
--- gdb/amd64fbsd-tdep.c |
228 |
+++ gdb/amd64fbsd-tdep.c |
229 |
@@ -23,6 +23,9 @@ |
230 |
#include "gdbcore.h" |
231 |
#include "regcache.h" |
232 |
#include "osabi.h" |
233 |
+#include "regset.h" |
234 |
+#include "i386fbsd-tdep.h" |
235 |
+#include "x86-xstate.h" |
236 |
|
237 |
#include "amd64-tdep.h" |
238 |
#include "bsd-uthread.h" |
239 |
@@ -169,6 +172,59 @@ static int amd64fbsd_jmp_buf_reg_offset[] = |
240 |
0 * 8 /* %rip */ |
241 |
}; |
242 |
|
243 |
+/* Implement the core_read_description gdbarch method. */ |
244 |
+ |
245 |
+static const struct target_desc * |
246 |
+amd64fbsd_core_read_description (struct gdbarch *gdbarch, |
247 |
+ struct target_ops *target, |
248 |
+ bfd *abfd) |
249 |
+{ |
250 |
+ return amd64_target_description (i386fbsd_core_read_xcr0 (abfd)); |
251 |
+} |
252 |
+ |
253 |
+/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ |
254 |
+ |
255 |
+static void |
256 |
+amd64fbsd_supply_xstateregset (const struct regset *regset, |
257 |
+ struct regcache *regcache, int regnum, |
258 |
+ const void *xstateregs, size_t len) |
259 |
+{ |
260 |
+ amd64_supply_xsave (regcache, regnum, xstateregs); |
261 |
+} |
262 |
+ |
263 |
+/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ |
264 |
+ |
265 |
+static void |
266 |
+amd64fbsd_collect_xstateregset (const struct regset *regset, |
267 |
+ const struct regcache *regcache, |
268 |
+ int regnum, void *xstateregs, size_t len) |
269 |
+{ |
270 |
+ amd64_collect_xsave (regcache, regnum, xstateregs, 1); |
271 |
+} |
272 |
+ |
273 |
+static const struct regset amd64fbsd_xstateregset = |
274 |
+ { |
275 |
+ NULL, |
276 |
+ amd64fbsd_supply_xstateregset, |
277 |
+ amd64fbsd_collect_xstateregset |
278 |
+ }; |
279 |
+ |
280 |
+/* Iterate over core file register note sections. */ |
281 |
+ |
282 |
+static void |
283 |
+amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, |
284 |
+ iterate_over_regset_sections_cb *cb, |
285 |
+ void *cb_data, |
286 |
+ const struct regcache *regcache) |
287 |
+{ |
288 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
289 |
+ |
290 |
+ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); |
291 |
+ cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data); |
292 |
+ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), |
293 |
+ &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); |
294 |
+} |
295 |
+ |
296 |
static void |
297 |
amd64fbsd_supply_uthread (struct regcache *regcache, |
298 |
int regnum, CORE_ADDR addr) |
299 |
@@ -233,6 +289,15 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
300 |
tdep->sc_reg_offset = amd64fbsd_sc_reg_offset; |
301 |
tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset); |
302 |
|
303 |
+ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; |
304 |
+ |
305 |
+ /* Iterate over core file register note sections. */ |
306 |
+ set_gdbarch_iterate_over_regset_sections |
307 |
+ (gdbarch, amd64fbsd_iterate_over_regset_sections); |
308 |
+ |
309 |
+ set_gdbarch_core_read_description (gdbarch, |
310 |
+ amd64fbsd_core_read_description); |
311 |
+ |
312 |
/* FreeBSD provides a user-level threads implementation. */ |
313 |
bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); |
314 |
bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); |
315 |
diff --git gdb/i386-tdep.c gdb/i386-tdep.c |
316 |
index 4d97915..0c7eb5a 100644 |
317 |
--- gdb/i386-tdep.c |
318 |
+++ gdb/i386-tdep.c |
319 |
@@ -8598,6 +8598,25 @@ i386_coff_osabi_sniffer (bfd *abfd) |
320 |
} |
321 |
|
322 |
|
323 |
+/* Return the target description for a specified XSAVE feature mask. */ |
324 |
+ |
325 |
+const struct target_desc * |
326 |
+i386_target_description (uint64_t xcr0) |
327 |
+{ |
328 |
+ switch (xcr0 & X86_XSTATE_ALL_MASK) |
329 |
+ { |
330 |
+ case X86_XSTATE_MPX_AVX512_MASK: |
331 |
+ case X86_XSTATE_AVX512_MASK: |
332 |
+ return tdesc_i386_avx512; |
333 |
+ case X86_XSTATE_MPX_MASK: |
334 |
+ return tdesc_i386_mpx; |
335 |
+ case X86_XSTATE_AVX_MASK: |
336 |
+ return tdesc_i386_avx; |
337 |
+ default: |
338 |
+ return tdesc_i386; |
339 |
+ } |
340 |
+} |
341 |
+ |
342 |
/* Provide a prototype to silence -Wmissing-prototypes. */ |
343 |
void _initialize_i386_tdep (void); |
344 |
|
345 |
diff --git gdb/i386-tdep.h gdb/i386-tdep.h |
346 |
index 8bfd412..7880f6c 100644 |
347 |
--- gdb/i386-tdep.h |
348 |
+++ gdb/i386-tdep.h |
349 |
@@ -328,6 +328,8 @@ enum record_i386_regnum |
350 |
/* Size of the largest register. */ |
351 |
#define I386_MAX_REGISTER_SIZE 64 |
352 |
|
353 |
+extern struct target_desc *tdesc_i386; |
354 |
+ |
355 |
/* Types for i386-specific registers. */ |
356 |
extern struct type *i387_ext_type (struct gdbarch *gdbarch); |
357 |
|
358 |
@@ -416,6 +418,7 @@ extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *); |
359 |
|
360 |
extern int i386_process_record (struct gdbarch *gdbarch, |
361 |
struct regcache *regcache, CORE_ADDR addr); |
362 |
+extern const struct target_desc *i386_target_description (uint64_t xcr0); |
363 |
|
364 |
|
365 |
|
366 |
diff --git gdb/i386bsd-nat.c gdb/i386bsd-nat.c |
367 |
index 16e0707..ac8a19b 100644 |
368 |
--- gdb/i386bsd-nat.c |
369 |
+++ gdb/i386bsd-nat.c |
370 |
@@ -81,6 +81,10 @@ static int i386bsd_r_reg_offset[] = |
371 |
so that we try PT_GETXMMREGS the first time around. */ |
372 |
static int have_ptrace_xmmregs = -1; |
373 |
#endif |
374 |
+ |
375 |
+#ifdef PT_GETXSTATE_INFO |
376 |
+size_t i386bsd_xsave_len; |
377 |
+#endif |
378 |
|
379 |
|
380 |
/* Supply the general-purpose registers in GREGS, to REGCACHE. */ |
381 |
@@ -148,7 +152,24 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, |
382 |
struct fpreg fpregs; |
383 |
#ifdef HAVE_PT_GETXMMREGS |
384 |
char xmmregs[512]; |
385 |
+#endif |
386 |
+ |
387 |
+#ifdef PT_GETXSTATE_INFO |
388 |
+ if (i386bsd_xsave_len != 0) |
389 |
+ { |
390 |
+ char *xstateregs; |
391 |
+ |
392 |
+ xstateregs = alloca (i386bsd_xsave_len); |
393 |
+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), |
394 |
+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) |
395 |
+ perror_with_name (_("Couldn't get extended state status")); |
396 |
|
397 |
+ i387_supply_xsave (regcache, -1, xstateregs); |
398 |
+ return; |
399 |
+ } |
400 |
+#endif |
401 |
+ |
402 |
+#ifdef HAVE_PT_GETXMMREGS |
403 |
if (have_ptrace_xmmregs != 0 |
404 |
&& ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), |
405 |
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0) |
406 |
@@ -158,18 +179,15 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, |
407 |
} |
408 |
else |
409 |
{ |
410 |
+ have_ptrace_xmmregs = 0; |
411 |
+#endif |
412 |
if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), |
413 |
(PTRACE_TYPE_ARG3) &fpregs, 0) == -1) |
414 |
perror_with_name (_("Couldn't get floating point status")); |
415 |
|
416 |
i387_supply_fsave (regcache, -1, &fpregs); |
417 |
+#ifdef HAVE_PT_GETXMMREGS |
418 |
} |
419 |
-#else |
420 |
- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), |
421 |
- (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) |
422 |
- perror_with_name (_("Couldn't get floating point status")); |
423 |
- |
424 |
- i387_supply_fsave (regcache, -1, &fpregs); |
425 |
#endif |
426 |
} |
427 |
} |
428 |
@@ -204,7 +222,28 @@ i386bsd_store_inferior_registers (struct target_ops *ops, |
429 |
struct fpreg fpregs; |
430 |
#ifdef HAVE_PT_GETXMMREGS |
431 |
char xmmregs[512]; |
432 |
+#endif |
433 |
+ |
434 |
+#ifdef PT_GETXSTATE_INFO |
435 |
+ if (i386bsd_xsave_len != 0) |
436 |
+ { |
437 |
+ char *xstateregs; |
438 |
+ |
439 |
+ xstateregs = alloca (i386bsd_xsave_len); |
440 |
+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), |
441 |
+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) |
442 |
+ perror_with_name (_("Couldn't get extended state status")); |
443 |
|
444 |
+ i387_collect_xsave (regcache, -1, xstateregs, 0); |
445 |
+ |
446 |
+ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), |
447 |
+ (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1) |
448 |
+ perror_with_name (_("Couldn't write extended state status")); |
449 |
+ return; |
450 |
+ } |
451 |
+#endif |
452 |
+ |
453 |
+#ifdef HAVE_PT_GETXMMREGS |
454 |
if (have_ptrace_xmmregs != 0 |
455 |
&& ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), |
456 |
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0) |
457 |
diff --git gdb/i386bsd-nat.h gdb/i386bsd-nat.h |
458 |
index a11f554..2f50c32 100644 |
459 |
--- gdb/i386bsd-nat.h |
460 |
+++ gdb/i386bsd-nat.h |
461 |
@@ -25,6 +25,9 @@ |
462 |
|
463 |
extern struct target_ops *i386bsd_target (void); |
464 |
|
465 |
+/* Low level i386 XSAVE info. */ |
466 |
+extern size_t i386bsd_xsave_len; |
467 |
+ |
468 |
/* low level i386 debug register functions used in i386fbsd-nat.c. */ |
469 |
|
470 |
extern void i386bsd_dr_set_control (unsigned long control); |
471 |
diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c |
472 |
index ad439e3..6c43f2c 100644 |
473 |
--- gdb/i386fbsd-nat.c |
474 |
+++ gdb/i386fbsd-nat.c |
475 |
@@ -116,6 +116,37 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) |
476 |
} |
477 |
|
478 |
|
479 |
+#ifdef PT_GETXSTATE_INFO |
480 |
+/* Implement the to_read_description method. */ |
481 |
+ |
482 |
+static const struct target_desc * |
483 |
+i386fbsd_read_description (struct target_ops *ops) |
484 |
+{ |
485 |
+ static int xsave_probed; |
486 |
+ static uint64_t xcr0; |
487 |
+ |
488 |
+ if (!xsave_probed) |
489 |
+ { |
490 |
+ struct ptrace_xstate_info info; |
491 |
+ |
492 |
+ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), |
493 |
+ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) |
494 |
+ { |
495 |
+ i386bsd_xsave_len = info.xsave_len; |
496 |
+ xcr0 = info.xsave_mask; |
497 |
+ } |
498 |
+ xsave_probed = 1; |
499 |
+ } |
500 |
+ |
501 |
+ if (i386bsd_xsave_len != 0) |
502 |
+ { |
503 |
+ return i386_target_description (xcr0); |
504 |
+ } |
505 |
+ else |
506 |
+ return tdesc_i386; |
507 |
+} |
508 |
+#endif |
509 |
+ |
510 |
/* Prevent warning from -Wmissing-prototypes. */ |
511 |
void _initialize_i386fbsd_nat (void); |
512 |
|
513 |
@@ -140,6 +171,9 @@ _initialize_i386fbsd_nat (void) |
514 |
|
515 |
#endif /* HAVE_PT_GETDBREGS */ |
516 |
|
517 |
+#ifdef PT_GETXSTATE_INFO |
518 |
+ t->to_read_description = i386fbsd_read_description; |
519 |
+#endif |
520 |
|
521 |
t->to_resume = i386fbsd_resume; |
522 |
t->to_pid_to_exec_file = fbsd_pid_to_exec_file; |
523 |
diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c |
524 |
index ed41706..99e08cb 100644 |
525 |
--- gdb/i386fbsd-tdep.c |
526 |
+++ gdb/i386fbsd-tdep.c |
527 |
@@ -22,6 +22,9 @@ |
528 |
#include "gdbcore.h" |
529 |
#include "osabi.h" |
530 |
#include "regcache.h" |
531 |
+#include "regset.h" |
532 |
+#include "i386fbsd-tdep.h" |
533 |
+#include "x86-xstate.h" |
534 |
|
535 |
#include "i386-tdep.h" |
536 |
#include "i387-tdep.h" |
537 |
@@ -235,6 +238,100 @@ static int i386fbsd_jmp_buf_reg_offset[] = |
538 |
0 * 4 /* %eip */ |
539 |
}; |
540 |
|
541 |
+/* Get XSAVE extended state xcr0 from core dump. */ |
542 |
+ |
543 |
+uint64_t |
544 |
+i386fbsd_core_read_xcr0 (bfd *abfd) |
545 |
+{ |
546 |
+ asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); |
547 |
+ uint64_t xcr0; |
548 |
+ |
549 |
+ if (xstate) |
550 |
+ { |
551 |
+ size_t size = bfd_section_size (abfd, xstate); |
552 |
+ |
553 |
+ /* Check extended state size. */ |
554 |
+ if (size < X86_XSTATE_AVX_SIZE) |
555 |
+ xcr0 = X86_XSTATE_SSE_MASK; |
556 |
+ else |
557 |
+ { |
558 |
+ char contents[8]; |
559 |
+ |
560 |
+ if (! bfd_get_section_contents (abfd, xstate, contents, |
561 |
+ I386_FBSD_XSAVE_XCR0_OFFSET, |
562 |
+ 8)) |
563 |
+ { |
564 |
+ warning (_("Couldn't read `xcr0' bytes from " |
565 |
+ "`.reg-xstate' section in core file.")); |
566 |
+ return 0; |
567 |
+ } |
568 |
+ |
569 |
+ xcr0 = bfd_get_64 (abfd, contents); |
570 |
+ } |
571 |
+ } |
572 |
+ else |
573 |
+ xcr0 = 0; |
574 |
+ |
575 |
+ return xcr0; |
576 |
+} |
577 |
+ |
578 |
+/* Implement the core_read_description gdbarch method. */ |
579 |
+ |
580 |
+static const struct target_desc * |
581 |
+i386fbsd_core_read_description (struct gdbarch *gdbarch, |
582 |
+ struct target_ops *target, |
583 |
+ bfd *abfd) |
584 |
+{ |
585 |
+ return i386_target_description (i386fbsd_core_read_xcr0 (abfd)); |
586 |
+} |
587 |
+ |
588 |
+/* Similar to i386_supply_fpregset, but use XSAVE extended state. */ |
589 |
+ |
590 |
+static void |
591 |
+i386fbsd_supply_xstateregset (const struct regset *regset, |
592 |
+ struct regcache *regcache, int regnum, |
593 |
+ const void *xstateregs, size_t len) |
594 |
+{ |
595 |
+ i387_supply_xsave (regcache, regnum, xstateregs); |
596 |
+} |
597 |
+ |
598 |
+/* Similar to i386_collect_fpregset, but use XSAVE extended state. */ |
599 |
+ |
600 |
+static void |
601 |
+i386fbsd_collect_xstateregset (const struct regset *regset, |
602 |
+ const struct regcache *regcache, |
603 |
+ int regnum, void *xstateregs, size_t len) |
604 |
+{ |
605 |
+ i387_collect_xsave (regcache, regnum, xstateregs, 1); |
606 |
+} |
607 |
+ |
608 |
+/* Register set definitions. */ |
609 |
+ |
610 |
+static const struct regset i386fbsd_xstateregset = |
611 |
+ { |
612 |
+ NULL, |
613 |
+ i386fbsd_supply_xstateregset, |
614 |
+ i386fbsd_collect_xstateregset |
615 |
+ }; |
616 |
+ |
617 |
+/* Iterate over core file register note sections. */ |
618 |
+ |
619 |
+static void |
620 |
+i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, |
621 |
+ iterate_over_regset_sections_cb *cb, |
622 |
+ void *cb_data, |
623 |
+ const struct regcache *regcache) |
624 |
+{ |
625 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
626 |
+ |
627 |
+ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); |
628 |
+ cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data); |
629 |
+ |
630 |
+ if (tdep->xcr0 & X86_XSTATE_AVX) |
631 |
+ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), |
632 |
+ &i386fbsd_xstateregset, "XSAVE extended state", cb_data); |
633 |
+} |
634 |
+ |
635 |
static void |
636 |
i386fbsd_supply_uthread (struct regcache *regcache, |
637 |
int regnum, CORE_ADDR addr) |
638 |
@@ -376,6 +473,15 @@ i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
639 |
/* FreeBSD 4.0 introduced a new `struct sigcontext'. */ |
640 |
tdep->sc_reg_offset = i386fbsd4_sc_reg_offset; |
641 |
tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset); |
642 |
+ |
643 |
+ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; |
644 |
+ |
645 |
+ /* Iterate over core file register note sections. */ |
646 |
+ set_gdbarch_iterate_over_regset_sections |
647 |
+ (gdbarch, i386fbsd_iterate_over_regset_sections); |
648 |
+ |
649 |
+ set_gdbarch_core_read_description (gdbarch, |
650 |
+ i386fbsd_core_read_description); |
651 |
} |
652 |
|
653 |
|
654 |
diff --git gdb/i386fbsd-tdep.h gdb/i386fbsd-tdep.h |
655 |
new file mode 100644 |
656 |
index 0000000..8d6f998 |
657 |
--- /dev/null |
658 |
+++ gdb/i386fbsd-tdep.h |
659 |
@@ -0,0 +1,31 @@ |
660 |
+/* Target-dependent code for FreeBSD x86. |
661 |
+ |
662 |
+ Copyright (C) 2015 Free Software Foundation, Inc. |
663 |
+ |
664 |
+ This file is part of GDB. |
665 |
+ |
666 |
+ This program is free software; you can redistribute it and/or modify |
667 |
+ it under the terms of the GNU General Public License as published by |
668 |
+ the Free Software Foundation; either version 3 of the License, or |
669 |
+ (at your option) any later version. |
670 |
+ |
671 |
+ This program is distributed in the hope that it will be useful, |
672 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
673 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
674 |
+ GNU General Public License for more details. |
675 |
+ |
676 |
+ You should have received a copy of the GNU General Public License |
677 |
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
678 |
+ |
679 |
+#ifndef I386FBSD_TDEP_H |
680 |
+#define I386FBSD_TDEP_H |
681 |
+ |
682 |
+/* Get XSAVE extended state xcr0 from core dump. */ |
683 |
+extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); |
684 |
+ |
685 |
+/* The format of the XSAVE extended area is determined by hardware. |
686 |
+ Cores store the XSAVE extended area in a NT_X86_XSTATE note that |
687 |
+ matches the layout on Linux. */ |
688 |
+#define I386_FBSD_XSAVE_XCR0_OFFSET 464 |
689 |
+ |
690 |
+#endif /* i386fbsd-tdep.h */ |