]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/x86-64-linux-nat.c
2003-07-17 Elena Zannoni <ezannoni@redhat.com>
[thirdparty/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"
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
50#include "x86-64-tdep.h"
eba29c8c 51#include "x86-64-linux-tdep.h"
53e95fcf 52
c4f35dd8
MK
53/* Which ptrace request retrieves which registers?
54 These apply to the corresponding SET requests as well. */
53e95fcf
JS
55
56#define GETREGS_SUPPLIES(regno) \
c4f35dd8
MK
57 (0 <= (regno) && (regno) < X86_64_NUM_GREGS)
58
53e95fcf
JS
59#define GETFPREGS_SUPPLIES(regno) \
60 (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
53e95fcf
JS
61\f
62
63/* Transfering the general-purpose registers between GDB, inferiors
64 and core files. */
65
66/* Fill GDB's register array with the general-purpose register values
67 in *GREGSETP. */
68
69void
c4f35dd8 70supply_gregset (elf_gregset_t *gregsetp)
53e95fcf 71{
eba29c8c 72 x86_64_linux_supply_gregset ((char *) gregsetp);
53e95fcf
JS
73}
74
75/* Fill register REGNO (if it is a general-purpose register) in
76 *GREGSETPS with the value in GDB's register array. If REGNO is -1,
77 do this for all registers. */
78
79void
c4f35dd8 80fill_gregset (elf_gregset_t *gregsetp, int regno)
53e95fcf 81{
eba29c8c 82 x86_64_linux_fill_gregset ((char *) gregsetp, regno);
53e95fcf
JS
83}
84
85/* Fetch all general-purpose registers from process/thread TID and
86 store their values in GDB's register array. */
87
88static void
89fetch_regs (int tid)
90{
91 elf_gregset_t regs;
92
93 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
7b3fabf0 94 perror_with_name ("Couldn't get registers");
53e95fcf
JS
95
96 supply_gregset (&regs);
97}
98
99/* Store all valid general-purpose registers in GDB's register array
100 into the process/thread specified by TID. */
101
102static void
103store_regs (int tid, int regno)
104{
105 elf_gregset_t regs;
106
107 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
108 perror_with_name ("Couldn't get registers");
109
110 fill_gregset (&regs, regno);
111
112 if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
113 perror_with_name ("Couldn't write registers");
114}
115\f
116
117/* Transfering floating-point registers between GDB, inferiors and cores. */
118
8dda9770 119/* Fill GDB's register array with the floating-point and SSE register
c4f35dd8 120 values in *FPREGSETP. */
53e95fcf
JS
121
122void
c4f35dd8 123supply_fpregset (elf_fpregset_t *fpregsetp)
53e95fcf 124{
c4f35dd8 125 x86_64_supply_fxsave ((char *) fpregsetp);
53e95fcf
JS
126}
127
8dda9770 128/* Fill register REGNUM (if it is a floating-point or SSE register) in
c4f35dd8
MK
129 *FPREGSETP with the value in GDB's register array. If REGNUM is
130 -1, do this for all registers. */
53e95fcf
JS
131
132void
c4f35dd8 133fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
53e95fcf 134{
c4f35dd8 135 x86_64_fill_fxsave ((char *) fpregsetp, regnum);
53e95fcf
JS
136}
137
138/* Fetch all floating-point registers from process/thread TID and store
139 thier values in GDB's register array. */
140
141static void
142fetch_fpregs (int tid)
143{
144 elf_fpregset_t fpregs;
145
146 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
147 perror_with_name ("Couldn't get floating point status");
148
149 supply_fpregset (&fpregs);
150}
151
152/* Store all valid floating-point registers in GDB's register array
153 into the process/thread specified by TID. */
154
155static void
156store_fpregs (int tid, int regno)
157{
158 elf_fpregset_t fpregs;
159
160 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
161 perror_with_name ("Couldn't get floating point status");
162
163 fill_fpregset (&fpregs, regno);
164
165 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
166 perror_with_name ("Couldn't write floating point status");
167}
168\f
169
170/* Transferring arbitrary registers between GDB and inferior. */
171
172/* Fetch register REGNO from the child process. If REGNO is -1, do
173 this for all registers (including the floating point and SSE
174 registers). */
175
176void
177fetch_inferior_registers (int regno)
178{
179 int tid;
180
a4b6fc86 181 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
182 tid = TIDGET (inferior_ptid);
183 if (tid == 0)
184 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf
JS
185
186 if (regno == -1)
187 {
188 fetch_regs (tid);
189 fetch_fpregs (tid);
190 return;
191 }
192
193 if (GETREGS_SUPPLIES (regno))
194 {
195 fetch_regs (tid);
196 return;
197 }
198
199 if (GETFPREGS_SUPPLIES (regno))
200 {
201 fetch_fpregs (tid);
202 return;
203 }
204
205 internal_error (__FILE__, __LINE__,
206 "Got request for bad register number %d.", regno);
207}
208
209/* Store register REGNO back into the child process. If REGNO is -1,
c4f35dd8 210 do this for all registers (including the floating-point and SSE
53e95fcf 211 registers). */
c4f35dd8 212
53e95fcf
JS
213void
214store_inferior_registers (int regno)
215{
216 int tid;
217
a4b6fc86 218 /* GNU/Linux LWP ID's are process ID's. */
c4f35dd8
MK
219 tid = TIDGET (inferior_ptid);
220 if (tid == 0)
221 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
53e95fcf
JS
222
223 if (regno == -1)
224 {
225 store_regs (tid, regno);
226 store_fpregs (tid, regno);
227 return;
228 }
229
230 if (GETREGS_SUPPLIES (regno))
231 {
232 store_regs (tid, regno);
233 return;
234 }
235
236 if (GETFPREGS_SUPPLIES (regno))
237 {
238 store_fpregs (tid, regno);
239 return;
240 }
241
242 internal_error (__FILE__, __LINE__,
243 "Got request to store bad register number %d.", regno);
244}
245\f
246
c4f35dd8
MK
247static unsigned long
248x86_64_linux_dr_get (int regnum)
249{
250 int tid;
251 unsigned long value;
53e95fcf 252
c4f35dd8
MK
253 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
254 multi-threaded processes here. For now, pretend there is just
255 one thread. */
256 tid = PIDGET (inferior_ptid);
53e95fcf 257
c4f35dd8
MK
258 /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
259 ptrace call fails breaks debugging remote targets. The correct
260 way to fix this is to add the hardware breakpoint and watchpoint
261 stuff to the target vectore. For now, just return zero if the
262 ptrace call fails. */
263 errno = 0;
264 value = ptrace (PT_READ_U, tid,
265 offsetof (struct user, u_debugreg[regnum]), 0);
266 if (errno != 0)
267#if 0
268 perror_with_name ("Couldn't read debug register");
269#else
270 return 0;
53e95fcf
JS
271#endif
272
c4f35dd8
MK
273 return value;
274}
53e95fcf
JS
275
276static void
c4f35dd8 277x86_64_linux_dr_set (int regnum, unsigned long value)
53e95fcf 278{
c4f35dd8 279 int tid;
53e95fcf 280
c4f35dd8
MK
281 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
282 multi-threaded processes here. For now, pretend there is just
283 one thread. */
284 tid = PIDGET (inferior_ptid);
53e95fcf 285
c4f35dd8
MK
286 errno = 0;
287 ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
288 if (errno != 0)
289 perror_with_name ("Couldn't write debug register");
290}
53e95fcf 291
c4f35dd8
MK
292void
293x86_64_linux_dr_set_control (unsigned long control)
294{
295 x86_64_linux_dr_set (DR_CONTROL, control);
296}
53e95fcf 297
c4f35dd8
MK
298void
299x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
b7c4cbf8 300{
c4f35dd8
MK
301 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
302
303 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
b7c4cbf8
AJ
304}
305
53e95fcf 306void
c4f35dd8 307x86_64_linux_dr_reset_addr (int regnum)
53e95fcf 308{
c4f35dd8
MK
309 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
310
311 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
53e95fcf 312}
8cfda98c 313
c4f35dd8
MK
314unsigned long
315x86_64_linux_dr_get_status (void)
8cfda98c 316{
c4f35dd8 317 return x86_64_linux_dr_get (DR_STATUS);
8cfda98c 318}
c43af07c
EZ
319
320extern ps_err_e
321ps_get_thread_area (const struct ps_prochandle *ph,
322 lwpid_t lwpid, int idx, void **base)
323{
324
325/* This definition comes from prctl.h, but some kernels may not have it. */
326#ifndef PTRACE_ARCH_PRCTL
327#define PTRACE_ARCH_PRCTL 30
328#endif
329
330 /* FIXME: ezannoni-2003-07-09 see comment above about include file order.
331 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:
337 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
338 return PS_OK;
339 break;
340 case GS:
341 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
342 return PS_OK;
343 break;
344 default: /* Should not happen. */
345 return PS_BADADDR;
346 }
347 return PS_ERR; /* ptrace failed. */
348}
349