xref: /openbsd-src/gnu/usr.bin/binutils/gdb/gdbserver/linux-x86-64-low.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* GNU/Linux/x86-64 specific low level interface, for the remote server
2b725ae77Skettenis    for GDB.
3*11efff7fSkettenis    Copyright 2002, 2004
4b725ae77Skettenis    Free Software Foundation, Inc.
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 "server.h"
24b725ae77Skettenis #include "linux-low.h"
25b725ae77Skettenis #include "i387-fp.h"
26b725ae77Skettenis 
27*11efff7fSkettenis /* Correct for all GNU/Linux targets (for quite some time).  */
28*11efff7fSkettenis #define GDB_GREGSET_T elf_gregset_t
29*11efff7fSkettenis #define GDB_FPREGSET_T elf_fpregset_t
30*11efff7fSkettenis 
31*11efff7fSkettenis #ifndef HAVE_ELF_FPREGSET_T
32*11efff7fSkettenis /* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
33*11efff7fSkettenis    via <sys/procfs.h>.  */
34*11efff7fSkettenis #ifdef HAVE_LINUX_ELF_H
35*11efff7fSkettenis #include <linux/elf.h>
36*11efff7fSkettenis #endif
37*11efff7fSkettenis #endif
38*11efff7fSkettenis 
39*11efff7fSkettenis #include "../gdb_proc_service.h"
40*11efff7fSkettenis 
41b725ae77Skettenis #include <sys/reg.h>
42b725ae77Skettenis #include <sys/procfs.h>
43b725ae77Skettenis #include <sys/ptrace.h>
44b725ae77Skettenis 
45*11efff7fSkettenis /* This definition comes from prctl.h, but some kernels may not have it.  */
46*11efff7fSkettenis #ifndef PTRACE_ARCH_PRCTL
47*11efff7fSkettenis #define PTRACE_ARCH_PRCTL      30
48*11efff7fSkettenis #endif
49*11efff7fSkettenis 
50*11efff7fSkettenis /* The following definitions come from prctl.h, but may be absent
51*11efff7fSkettenis    for certain configurations.  */
52*11efff7fSkettenis #ifndef ARCH_GET_FS
53*11efff7fSkettenis #define ARCH_SET_GS 0x1001
54*11efff7fSkettenis #define ARCH_SET_FS 0x1002
55*11efff7fSkettenis #define ARCH_GET_FS 0x1003
56*11efff7fSkettenis #define ARCH_GET_GS 0x1004
57*11efff7fSkettenis #endif
58*11efff7fSkettenis 
59b725ae77Skettenis static int x86_64_regmap[] = {
60b725ae77Skettenis   RAX * 8, RBX * 8, RCX * 8, RDX * 8,
61b725ae77Skettenis   RSI * 8, RDI * 8, RBP * 8, RSP * 8,
62b725ae77Skettenis   R8 * 8, R9 * 8, R10 * 8, R11 * 8,
63b725ae77Skettenis   R12 * 8, R13 * 8, R14 * 8, R15 * 8,
64b725ae77Skettenis   RIP * 8, EFLAGS * 8, CS * 8, SS * 8,
65b725ae77Skettenis   DS * 8, ES * 8, FS * 8, GS * 8
66b725ae77Skettenis };
67b725ae77Skettenis 
68b725ae77Skettenis #define X86_64_NUM_GREGS (sizeof(x86_64_regmap)/sizeof(int))
69b725ae77Skettenis 
70*11efff7fSkettenis /* Called by libthread_db.  */
71*11efff7fSkettenis 
72*11efff7fSkettenis ps_err_e
ps_get_thread_area(const struct ps_prochandle * ph,lwpid_t lwpid,int idx,void ** base)73*11efff7fSkettenis ps_get_thread_area (const struct ps_prochandle *ph,
74*11efff7fSkettenis                     lwpid_t lwpid, int idx, void **base)
75*11efff7fSkettenis {
76*11efff7fSkettenis   switch (idx)
77*11efff7fSkettenis     {
78*11efff7fSkettenis     case FS:
79*11efff7fSkettenis       if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
80*11efff7fSkettenis 	return PS_OK;
81*11efff7fSkettenis       break;
82*11efff7fSkettenis     case GS:
83*11efff7fSkettenis       if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
84*11efff7fSkettenis 	return PS_OK;
85*11efff7fSkettenis       break;
86*11efff7fSkettenis     default:
87*11efff7fSkettenis       return PS_BADADDR;
88*11efff7fSkettenis     }
89*11efff7fSkettenis   return PS_ERR;
90*11efff7fSkettenis }
91*11efff7fSkettenis 
92b725ae77Skettenis static void
x86_64_fill_gregset(void * buf)93b725ae77Skettenis x86_64_fill_gregset (void *buf)
94b725ae77Skettenis {
95b725ae77Skettenis   int i;
96b725ae77Skettenis 
97b725ae77Skettenis   for (i = 0; i < X86_64_NUM_GREGS; i++)
98b725ae77Skettenis     collect_register (i, ((char *) buf) + x86_64_regmap[i]);
99b725ae77Skettenis }
100b725ae77Skettenis 
101b725ae77Skettenis static void
x86_64_store_gregset(const void * buf)102b725ae77Skettenis x86_64_store_gregset (const void *buf)
103b725ae77Skettenis {
104b725ae77Skettenis   int i;
105b725ae77Skettenis 
106b725ae77Skettenis   for (i = 0; i < X86_64_NUM_GREGS; i++)
107b725ae77Skettenis     supply_register (i, ((char *) buf) + x86_64_regmap[i]);
108b725ae77Skettenis }
109b725ae77Skettenis 
110b725ae77Skettenis static void
x86_64_fill_fpregset(void * buf)111b725ae77Skettenis x86_64_fill_fpregset (void *buf)
112b725ae77Skettenis {
113b725ae77Skettenis   i387_cache_to_fxsave (buf);
114b725ae77Skettenis }
115b725ae77Skettenis 
116b725ae77Skettenis static void
x86_64_store_fpregset(const void * buf)117b725ae77Skettenis x86_64_store_fpregset (const void *buf)
118b725ae77Skettenis {
119b725ae77Skettenis   i387_fxsave_to_cache (buf);
120b725ae77Skettenis }
121b725ae77Skettenis 
122b725ae77Skettenis struct regset_info target_regsets[] = {
123b725ae77Skettenis   { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
124b725ae77Skettenis     GENERAL_REGS,
125b725ae77Skettenis     x86_64_fill_gregset, x86_64_store_gregset },
126b725ae77Skettenis   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
127b725ae77Skettenis     FP_REGS,
128b725ae77Skettenis     x86_64_fill_fpregset, x86_64_store_fpregset },
129b725ae77Skettenis   { 0, 0, -1, -1, NULL, NULL }
130b725ae77Skettenis };
131b725ae77Skettenis 
132b725ae77Skettenis struct linux_target_ops the_low_target = {
133b725ae77Skettenis   -1,
134b725ae77Skettenis   NULL,
135b725ae77Skettenis   NULL,
136b725ae77Skettenis   NULL,
137b725ae77Skettenis };
138