* amd64-tdep.h (amd64_fill_fxsave): Remove prototype.
[deliverable/binutils-gdb.git] / gdb / amd64-linux-nat.c
CommitLineData
a4b6fc86 1/* Native-dependent code for GNU/Linux x86-64.
0a65a603 2
af233647 3 Copyright 2001, 2002, 2003, 2004 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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
24#include "inferior.h"
25#include "gdbcore.h"
26#include "regcache.h"
4056d258 27#include "linux-nat.h"
c4f35dd8 28
53e95fcf 29#include "gdb_assert.h"
30d52491 30#include "gdb_string.h"
53e95fcf
JS
31#include <sys/ptrace.h>
32#include <sys/debugreg.h>
33#include <sys/syscall.h>
34#include <sys/procfs.h>
c43af07c
EZ
35#include <asm/prctl.h>
36/* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
37 <asm/ptrace.h> because the latter redefines FS and GS for no apparent
38 reason, and those definitions don't match the ones that libpthread_db
39 uses, which come from <sys/reg.h>. */
40/* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
41 been removed from ptrace.h in the kernel. However, better safe than
42 sorry. */
43#include <asm/ptrace.h>
33a0a2ac 44#include <sys/reg.h>
c43af07c 45#include "gdb_proc_service.h"
33a0a2ac 46
c4f35dd8
MK
47/* Prototypes for supply_gregset etc. */
48#include "gregset.h"
49
9c1488cb
MK
50#include "amd64-tdep.h"
51#include "amd64-linux-tdep.h"
60fac5b8
MK
52#include "i386-linux-tdep.h"
53#include "amd64-nat.h"
54
55/* Mapping between the general-purpose registers in GNU/Linux x86-64
56 `struct user' format and GDB's register cache layout. */
57
430eaf2e 58static int amd64_linux_gregset64_reg_offset[] =
60fac5b8
MK
59{
60 RAX * 8, RBX * 8, /* %rax, %rbx */
61 RCX * 8, RDX * 8, /* %rcx, %rdx */
62 RSI * 8, RDI * 8, /* %rsi, %rdi */
63 RBP * 8, RSP * 8, /* %rbp, %rsp */
64 R8 * 8, R9 * 8, /* %r8 ... */
65 R10 * 8, R11 * 8,
66 R12 * 8, R13 * 8,
67 R14 * 8, R15 * 8, /* ... %r15 */
68 RIP * 8, EFLAGS * 8, /* %rip, %eflags */
af233647 69 CS * 8, SS * 8, /* %cs, %ss */
60fac5b8
MK
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. */
430eaf2e 84static int amd64_linux_gregset32_reg_offset[] =
60fac5b8 85{
f5859b4d
MK
86 RAX * 8, RCX * 8, /* %eax, %ecx */
87 RDX * 8, RBX * 8, /* %edx, %ebx */
88 RSP * 8, RBP * 8, /* %esp, %ebp */
89 RSI * 8, RDI * 8, /* %esi, %edi */
90 RIP * 8, EFLAGS * 8, /* %eip, %eflags */
91 CS * 8, SS * 8, /* %cs, %ss */
92 DS * 8, ES * 8, /* %ds, %es */
93 FS * 8, GS * 8, /* %fs, %gs */
60fac5b8
MK
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,
f5859b4d 97 ORIG_RAX * 8 /* "orig_eax" */
60fac5b8 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{
90f90721 169 amd64_supply_fxsave (current_regcache, -1, fpregsetp);
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{
722d18c2 179 amd64_collect_fxsave (current_regcache, regnum, fpregsetp);
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 279static unsigned long
430eaf2e 280amd64_linux_dr_get (int regnum)
c4f35dd8
MK
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
430eaf2e 309amd64_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 324void
430eaf2e 325amd64_linux_dr_set_control (unsigned long control)
c4f35dd8 326{
430eaf2e 327 amd64_linux_dr_set (DR_CONTROL, control);
c4f35dd8 328}
53e95fcf 329
c4f35dd8 330void
430eaf2e 331amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
b7c4cbf8 332{
c4f35dd8
MK
333 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
334
430eaf2e 335 amd64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
b7c4cbf8
AJ
336}
337
53e95fcf 338void
430eaf2e 339amd64_linux_dr_reset_addr (int regnum)
53e95fcf 340{
c4f35dd8
MK
341 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
342
430eaf2e 343 amd64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
53e95fcf 344}
8cfda98c 345
c4f35dd8 346unsigned long
430eaf2e 347amd64_linux_dr_get_status (void)
8cfda98c 348{
430eaf2e 349 return amd64_linux_dr_get (DR_STATUS);
8cfda98c 350}
5bca7895 351\f
c43af07c 352
50d71875
AC
353/* This function is called by libthread_db as part of its handling of
354 a request for a thread's local storage address. */
355
5bca7895 356ps_err_e
c43af07c
EZ
357ps_get_thread_area (const struct ps_prochandle *ph,
358 lwpid_t lwpid, int idx, void **base)
359{
50d71875
AC
360 if (gdbarch_ptr_bit (current_gdbarch) == 32)
361 {
362 /* The full structure is found in <asm-i386/ldt.h>. The second
363 integer is the LDT's base_address and that is used to locate
364 the thread's local storage. See i386-linux-nat.c more
365 info. */
366 unsigned int desc[4];
367
368 /* This code assumes that "int" is 32 bits and that
369 GET_THREAD_AREA returns no more than 4 int values. */
370 gdb_assert (sizeof (int) == 4);
371#ifndef PTRACE_GET_THREAD_AREA
372#define PTRACE_GET_THREAD_AREA 25
373#endif
374 if (ptrace (PTRACE_GET_THREAD_AREA,
375 lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
376 return PS_ERR;
377
378 /* Extend the value to 64 bits. Here it's assumed that a "long"
379 and a "void *" are the same. */
380 (*base) = (void *) (long) desc[1];
381 return PS_OK;
382 }
383 else
384 {
385 /* This definition comes from prctl.h, but some kernels may not
386 have it. */
c43af07c
EZ
387#ifndef PTRACE_ARCH_PRCTL
388#define PTRACE_ARCH_PRCTL 30
389#endif
50d71875
AC
390 /* FIXME: ezannoni-2003-07-09 see comment above about include
391 file order. We could be getting bogus values for these two. */
392 gdb_assert (FS < ELF_NGREG);
393 gdb_assert (GS < ELF_NGREG);
394 switch (idx)
395 {
396 case FS:
397 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
398 return PS_OK;
399 break;
400 case GS:
401 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
402 return PS_OK;
403 break;
404 default: /* Should not happen. */
405 return PS_BADADDR;
406 }
c43af07c 407 }
b6d42148 408 return PS_ERR; /* ptrace failed. */
c43af07c 409}
5bca7895 410\f
c43af07c 411
4056d258
ML
412void
413child_post_startup_inferior (ptid_t ptid)
414{
415 i386_cleanup_dregs ();
416 linux_child_post_startup_inferior (ptid);
417}
60fac5b8
MK
418\f
419
420/* Provide a prototype to silence -Wmissing-prototypes. */
430eaf2e 421void _initialize_amd64_linux_nat (void);
60fac5b8
MK
422
423void
430eaf2e 424_initialize_amd64_linux_nat (void)
60fac5b8 425{
430eaf2e 426 amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
60fac5b8 427 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
430eaf2e 428 amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
60fac5b8 429
430eaf2e 430 gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
60fac5b8 431 == amd64_native_gregset32_num_regs);
430eaf2e 432 gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
60fac5b8
MK
433 == amd64_native_gregset64_num_regs);
434}
This page took 0.396878 seconds and 4 git commands to generate.