Really remove file.
[deliverable/binutils-gdb.git] / gdb / amd64-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 "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
57 static 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 \f
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. */
83 static 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 \f
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
106 void
107 supply_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
116 void
117 fill_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
127 void
128 supply_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
137 void
138 fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
139 {
140 amd64_collect_fxsave (current_regcache, regnum, fpregsetp);
141 }
142 \f
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
150 void
151 fetch_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
187 void
188 store_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 \f
229
230 static unsigned long
231 amd64_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
259 static void
260 amd64_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
275 void
276 amd64_linux_dr_set_control (unsigned long control)
277 {
278 amd64_linux_dr_set (DR_CONTROL, control);
279 }
280
281 void
282 amd64_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
289 void
290 amd64_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
297 unsigned long
298 amd64_linux_dr_get_status (void)
299 {
300 return amd64_linux_dr_get (DR_STATUS);
301 }
302 \f
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
307 ps_err_e
308 ps_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 \f
362
363 void
364 child_post_startup_inferior (ptid_t ptid)
365 {
366 i386_cleanup_dregs ();
367 linux_child_post_startup_inferior (ptid);
368 }
369 \f
370
371 /* Provide a prototype to silence -Wmissing-prototypes. */
372 void _initialize_amd64_linux_nat (void);
373
374 void
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 }
This page took 0.043841 seconds and 4 git commands to generate.