2004-02-21 H.J. Lu <hongjiu.lu@intel.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, 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 "x86-64-tdep.h"
51 #include "x86-64-linux-tdep.h"
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
58 static int x86_64_linux_gregset64_reg_offset[] =
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 */
69 CS * 8, SS * 8, /* %cs, %ss */
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. */
84 static 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 };
99
100 /* Which ptrace request retrieves which registers?
101 These apply to the corresponding SET requests as well. */
102
103 #define GETFPREGS_SUPPLIES(regno) \
104 (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
105 \f
106
107 /* Transfering the general-purpose registers between GDB, inferiors
108 and core files. */
109
110 /* Fill GDB's register cache with the general-purpose register values
111 in *GREGSETP. */
112
113 void
114 supply_gregset (elf_gregset_t *gregsetp)
115 {
116 amd64_supply_native_gregset (current_regcache, gregsetp, -1);
117 }
118
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,
121 do this for all registers. */
122
123 void
124 fill_gregset (elf_gregset_t *gregsetp, int regnum)
125 {
126 amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
127 }
128
129 /* Fetch all general-purpose registers from process/thread TID and
130 store their values in GDB's register cache. */
131
132 static void
133 fetch_regs (int tid)
134 {
135 elf_gregset_t regs;
136
137 if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
138 perror_with_name ("Couldn't get registers");
139
140 supply_gregset (&regs);
141 }
142
143 /* Store all valid general-purpose registers in GDB's register cache
144 into the process/thread specified by TID. */
145
146 static void
147 store_regs (int tid, int regnum)
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
154 fill_gregset (&regs, regnum);
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
163 /* Fill GDB's register cache with the floating-point and SSE register
164 values in *FPREGSETP. */
165
166 void
167 supply_fpregset (elf_fpregset_t *fpregsetp)
168 {
169 x86_64_supply_fxsave (current_regcache, -1, fpregsetp);
170 }
171
172 /* Fill register REGNUM (if it is a floating-point or SSE register) in
173 *FPREGSETP with the value in GDB's register cache. If REGNUM is
174 -1, do this for all registers. */
175
176 void
177 fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
178 {
179 x86_64_fill_fxsave ((char *) fpregsetp, regnum);
180 }
181
182 /* Fetch all floating-point registers from process/thread TID and store
183 thier values in GDB's register cache. */
184
185 static void
186 fetch_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
196 /* Store all valid floating-point registers in GDB's register cache
197 into the process/thread specified by TID. */
198
199 static void
200 store_fpregs (int tid, int regnum)
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
207 fill_fpregset (&fpregs, regnum);
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
216 /* Fetch register REGNUM from the child process. If REGNUM is -1, do
217 this for all registers (including the floating point and SSE
218 registers). */
219
220 void
221 fetch_inferior_registers (int regnum)
222 {
223 int tid;
224
225 /* GNU/Linux LWP ID's are process ID's. */
226 tid = TIDGET (inferior_ptid);
227 if (tid == 0)
228 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
229
230 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
231 {
232 fetch_regs (tid);
233 if (regnum != -1)
234 return;
235 }
236
237 if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
238 {
239 fetch_fpregs (tid);
240 return;
241 }
242
243 internal_error (__FILE__, __LINE__,
244 "Got request for bad register number %d.", regnum);
245 }
246
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
249 registers). */
250
251 void
252 store_inferior_registers (int regnum)
253 {
254 int tid;
255
256 /* GNU/Linux LWP ID's are process ID's. */
257 tid = TIDGET (inferior_ptid);
258 if (tid == 0)
259 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
260
261 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
262 {
263 store_regs (tid, regnum);
264 if (regnum != -1)
265 return;
266 }
267
268 if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
269 {
270 store_fpregs (tid, regnum);
271 return;
272 }
273
274 internal_error (__FILE__, __LINE__,
275 "Got request to store bad register number %d.", regnum);
276 }
277 \f
278
279 static unsigned long
280 x86_64_linux_dr_get (int regnum)
281 {
282 int tid;
283 unsigned long value;
284
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);
289
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;
303 #endif
304
305 return value;
306 }
307
308 static void
309 x86_64_linux_dr_set (int regnum, unsigned long value)
310 {
311 int tid;
312
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);
317
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 }
323
324 void
325 x86_64_linux_dr_set_control (unsigned long control)
326 {
327 x86_64_linux_dr_set (DR_CONTROL, control);
328 }
329
330 void
331 x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
332 {
333 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
334
335 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
336 }
337
338 void
339 x86_64_linux_dr_reset_addr (int regnum)
340 {
341 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
342
343 x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
344 }
345
346 unsigned long
347 x86_64_linux_dr_get_status (void)
348 {
349 return x86_64_linux_dr_get (DR_STATUS);
350 }
351 \f
352
353 ps_err_e
354 ps_get_thread_area (const struct ps_prochandle *ph,
355 lwpid_t lwpid, int idx, void **base)
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 \f
382
383 void
384 child_post_startup_inferior (ptid_t ptid)
385 {
386 i386_cleanup_dregs ();
387 linux_child_post_startup_inferior (ptid);
388 }
389 \f
390
391 /* Provide a prototype to silence -Wmissing-prototypes. */
392 void _initialize_x86_64_linux_nat (void);
393
394 void
395 _initialize_x86_64_linux_nat (void)
396 {
397 amd64_native_gregset32_reg_offset = x86_64_linux_gregset32_reg_offset;
398 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
399 amd64_native_gregset64_reg_offset = x86_64_linux_gregset64_reg_offset;
400
401 gdb_assert (ARRAY_SIZE (x86_64_linux_gregset32_reg_offset)
402 == amd64_native_gregset32_num_regs);
403 gdb_assert (ARRAY_SIZE (x86_64_linux_gregset64_reg_offset)
404 == amd64_native_gregset64_num_regs);
405 }
This page took 0.071052 seconds and 5 git commands to generate.