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