PR 10867
[deliverable/binutils-gdb.git] / gdb / amd64-linux-nat.c
CommitLineData
a4b6fc86 1/* Native-dependent code for GNU/Linux x86-64.
0a65a603 2
4c38e0a4 3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
f973ed9c 4 Free Software Foundation, Inc.
53e95fcf
JS
5 Contributed by Jiri Smid, SuSE Labs.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
53e95fcf
JS
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
53e95fcf
JS
21
22#include "defs.h"
23#include "inferior.h"
24#include "gdbcore.h"
25#include "regcache.h"
a055a187 26#include "regset.h"
4056d258 27#include "linux-nat.h"
8695c747 28#include "amd64-linux-tdep.h"
c4f35dd8 29
53e95fcf 30#include "gdb_assert.h"
30d52491 31#include "gdb_string.h"
a055a187
L
32#include "elf/common.h"
33#include <sys/uio.h>
53e95fcf
JS
34#include <sys/ptrace.h>
35#include <sys/debugreg.h>
36#include <sys/syscall.h>
37#include <sys/procfs.h>
c43af07c
EZ
38#include <asm/prctl.h>
39/* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
40 <asm/ptrace.h> because the latter redefines FS and GS for no apparent
41 reason, and those definitions don't match the ones that libpthread_db
42 uses, which come from <sys/reg.h>. */
43/* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
44 been removed from ptrace.h in the kernel. However, better safe than
45 sorry. */
46#include <asm/ptrace.h>
33a0a2ac 47#include <sys/reg.h>
c43af07c 48#include "gdb_proc_service.h"
33a0a2ac 49
c4f35dd8
MK
50/* Prototypes for supply_gregset etc. */
51#include "gregset.h"
52
9c1488cb 53#include "amd64-tdep.h"
60fac5b8
MK
54#include "i386-linux-tdep.h"
55#include "amd64-nat.h"
9bb9e8ad 56#include "i386-nat.h"
a055a187
L
57#include "i386-xstate.h"
58
59#ifndef PTRACE_GETREGSET
60#define PTRACE_GETREGSET 0x4204
61#endif
62
63#ifndef PTRACE_SETREGSET
64#define PTRACE_SETREGSET 0x4205
65#endif
66
67/* Does the current host support PTRACE_GETREGSET? */
68static int have_ptrace_getregset = -1;
60fac5b8
MK
69
70/* Mapping between the general-purpose registers in GNU/Linux x86-64
71 `struct user' format and GDB's register cache layout. */
72
430eaf2e 73static int amd64_linux_gregset64_reg_offset[] =
60fac5b8
MK
74{
75 RAX * 8, RBX * 8, /* %rax, %rbx */
76 RCX * 8, RDX * 8, /* %rcx, %rdx */
77 RSI * 8, RDI * 8, /* %rsi, %rdi */
78 RBP * 8, RSP * 8, /* %rbp, %rsp */
79 R8 * 8, R9 * 8, /* %r8 ... */
80 R10 * 8, R11 * 8,
81 R12 * 8, R13 * 8,
82 R14 * 8, R15 * 8, /* ... %r15 */
83 RIP * 8, EFLAGS * 8, /* %rip, %eflags */
af233647 84 CS * 8, SS * 8, /* %cs, %ss */
60fac5b8 85 DS * 8, ES * 8, /* %ds, %es */
8695c747
DJ
86 FS * 8, GS * 8, /* %fs, %gs */
87 -1, -1, -1, -1, -1, -1, -1, -1,
88 -1, -1, -1, -1, -1, -1, -1, -1,
89 -1, -1, -1, -1, -1, -1, -1, -1,
90 -1, -1, -1, -1, -1, -1, -1, -1, -1,
a055a187
L
91 -1, -1, -1, -1, -1, -1, -1, -1,
92 -1, -1, -1, -1, -1, -1, -1, -1,
8695c747 93 ORIG_RAX * 8
60fac5b8
MK
94};
95\f
96
97/* Mapping between the general-purpose registers in GNU/Linux x86-64
98 `struct user' format and GDB's register cache layout for GNU/Linux
99 i386.
100
101 Note that most GNU/Linux x86-64 registers are 64-bit, while the
102 GNU/Linux i386 registers are all 32-bit, but since we're
103 little-endian we get away with that. */
104
105/* From <sys/reg.h> on GNU/Linux i386. */
430eaf2e 106static int amd64_linux_gregset32_reg_offset[] =
60fac5b8 107{
f5859b4d
MK
108 RAX * 8, RCX * 8, /* %eax, %ecx */
109 RDX * 8, RBX * 8, /* %edx, %ebx */
110 RSP * 8, RBP * 8, /* %esp, %ebp */
111 RSI * 8, RDI * 8, /* %esi, %edi */
112 RIP * 8, EFLAGS * 8, /* %eip, %eflags */
113 CS * 8, SS * 8, /* %cs, %ss */
114 DS * 8, ES * 8, /* %ds, %es */
115 FS * 8, GS * 8, /* %fs, %gs */
60fac5b8
MK
116 -1, -1, -1, -1, -1, -1, -1, -1,
117 -1, -1, -1, -1, -1, -1, -1, -1,
118 -1, -1, -1, -1, -1, -1, -1, -1, -1,
a055a187 119 -1, -1, -1, -1, -1, -1, -1, -1,
f5859b4d 120 ORIG_RAX * 8 /* "orig_eax" */
60fac5b8 121};
53e95fcf
JS
122\f
123
124/* Transfering the general-purpose registers between GDB, inferiors
125 and core files. */
126
60fac5b8 127/* Fill GDB's register cache with the general-purpose register values
53e95fcf
JS
128 in *GREGSETP. */
129
130void
7f7fe91e 131supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
53e95fcf 132{
7f7fe91e 133 amd64_supply_native_gregset (regcache, gregsetp, -1);
53e95fcf
JS
134}
135
60fac5b8
MK
136/* Fill register REGNUM (if it is a general-purpose register) in
137 *GREGSETP with the value in GDB's register cache. If REGNUM is -1,
53e95fcf
JS
138 do this for all registers. */
139
140void
7f7fe91e
UW
141fill_gregset (const struct regcache *regcache,
142 elf_gregset_t *gregsetp, int regnum)
53e95fcf 143{
7f7fe91e 144 amd64_collect_native_gregset (regcache, gregsetp, regnum);
53e95fcf
JS
145}
146
53e95fcf
JS
147/* Transfering floating-point registers between GDB, inferiors and cores. */
148
60fac5b8 149/* Fill GDB's register cache with the floating-point and SSE register
c4f35dd8 150 values in *FPREGSETP. */
53e95fcf
JS
151
152void
7f7fe91e 153supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
53e95fcf 154{
7f7fe91e 155 amd64_supply_fxsave (regcache, -1, fpregsetp);
53e95fcf
JS
156}
157
8dda9770 158/* Fill register REGNUM (if it is a floating-point or SSE register) in
60fac5b8 159 *FPREGSETP with the value in GDB's register cache. If REGNUM is
c4f35dd8 160 -1, do this for all registers. */
53e95fcf
JS
161
162void
7f7fe91e
UW
163fill_fpregset (const struct regcache *regcache,
164 elf_fpregset_t *fpregsetp, int regnum)
53e95fcf 165{
7f7fe91e 166 amd64_collect_fxsave (regcache, regnum, fpregsetp);
53e95fcf 167}
53e95fcf
JS
168\f
169
170/* Transferring arbitrary registers between GDB and inferior. */
171
60fac5b8 172/* Fetch register REGNUM from the child process. If REGNUM is -1, do
53e95fcf
JS
173 this for all registers (including the floating point and SSE
174 registers). */
175
10d6c8cd 176static void
28439f5e
PA
177amd64_linux_fetch_inferior_registers (struct target_ops *ops,
178 struct regcache *regcache, int regnum)
53e95fcf 179{
f8028488 180 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
181 int tid;
182
a4b6fc86 183 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
184 tid = TIDGET (inferior_ptid);
185 if (tid == 0)
186 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf 187
f8028488 188 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 189 {
99679982
MK
190 elf_gregset_t regs;
191
192 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 193 perror_with_name (_("Couldn't get registers"));
99679982 194
56be3814 195 amd64_supply_native_gregset (regcache, &regs, -1);
60fac5b8
MK
196 if (regnum != -1)
197 return;
53e95fcf
JS
198 }
199
f8028488 200 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 201 {
99679982 202 elf_fpregset_t fpregs;
53e95fcf 203
a055a187
L
204 if (have_ptrace_getregset)
205 {
206 char xstateregs[I386_XSTATE_MAX_SIZE];
207 struct iovec iov;
208
209 iov.iov_base = xstateregs;
210 iov.iov_len = sizeof (xstateregs);
211 if (ptrace (PTRACE_GETREGSET, tid,
212 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
213 perror_with_name (_("Couldn't get extended state status"));
99679982 214
a055a187
L
215 amd64_supply_xsave (regcache, -1, xstateregs);
216 }
217 else
218 {
219 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
220 perror_with_name (_("Couldn't get floating point status"));
221
222 amd64_supply_fxsave (regcache, -1, &fpregs);
223 }
99679982 224 }
53e95fcf
JS
225}
226
60fac5b8
MK
227/* Store register REGNUM back into the child process. If REGNUM is
228 -1, do this for all registers (including the floating-point and SSE
53e95fcf 229 registers). */
c4f35dd8 230
10d6c8cd 231static void
28439f5e
PA
232amd64_linux_store_inferior_registers (struct target_ops *ops,
233 struct regcache *regcache, int regnum)
53e95fcf 234{
f8028488 235 struct gdbarch *gdbarch = get_regcache_arch (regcache);
53e95fcf
JS
236 int tid;
237
a4b6fc86 238 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
239 tid = TIDGET (inferior_ptid);
240 if (tid == 0)
241 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf 242
f8028488 243 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 244 {
99679982
MK
245 elf_gregset_t regs;
246
247 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 248 perror_with_name (_("Couldn't get registers"));
99679982 249
56be3814 250 amd64_collect_native_gregset (regcache, &regs, regnum);
99679982
MK
251
252 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
edefbb7c 253 perror_with_name (_("Couldn't write registers"));
99679982 254
60fac5b8
MK
255 if (regnum != -1)
256 return;
53e95fcf
JS
257 }
258
f8028488 259 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
53e95fcf 260 {
99679982
MK
261 elf_fpregset_t fpregs;
262
a055a187
L
263 if (have_ptrace_getregset)
264 {
265 char xstateregs[I386_XSTATE_MAX_SIZE];
266 struct iovec iov;
267
268 iov.iov_base = xstateregs;
269 iov.iov_len = sizeof (xstateregs);
270 if (ptrace (PTRACE_GETREGSET, tid,
271 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
272 perror_with_name (_("Couldn't get extended state status"));
99679982 273
a055a187
L
274 amd64_collect_xsave (regcache, regnum, xstateregs, 0);
275
276 if (ptrace (PTRACE_SETREGSET, tid,
277 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
278 perror_with_name (_("Couldn't write extended state status"));
279 }
280 else
281 {
282 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
283 perror_with_name (_("Couldn't get floating point status"));
99679982 284
a055a187 285 amd64_collect_fxsave (regcache, regnum, &fpregs);
99679982 286
a055a187
L
287 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
288 perror_with_name (_("Couldn't write floating point status"));
289 }
53e95fcf 290 }
53e95fcf
JS
291}
292\f
9f0bdab8
DJ
293/* Support for debug registers. */
294
295static unsigned long amd64_linux_dr[DR_CONTROL + 1];
53e95fcf 296
c4f35dd8 297static unsigned long
9f0bdab8 298amd64_linux_dr_get (ptid_t ptid, int regnum)
c4f35dd8
MK
299{
300 int tid;
301 unsigned long value;
53e95fcf 302
9f0bdab8
DJ
303 tid = TIDGET (ptid);
304 if (tid == 0)
305 tid = PIDGET (ptid);
53e95fcf 306
c4f35dd8
MK
307 /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
308 ptrace call fails breaks debugging remote targets. The correct
309 way to fix this is to add the hardware breakpoint and watchpoint
9f0bdab8 310 stuff to the target vector. For now, just return zero if the
c4f35dd8
MK
311 ptrace call fails. */
312 errno = 0;
9f0bdab8 313 value = ptrace (PTRACE_PEEKUSER, tid,
c4f35dd8
MK
314 offsetof (struct user, u_debugreg[regnum]), 0);
315 if (errno != 0)
316#if 0
edefbb7c 317 perror_with_name (_("Couldn't read debug register"));
c4f35dd8
MK
318#else
319 return 0;
53e95fcf
JS
320#endif
321
c4f35dd8
MK
322 return value;
323}
53e95fcf 324
a79d3c27
JK
325/* Set debug register REGNUM to VALUE in only the one LWP of PTID. */
326
53e95fcf 327static void
9f0bdab8 328amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
53e95fcf 329{
c4f35dd8 330 int tid;
53e95fcf 331
9f0bdab8
DJ
332 tid = TIDGET (ptid);
333 if (tid == 0)
334 tid = PIDGET (ptid);
53e95fcf 335
c4f35dd8 336 errno = 0;
9f0bdab8
DJ
337 ptrace (PTRACE_POKEUSER, tid,
338 offsetof (struct user, u_debugreg[regnum]), value);
c4f35dd8 339 if (errno != 0)
edefbb7c 340 perror_with_name (_("Couldn't write debug register"));
c4f35dd8 341}
53e95fcf 342
a79d3c27
JK
343/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST. */
344
9bb9e8ad 345static void
430eaf2e 346amd64_linux_dr_set_control (unsigned long control)
c4f35dd8 347{
9f0bdab8
DJ
348 struct lwp_info *lp;
349 ptid_t ptid;
350
351 amd64_linux_dr[DR_CONTROL] = control;
352 ALL_LWPS (lp, ptid)
353 amd64_linux_dr_set (ptid, DR_CONTROL, control);
c4f35dd8 354}
53e95fcf 355
a79d3c27
JK
356/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST. */
357
9bb9e8ad 358static void
430eaf2e 359amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
b7c4cbf8 360{
9f0bdab8
DJ
361 struct lwp_info *lp;
362 ptid_t ptid;
363
c4f35dd8
MK
364 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
365
9f0bdab8
DJ
366 amd64_linux_dr[DR_FIRSTADDR + regnum] = addr;
367 ALL_LWPS (lp, ptid)
368 amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
b7c4cbf8
AJ
369}
370
a79d3c27
JK
371/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST. */
372
9bb9e8ad 373static void
430eaf2e 374amd64_linux_dr_reset_addr (int regnum)
53e95fcf 375{
9f0bdab8 376 amd64_linux_dr_set_addr (regnum, 0);
53e95fcf 377}
8cfda98c 378
a79d3c27
JK
379/* Get DR_STATUS from only the one LWP of INFERIOR_PTID. */
380
9bb9e8ad 381static unsigned long
430eaf2e 382amd64_linux_dr_get_status (void)
8cfda98c 383{
9f0bdab8
DJ
384 return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
385}
386
a79d3c27
JK
387/* Unset MASK bits in DR_STATUS in all LWPs of LWP_LIST. */
388
389static void
390amd64_linux_dr_unset_status (unsigned long mask)
391{
392 struct lwp_info *lp;
393 ptid_t ptid;
394
395 ALL_LWPS (lp, ptid)
396 {
397 unsigned long value;
398
399 value = amd64_linux_dr_get (ptid, DR_STATUS);
400 value &= ~mask;
401 amd64_linux_dr_set (ptid, DR_STATUS, value);
402 }
403}
404
405
9f0bdab8
DJ
406static void
407amd64_linux_new_thread (ptid_t ptid)
408{
409 int i;
410
411 for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
412 amd64_linux_dr_set (ptid, i, amd64_linux_dr[i]);
413
414 amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
8cfda98c 415}
5bca7895 416\f
c43af07c 417
50d71875
AC
418/* This function is called by libthread_db as part of its handling of
419 a request for a thread's local storage address. */
420
5bca7895 421ps_err_e
c43af07c
EZ
422ps_get_thread_area (const struct ps_prochandle *ph,
423 lwpid_t lwpid, int idx, void **base)
424{
a97b0ac8 425 if (gdbarch_ptr_bit (target_gdbarch) == 32)
50d71875
AC
426 {
427 /* The full structure is found in <asm-i386/ldt.h>. The second
428 integer is the LDT's base_address and that is used to locate
429 the thread's local storage. See i386-linux-nat.c more
430 info. */
431 unsigned int desc[4];
432
433 /* This code assumes that "int" is 32 bits and that
434 GET_THREAD_AREA returns no more than 4 int values. */
435 gdb_assert (sizeof (int) == 4);
436#ifndef PTRACE_GET_THREAD_AREA
437#define PTRACE_GET_THREAD_AREA 25
438#endif
439 if (ptrace (PTRACE_GET_THREAD_AREA,
440 lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
441 return PS_ERR;
442
443 /* Extend the value to 64 bits. Here it's assumed that a "long"
444 and a "void *" are the same. */
445 (*base) = (void *) (long) desc[1];
446 return PS_OK;
447 }
448 else
449 {
450 /* This definition comes from prctl.h, but some kernels may not
451 have it. */
c43af07c
EZ
452#ifndef PTRACE_ARCH_PRCTL
453#define PTRACE_ARCH_PRCTL 30
454#endif
50d71875
AC
455 /* FIXME: ezannoni-2003-07-09 see comment above about include
456 file order. We could be getting bogus values for these two. */
457 gdb_assert (FS < ELF_NGREG);
458 gdb_assert (GS < ELF_NGREG);
459 switch (idx)
460 {
461 case FS:
462 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
463 return PS_OK;
464 break;
465 case GS:
466 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
467 return PS_OK;
468 break;
469 default: /* Should not happen. */
470 return PS_BADADDR;
471 }
c43af07c 472 }
b6d42148 473 return PS_ERR; /* ptrace failed. */
c43af07c 474}
5bca7895 475\f
c43af07c 476
10d6c8cd
DJ
477static void (*super_post_startup_inferior) (ptid_t ptid);
478
479static void
480amd64_linux_child_post_startup_inferior (ptid_t ptid)
4056d258
ML
481{
482 i386_cleanup_dregs ();
10d6c8cd 483 super_post_startup_inferior (ptid);
4056d258 484}
60fac5b8
MK
485\f
486
5b009018
PA
487/* When GDB is built as a 64-bit application on linux, the
488 PTRACE_GETSIGINFO data is always presented in 64-bit layout. Since
489 debugging a 32-bit inferior with a 64-bit GDB should look the same
490 as debugging it with a 32-bit GDB, we do the 32-bit <-> 64-bit
491 conversion in-place ourselves. */
492
493/* These types below (compat_*) define a siginfo type that is layout
494 compatible with the siginfo type exported by the 32-bit userspace
495 support. */
496
497typedef int compat_int_t;
498typedef unsigned int compat_uptr_t;
499
500typedef int compat_time_t;
501typedef int compat_timer_t;
502typedef int compat_clock_t;
503
504struct compat_timeval
505{
506 compat_time_t tv_sec;
507 int tv_usec;
508};
509
510typedef union compat_sigval
511{
512 compat_int_t sival_int;
513 compat_uptr_t sival_ptr;
514} compat_sigval_t;
515
516typedef struct compat_siginfo
517{
518 int si_signo;
519 int si_errno;
520 int si_code;
521
522 union
523 {
524 int _pad[((128 / sizeof (int)) - 3)];
525
526 /* kill() */
527 struct
528 {
529 unsigned int _pid;
530 unsigned int _uid;
531 } _kill;
532
533 /* POSIX.1b timers */
534 struct
535 {
536 compat_timer_t _tid;
537 int _overrun;
538 compat_sigval_t _sigval;
539 } _timer;
540
541 /* POSIX.1b signals */
542 struct
543 {
544 unsigned int _pid;
545 unsigned int _uid;
546 compat_sigval_t _sigval;
547 } _rt;
548
549 /* SIGCHLD */
550 struct
551 {
552 unsigned int _pid;
553 unsigned int _uid;
554 int _status;
555 compat_clock_t _utime;
556 compat_clock_t _stime;
557 } _sigchld;
558
559 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
560 struct
561 {
562 unsigned int _addr;
563 } _sigfault;
564
565 /* SIGPOLL */
566 struct
567 {
568 int _band;
569 int _fd;
570 } _sigpoll;
571 } _sifields;
572} compat_siginfo_t;
573
574#define cpt_si_pid _sifields._kill._pid
575#define cpt_si_uid _sifields._kill._uid
576#define cpt_si_timerid _sifields._timer._tid
577#define cpt_si_overrun _sifields._timer._overrun
578#define cpt_si_status _sifields._sigchld._status
579#define cpt_si_utime _sifields._sigchld._utime
580#define cpt_si_stime _sifields._sigchld._stime
581#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
582#define cpt_si_addr _sifields._sigfault._addr
583#define cpt_si_band _sifields._sigpoll._band
584#define cpt_si_fd _sifields._sigpoll._fd
585
14064aa2
DE
586/* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun.
587 In their place is si_timer1,si_timer2. */
588#ifndef si_timerid
589#define si_timerid si_timer1
590#endif
591#ifndef si_overrun
592#define si_overrun si_timer2
593#endif
594
5b009018
PA
595static void
596compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
597{
598 memset (to, 0, sizeof (*to));
599
600 to->si_signo = from->si_signo;
601 to->si_errno = from->si_errno;
602 to->si_code = from->si_code;
603
604 if (to->si_code < 0)
605 {
606 to->cpt_si_ptr = (intptr_t) from->si_ptr;
607 }
608 else if (to->si_code == SI_USER)
609 {
610 to->cpt_si_pid = from->si_pid;
611 to->cpt_si_uid = from->si_uid;
612 }
613 else if (to->si_code == SI_TIMER)
614 {
615 to->cpt_si_timerid = from->si_timerid;
616 to->cpt_si_overrun = from->si_overrun;
617 to->cpt_si_ptr = (intptr_t) from->si_ptr;
618 }
619 else
620 {
621 switch (to->si_signo)
622 {
623 case SIGCHLD:
624 to->cpt_si_pid = from->si_pid;
625 to->cpt_si_uid = from->si_uid;
626 to->cpt_si_status = from->si_status;
627 to->cpt_si_utime = from->si_utime;
628 to->cpt_si_stime = from->si_stime;
629 break;
630 case SIGILL:
631 case SIGFPE:
632 case SIGSEGV:
633 case SIGBUS:
634 to->cpt_si_addr = (intptr_t) from->si_addr;
635 break;
636 case SIGPOLL:
637 to->cpt_si_band = from->si_band;
638 to->cpt_si_fd = from->si_fd;
639 break;
640 default:
641 to->cpt_si_pid = from->si_pid;
642 to->cpt_si_uid = from->si_uid;
643 to->cpt_si_ptr = (intptr_t) from->si_ptr;
644 break;
645 }
646 }
647}
648
649static void
650siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
651{
652 memset (to, 0, sizeof (*to));
653
654 to->si_signo = from->si_signo;
655 to->si_errno = from->si_errno;
656 to->si_code = from->si_code;
657
658 if (to->si_code < 0)
659 {
660 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
661 }
662 else if (to->si_code == SI_USER)
663 {
664 to->si_pid = from->cpt_si_pid;
665 to->si_uid = from->cpt_si_uid;
666 }
667 else if (to->si_code == SI_TIMER)
668 {
669 to->si_timerid = from->cpt_si_timerid;
670 to->si_overrun = from->cpt_si_overrun;
671 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
672 }
673 else
674 {
675 switch (to->si_signo)
676 {
677 case SIGCHLD:
678 to->si_pid = from->cpt_si_pid;
679 to->si_uid = from->cpt_si_uid;
680 to->si_status = from->cpt_si_status;
681 to->si_utime = from->cpt_si_utime;
682 to->si_stime = from->cpt_si_stime;
683 break;
684 case SIGILL:
685 case SIGFPE:
686 case SIGSEGV:
687 case SIGBUS:
688 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
689 break;
690 case SIGPOLL:
691 to->si_band = from->cpt_si_band;
692 to->si_fd = from->cpt_si_fd;
693 break;
694 default:
695 to->si_pid = from->cpt_si_pid;
696 to->si_uid = from->cpt_si_uid;
697 to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
698 break;
699 }
700 }
701}
702
703/* Convert a native/host siginfo object, into/from the siginfo in the
704 layout of the inferiors' architecture. Returns true if any
705 conversion was done; false otherwise. If DIRECTION is 1, then copy
706 from INF to NATIVE. If DIRECTION is 0, copy from NATIVE to
707 INF. */
708
709static int
710amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
711{
712 /* Is the inferior 32-bit? If so, then do fixup the siginfo
713 object. */
714 if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32)
715 {
716 gdb_assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t));
717
718 if (direction == 0)
719 compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
720 else
721 siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
722
723 return 1;
724 }
725 else
726 return 0;
727}
728
90884b2b
L
729/* Get Linux/x86 target description from running target.
730
731 Value of CS segment register:
732 1. 64bit process: 0x33.
733 2. 32bit process: 0x23.
734 */
735
736#define AMD64_LINUX_USER64_CS 0x33
737
738static const struct target_desc *
739amd64_linux_read_description (struct target_ops *ops)
740{
741 unsigned long cs;
742 int tid;
a055a187
L
743 int is_64bit;
744 static uint64_t xcr0;
90884b2b
L
745
746 /* GNU/Linux LWP ID's are process ID's. */
747 tid = TIDGET (inferior_ptid);
748 if (tid == 0)
749 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
750
751 /* Get CS register. */
752 errno = 0;
753 cs = ptrace (PTRACE_PEEKUSER, tid,
754 offsetof (struct user_regs_struct, cs), 0);
755 if (errno != 0)
756 perror_with_name (_("Couldn't get CS register"));
757
a055a187
L
758 is_64bit = cs == AMD64_LINUX_USER64_CS;
759
760 if (have_ptrace_getregset == -1)
761 {
762 uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))];
763 struct iovec iov;
764
765 iov.iov_base = xstateregs;
766 iov.iov_len = sizeof (xstateregs);
767
768 /* Check if PTRACE_GETREGSET works. */
769 if (ptrace (PTRACE_GETREGSET, tid,
770 (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
771 have_ptrace_getregset = 0;
772 else
773 {
774 have_ptrace_getregset = 1;
775
776 /* Get XCR0 from XSAVE extended state. */
777 xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
778 / sizeof (uint64_t))];
779 }
780 }
781
782 /* Check the native XCR0 only if PTRACE_GETREGSET is available. */
783 if (have_ptrace_getregset
784 && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
785 {
786 if (is_64bit)
787 return tdesc_amd64_avx_linux;
788 else
789 return tdesc_i386_avx_linux;
790 }
90884b2b 791 else
a055a187
L
792 {
793 if (is_64bit)
794 return tdesc_amd64_linux;
795 else
796 return tdesc_i386_linux;
797 }
90884b2b
L
798}
799
60fac5b8 800/* Provide a prototype to silence -Wmissing-prototypes. */
430eaf2e 801void _initialize_amd64_linux_nat (void);
60fac5b8
MK
802
803void
430eaf2e 804_initialize_amd64_linux_nat (void)
60fac5b8 805{
10d6c8cd
DJ
806 struct target_ops *t;
807
430eaf2e 808 amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
60fac5b8 809 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
430eaf2e 810 amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
8695c747 811 amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
60fac5b8 812
430eaf2e 813 gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
60fac5b8 814 == amd64_native_gregset32_num_regs);
430eaf2e 815 gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
60fac5b8 816 == amd64_native_gregset64_num_regs);
10d6c8cd
DJ
817
818 /* Fill in the generic GNU/Linux methods. */
819 t = linux_target ();
820
c03374d5
DJ
821 i386_use_watchpoints (t);
822
9bb9e8ad
PM
823 i386_dr_low.set_control = amd64_linux_dr_set_control;
824 i386_dr_low.set_addr = amd64_linux_dr_set_addr;
825 i386_dr_low.reset_addr = amd64_linux_dr_reset_addr;
826 i386_dr_low.get_status = amd64_linux_dr_get_status;
a79d3c27 827 i386_dr_low.unset_status = amd64_linux_dr_unset_status;
9bb9e8ad
PM
828 i386_set_debug_register_length (8);
829
10d6c8cd
DJ
830 /* Override the GNU/Linux inferior startup hook. */
831 super_post_startup_inferior = t->to_post_startup_inferior;
832 t->to_post_startup_inferior = amd64_linux_child_post_startup_inferior;
833
834 /* Add our register access methods. */
835 t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
836 t->to_store_registers = amd64_linux_store_inferior_registers;
837
90884b2b
L
838 t->to_read_description = amd64_linux_read_description;
839
10d6c8cd 840 /* Register the target. */
f973ed9c 841 linux_nat_add_target (t);
9f0bdab8 842 linux_nat_set_new_thread (t, amd64_linux_new_thread);
5b009018 843 linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
60fac5b8 844}
This page took 0.775773 seconds and 4 git commands to generate.