Add target description for avx-avx512.
[deliverable/binutils-gdb.git] / gdb / amd64-linux-nat.c
CommitLineData
a4b6fc86 1/* Native-dependent code for GNU/Linux x86-64.
0a65a603 2
61baf725 3 Copyright (C) 2001-2017 Free Software Foundation, Inc.
53e95fcf
JS
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
53e95fcf
JS
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
53e95fcf
JS
20
21#include "defs.h"
22#include "inferior.h"
53e95fcf 23#include "regcache.h"
a055a187 24#include "elf/common.h"
35782f14 25#include <sys/uio.h>
5826e159 26#include "nat/gdb_ptrace.h"
c43af07c 27#include <asm/prctl.h>
33a0a2ac 28#include <sys/reg.h>
c4f35dd8 29#include "gregset.h"
3116063b 30#include "gdb_proc_service.h"
c4f35dd8 31
3116063b
GB
32#include "amd64-nat.h"
33#include "linux-nat.h"
9c1488cb 34#include "amd64-tdep.h"
3116063b 35#include "amd64-linux-tdep.h"
60fac5b8 36#include "i386-linux-tdep.h"
df7e5265 37#include "x86-xstate.h"
a055a187 38
040baaf6 39#include "x86-linux-nat.h"
ca9b78ce 40#include "nat/linux-ptrace.h"
93813b37 41#include "nat/amd64-linux-siginfo.h"
60fac5b8 42
2735833d
WT
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
60fac5b8
MK
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. */
430eaf2e 58static int amd64_linux_gregset32_reg_offset[] =
60fac5b8 59{
f5859b4d
MK
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 */
60fac5b8
MK
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,
a055a187 71 -1, -1, -1, -1, -1, -1, -1, -1,
01f9f808
MS
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" */
60fac5b8 77};
53e95fcf
JS
78\f
79
80/* Transfering the general-purpose registers between GDB, inferiors
81 and core files. */
82
60fac5b8 83/* Fill GDB's register cache with the general-purpose register values
53e95fcf
JS
84 in *GREGSETP. */
85
86void
7f7fe91e 87supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
53e95fcf 88{
7f7fe91e 89 amd64_supply_native_gregset (regcache, gregsetp, -1);
53e95fcf
JS
90}
91
60fac5b8
MK
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,
53e95fcf
JS
94 do this for all registers. */
95
96void
7f7fe91e
UW
97fill_gregset (const struct regcache *regcache,
98 elf_gregset_t *gregsetp, int regnum)
53e95fcf 99{
7f7fe91e 100 amd64_collect_native_gregset (regcache, gregsetp, regnum);
53e95fcf
JS
101}
102
53e95fcf
JS
103/* Transfering floating-point registers between GDB, inferiors and cores. */
104
60fac5b8 105/* Fill GDB's register cache with the floating-point and SSE register
c4f35dd8 106 values in *FPREGSETP. */
53e95fcf
JS
107
108void
7f7fe91e 109supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
53e95fcf 110{
7f7fe91e 111 amd64_supply_fxsave (regcache, -1, fpregsetp);
53e95fcf
JS
112}
113
8dda9770 114/* Fill register REGNUM (if it is a floating-point or SSE register) in
60fac5b8 115 *FPREGSETP with the value in GDB's register cache. If REGNUM is
c4f35dd8 116 -1, do this for all registers. */
53e95fcf
JS
117
118void
7f7fe91e
UW
119fill_fpregset (const struct regcache *regcache,
120 elf_fpregset_t *fpregsetp, int regnum)
53e95fcf 121{
7f7fe91e 122 amd64_collect_fxsave (regcache, regnum, fpregsetp);
53e95fcf 123}
53e95fcf
JS
124\f
125
126/* Transferring arbitrary registers between GDB and inferior. */
127
60fac5b8 128/* Fetch register REGNUM from the child process. If REGNUM is -1, do
53e95fcf
JS
129 this for all registers (including the floating point and SSE
130 registers). */
131
10d6c8cd 132static void
28439f5e
PA
133amd64_linux_fetch_inferior_registers (struct target_ops *ops,
134 struct regcache *regcache, int regnum)
53e95fcf 135{
f8028488 136 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
137 int tid;
138
a4b6fc86 139 /* GNU/Linux LWP ID's are process ID's. */
dfd4cc63 140 tid = ptid_get_lwp (inferior_ptid);
c4f35dd8 141 if (tid == 0)
dfd4cc63 142 tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
53e95fcf 143
f8028488 144 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 145 {
99679982
MK
146 elf_gregset_t regs;
147
148 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 149 perror_with_name (_("Couldn't get registers"));
99679982 150
56be3814 151 amd64_supply_native_gregset (regcache, &regs, -1);
60fac5b8
MK
152 if (regnum != -1)
153 return;
53e95fcf
JS
154 }
155
f8028488 156 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 157 {
99679982 158 elf_fpregset_t fpregs;
53e95fcf 159
0bdb2f78 160 if (have_ptrace_getregset == TRIBOOL_TRUE)
a055a187 161 {
df7e5265 162 char xstateregs[X86_XSTATE_MAX_SIZE];
a055a187
L
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"));
99679982 170
a055a187
L
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 }
2735833d
WT
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
99679982 204 }
53e95fcf
JS
205}
206
60fac5b8
MK
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
53e95fcf 209 registers). */
c4f35dd8 210
10d6c8cd 211static void
28439f5e
PA
212amd64_linux_store_inferior_registers (struct target_ops *ops,
213 struct regcache *regcache, int regnum)
53e95fcf 214{
f8028488 215 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
216 int tid;
217
a4b6fc86 218 /* GNU/Linux LWP ID's are process ID's. */
dfd4cc63 219 tid = ptid_get_lwp (inferior_ptid);
c4f35dd8 220 if (tid == 0)
dfd4cc63 221 tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
53e95fcf 222
f8028488 223 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 224 {
99679982
MK
225 elf_gregset_t regs;
226
227 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 228 perror_with_name (_("Couldn't get registers"));
99679982 229
56be3814 230 amd64_collect_native_gregset (regcache, &regs, regnum);
99679982
MK
231
232 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 233 perror_with_name (_("Couldn't write registers"));
99679982 234
60fac5b8
MK
235 if (regnum != -1)
236 return;
53e95fcf
JS
237 }
238
f8028488 239 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 240 {
99679982
MK
241 elf_fpregset_t fpregs;
242
0bdb2f78 243 if (have_ptrace_getregset == TRIBOOL_TRUE)
a055a187 244 {
df7e5265 245 char xstateregs[X86_XSTATE_MAX_SIZE];
a055a187
L
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"));
99679982 253
a055a187
L
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"));
99679982 264
a055a187 265 amd64_collect_fxsave (regcache, regnum, &fpregs);
99679982 266
a055a187
L
267 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
268 perror_with_name (_("Couldn't write floating point status"));
269 }
2735833d
WT
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
53e95fcf 294 }
53e95fcf
JS
295}
296\f
1aa7e42c 297
50d71875
AC
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
5bca7895 301ps_err_e
754653a7 302ps_get_thread_area (struct ps_prochandle *ph,
c43af07c
EZ
303 lwpid_t lwpid, int idx, void **base)
304{
f5656ead 305 if (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 32)
50d71875 306 {
8c420b8d
GB
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;
50d71875
AC
319 }
320 else
321 {
2735833d 322
50d71875
AC
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:
6fea9e18
L
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
50d71875
AC
346 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
347 return PS_OK;
348 break;
349 case GS:
6fea9e18
L
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
50d71875
AC
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 }
c43af07c 369 }
b6d42148 370 return PS_ERR; /* ptrace failed. */
c43af07c 371}
5bca7895 372\f
c43af07c 373
9cf12d57 374/* Convert a ptrace/host siginfo object, into/from the siginfo in the
5b009018
PA
375 layout of the inferiors' architecture. Returns true if any
376 conversion was done; false otherwise. If DIRECTION is 1, then copy
9cf12d57 377 from INF to PTRACE. If DIRECTION is 0, copy from PTRACE to
5b009018
PA
378 INF. */
379
380static int
9cf12d57 381amd64_linux_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
5b009018 382{
ba224c70
L
383 struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
384
5b009018
PA
385 /* Is the inferior 32-bit? If so, then do fixup the siginfo
386 object. */
ba224c70 387 if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
9cf12d57 388 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
93813b37 389 FIXUP_32);
ba224c70
L
390 /* No fixup for native x32 GDB. */
391 else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8)
9cf12d57 392 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
93813b37 393 FIXUP_X32);
5b009018
PA
394 else
395 return 0;
396}
c1e246a0
GB
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 1.01092 seconds and 4 git commands to generate.