1/* Native-dependent code for GNU/Linux x86-64.
2
3   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
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"
27#include "linux-nat.h"
28
29#include "gdb_assert.h"
30#include "gdb_string.h"
31#include <sys/ptrace.h>
32#include <sys/debugreg.h>
33#include <sys/syscall.h>
34#include <sys/procfs.h>
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>
44#include <sys/reg.h>
45#include "gdb_proc_service.h"
46
47/* Prototypes for supply_gregset etc.  */
48#include "gregset.h"
49
50#include "amd64-tdep.h"
51#include "i386-linux-tdep.h"
52#include "amd64-nat.h"
53
54/* Mapping between the general-purpose registers in GNU/Linux x86-64
55   `struct user' format and GDB's register cache layout.  */
56
57static int amd64_linux_gregset64_reg_offset[] =
58{
59  RAX * 8, RBX * 8,		/* %rax, %rbx */
60  RCX * 8, RDX * 8,		/* %rcx, %rdx */
61  RSI * 8, RDI * 8,		/* %rsi, %rdi */
62  RBP * 8, RSP * 8,		/* %rbp, %rsp */
63  R8 * 8, R9 * 8,		/* %r8 ... */
64  R10 * 8, R11 * 8,
65  R12 * 8, R13 * 8,
66  R14 * 8, R15 * 8,		/* ... %r15 */
67  RIP * 8, EFLAGS * 8,		/* %rip, %eflags */
68  CS * 8, SS * 8,		/* %cs, %ss */
69  DS * 8, ES * 8,		/* %ds, %es */
70  FS * 8, GS * 8		/* %fs, %gs */
71};
72
73
74/* Mapping between the general-purpose registers in GNU/Linux x86-64
75   `struct user' format and GDB's register cache layout for GNU/Linux
76   i386.
77
78   Note that most GNU/Linux x86-64 registers are 64-bit, while the
79   GNU/Linux i386 registers are all 32-bit, but since we're
80   little-endian we get away with that.  */
81
82/* From <sys/reg.h> on GNU/Linux i386.  */
83static int amd64_linux_gregset32_reg_offset[] =
84{
85  RAX * 8, RCX * 8,		/* %eax, %ecx */
86  RDX * 8, RBX * 8,		/* %edx, %ebx */
87  RSP * 8, RBP * 8,		/* %esp, %ebp */
88  RSI * 8, RDI * 8,		/* %esi, %edi */
89  RIP * 8, EFLAGS * 8,		/* %eip, %eflags */
90  CS * 8, SS * 8,		/* %cs, %ss */
91  DS * 8, ES * 8,		/* %ds, %es */
92  FS * 8, GS * 8,		/* %fs, %gs */
93  -1, -1, -1, -1, -1, -1, -1, -1,
94  -1, -1, -1, -1, -1, -1, -1, -1,
95  -1, -1, -1, -1, -1, -1, -1, -1, -1,
96  ORIG_RAX * 8			/* "orig_eax" */
97};
98
99
100/* Transfering the general-purpose registers between GDB, inferiors
101   and core files.  */
102
103/* Fill GDB's register cache with the general-purpose register values
104   in *GREGSETP.  */
105
106void
107supply_gregset (elf_gregset_t *gregsetp)
108{
109  amd64_supply_native_gregset (current_regcache, gregsetp, -1);
110}
111
112/* Fill register REGNUM (if it is a general-purpose register) in
113   *GREGSETP with the value in GDB's register cache.  If REGNUM is -1,
114   do this for all registers.  */
115
116void
117fill_gregset (elf_gregset_t *gregsetp, int regnum)
118{
119  amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
120}
121
122/* Transfering floating-point registers between GDB, inferiors and cores.  */
123
124/* Fill GDB's register cache with the floating-point and SSE register
125   values in *FPREGSETP.  */
126
127void
128supply_fpregset (elf_fpregset_t *fpregsetp)
129{
130  amd64_supply_fxsave (current_regcache, -1, fpregsetp);
131}
132
133/* Fill register REGNUM (if it is a floating-point or SSE register) in
134   *FPREGSETP with the value in GDB's register cache.  If REGNUM is
135   -1, do this for all registers.  */
136
137void
138fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
139{
140  amd64_collect_fxsave (current_regcache, regnum, fpregsetp);
141}
142
143
144/* Transferring arbitrary registers between GDB and inferior.  */
145
146/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
147   this for all registers (including the floating point and SSE
148   registers).  */
149
150void
151fetch_inferior_registers (int regnum)
152{
153  int tid;
154
155  /* GNU/Linux LWP ID's are process ID's.  */
156  tid = TIDGET (inferior_ptid);
157  if (tid == 0)
158    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
159
160  if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
161    {
162      elf_gregset_t regs;
163
164      if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
165	perror_with_name ("Couldn't get registers");
166
167      amd64_supply_native_gregset (current_regcache, &regs, -1);
168      if (regnum != -1)
169	return;
170    }
171
172  if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
173    {
174      elf_fpregset_t fpregs;
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 (current_regcache, -1, &fpregs);
180    }
181}
182
183/* Store register REGNUM back into the child process.  If REGNUM is
184   -1, do this for all registers (including the floating-point and SSE
185   registers).  */
186
187void
188store_inferior_registers (int regnum)
189{
190  int tid;
191
192  /* GNU/Linux LWP ID's are process ID's.  */
193  tid = TIDGET (inferior_ptid);
194  if (tid == 0)
195    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
196
197  if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
198    {
199      elf_gregset_t regs;
200
201      if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
202	perror_with_name ("Couldn't get registers");
203
204      amd64_collect_native_gregset (current_regcache, &regs, regnum);
205
206      if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
207	perror_with_name ("Couldn't write registers");
208
209      if (regnum != -1)
210	return;
211    }
212
213  if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
214    {
215      elf_fpregset_t fpregs;
216
217      if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
218	perror_with_name ("Couldn't get floating point status");
219
220      amd64_collect_fxsave (current_regcache, regnum, &fpregs);
221
222      if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
223	perror_with_name ("Couldn't write floating point status");
224
225      return;
226    }
227}
228
229
230static unsigned long
231amd64_linux_dr_get (int regnum)
232{
233  int tid;
234  unsigned long value;
235
236  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
237     multi-threaded processes here.  For now, pretend there is just
238     one thread.  */
239  tid = PIDGET (inferior_ptid);
240
241  /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
242     ptrace call fails breaks debugging remote targets.  The correct
243     way to fix this is to add the hardware breakpoint and watchpoint
244     stuff to the target vectore.  For now, just return zero if the
245     ptrace call fails.  */
246  errno = 0;
247  value = ptrace (PT_READ_U, tid,
248		  offsetof (struct user, u_debugreg[regnum]), 0);
249  if (errno != 0)
250#if 0
251    perror_with_name ("Couldn't read debug register");
252#else
253    return 0;
254#endif
255
256  return value;
257}
258
259static void
260amd64_linux_dr_set (int regnum, unsigned long value)
261{
262  int tid;
263
264  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
265     multi-threaded processes here.  For now, pretend there is just
266     one thread.  */
267  tid = PIDGET (inferior_ptid);
268
269  errno = 0;
270  ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
271  if (errno != 0)
272    perror_with_name ("Couldn't write debug register");
273}
274
275void
276amd64_linux_dr_set_control (unsigned long control)
277{
278  amd64_linux_dr_set (DR_CONTROL, control);
279}
280
281void
282amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
283{
284  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
285
286  amd64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
287}
288
289void
290amd64_linux_dr_reset_addr (int regnum)
291{
292  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
293
294  amd64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
295}
296
297unsigned long
298amd64_linux_dr_get_status (void)
299{
300  return amd64_linux_dr_get (DR_STATUS);
301}
302
303
304/* This function is called by libthread_db as part of its handling of
305   a request for a thread's local storage address.  */
306
307ps_err_e
308ps_get_thread_area (const struct ps_prochandle *ph,
309                    lwpid_t lwpid, int idx, void **base)
310{
311  if (gdbarch_ptr_bit (current_gdbarch) == 32)
312    {
313      /* The full structure is found in <asm-i386/ldt.h>.  The second
314	 integer is the LDT's base_address and that is used to locate
315	 the thread's local storage.  See i386-linux-nat.c more
316	 info.  */
317      unsigned int desc[4];
318
319      /* This code assumes that "int" is 32 bits and that
320	 GET_THREAD_AREA returns no more than 4 int values.  */
321      gdb_assert (sizeof (int) == 4);
322#ifndef PTRACE_GET_THREAD_AREA
323#define PTRACE_GET_THREAD_AREA 25
324#endif
325      if  (ptrace (PTRACE_GET_THREAD_AREA,
326		   lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
327	return PS_ERR;
328
329      /* Extend the value to 64 bits.  Here it's assumed that a "long"
330	 and a "void *" are the same.  */
331      (*base) = (void *) (long) desc[1];
332      return PS_OK;
333    }
334  else
335    {
336      /* This definition comes from prctl.h, but some kernels may not
337         have it.  */
338#ifndef PTRACE_ARCH_PRCTL
339#define PTRACE_ARCH_PRCTL      30
340#endif
341      /* FIXME: ezannoni-2003-07-09 see comment above about include
342	 file order.  We could be getting bogus values for these two.  */
343      gdb_assert (FS < ELF_NGREG);
344      gdb_assert (GS < ELF_NGREG);
345      switch (idx)
346	{
347	case FS:
348	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
349	    return PS_OK;
350	  break;
351	case GS:
352	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
353	    return PS_OK;
354	  break;
355	default:                   /* Should not happen.  */
356	  return PS_BADADDR;
357	}
358    }
359  return PS_ERR;               /* ptrace failed.  */
360}
361
362
363void
364child_post_startup_inferior (ptid_t ptid)
365{
366  i386_cleanup_dregs ();
367  linux_child_post_startup_inferior (ptid);
368}
369
370
371/* Provide a prototype to silence -Wmissing-prototypes.  */
372void _initialize_amd64_linux_nat (void);
373
374void
375_initialize_amd64_linux_nat (void)
376{
377  amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
378  amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
379  amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
380
381  gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
382	      == amd64_native_gregset32_num_regs);
383  gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
384	      == amd64_native_gregset64_num_regs);
385}
386