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