OSDN Git Service

Updated copyright notices for most files.
[pf3gnuchains/pf3gnuchains4x.git] / gdb / amd64-linux-nat.c
1 /* Native-dependent code for GNU/Linux x86-64.
2
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4    Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>.  */
21
22 #include "defs.h"
23 #include "inferior.h"
24 #include "gdbcore.h"
25 #include "regcache.h"
26 #include "linux-nat.h"
27 #include "amd64-linux-tdep.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   -1, -1, -1, -1, -1, -1, -1, -1,
72   -1, -1, -1, -1, -1, -1, -1, -1,
73   -1, -1, -1, -1, -1, -1, -1, -1,
74   -1, -1, -1, -1, -1, -1, -1, -1, -1,
75   ORIG_RAX * 8
76 };
77 \f
78
79 /* Mapping between the general-purpose registers in GNU/Linux x86-64
80    `struct user' format and GDB's register cache layout for GNU/Linux
81    i386.
82
83    Note that most GNU/Linux x86-64 registers are 64-bit, while the
84    GNU/Linux i386 registers are all 32-bit, but since we're
85    little-endian we get away with that.  */
86
87 /* From <sys/reg.h> on GNU/Linux i386.  */
88 static int amd64_linux_gregset32_reg_offset[] =
89 {
90   RAX * 8, RCX * 8,             /* %eax, %ecx */
91   RDX * 8, RBX * 8,             /* %edx, %ebx */
92   RSP * 8, RBP * 8,             /* %esp, %ebp */
93   RSI * 8, RDI * 8,             /* %esi, %edi */
94   RIP * 8, EFLAGS * 8,          /* %eip, %eflags */
95   CS * 8, SS * 8,               /* %cs, %ss */
96   DS * 8, ES * 8,               /* %ds, %es */
97   FS * 8, GS * 8,               /* %fs, %gs */
98   -1, -1, -1, -1, -1, -1, -1, -1,
99   -1, -1, -1, -1, -1, -1, -1, -1,
100   -1, -1, -1, -1, -1, -1, -1, -1, -1,
101   ORIG_RAX * 8                  /* "orig_eax" */
102 };
103 \f
104
105 /* Transfering the general-purpose registers between GDB, inferiors
106    and core files.  */
107
108 /* Fill GDB's register cache with the general-purpose register values
109    in *GREGSETP.  */
110
111 void
112 supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
113 {
114   amd64_supply_native_gregset (regcache, gregsetp, -1);
115 }
116
117 /* Fill register REGNUM (if it is a general-purpose register) in
118    *GREGSETP with the value in GDB's register cache.  If REGNUM is -1,
119    do this for all registers.  */
120
121 void
122 fill_gregset (const struct regcache *regcache,
123               elf_gregset_t *gregsetp, int regnum)
124 {
125   amd64_collect_native_gregset (regcache, gregsetp, regnum);
126 }
127
128 /* Transfering floating-point registers between GDB, inferiors and cores.  */
129
130 /* Fill GDB's register cache with the floating-point and SSE register
131    values in *FPREGSETP.  */
132
133 void
134 supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
135 {
136   amd64_supply_fxsave (regcache, -1, fpregsetp);
137 }
138
139 /* Fill register REGNUM (if it is a floating-point or SSE register) in
140    *FPREGSETP with the value in GDB's register cache.  If REGNUM is
141    -1, do this for all registers.  */
142
143 void
144 fill_fpregset (const struct regcache *regcache,
145                elf_fpregset_t *fpregsetp, int regnum)
146 {
147   amd64_collect_fxsave (regcache, regnum, fpregsetp);
148 }
149 \f
150
151 /* Transferring arbitrary registers between GDB and inferior.  */
152
153 /* Fetch register REGNUM from the child process.  If REGNUM is -1, do
154    this for all registers (including the floating point and SSE
155    registers).  */
156
157 static void
158 amd64_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
159 {
160   struct gdbarch *gdbarch = get_regcache_arch (regcache);
161   int tid;
162
163   /* GNU/Linux LWP ID's are process ID's.  */
164   tid = TIDGET (inferior_ptid);
165   if (tid == 0)
166     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
167
168   if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
169     {
170       elf_gregset_t regs;
171
172       if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
173         perror_with_name (_("Couldn't get registers"));
174
175       amd64_supply_native_gregset (regcache, &regs, -1);
176       if (regnum != -1)
177         return;
178     }
179
180   if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
181     {
182       elf_fpregset_t fpregs;
183
184       if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
185         perror_with_name (_("Couldn't get floating point status"));
186
187       amd64_supply_fxsave (regcache, -1, &fpregs);
188     }
189 }
190
191 /* Store register REGNUM back into the child process.  If REGNUM is
192    -1, do this for all registers (including the floating-point and SSE
193    registers).  */
194
195 static void
196 amd64_linux_store_inferior_registers (struct regcache *regcache, int regnum)
197 {
198   struct gdbarch *gdbarch = get_regcache_arch (regcache);
199   int tid;
200
201   /* GNU/Linux LWP ID's are process ID's.  */
202   tid = TIDGET (inferior_ptid);
203   if (tid == 0)
204     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
205
206   if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
207     {
208       elf_gregset_t regs;
209
210       if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
211         perror_with_name (_("Couldn't get registers"));
212
213       amd64_collect_native_gregset (regcache, &regs, regnum);
214
215       if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
216         perror_with_name (_("Couldn't write registers"));
217
218       if (regnum != -1)
219         return;
220     }
221
222   if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
223     {
224       elf_fpregset_t fpregs;
225
226       if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
227         perror_with_name (_("Couldn't get floating point status"));
228
229       amd64_collect_fxsave (regcache, regnum, &fpregs);
230
231       if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
232         perror_with_name (_("Couldn't write floating point status"));
233
234       return;
235     }
236 }
237 \f
238 /* Support for debug registers.  */
239
240 static unsigned long amd64_linux_dr[DR_CONTROL + 1];
241
242 static unsigned long
243 amd64_linux_dr_get (ptid_t ptid, int regnum)
244 {
245   int tid;
246   unsigned long value;
247
248   tid = TIDGET (ptid);
249   if (tid == 0)
250     tid = PIDGET (ptid);
251
252   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
253      ptrace call fails breaks debugging remote targets.  The correct
254      way to fix this is to add the hardware breakpoint and watchpoint
255      stuff to the target vector.  For now, just return zero if the
256      ptrace call fails.  */
257   errno = 0;
258   value = ptrace (PTRACE_PEEKUSER, tid,
259                   offsetof (struct user, u_debugreg[regnum]), 0);
260   if (errno != 0)
261 #if 0
262     perror_with_name (_("Couldn't read debug register"));
263 #else
264     return 0;
265 #endif
266
267   return value;
268 }
269
270 static void
271 amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
272 {
273   int tid;
274
275   tid = TIDGET (ptid);
276   if (tid == 0)
277     tid = PIDGET (ptid);
278
279   errno = 0;
280   ptrace (PTRACE_POKEUSER, tid,
281           offsetof (struct user, u_debugreg[regnum]), value);
282   if (errno != 0)
283     perror_with_name (_("Couldn't write debug register"));
284 }
285
286 void
287 amd64_linux_dr_set_control (unsigned long control)
288 {
289   struct lwp_info *lp;
290   ptid_t ptid;
291
292   amd64_linux_dr[DR_CONTROL] = control;
293   ALL_LWPS (lp, ptid)
294     amd64_linux_dr_set (ptid, DR_CONTROL, control);
295 }
296
297 void
298 amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
299 {
300   struct lwp_info *lp;
301   ptid_t ptid;
302
303   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
304
305   amd64_linux_dr[DR_FIRSTADDR + regnum] = addr;
306   ALL_LWPS (lp, ptid)
307     amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
308 }
309
310 void
311 amd64_linux_dr_reset_addr (int regnum)
312 {
313   amd64_linux_dr_set_addr (regnum, 0);
314 }
315
316 unsigned long
317 amd64_linux_dr_get_status (void)
318 {
319   return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
320 }
321
322 static void
323 amd64_linux_new_thread (ptid_t ptid)
324 {
325   int i;
326
327   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
328     amd64_linux_dr_set (ptid, i, amd64_linux_dr[i]);
329
330   amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
331 }
332 \f
333
334 /* This function is called by libthread_db as part of its handling of
335    a request for a thread's local storage address.  */
336
337 ps_err_e
338 ps_get_thread_area (const struct ps_prochandle *ph,
339                     lwpid_t lwpid, int idx, void **base)
340 {
341   if (gdbarch_ptr_bit (current_gdbarch) == 32)
342     {
343       /* The full structure is found in <asm-i386/ldt.h>.  The second
344          integer is the LDT's base_address and that is used to locate
345          the thread's local storage.  See i386-linux-nat.c more
346          info.  */
347       unsigned int desc[4];
348
349       /* This code assumes that "int" is 32 bits and that
350          GET_THREAD_AREA returns no more than 4 int values.  */
351       gdb_assert (sizeof (int) == 4);   
352 #ifndef PTRACE_GET_THREAD_AREA
353 #define PTRACE_GET_THREAD_AREA 25
354 #endif
355       if  (ptrace (PTRACE_GET_THREAD_AREA, 
356                    lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
357         return PS_ERR;
358       
359       /* Extend the value to 64 bits.  Here it's assumed that a "long"
360          and a "void *" are the same.  */
361       (*base) = (void *) (long) desc[1];
362       return PS_OK;
363     }
364   else
365     {
366       /* This definition comes from prctl.h, but some kernels may not
367          have it.  */
368 #ifndef PTRACE_ARCH_PRCTL
369 #define PTRACE_ARCH_PRCTL      30
370 #endif
371       /* FIXME: ezannoni-2003-07-09 see comment above about include
372          file order.  We could be getting bogus values for these two.  */
373       gdb_assert (FS < ELF_NGREG);
374       gdb_assert (GS < ELF_NGREG);
375       switch (idx)
376         {
377         case FS:
378           if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
379             return PS_OK;
380           break;
381         case GS:
382           if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
383             return PS_OK;
384           break;
385         default:                   /* Should not happen.  */
386           return PS_BADADDR;
387         }
388     }
389   return PS_ERR;               /* ptrace failed.  */
390 }
391 \f
392
393 static void (*super_post_startup_inferior) (ptid_t ptid);
394
395 static void
396 amd64_linux_child_post_startup_inferior (ptid_t ptid)
397 {
398   i386_cleanup_dregs ();
399   super_post_startup_inferior (ptid);
400 }
401 \f
402
403 /* Provide a prototype to silence -Wmissing-prototypes.  */
404 void _initialize_amd64_linux_nat (void);
405
406 void
407 _initialize_amd64_linux_nat (void)
408 {
409   struct target_ops *t;
410
411   amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
412   amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
413   amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
414   amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
415
416   gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
417               == amd64_native_gregset32_num_regs);
418   gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
419               == amd64_native_gregset64_num_regs);
420
421   /* Fill in the generic GNU/Linux methods.  */
422   t = linux_target ();
423
424   i386_use_watchpoints (t);
425
426   /* Override the GNU/Linux inferior startup hook.  */
427   super_post_startup_inferior = t->to_post_startup_inferior;
428   t->to_post_startup_inferior = amd64_linux_child_post_startup_inferior;
429
430   /* Add our register access methods.  */
431   t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
432   t->to_store_registers = amd64_linux_store_inferior_registers;
433
434   /* Register the target.  */
435   linux_nat_add_target (t);
436   linux_nat_set_new_thread (t, amd64_linux_new_thread);
437 }