Add target description for avx-avx512.
[deliverable/binutils-gdb.git] / gdb / amd64-linux-nat.c
... / ...
CommitLineData
1/* Native-dependent code for GNU/Linux x86-64.
2
3 Copyright (C) 2001-2017 Free Software Foundation, Inc.
4 Contributed by Jiri Smid, SuSE Labs.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21#include "defs.h"
22#include "inferior.h"
23#include "regcache.h"
24#include "elf/common.h"
25#include <sys/uio.h>
26#include "nat/gdb_ptrace.h"
27#include <asm/prctl.h>
28#include <sys/reg.h>
29#include "gregset.h"
30#include "gdb_proc_service.h"
31
32#include "amd64-nat.h"
33#include "linux-nat.h"
34#include "amd64-tdep.h"
35#include "amd64-linux-tdep.h"
36#include "i386-linux-tdep.h"
37#include "x86-xstate.h"
38
39#include "x86-linux-nat.h"
40#include "nat/linux-ptrace.h"
41#include "nat/amd64-linux-siginfo.h"
42
43/* This definition comes from prctl.h. Kernels older than 2.5.64
44 do not have it. */
45#ifndef PTRACE_ARCH_PRCTL
46#define PTRACE_ARCH_PRCTL 30
47#endif
48
49/* Mapping between the general-purpose registers in GNU/Linux x86-64
50 `struct user' format and GDB's register cache layout for GNU/Linux
51 i386.
52
53 Note that most GNU/Linux x86-64 registers are 64-bit, while the
54 GNU/Linux i386 registers are all 32-bit, but since we're
55 little-endian we get away with that. */
56
57/* From <sys/reg.h> on GNU/Linux i386. */
58static int amd64_linux_gregset32_reg_offset[] =
59{
60 RAX * 8, RCX * 8, /* %eax, %ecx */
61 RDX * 8, RBX * 8, /* %edx, %ebx */
62 RSP * 8, RBP * 8, /* %esp, %ebp */
63 RSI * 8, RDI * 8, /* %esi, %edi */
64 RIP * 8, EFLAGS * 8, /* %eip, %eflags */
65 CS * 8, SS * 8, /* %cs, %ss */
66 DS * 8, ES * 8, /* %ds, %es */
67 FS * 8, GS * 8, /* %fs, %gs */
68 -1, -1, -1, -1, -1, -1, -1, -1,
69 -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, /* MPX registers BND0 ... BND3. */
73 -1, -1, /* MPX registers BNDCFGU, BNDSTATUS. */
74 -1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512) */
75 -1, -1, -1, -1, -1, -1, -1, -1, /* zmm0 ... zmm7 (AVX512) */
76 ORIG_RAX * 8 /* "orig_eax" */
77};
78\f
79
80/* Transfering the general-purpose registers between GDB, inferiors
81 and core files. */
82
83/* Fill GDB's register cache with the general-purpose register values
84 in *GREGSETP. */
85
86void
87supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
88{
89 amd64_supply_native_gregset (regcache, gregsetp, -1);
90}
91
92/* Fill register REGNUM (if it is a general-purpose register) in
93 *GREGSETP with the value in GDB's register cache. If REGNUM is -1,
94 do this for all registers. */
95
96void
97fill_gregset (const struct regcache *regcache,
98 elf_gregset_t *gregsetp, int regnum)
99{
100 amd64_collect_native_gregset (regcache, gregsetp, regnum);
101}
102
103/* Transfering floating-point registers between GDB, inferiors and cores. */
104
105/* Fill GDB's register cache with the floating-point and SSE register
106 values in *FPREGSETP. */
107
108void
109supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
110{
111 amd64_supply_fxsave (regcache, -1, fpregsetp);
112}
113
114/* Fill register REGNUM (if it is a floating-point or SSE register) in
115 *FPREGSETP with the value in GDB's register cache. If REGNUM is
116 -1, do this for all registers. */
117
118void
119fill_fpregset (const struct regcache *regcache,
120 elf_fpregset_t *fpregsetp, int regnum)
121{
122 amd64_collect_fxsave (regcache, regnum, fpregsetp);
123}
124\f
125
126/* Transferring arbitrary registers between GDB and inferior. */
127
128/* Fetch register REGNUM from the child process. If REGNUM is -1, do
129 this for all registers (including the floating point and SSE
130 registers). */
131
132static void
133amd64_linux_fetch_inferior_registers (struct target_ops *ops,
134 struct regcache *regcache, int regnum)
135{
136 struct gdbarch *gdbarch = get_regcache_arch (regcache);
137 int tid;
138
139 /* GNU/Linux LWP ID's are process ID's. */
140 tid = ptid_get_lwp (inferior_ptid);
141 if (tid == 0)
142 tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
143
144 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
145 {
146 elf_gregset_t regs;
147
148 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
149 perror_with_name (_("Couldn't get registers"));
150
151 amd64_supply_native_gregset (regcache, &regs, -1);
152 if (regnum != -1)
153 return;
154 }
155
156 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
157 {
158 elf_fpregset_t fpregs;
159
160 if (have_ptrace_getregset == TRIBOOL_TRUE)
161 {
162 char xstateregs[X86_XSTATE_MAX_SIZE];
163 struct iovec iov;
164
165 iov.iov_base = xstateregs;
166 iov.iov_len = sizeof (xstateregs);
167 if (ptrace (PTRACE_GETREGSET, tid,
168 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
169 perror_with_name (_("Couldn't get extended state status"));
170
171 amd64_supply_xsave (regcache, -1, xstateregs);
172 }
173 else
174 {
175 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
176 perror_with_name (_("Couldn't get floating point status"));
177
178 amd64_supply_fxsave (regcache, -1, &fpregs);
179 }
180#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
181 {
182 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
183 fs_base and gs_base fields of user_regs_struct can be
184 used directly. */
185 unsigned long base;
186
187 if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
188 {
189 if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_FS) < 0)
190 perror_with_name (_("Couldn't get segment register fs_base"));
191
192 regcache_raw_supply (regcache, AMD64_FSBASE_REGNUM, &base);
193 }
194
195 if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
196 {
197 if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_GS) < 0)
198 perror_with_name (_("Couldn't get segment register gs_base"));
199
200 regcache_raw_supply (regcache, AMD64_GSBASE_REGNUM, &base);
201 }
202 }
203#endif
204 }
205}
206
207/* Store register REGNUM back into the child process. If REGNUM is
208 -1, do this for all registers (including the floating-point and SSE
209 registers). */
210
211static void
212amd64_linux_store_inferior_registers (struct target_ops *ops,
213 struct regcache *regcache, int regnum)
214{
215 struct gdbarch *gdbarch = get_regcache_arch (regcache);
216 int tid;
217
218 /* GNU/Linux LWP ID's are process ID's. */
219 tid = ptid_get_lwp (inferior_ptid);
220 if (tid == 0)
221 tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
222
223 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
224 {
225 elf_gregset_t regs;
226
227 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
228 perror_with_name (_("Couldn't get registers"));
229
230 amd64_collect_native_gregset (regcache, &regs, regnum);
231
232 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
233 perror_with_name (_("Couldn't write registers"));
234
235 if (regnum != -1)
236 return;
237 }
238
239 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
240 {
241 elf_fpregset_t fpregs;
242
243 if (have_ptrace_getregset == TRIBOOL_TRUE)
244 {
245 char xstateregs[X86_XSTATE_MAX_SIZE];
246 struct iovec iov;
247
248 iov.iov_base = xstateregs;
249 iov.iov_len = sizeof (xstateregs);
250 if (ptrace (PTRACE_GETREGSET, tid,
251 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
252 perror_with_name (_("Couldn't get extended state status"));
253
254 amd64_collect_xsave (regcache, regnum, xstateregs, 0);
255
256 if (ptrace (PTRACE_SETREGSET, tid,
257 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
258 perror_with_name (_("Couldn't write extended state status"));
259 }
260 else
261 {
262 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
263 perror_with_name (_("Couldn't get floating point status"));
264
265 amd64_collect_fxsave (regcache, regnum, &fpregs);
266
267 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
268 perror_with_name (_("Couldn't write floating point status"));
269 }
270
271#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
272 {
273 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
274 fs_base and gs_base fields of user_regs_struct can be
275 used directly. */
276 void *base;
277
278 if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
279 {
280 regcache_raw_collect (regcache, AMD64_FSBASE_REGNUM, &base);
281
282 if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_FS) < 0)
283 perror_with_name (_("Couldn't write segment register fs_base"));
284 }
285 if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
286 {
287
288 regcache_raw_collect (regcache, AMD64_GSBASE_REGNUM, &base);
289 if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_GS) < 0)
290 perror_with_name (_("Couldn't write segment register gs_base"));
291 }
292 }
293#endif
294 }
295}
296\f
297
298/* This function is called by libthread_db as part of its handling of
299 a request for a thread's local storage address. */
300
301ps_err_e
302ps_get_thread_area (struct ps_prochandle *ph,
303 lwpid_t lwpid, int idx, void **base)
304{
305 if (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 32)
306 {
307 unsigned int base_addr;
308 ps_err_e result;
309
310 result = x86_linux_get_thread_area (lwpid, (void *) (long) idx,
311 &base_addr);
312 if (result == PS_OK)
313 {
314 /* Extend the value to 64 bits. Here it's assumed that
315 a "long" and a "void *" are the same. */
316 (*base) = (void *) (long) base_addr;
317 }
318 return result;
319 }
320 else
321 {
322
323 /* FIXME: ezannoni-2003-07-09 see comment above about include
324 file order. We could be getting bogus values for these two. */
325 gdb_assert (FS < ELF_NGREG);
326 gdb_assert (GS < ELF_NGREG);
327 switch (idx)
328 {
329 case FS:
330#ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
331 {
332 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
333 fs_base and gs_base fields of user_regs_struct can be
334 used directly. */
335 unsigned long fs;
336 errno = 0;
337 fs = ptrace (PTRACE_PEEKUSER, lwpid,
338 offsetof (struct user_regs_struct, fs_base), 0);
339 if (errno == 0)
340 {
341 *base = (void *) fs;
342 return PS_OK;
343 }
344 }
345#endif
346 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
347 return PS_OK;
348 break;
349 case GS:
350#ifdef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
351 {
352 unsigned long gs;
353 errno = 0;
354 gs = ptrace (PTRACE_PEEKUSER, lwpid,
355 offsetof (struct user_regs_struct, gs_base), 0);
356 if (errno == 0)
357 {
358 *base = (void *) gs;
359 return PS_OK;
360 }
361 }
362#endif
363 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
364 return PS_OK;
365 break;
366 default: /* Should not happen. */
367 return PS_BADADDR;
368 }
369 }
370 return PS_ERR; /* ptrace failed. */
371}
372\f
373
374/* Convert a ptrace/host siginfo object, into/from the siginfo in the
375 layout of the inferiors' architecture. Returns true if any
376 conversion was done; false otherwise. If DIRECTION is 1, then copy
377 from INF to PTRACE. If DIRECTION is 0, copy from PTRACE to
378 INF. */
379
380static int
381amd64_linux_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
382{
383 struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
384
385 /* Is the inferior 32-bit? If so, then do fixup the siginfo
386 object. */
387 if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
388 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
389 FIXUP_32);
390 /* No fixup for native x32 GDB. */
391 else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8)
392 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
393 FIXUP_X32);
394 else
395 return 0;
396}
397
398/* Provide a prototype to silence -Wmissing-prototypes. */
399void _initialize_amd64_linux_nat (void);
400
401void
402_initialize_amd64_linux_nat (void)
403{
404 struct target_ops *t;
405
406 amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
407 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
408 amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
409 amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
410
411 gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
412 == amd64_native_gregset32_num_regs);
413
414 /* Create a generic x86 GNU/Linux target. */
415 t = x86_linux_create_target ();
416
417 /* Add our register access methods. */
418 t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
419 t->to_store_registers = amd64_linux_store_inferior_registers;
420
421 /* Add the target. */
422 x86_linux_add_target (t);
423
424 /* Add our siginfo layout converter. */
425 linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
426}
This page took 0.025623 seconds and 4 git commands to generate.