daily update
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-x86-64-low.c
CommitLineData
58caa3dc
DJ
1/* GNU/Linux/x86-64 specific low level interface, for the remote server
2 for GDB.
9b254dd1
DJ
3 Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
58caa3dc
DJ
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
58caa3dc
DJ
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
58caa3dc
DJ
20
21#include "server.h"
22#include "linux-low.h"
23#include "i387-fp.h"
24
0050a760 25#include "gdb_proc_service.h"
fd500816 26
d05b4ac3
UW
27/* Defined in auto-generated file reg-x86-64-linux.c. */
28void init_registers_x86_64_linux (void);
29
58caa3dc
DJ
30#include <sys/reg.h>
31#include <sys/procfs.h>
32#include <sys/ptrace.h>
33
fd500816
DJ
34/* This definition comes from prctl.h, but some kernels may not have it. */
35#ifndef PTRACE_ARCH_PRCTL
36#define PTRACE_ARCH_PRCTL 30
37#endif
38
43360365
JB
39/* The following definitions come from prctl.h, but may be absent
40 for certain configurations. */
41#ifndef ARCH_GET_FS
42#define ARCH_SET_GS 0x1001
43#define ARCH_SET_FS 0x1002
44#define ARCH_GET_FS 0x1003
45#define ARCH_GET_GS 0x1004
46#endif
47
09ec9b38 48static int x86_64_regmap[] = {
638c1580
ML
49 RAX * 8, RBX * 8, RCX * 8, RDX * 8,
50 RSI * 8, RDI * 8, RBP * 8, RSP * 8,
51 R8 * 8, R9 * 8, R10 * 8, R11 * 8,
52 R12 * 8, R13 * 8, R14 * 8, R15 * 8,
09ec9b38 53 RIP * 8, EFLAGS * 8, CS * 8, SS * 8,
8695c747
DJ
54 DS * 8, ES * 8, FS * 8, GS * 8,
55 -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 ORIG_RAX * 8
58caa3dc
DJ
60};
61
09ec9b38
ML
62#define X86_64_NUM_GREGS (sizeof(x86_64_regmap)/sizeof(int))
63
fd500816
DJ
64/* Called by libthread_db. */
65
66ps_err_e
67ps_get_thread_area (const struct ps_prochandle *ph,
68 lwpid_t lwpid, int idx, void **base)
69{
70 switch (idx)
71 {
72 case FS:
73 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
74 return PS_OK;
75 break;
76 case GS:
77 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
78 return PS_OK;
79 break;
80 default:
81 return PS_BADADDR;
82 }
83 return PS_ERR;
84}
85
58caa3dc
DJ
86static void
87x86_64_fill_gregset (void *buf)
88{
89 int i;
90
de220d0f 91 for (i = 0; i < X86_64_NUM_GREGS; i++)
8695c747
DJ
92 if (x86_64_regmap[i] != -1)
93 collect_register (i, ((char *) buf) + x86_64_regmap[i]);
58caa3dc
DJ
94}
95
96static void
638c1580 97x86_64_store_gregset (const void *buf)
58caa3dc
DJ
98{
99 int i;
100
de220d0f 101 for (i = 0; i < X86_64_NUM_GREGS; i++)
8695c747
DJ
102 if (x86_64_regmap[i] != -1)
103 supply_register (i, ((char *) buf) + x86_64_regmap[i]);
58caa3dc
DJ
104}
105
106static void
107x86_64_fill_fpregset (void *buf)
108{
109 i387_cache_to_fxsave (buf);
110}
111
112static void
638c1580 113x86_64_store_fpregset (const void *buf)
58caa3dc
DJ
114{
115 i387_fxsave_to_cache (buf);
116}
117
58caa3dc
DJ
118struct regset_info target_regsets[] = {
119 { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
0d62e5e8 120 GENERAL_REGS,
58caa3dc
DJ
121 x86_64_fill_gregset, x86_64_store_gregset },
122 { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
0d62e5e8 123 FP_REGS,
58caa3dc 124 x86_64_fill_fpregset, x86_64_store_fpregset },
0d62e5e8 125 { 0, 0, -1, -1, NULL, NULL }
58caa3dc 126};
2ec06d2e 127
011a70c2
DJ
128static const unsigned char x86_64_breakpoint[] = { 0xCC };
129#define x86_64_breakpoint_len 1
130
131extern int debug_threads;
132
133static CORE_ADDR
134x86_64_get_pc ()
135{
136 unsigned long pc;
137
138 collect_register_by_name ("rip", &pc);
139
140 if (debug_threads)
141 fprintf (stderr, "stop pc (before any decrement) is %08lx\n", pc);
142 return pc;
143}
144
145static void
146x86_64_set_pc (CORE_ADDR newpc)
147{
148 if (debug_threads)
149 fprintf (stderr, "set pc to %08lx\n", (long) newpc);
150 supply_register_by_name ("rip", &newpc);
151}
152
153static int
154x86_64_breakpoint_at (CORE_ADDR pc)
155{
156 unsigned char c;
157
158 read_inferior_memory (pc, &c, 1);
159 if (c == 0xCC)
160 return 1;
161
162 return 0;
163}
164
2ec06d2e 165struct linux_target_ops the_low_target = {
d05b4ac3 166 init_registers_x86_64_linux,
2ec06d2e
DJ
167 -1,
168 NULL,
169 NULL,
170 NULL,
011a70c2
DJ
171 x86_64_get_pc,
172 x86_64_set_pc,
173 x86_64_breakpoint,
174 x86_64_breakpoint_len,
175 NULL,
176 1,
177 x86_64_breakpoint_at,
23181151
DJ
178 NULL,
179 NULL,
180 NULL,
181 NULL,
ee1a7ae4
UW
182 NULL,
183 NULL,
2ec06d2e 184};
This page took 0.431416 seconds and 4 git commands to generate.