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 
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 
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 
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 
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 
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 
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 
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 }
386