* alphafbsd-tdep.c (alphafbsd_sigcontext_addr): Use
[deliverable/binutils-gdb.git] / gdb / x86-64-linux-nat.c
CommitLineData
a4b6fc86 1/* Native-dependent code for GNU/Linux x86-64.
0a65a603 2
1bac305b 3 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
0a65a603 4
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
11 the Free Software Foundation; either version 2 of the License, or
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
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24#include "defs.h"
25#include "inferior.h"
26#include "gdbcore.h"
27#include "regcache.h"
4056d258 28#include "linux-nat.h"
c4f35dd8 29
53e95fcf 30#include "gdb_assert.h"
30d52491 31#include "gdb_string.h"
53e95fcf
JS
32#include <sys/ptrace.h>
33#include <sys/debugreg.h>
34#include <sys/syscall.h>
35#include <sys/procfs.h>
c43af07c
EZ
36#include <asm/prctl.h>
37/* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
38 <asm/ptrace.h> because the latter redefines FS and GS for no apparent
39 reason, and those definitions don't match the ones that libpthread_db
40 uses, which come from <sys/reg.h>. */
41/* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
42 been removed from ptrace.h in the kernel. However, better safe than
43 sorry. */
44#include <asm/ptrace.h>
33a0a2ac 45#include <sys/reg.h>
c43af07c 46#include "gdb_proc_service.h"
33a0a2ac 47
c4f35dd8
MK
48/* Prototypes for supply_gregset etc. */
49#include "gregset.h"
50
51#include "x86-64-tdep.h"
eba29c8c 52#include "x86-64-linux-tdep.h"
60fac5b8
MK
53#include "i386-linux-tdep.h"
54#include "amd64-nat.h"
55
56/* Mapping between the general-purpose registers in GNU/Linux x86-64
57 `struct user' format and GDB's register cache layout. */
58
59static int x86_64_linux_gregset64_reg_offset[] =
60{
61 RAX * 8, RBX * 8, /* %rax, %rbx */
62 RCX * 8, RDX * 8, /* %rcx, %rdx */
63 RSI * 8, RDI * 8, /* %rsi, %rdi */
64 RBP * 8, RSP * 8, /* %rbp, %rsp */
65 R8 * 8, R9 * 8, /* %r8 ... */
66 R10 * 8, R11 * 8,
67 R12 * 8, R13 * 8,
68 R14 * 8, R15 * 8, /* ... %r15 */
69 RIP * 8, EFLAGS * 8, /* %rip, %eflags */
70 DS * 8, ES * 8, /* %ds, %es */
71 FS * 8, GS * 8 /* %fs, %gs */
72};
73\f
74
75/* Mapping between the general-purpose registers in GNU/Linux x86-64
76 `struct user' format and GDB's register cache layout for GNU/Linux
77 i386.
78
79 Note that most GNU/Linux x86-64 registers are 64-bit, while the
80 GNU/Linux i386 registers are all 32-bit, but since we're
81 little-endian we get away with that. */
82
83/* From <sys/reg.h> on GNU/Linux i386. */
84static int x86_64_linux_gregset32_reg_offset[] =
85{
86 10 * 8, 11 * 8, /* %eax, %ecx */
87 12 * 8, 13 * 8, /* %edx, %ebx */
88 19 * 8, 4 * 8, /* %esp, %ebp */
89 13 * 8, 14 * 8, /* %esi, %edi */
90 16 * 8, 18 * 8, /* %eip, %eflags */
91 17 * 8, 20 * 8, /* %cs, %ss */
92 23 * 8, 24 * 8, /* %ds, %es */
93 25 * 4, 26 * 4, /* %fs, %gs */
94 -1, -1, -1, -1, -1, -1, -1, -1,
95 -1, -1, -1, -1, -1, -1, -1, -1,
96 -1, -1, -1, -1, -1, -1, -1, -1, -1,
97 15 * 8 /* "orig_eax" */
98};
53e95fcf 99
c4f35dd8
MK
100/* Which ptrace request retrieves which registers?
101 These apply to the corresponding SET requests as well. */
53e95fcf 102
53e95fcf
JS
103#define GETFPREGS_SUPPLIES(regno) \
104 (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
53e95fcf
JS
105\f
106
107/* Transfering the general-purpose registers between GDB, inferiors
108 and core files. */
109
60fac5b8 110/* Fill GDB's register cache with the general-purpose register values
53e95fcf
JS
111 in *GREGSETP. */
112
113void
c4f35dd8 114supply_gregset (elf_gregset_t *gregsetp)
53e95fcf 115{
60fac5b8 116 amd64_supply_native_gregset (current_regcache, gregsetp, -1);
53e95fcf
JS
117}
118
60fac5b8
MK
119/* Fill register REGNUM (if it is a general-purpose register) in
120 *GREGSETP with the value in GDB's register cache. If REGNUM is -1,
53e95fcf
JS
121 do this for all registers. */
122
123void
60fac5b8 124fill_gregset (elf_gregset_t *gregsetp, int regnum)
53e95fcf 125{
60fac5b8 126 amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
53e95fcf
JS
127}
128
129/* Fetch all general-purpose registers from process/thread TID and
60fac5b8 130 store their values in GDB's register cache. */
53e95fcf
JS
131
132static void
133fetch_regs (int tid)
134{
135 elf_gregset_t regs;
136
137 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
7b3fabf0 138 perror_with_name ("Couldn't get registers");
53e95fcf
JS
139
140 supply_gregset (&regs);
141}
142
60fac5b8 143/* Store all valid general-purpose registers in GDB's register cache
53e95fcf
JS
144 into the process/thread specified by TID. */
145
146static void
60fac5b8 147store_regs (int tid, int regnum)
53e95fcf
JS
148{
149 elf_gregset_t regs;
150
151 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
152 perror_with_name ("Couldn't get registers");
153
60fac5b8 154 fill_gregset (&regs, regnum);
53e95fcf
JS
155
156 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
157 perror_with_name ("Couldn't write registers");
158}
159\f
160
161/* Transfering floating-point registers between GDB, inferiors and cores. */
162
60fac5b8 163/* Fill GDB's register cache with the floating-point and SSE register
c4f35dd8 164 values in *FPREGSETP. */
53e95fcf
JS
165
166void
c4f35dd8 167supply_fpregset (elf_fpregset_t *fpregsetp)
53e95fcf 168{
0485f6ad 169 x86_64_supply_fxsave ((const char *) fpregsetp, -1);
53e95fcf
JS
170}
171
8dda9770 172/* Fill register REGNUM (if it is a floating-point or SSE register) in
60fac5b8 173 *FPREGSETP with the value in GDB's register cache. If REGNUM is
c4f35dd8 174 -1, do this for all registers. */
53e95fcf
JS
175
176void
c4f35dd8 177fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
53e95fcf 178{
c4f35dd8 179 x86_64_fill_fxsave ((char *) fpregsetp, regnum);
53e95fcf
JS
180}
181
182/* Fetch all floating-point registers from process/thread TID and store
60fac5b8 183 thier values in GDB's register cache. */
53e95fcf
JS
184
185static void
186fetch_fpregs (int tid)
187{
188 elf_fpregset_t fpregs;
189
190 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
191 perror_with_name ("Couldn't get floating point status");
192
193 supply_fpregset (&fpregs);
194}
195
60fac5b8 196/* Store all valid floating-point registers in GDB's register cache
53e95fcf
JS
197 into the process/thread specified by TID. */
198
199static void
60fac5b8 200store_fpregs (int tid, int regnum)
53e95fcf
JS
201{
202 elf_fpregset_t fpregs;
203
204 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
205 perror_with_name ("Couldn't get floating point status");
206
60fac5b8 207 fill_fpregset (&fpregs, regnum);
53e95fcf
JS
208
209 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
210 perror_with_name ("Couldn't write floating point status");
211}
212\f
213
214/* Transferring arbitrary registers between GDB and inferior. */
215
60fac5b8 216/* Fetch register REGNUM from the child process. If REGNUM is -1, do
53e95fcf
JS
217 this for all registers (including the floating point and SSE
218 registers). */
219
220void
60fac5b8 221fetch_inferior_registers (int regnum)
53e95fcf
JS
222{
223 int tid;
224
a4b6fc86 225 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
226 tid = TIDGET (inferior_ptid);
227 if (tid == 0)
228 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf 229
60fac5b8 230 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
53e95fcf
JS
231 {
232 fetch_regs (tid);
60fac5b8
MK
233 if (regnum != -1)
234 return;
53e95fcf
JS
235 }
236
60fac5b8 237 if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
53e95fcf
JS
238 {
239 fetch_fpregs (tid);
240 return;
241 }
242
243 internal_error (__FILE__, __LINE__,
60fac5b8 244 "Got request for bad register number %d.", regnum);
53e95fcf
JS
245}
246
60fac5b8
MK
247/* Store register REGNUM back into the child process. If REGNUM is
248 -1, do this for all registers (including the floating-point and SSE
53e95fcf 249 registers). */
c4f35dd8 250
53e95fcf 251void
60fac5b8 252store_inferior_registers (int regnum)
53e95fcf
JS
253{
254 int tid;
255
a4b6fc86 256 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
257 tid = TIDGET (inferior_ptid);
258 if (tid == 0)
259 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf 260
60fac5b8 261 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
53e95fcf 262 {
60fac5b8
MK
263 store_regs (tid, regnum);
264 if (regnum != -1)
265 return;
53e95fcf
JS
266 }
267
60fac5b8 268 if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
53e95fcf 269 {
60fac5b8 270 store_fpregs (tid, regnum);
53e95fcf
JS
271 return;
272 }
273
274 internal_error (__FILE__, __LINE__,
60fac5b8 275 "Got request to store bad register number %d.", regnum);
53e95fcf
JS
276}
277\f
278
c4f35dd8
MK
279static unsigned long
280x86_64_linux_dr_get (int regnum)
281{
282 int tid;
283 unsigned long value;
53e95fcf 284
c4f35dd8
MK
285 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
286 multi-threaded processes here. For now, pretend there is just
287 one thread. */
288 tid = PIDGET (inferior_ptid);
53e95fcf 289
c4f35dd8
MK
290 /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
291 ptrace call fails breaks debugging remote targets. The correct
292 way to fix this is to add the hardware breakpoint and watchpoint
293 stuff to the target vectore. For now, just return zero if the
294 ptrace call fails. */
295 errno = 0;
296 value = ptrace (PT_READ_U, tid,
297 offsetof (struct user, u_debugreg[regnum]), 0);
298 if (errno != 0)
299#if 0
300 perror_with_name ("Couldn't read debug register");
301#else
302 return 0;
53e95fcf
JS
303#endif
304
c4f35dd8
MK
305 return value;
306}
53e95fcf
JS
307
308static void
c4f35dd8 309x86_64_linux_dr_set (int regnum, unsigned long value)
53e95fcf 310{
c4f35dd8 311 int tid;
53e95fcf 312
c4f35dd8
MK
313 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
314 multi-threaded processes here. For now, pretend there is just
315 one thread. */
316 tid = PIDGET (inferior_ptid);
53e95fcf 317
c4f35dd8
MK
318 errno = 0;
319 ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
320 if (errno != 0)
321 perror_with_name ("Couldn't write debug register");
322}
53e95fcf 323
c4f35dd8
MK
324void
325x86_64_linux_dr_set_control (unsigned long control)
326{
327 x86_64_linux_dr_set (DR_CONTROL, control);
328}
53e95fcf 329
c4f35dd8
MK
330void
331x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
b7c4cbf8 332{
c4f35dd8
MK
333 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
334
335 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
b7c4cbf8
AJ
336}
337
53e95fcf 338void
c4f35dd8 339x86_64_linux_dr_reset_addr (int regnum)
53e95fcf 340{
c4f35dd8
MK
341 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
342
343 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
53e95fcf 344}
8cfda98c 345
c4f35dd8
MK
346unsigned long
347x86_64_linux_dr_get_status (void)
8cfda98c 348{
c4f35dd8 349 return x86_64_linux_dr_get (DR_STATUS);
8cfda98c 350}
c43af07c
EZ
351
352extern ps_err_e
353ps_get_thread_area (const struct ps_prochandle *ph,
354 lwpid_t lwpid, int idx, void **base)
355{
356
357/* This definition comes from prctl.h, but some kernels may not have it. */
358#ifndef PTRACE_ARCH_PRCTL
359#define PTRACE_ARCH_PRCTL 30
360#endif
361
362 /* FIXME: ezannoni-2003-07-09 see comment above about include file order.
363 We could be getting bogus values for these two. */
364 gdb_assert (FS < ELF_NGREG);
365 gdb_assert (GS < ELF_NGREG);
366 switch (idx)
367 {
368 case FS:
369 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
370 return PS_OK;
371 break;
372 case GS:
373 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
374 return PS_OK;
375 break;
376 default: /* Should not happen. */
377 return PS_BADADDR;
378 }
379 return PS_ERR; /* ptrace failed. */
380}
381
4056d258
ML
382void
383child_post_startup_inferior (ptid_t ptid)
384{
385 i386_cleanup_dregs ();
386 linux_child_post_startup_inferior (ptid);
387}
60fac5b8
MK
388\f
389
390/* Provide a prototype to silence -Wmissing-prototypes. */
391void _initialize_x86_64_linux_nat (void);
392
393void
394_initialize_x86_64_linux_nat (void)
395{
396 amd64_native_gregset32_reg_offset = x86_64_linux_gregset32_reg_offset;
397 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
398 amd64_native_gregset64_reg_offset = x86_64_linux_gregset64_reg_offset;
399
400 gdb_assert (ARRAY_SIZE (x86_64_linux_gregset32_reg_offset)
401 == amd64_native_gregset32_num_regs);
402 gdb_assert (ARRAY_SIZE (x86_64_linux_gregset64_reg_offset)
403 == amd64_native_gregset64_num_regs);
404}
This page took 0.381929 seconds and 4 git commands to generate.