xref: /openbsd-src/gnu/usr.bin/binutils/gdb/amd64-linux-nat.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Native-dependent code for GNU/Linux x86-64.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis    Contributed by Jiri Smid, SuSE Labs.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22b725ae77Skettenis 
23b725ae77Skettenis #include "defs.h"
24b725ae77Skettenis #include "inferior.h"
25b725ae77Skettenis #include "gdbcore.h"
26b725ae77Skettenis #include "regcache.h"
27b725ae77Skettenis #include "linux-nat.h"
28b725ae77Skettenis 
29b725ae77Skettenis #include "gdb_assert.h"
30b725ae77Skettenis #include "gdb_string.h"
31b725ae77Skettenis #include <sys/ptrace.h>
32b725ae77Skettenis #include <sys/debugreg.h>
33b725ae77Skettenis #include <sys/syscall.h>
34b725ae77Skettenis #include <sys/procfs.h>
35b725ae77Skettenis #include <asm/prctl.h>
36b725ae77Skettenis /* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
37b725ae77Skettenis    <asm/ptrace.h> because the latter redefines FS and GS for no apparent
38b725ae77Skettenis    reason, and those definitions don't match the ones that libpthread_db
39b725ae77Skettenis    uses, which come from <sys/reg.h>.  */
40b725ae77Skettenis /* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
41b725ae77Skettenis    been removed from ptrace.h in the kernel.  However, better safe than
42b725ae77Skettenis    sorry.  */
43b725ae77Skettenis #include <asm/ptrace.h>
44b725ae77Skettenis #include <sys/reg.h>
45b725ae77Skettenis #include "gdb_proc_service.h"
46b725ae77Skettenis 
47b725ae77Skettenis /* Prototypes for supply_gregset etc.  */
48b725ae77Skettenis #include "gregset.h"
49b725ae77Skettenis 
50b725ae77Skettenis #include "amd64-tdep.h"
51b725ae77Skettenis #include "i386-linux-tdep.h"
52b725ae77Skettenis #include "amd64-nat.h"
53b725ae77Skettenis 
54b725ae77Skettenis /* Mapping between the general-purpose registers in GNU/Linux x86-64
55b725ae77Skettenis    `struct user' format and GDB's register cache layout.  */
56b725ae77Skettenis 
57b725ae77Skettenis static int amd64_linux_gregset64_reg_offset[] =
58b725ae77Skettenis {
59b725ae77Skettenis   RAX * 8, RBX * 8,		/* %rax, %rbx */
60b725ae77Skettenis   RCX * 8, RDX * 8,		/* %rcx, %rdx */
61b725ae77Skettenis   RSI * 8, RDI * 8,		/* %rsi, %rdi */
62b725ae77Skettenis   RBP * 8, RSP * 8,		/* %rbp, %rsp */
63b725ae77Skettenis   R8 * 8, R9 * 8,		/* %r8 ... */
64b725ae77Skettenis   R10 * 8, R11 * 8,
65b725ae77Skettenis   R12 * 8, R13 * 8,
66b725ae77Skettenis   R14 * 8, R15 * 8,		/* ... %r15 */
67b725ae77Skettenis   RIP * 8, EFLAGS * 8,		/* %rip, %eflags */
68b725ae77Skettenis   CS * 8, SS * 8,		/* %cs, %ss */
69b725ae77Skettenis   DS * 8, ES * 8,		/* %ds, %es */
70b725ae77Skettenis   FS * 8, GS * 8		/* %fs, %gs */
71b725ae77Skettenis };
72b725ae77Skettenis 
73b725ae77Skettenis 
74b725ae77Skettenis /* Mapping between the general-purpose registers in GNU/Linux x86-64
75b725ae77Skettenis    `struct user' format and GDB's register cache layout for GNU/Linux
76b725ae77Skettenis    i386.
77b725ae77Skettenis 
78b725ae77Skettenis    Note that most GNU/Linux x86-64 registers are 64-bit, while the
79b725ae77Skettenis    GNU/Linux i386 registers are all 32-bit, but since we're
80b725ae77Skettenis    little-endian we get away with that.  */
81b725ae77Skettenis 
82b725ae77Skettenis /* From <sys/reg.h> on GNU/Linux i386.  */
83b725ae77Skettenis static int amd64_linux_gregset32_reg_offset[] =
84b725ae77Skettenis {
85b725ae77Skettenis   RAX * 8, RCX * 8,		/* %eax, %ecx */
86b725ae77Skettenis   RDX * 8, RBX * 8,		/* %edx, %ebx */
87b725ae77Skettenis   RSP * 8, RBP * 8,		/* %esp, %ebp */
88b725ae77Skettenis   RSI * 8, RDI * 8,		/* %esi, %edi */
89b725ae77Skettenis   RIP * 8, EFLAGS * 8,		/* %eip, %eflags */
90b725ae77Skettenis   CS * 8, SS * 8,		/* %cs, %ss */
91b725ae77Skettenis   DS * 8, ES * 8,		/* %ds, %es */
92b725ae77Skettenis   FS * 8, GS * 8,		/* %fs, %gs */
93b725ae77Skettenis   -1, -1, -1, -1, -1, -1, -1, -1,
94b725ae77Skettenis   -1, -1, -1, -1, -1, -1, -1, -1,
95b725ae77Skettenis   -1, -1, -1, -1, -1, -1, -1, -1, -1,
96b725ae77Skettenis   ORIG_RAX * 8			/* "orig_eax" */
97b725ae77Skettenis };
98b725ae77Skettenis 
99b725ae77Skettenis 
100b725ae77Skettenis /* Transfering the general-purpose registers between GDB, inferiors
101b725ae77Skettenis    and core files.  */
102b725ae77Skettenis 
103b725ae77Skettenis /* Fill GDB's register cache with the general-purpose register values
104b725ae77Skettenis    in *GREGSETP.  */
105b725ae77Skettenis 
106b725ae77Skettenis void
supply_gregset(elf_gregset_t * gregsetp)107b725ae77Skettenis supply_gregset (elf_gregset_t *gregsetp)
108b725ae77Skettenis {
109b725ae77Skettenis   amd64_supply_native_gregset (current_regcache, gregsetp, -1);
110b725ae77Skettenis }
111b725ae77Skettenis 
112b725ae77Skettenis /* Fill register REGNUM (if it is a general-purpose register) in
113b725ae77Skettenis    *GREGSETP with the value in GDB's register cache.  If REGNUM is -1,
114b725ae77Skettenis    do this for all registers.  */
115b725ae77Skettenis 
116b725ae77Skettenis void
fill_gregset(elf_gregset_t * gregsetp,int regnum)117b725ae77Skettenis fill_gregset (elf_gregset_t *gregsetp, int regnum)
118b725ae77Skettenis {
119b725ae77Skettenis   amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
120b725ae77Skettenis }
121b725ae77Skettenis 
122b725ae77Skettenis /* Transfering floating-point registers between GDB, inferiors and cores.  */
123b725ae77Skettenis 
124b725ae77Skettenis /* Fill GDB's register cache with the floating-point and SSE register
125b725ae77Skettenis    values in *FPREGSETP.  */
126b725ae77Skettenis 
127b725ae77Skettenis void
supply_fpregset(elf_fpregset_t * fpregsetp)128b725ae77Skettenis supply_fpregset (elf_fpregset_t *fpregsetp)
129b725ae77Skettenis {
130b725ae77Skettenis   amd64_supply_fxsave (current_regcache, -1, fpregsetp);
131b725ae77Skettenis }
132b725ae77Skettenis 
133b725ae77Skettenis /* Fill register REGNUM (if it is a floating-point or SSE register) in
134b725ae77Skettenis    *FPREGSETP with the value in GDB's register cache.  If REGNUM is
135b725ae77Skettenis    -1, do this for all registers.  */
136b725ae77Skettenis 
137b725ae77Skettenis void
fill_fpregset(elf_fpregset_t * fpregsetp,int regnum)138b725ae77Skettenis fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
139b725ae77Skettenis {
140*11efff7fSkettenis   amd64_collect_fxsave (current_regcache, regnum, fpregsetp);
141b725ae77Skettenis }
142b725ae77Skettenis 
143b725ae77Skettenis 
144b725ae77Skettenis /* Transferring arbitrary registers between GDB and inferior.  */
145b725ae77Skettenis 
146b725ae77Skettenis /* Fetch register REGNUM from the child process.  If REGNUM is -1, do
147b725ae77Skettenis    this for all registers (including the floating point and SSE
148b725ae77Skettenis    registers).  */
149b725ae77Skettenis 
150b725ae77Skettenis void
fetch_inferior_registers(int regnum)151b725ae77Skettenis fetch_inferior_registers (int regnum)
152b725ae77Skettenis {
153b725ae77Skettenis   int tid;
154b725ae77Skettenis 
155b725ae77Skettenis   /* GNU/Linux LWP ID's are process ID's.  */
156b725ae77Skettenis   tid = TIDGET (inferior_ptid);
157b725ae77Skettenis   if (tid == 0)
158b725ae77Skettenis     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
159b725ae77Skettenis 
160b725ae77Skettenis   if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
161b725ae77Skettenis     {
162*11efff7fSkettenis       elf_gregset_t regs;
163*11efff7fSkettenis 
164*11efff7fSkettenis       if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
165*11efff7fSkettenis 	perror_with_name ("Couldn't get registers");
166*11efff7fSkettenis 
167*11efff7fSkettenis       amd64_supply_native_gregset (current_regcache, &regs, -1);
168b725ae77Skettenis       if (regnum != -1)
169b725ae77Skettenis 	return;
170b725ae77Skettenis     }
171b725ae77Skettenis 
172*11efff7fSkettenis   if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
173b725ae77Skettenis     {
174*11efff7fSkettenis       elf_fpregset_t fpregs;
175b725ae77Skettenis 
176*11efff7fSkettenis       if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
177*11efff7fSkettenis 	perror_with_name ("Couldn't get floating point status");
178*11efff7fSkettenis 
179*11efff7fSkettenis       amd64_supply_fxsave (current_regcache, -1, &fpregs);
180*11efff7fSkettenis     }
181b725ae77Skettenis }
182b725ae77Skettenis 
183b725ae77Skettenis /* Store register REGNUM back into the child process.  If REGNUM is
184b725ae77Skettenis    -1, do this for all registers (including the floating-point and SSE
185b725ae77Skettenis    registers).  */
186b725ae77Skettenis 
187b725ae77Skettenis void
store_inferior_registers(int regnum)188b725ae77Skettenis store_inferior_registers (int regnum)
189b725ae77Skettenis {
190b725ae77Skettenis   int tid;
191b725ae77Skettenis 
192b725ae77Skettenis   /* GNU/Linux LWP ID's are process ID's.  */
193b725ae77Skettenis   tid = TIDGET (inferior_ptid);
194b725ae77Skettenis   if (tid == 0)
195b725ae77Skettenis     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
196b725ae77Skettenis 
197b725ae77Skettenis   if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
198b725ae77Skettenis     {
199*11efff7fSkettenis       elf_gregset_t regs;
200*11efff7fSkettenis 
201*11efff7fSkettenis       if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
202*11efff7fSkettenis 	perror_with_name ("Couldn't get registers");
203*11efff7fSkettenis 
204*11efff7fSkettenis       amd64_collect_native_gregset (current_regcache, &regs, regnum);
205*11efff7fSkettenis 
206*11efff7fSkettenis       if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
207*11efff7fSkettenis 	perror_with_name ("Couldn't write registers");
208*11efff7fSkettenis 
209b725ae77Skettenis       if (regnum != -1)
210b725ae77Skettenis 	return;
211b725ae77Skettenis     }
212b725ae77Skettenis 
213*11efff7fSkettenis   if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
214b725ae77Skettenis     {
215*11efff7fSkettenis       elf_fpregset_t fpregs;
216*11efff7fSkettenis 
217*11efff7fSkettenis       if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
218*11efff7fSkettenis 	perror_with_name ("Couldn't get floating point status");
219*11efff7fSkettenis 
220*11efff7fSkettenis       amd64_collect_fxsave (current_regcache, regnum, &fpregs);
221*11efff7fSkettenis 
222*11efff7fSkettenis       if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
223*11efff7fSkettenis 	perror_with_name ("Couldn't write floating point status");
224*11efff7fSkettenis 
225b725ae77Skettenis       return;
226b725ae77Skettenis     }
227b725ae77Skettenis }
228b725ae77Skettenis 
229b725ae77Skettenis 
230b725ae77Skettenis static unsigned long
amd64_linux_dr_get(int regnum)231b725ae77Skettenis amd64_linux_dr_get (int regnum)
232b725ae77Skettenis {
233b725ae77Skettenis   int tid;
234b725ae77Skettenis   unsigned long value;
235b725ae77Skettenis 
236b725ae77Skettenis   /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
237b725ae77Skettenis      multi-threaded processes here.  For now, pretend there is just
238b725ae77Skettenis      one thread.  */
239b725ae77Skettenis   tid = PIDGET (inferior_ptid);
240b725ae77Skettenis 
241b725ae77Skettenis   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
242b725ae77Skettenis      ptrace call fails breaks debugging remote targets.  The correct
243b725ae77Skettenis      way to fix this is to add the hardware breakpoint and watchpoint
244b725ae77Skettenis      stuff to the target vectore.  For now, just return zero if the
245b725ae77Skettenis      ptrace call fails.  */
246b725ae77Skettenis   errno = 0;
247b725ae77Skettenis   value = ptrace (PT_READ_U, tid,
248b725ae77Skettenis 		  offsetof (struct user, u_debugreg[regnum]), 0);
249b725ae77Skettenis   if (errno != 0)
250b725ae77Skettenis #if 0
251b725ae77Skettenis     perror_with_name ("Couldn't read debug register");
252b725ae77Skettenis #else
253b725ae77Skettenis     return 0;
254b725ae77Skettenis #endif
255b725ae77Skettenis 
256b725ae77Skettenis   return value;
257b725ae77Skettenis }
258b725ae77Skettenis 
259b725ae77Skettenis static void
amd64_linux_dr_set(int regnum,unsigned long value)260b725ae77Skettenis amd64_linux_dr_set (int regnum, unsigned long value)
261b725ae77Skettenis {
262b725ae77Skettenis   int tid;
263b725ae77Skettenis 
264b725ae77Skettenis   /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
265b725ae77Skettenis      multi-threaded processes here.  For now, pretend there is just
266b725ae77Skettenis      one thread.  */
267b725ae77Skettenis   tid = PIDGET (inferior_ptid);
268b725ae77Skettenis 
269b725ae77Skettenis   errno = 0;
270b725ae77Skettenis   ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
271b725ae77Skettenis   if (errno != 0)
272b725ae77Skettenis     perror_with_name ("Couldn't write debug register");
273b725ae77Skettenis }
274b725ae77Skettenis 
275b725ae77Skettenis void
amd64_linux_dr_set_control(unsigned long control)276b725ae77Skettenis amd64_linux_dr_set_control (unsigned long control)
277b725ae77Skettenis {
278b725ae77Skettenis   amd64_linux_dr_set (DR_CONTROL, control);
279b725ae77Skettenis }
280b725ae77Skettenis 
281b725ae77Skettenis void
amd64_linux_dr_set_addr(int regnum,CORE_ADDR addr)282b725ae77Skettenis amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
283b725ae77Skettenis {
284b725ae77Skettenis   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
285b725ae77Skettenis 
286b725ae77Skettenis   amd64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
287b725ae77Skettenis }
288b725ae77Skettenis 
289b725ae77Skettenis void
amd64_linux_dr_reset_addr(int regnum)290b725ae77Skettenis amd64_linux_dr_reset_addr (int regnum)
291b725ae77Skettenis {
292b725ae77Skettenis   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
293b725ae77Skettenis 
294b725ae77Skettenis   amd64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
295b725ae77Skettenis }
296b725ae77Skettenis 
297b725ae77Skettenis unsigned long
amd64_linux_dr_get_status(void)298b725ae77Skettenis amd64_linux_dr_get_status (void)
299b725ae77Skettenis {
300b725ae77Skettenis   return amd64_linux_dr_get (DR_STATUS);
301b725ae77Skettenis }
302b725ae77Skettenis 
303b725ae77Skettenis 
304b725ae77Skettenis /* This function is called by libthread_db as part of its handling of
305b725ae77Skettenis    a request for a thread's local storage address.  */
306b725ae77Skettenis 
307b725ae77Skettenis ps_err_e
ps_get_thread_area(const struct ps_prochandle * ph,lwpid_t lwpid,int idx,void ** base)308b725ae77Skettenis ps_get_thread_area (const struct ps_prochandle *ph,
309b725ae77Skettenis                     lwpid_t lwpid, int idx, void **base)
310b725ae77Skettenis {
311b725ae77Skettenis   if (gdbarch_ptr_bit (current_gdbarch) == 32)
312b725ae77Skettenis     {
313b725ae77Skettenis       /* The full structure is found in <asm-i386/ldt.h>.  The second
314b725ae77Skettenis 	 integer is the LDT's base_address and that is used to locate
315b725ae77Skettenis 	 the thread's local storage.  See i386-linux-nat.c more
316b725ae77Skettenis 	 info.  */
317b725ae77Skettenis       unsigned int desc[4];
318b725ae77Skettenis 
319b725ae77Skettenis       /* This code assumes that "int" is 32 bits and that
320b725ae77Skettenis 	 GET_THREAD_AREA returns no more than 4 int values.  */
321b725ae77Skettenis       gdb_assert (sizeof (int) == 4);
322b725ae77Skettenis #ifndef PTRACE_GET_THREAD_AREA
323b725ae77Skettenis #define PTRACE_GET_THREAD_AREA 25
324b725ae77Skettenis #endif
325b725ae77Skettenis       if  (ptrace (PTRACE_GET_THREAD_AREA,
326b725ae77Skettenis 		   lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
327b725ae77Skettenis 	return PS_ERR;
328b725ae77Skettenis 
329b725ae77Skettenis       /* Extend the value to 64 bits.  Here it's assumed that a "long"
330b725ae77Skettenis 	 and a "void *" are the same.  */
331b725ae77Skettenis       (*base) = (void *) (long) desc[1];
332b725ae77Skettenis       return PS_OK;
333b725ae77Skettenis     }
334b725ae77Skettenis   else
335b725ae77Skettenis     {
336b725ae77Skettenis       /* This definition comes from prctl.h, but some kernels may not
337b725ae77Skettenis          have it.  */
338b725ae77Skettenis #ifndef PTRACE_ARCH_PRCTL
339b725ae77Skettenis #define PTRACE_ARCH_PRCTL      30
340b725ae77Skettenis #endif
341b725ae77Skettenis       /* FIXME: ezannoni-2003-07-09 see comment above about include
342b725ae77Skettenis 	 file order.  We could be getting bogus values for these two.  */
343b725ae77Skettenis       gdb_assert (FS < ELF_NGREG);
344b725ae77Skettenis       gdb_assert (GS < ELF_NGREG);
345b725ae77Skettenis       switch (idx)
346b725ae77Skettenis 	{
347b725ae77Skettenis 	case FS:
348b725ae77Skettenis 	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
349b725ae77Skettenis 	    return PS_OK;
350b725ae77Skettenis 	  break;
351b725ae77Skettenis 	case GS:
352b725ae77Skettenis 	  if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
353b725ae77Skettenis 	    return PS_OK;
354b725ae77Skettenis 	  break;
355b725ae77Skettenis 	default:                   /* Should not happen.  */
356b725ae77Skettenis 	  return PS_BADADDR;
357b725ae77Skettenis 	}
358b725ae77Skettenis     }
359b725ae77Skettenis   return PS_ERR;               /* ptrace failed.  */
360b725ae77Skettenis }
361b725ae77Skettenis 
362b725ae77Skettenis 
363b725ae77Skettenis void
child_post_startup_inferior(ptid_t ptid)364b725ae77Skettenis child_post_startup_inferior (ptid_t ptid)
365b725ae77Skettenis {
366b725ae77Skettenis   i386_cleanup_dregs ();
367b725ae77Skettenis   linux_child_post_startup_inferior (ptid);
368b725ae77Skettenis }
369b725ae77Skettenis 
370b725ae77Skettenis 
371b725ae77Skettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
372b725ae77Skettenis void _initialize_amd64_linux_nat (void);
373b725ae77Skettenis 
374b725ae77Skettenis void
_initialize_amd64_linux_nat(void)375b725ae77Skettenis _initialize_amd64_linux_nat (void)
376b725ae77Skettenis {
377b725ae77Skettenis   amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
378b725ae77Skettenis   amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
379b725ae77Skettenis   amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
380b725ae77Skettenis 
381b725ae77Skettenis   gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
382b725ae77Skettenis 	      == amd64_native_gregset32_num_regs);
383b725ae77Skettenis   gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
384b725ae77Skettenis 	      == amd64_native_gregset64_num_regs);
385b725ae77Skettenis }
386