2003-07-17 Elena Zannoni <ezannoni@redhat.com>
[deliverable/binutils-gdb.git] / gdb / x86-64-linux-nat.c
1 /* Native-dependent code for GNU/Linux x86-64.
2
3 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
4
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"
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 "x86-64-tdep.h"
51 #include "x86-64-linux-tdep.h"
52
53 /* Which ptrace request retrieves which registers?
54 These apply to the corresponding SET requests as well. */
55
56 #define GETREGS_SUPPLIES(regno) \
57 (0 <= (regno) && (regno) < X86_64_NUM_GREGS)
58
59 #define GETFPREGS_SUPPLIES(regno) \
60 (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
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
69 void
70 supply_gregset (elf_gregset_t *gregsetp)
71 {
72 x86_64_linux_supply_gregset ((char *) gregsetp);
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
79 void
80 fill_gregset (elf_gregset_t *gregsetp, int regno)
81 {
82 x86_64_linux_fill_gregset ((char *) gregsetp, regno);
83 }
84
85 /* Fetch all general-purpose registers from process/thread TID and
86 store their values in GDB's register array. */
87
88 static void
89 fetch_regs (int tid)
90 {
91 elf_gregset_t regs;
92
93 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
94 perror_with_name ("Couldn't get registers");
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
102 static void
103 store_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
119 /* Fill GDB's register array with the floating-point and SSE register
120 values in *FPREGSETP. */
121
122 void
123 supply_fpregset (elf_fpregset_t *fpregsetp)
124 {
125 x86_64_supply_fxsave ((char *) fpregsetp);
126 }
127
128 /* Fill register REGNUM (if it is a floating-point or SSE register) in
129 *FPREGSETP with the value in GDB's register array. If REGNUM is
130 -1, do this for all registers. */
131
132 void
133 fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
134 {
135 x86_64_fill_fxsave ((char *) fpregsetp, regnum);
136 }
137
138 /* Fetch all floating-point registers from process/thread TID and store
139 thier values in GDB's register array. */
140
141 static void
142 fetch_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
155 static void
156 store_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
176 void
177 fetch_inferior_registers (int regno)
178 {
179 int tid;
180
181 /* GNU/Linux LWP ID's are process ID's. */
182 tid = TIDGET (inferior_ptid);
183 if (tid == 0)
184 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
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,
210 do this for all registers (including the floating-point and SSE
211 registers). */
212
213 void
214 store_inferior_registers (int regno)
215 {
216 int tid;
217
218 /* GNU/Linux LWP ID's are process ID's. */
219 tid = TIDGET (inferior_ptid);
220 if (tid == 0)
221 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
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
247 static unsigned long
248 x86_64_linux_dr_get (int regnum)
249 {
250 int tid;
251 unsigned long value;
252
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);
257
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;
271 #endif
272
273 return value;
274 }
275
276 static void
277 x86_64_linux_dr_set (int regnum, unsigned long value)
278 {
279 int tid;
280
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);
285
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 }
291
292 void
293 x86_64_linux_dr_set_control (unsigned long control)
294 {
295 x86_64_linux_dr_set (DR_CONTROL, control);
296 }
297
298 void
299 x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
300 {
301 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
302
303 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
304 }
305
306 void
307 x86_64_linux_dr_reset_addr (int regnum)
308 {
309 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
310
311 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
312 }
313
314 unsigned long
315 x86_64_linux_dr_get_status (void)
316 {
317 return x86_64_linux_dr_get (DR_STATUS);
318 }
319
320 extern ps_err_e
321 ps_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
This page took 0.036905 seconds and 5 git commands to generate.