]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/amd64-linux-nat.c
Remove unnecessary function prototypes.
[thirdparty/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) */
51547df6 76 -1, /* PKEYS register PKRU */
01f9f808 77 ORIG_RAX * 8 /* "orig_eax" */
60fac5b8 78};
53e95fcf
JS
79\f
80
81/* Transfering the general-purpose registers between GDB, inferiors
82 and core files. */
83
60fac5b8 84/* Fill GDB's register cache with the general-purpose register values
53e95fcf
JS
85 in *GREGSETP. */
86
87void
7f7fe91e 88supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
53e95fcf 89{
7f7fe91e 90 amd64_supply_native_gregset (regcache, gregsetp, -1);
53e95fcf
JS
91}
92
60fac5b8
MK
93/* Fill register REGNUM (if it is a general-purpose register) in
94 *GREGSETP with the value in GDB's register cache. If REGNUM is -1,
53e95fcf
JS
95 do this for all registers. */
96
97void
7f7fe91e
UW
98fill_gregset (const struct regcache *regcache,
99 elf_gregset_t *gregsetp, int regnum)
53e95fcf 100{
7f7fe91e 101 amd64_collect_native_gregset (regcache, gregsetp, regnum);
53e95fcf
JS
102}
103
53e95fcf
JS
104/* Transfering floating-point registers between GDB, inferiors and cores. */
105
60fac5b8 106/* Fill GDB's register cache with the floating-point and SSE register
c4f35dd8 107 values in *FPREGSETP. */
53e95fcf
JS
108
109void
7f7fe91e 110supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
53e95fcf 111{
7f7fe91e 112 amd64_supply_fxsave (regcache, -1, fpregsetp);
53e95fcf
JS
113}
114
8dda9770 115/* Fill register REGNUM (if it is a floating-point or SSE register) in
60fac5b8 116 *FPREGSETP with the value in GDB's register cache. If REGNUM is
c4f35dd8 117 -1, do this for all registers. */
53e95fcf
JS
118
119void
7f7fe91e
UW
120fill_fpregset (const struct regcache *regcache,
121 elf_fpregset_t *fpregsetp, int regnum)
53e95fcf 122{
7f7fe91e 123 amd64_collect_fxsave (regcache, regnum, fpregsetp);
53e95fcf 124}
53e95fcf
JS
125\f
126
127/* Transferring arbitrary registers between GDB and inferior. */
128
60fac5b8 129/* Fetch register REGNUM from the child process. If REGNUM is -1, do
53e95fcf
JS
130 this for all registers (including the floating point and SSE
131 registers). */
132
10d6c8cd 133static void
28439f5e
PA
134amd64_linux_fetch_inferior_registers (struct target_ops *ops,
135 struct regcache *regcache, int regnum)
53e95fcf 136{
f8028488 137 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
138 int tid;
139
a4b6fc86 140 /* GNU/Linux LWP ID's are process ID's. */
6a06fbb7 141 tid = ptid_get_lwp (regcache_get_ptid (regcache));
c4f35dd8 142 if (tid == 0)
6a06fbb7 143 tid = ptid_get_pid (regcache_get_ptid (regcache)); /* Not a threaded program. */
53e95fcf 144
f8028488 145 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 146 {
99679982
MK
147 elf_gregset_t regs;
148
149 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 150 perror_with_name (_("Couldn't get registers"));
99679982 151
56be3814 152 amd64_supply_native_gregset (regcache, &regs, -1);
60fac5b8
MK
153 if (regnum != -1)
154 return;
53e95fcf
JS
155 }
156
f8028488 157 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 158 {
99679982 159 elf_fpregset_t fpregs;
53e95fcf 160
0bdb2f78 161 if (have_ptrace_getregset == TRIBOOL_TRUE)
a055a187 162 {
df7e5265 163 char xstateregs[X86_XSTATE_MAX_SIZE];
a055a187
L
164 struct iovec iov;
165
166 iov.iov_base = xstateregs;
167 iov.iov_len = sizeof (xstateregs);
168 if (ptrace (PTRACE_GETREGSET, tid,
169 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
170 perror_with_name (_("Couldn't get extended state status"));
99679982 171
a055a187
L
172 amd64_supply_xsave (regcache, -1, xstateregs);
173 }
174 else
175 {
176 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
177 perror_with_name (_("Couldn't get floating point status"));
178
179 amd64_supply_fxsave (regcache, -1, &fpregs);
180 }
2735833d
WT
181#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
182 {
183 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
184 fs_base and gs_base fields of user_regs_struct can be
185 used directly. */
186 unsigned long base;
187
188 if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
189 {
190 if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_FS) < 0)
191 perror_with_name (_("Couldn't get segment register fs_base"));
192
193 regcache_raw_supply (regcache, AMD64_FSBASE_REGNUM, &base);
194 }
195
196 if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
197 {
198 if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_GS) < 0)
199 perror_with_name (_("Couldn't get segment register gs_base"));
200
201 regcache_raw_supply (regcache, AMD64_GSBASE_REGNUM, &base);
202 }
203 }
204#endif
99679982 205 }
53e95fcf
JS
206}
207
60fac5b8
MK
208/* Store register REGNUM back into the child process. If REGNUM is
209 -1, do this for all registers (including the floating-point and SSE
53e95fcf 210 registers). */
c4f35dd8 211
10d6c8cd 212static void
28439f5e
PA
213amd64_linux_store_inferior_registers (struct target_ops *ops,
214 struct regcache *regcache, int regnum)
53e95fcf 215{
f8028488 216 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
217 int tid;
218
a4b6fc86 219 /* GNU/Linux LWP ID's are process ID's. */
6a06fbb7 220 tid = ptid_get_lwp (regcache_get_ptid (regcache));
c4f35dd8 221 if (tid == 0)
6a06fbb7 222 tid = ptid_get_pid (regcache_get_ptid (regcache)); /* Not a threaded program. */
53e95fcf 223
f8028488 224 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 225 {
99679982
MK
226 elf_gregset_t regs;
227
228 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 229 perror_with_name (_("Couldn't get registers"));
99679982 230
56be3814 231 amd64_collect_native_gregset (regcache, &regs, regnum);
99679982
MK
232
233 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 234 perror_with_name (_("Couldn't write registers"));
99679982 235
60fac5b8
MK
236 if (regnum != -1)
237 return;
53e95fcf
JS
238 }
239
f8028488 240 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 241 {
99679982
MK
242 elf_fpregset_t fpregs;
243
0bdb2f78 244 if (have_ptrace_getregset == TRIBOOL_TRUE)
a055a187 245 {
df7e5265 246 char xstateregs[X86_XSTATE_MAX_SIZE];
a055a187
L
247 struct iovec iov;
248
249 iov.iov_base = xstateregs;
250 iov.iov_len = sizeof (xstateregs);
251 if (ptrace (PTRACE_GETREGSET, tid,
252 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
253 perror_with_name (_("Couldn't get extended state status"));
99679982 254
a055a187
L
255 amd64_collect_xsave (regcache, regnum, xstateregs, 0);
256
257 if (ptrace (PTRACE_SETREGSET, tid,
258 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
259 perror_with_name (_("Couldn't write extended state status"));
260 }
261 else
262 {
263 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
264 perror_with_name (_("Couldn't get floating point status"));
99679982 265
a055a187 266 amd64_collect_fxsave (regcache, regnum, &fpregs);
99679982 267
a055a187
L
268 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
269 perror_with_name (_("Couldn't write floating point status"));
270 }
2735833d
WT
271
272#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
273 {
274 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
275 fs_base and gs_base fields of user_regs_struct can be
276 used directly. */
277 void *base;
278
279 if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
280 {
281 regcache_raw_collect (regcache, AMD64_FSBASE_REGNUM, &base);
282
283 if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_FS) < 0)
284 perror_with_name (_("Couldn't write segment register fs_base"));
285 }
286 if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
287 {
288
289 regcache_raw_collect (regcache, AMD64_GSBASE_REGNUM, &base);
290 if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_GS) < 0)
291 perror_with_name (_("Couldn't write segment register gs_base"));
292 }
293 }
294#endif
53e95fcf 295 }
53e95fcf
JS
296}
297\f
1aa7e42c 298
50d71875
AC
299/* This function is called by libthread_db as part of its handling of
300 a request for a thread's local storage address. */
301
5bca7895 302ps_err_e
754653a7 303ps_get_thread_area (struct ps_prochandle *ph,
c43af07c
EZ
304 lwpid_t lwpid, int idx, void **base)
305{
f5656ead 306 if (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 32)
50d71875 307 {
8c420b8d
GB
308 unsigned int base_addr;
309 ps_err_e result;
310
311 result = x86_linux_get_thread_area (lwpid, (void *) (long) idx,
312 &base_addr);
313 if (result == PS_OK)
314 {
315 /* Extend the value to 64 bits. Here it's assumed that
316 a "long" and a "void *" are the same. */
317 (*base) = (void *) (long) base_addr;
318 }
319 return result;
50d71875
AC
320 }
321 else
322 {
2735833d 323
50d71875
AC
324 /* FIXME: ezannoni-2003-07-09 see comment above about include
325 file order. We could be getting bogus values for these two. */
326 gdb_assert (FS < ELF_NGREG);
327 gdb_assert (GS < ELF_NGREG);
328 switch (idx)
329 {
330 case FS:
6fea9e18
L
331#ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
332 {
333 /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
334 fs_base and gs_base fields of user_regs_struct can be
335 used directly. */
336 unsigned long fs;
337 errno = 0;
338 fs = ptrace (PTRACE_PEEKUSER, lwpid,
339 offsetof (struct user_regs_struct, fs_base), 0);
340 if (errno == 0)
341 {
342 *base = (void *) fs;
343 return PS_OK;
344 }
345 }
346#endif
50d71875
AC
347 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
348 return PS_OK;
349 break;
350 case GS:
6fea9e18
L
351#ifdef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
352 {
353 unsigned long gs;
354 errno = 0;
355 gs = ptrace (PTRACE_PEEKUSER, lwpid,
356 offsetof (struct user_regs_struct, gs_base), 0);
357 if (errno == 0)
358 {
359 *base = (void *) gs;
360 return PS_OK;
361 }
362 }
363#endif
50d71875
AC
364 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
365 return PS_OK;
366 break;
367 default: /* Should not happen. */
368 return PS_BADADDR;
369 }
c43af07c 370 }
b6d42148 371 return PS_ERR; /* ptrace failed. */
c43af07c 372}
5bca7895 373\f
c43af07c 374
9cf12d57 375/* Convert a ptrace/host siginfo object, into/from the siginfo in the
5b009018
PA
376 layout of the inferiors' architecture. Returns true if any
377 conversion was done; false otherwise. If DIRECTION is 1, then copy
9cf12d57 378 from INF to PTRACE. If DIRECTION is 0, copy from PTRACE to
5b009018
PA
379 INF. */
380
381static int
9cf12d57 382amd64_linux_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
5b009018 383{
ba224c70
L
384 struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
385
5b009018
PA
386 /* Is the inferior 32-bit? If so, then do fixup the siginfo
387 object. */
ba224c70 388 if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
9cf12d57 389 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
93813b37 390 FIXUP_32);
ba224c70
L
391 /* No fixup for native x32 GDB. */
392 else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8)
9cf12d57 393 return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
93813b37 394 FIXUP_X32);
5b009018
PA
395 else
396 return 0;
397}
c1e246a0 398
c1e246a0
GB
399void
400_initialize_amd64_linux_nat (void)
401{
402 struct target_ops *t;
403
404 amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
405 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
406 amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
407 amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
408
409 gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
410 == amd64_native_gregset32_num_regs);
411
412 /* Create a generic x86 GNU/Linux target. */
413 t = x86_linux_create_target ();
414
415 /* Add our register access methods. */
416 t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
417 t->to_store_registers = amd64_linux_store_inferior_registers;
418
419 /* Add the target. */
420 x86_linux_add_target (t);
421
422 /* Add our siginfo layout converter. */
423 linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
424}