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