]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/linux-i386-low.c
Updated copyright notices for most files.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / linux-i386-low.c
CommitLineData
0a30fbc4 1/* GNU/Linux/i386 specific low level interface, for the remote server for GDB.
6aba47ca 2 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
9b254dd1 3 2007, 2008 Free Software Foundation, Inc.
0a30fbc4
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
0a30fbc4
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/>. */
0a30fbc4
DJ
19
20#include "server.h"
58caa3dc
DJ
21#include "linux-low.h"
22#include "i387-fp.h"
0a30fbc4 23
0050a760 24#include "gdb_proc_service.h"
fd500816
DJ
25
26#include <sys/ptrace.h>
27
0a30fbc4
DJ
28#ifdef HAVE_SYS_REG_H
29#include <sys/reg.h>
30#endif
31
fd500816
DJ
32#ifndef PTRACE_GET_THREAD_AREA
33#define PTRACE_GET_THREAD_AREA 25
34#endif
35
58caa3dc 36/* This module only supports access to the general purpose registers. */
0a30fbc4 37
2ec06d2e 38#define i386_num_regs 16
0a30fbc4
DJ
39
40/* This stuff comes from i386-linux-nat.c. */
41
42/* Mapping between the general-purpose registers in `struct user'
43 format and GDB's register array layout. */
2ec06d2e 44static int i386_regmap[] =
0a30fbc4
DJ
45{
46 EAX * 4, ECX * 4, EDX * 4, EBX * 4,
47 UESP * 4, EBP * 4, ESI * 4, EDI * 4,
48 EIP * 4, EFL * 4, CS * 4, SS * 4,
49 DS * 4, ES * 4, FS * 4, GS * 4
50};
51
fd500816
DJ
52/* Called by libthread_db. */
53
54ps_err_e
55ps_get_thread_area (const struct ps_prochandle *ph,
56 lwpid_t lwpid, int idx, void **base)
57{
58 unsigned int desc[4];
59
60 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid,
61 (void *) idx, (unsigned long) &desc) < 0)
62 return PS_ERR;
63
64 *(int *)base = desc[1];
65 return PS_OK;
66}
67
2ec06d2e
DJ
68static int
69i386_cannot_store_register (int regno)
0a30fbc4 70{
2ec06d2e 71 return (regno >= i386_num_regs);
0a30fbc4
DJ
72}
73
2ec06d2e
DJ
74static int
75i386_cannot_fetch_register (int regno)
0a30fbc4 76{
2ec06d2e 77 return (regno >= i386_num_regs);
0a30fbc4 78}
58caa3dc
DJ
79
80
e9d25b98 81#ifdef HAVE_PTRACE_GETREGS
58caa3dc
DJ
82#include <sys/procfs.h>
83#include <sys/ptrace.h>
84
85static void
86i386_fill_gregset (void *buf)
87{
88 int i;
89
2ec06d2e
DJ
90 for (i = 0; i < i386_num_regs; i++)
91 collect_register (i, ((char *) buf) + i386_regmap[i]);
58caa3dc
DJ
92
93 collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
94}
95
96static void
0d62e5e8 97i386_store_gregset (const void *buf)
58caa3dc
DJ
98{
99 int i;
100
2ec06d2e
DJ
101 for (i = 0; i < i386_num_regs; i++)
102 supply_register (i, ((char *) buf) + i386_regmap[i]);
58caa3dc
DJ
103
104 supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
105}
106
107static void
108i386_fill_fpregset (void *buf)
109{
110 i387_cache_to_fsave (buf);
111}
112
113static void
0d62e5e8 114i386_store_fpregset (const void *buf)
58caa3dc
DJ
115{
116 i387_fsave_to_cache (buf);
117}
118
119static void
120i386_fill_fpxregset (void *buf)
121{
122 i387_cache_to_fxsave (buf);
123}
124
125static void
0d62e5e8 126i386_store_fpxregset (const void *buf)
58caa3dc
DJ
127{
128 i387_fxsave_to_cache (buf);
129}
130
e9d25b98 131#endif /* HAVE_PTRACE_GETREGS */
58caa3dc
DJ
132
133struct regset_info target_regsets[] = {
e9d25b98 134#ifdef HAVE_PTRACE_GETREGS
58caa3dc 135 { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
0d62e5e8 136 GENERAL_REGS,
58caa3dc 137 i386_fill_gregset, i386_store_gregset },
e9d25b98 138# ifdef HAVE_PTRACE_GETFPXREGS
58caa3dc 139 { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t),
0d62e5e8 140 EXTENDED_REGS,
58caa3dc 141 i386_fill_fpxregset, i386_store_fpxregset },
e9d25b98 142# endif
58caa3dc 143 { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
0d62e5e8 144 FP_REGS,
58caa3dc 145 i386_fill_fpregset, i386_store_fpregset },
e9d25b98 146#endif /* HAVE_PTRACE_GETREGS */
0d62e5e8 147 { 0, 0, -1, -1, NULL, NULL }
58caa3dc
DJ
148};
149
f450004a 150static const unsigned char i386_breakpoint[] = { 0xCC };
611cb4a5
DJ
151#define i386_breakpoint_len 1
152
0d62e5e8
DJ
153extern int debug_threads;
154
611cb4a5 155static CORE_ADDR
0d62e5e8 156i386_get_pc ()
611cb4a5
DJ
157{
158 unsigned long pc;
159
611cb4a5 160 collect_register_by_name ("eip", &pc);
0d62e5e8
DJ
161
162 if (debug_threads)
163 fprintf (stderr, "stop pc (before any decrement) is %08lx\n", pc);
164 return pc;
611cb4a5
DJ
165}
166
167static void
168i386_set_pc (CORE_ADDR newpc)
169{
0d62e5e8
DJ
170 if (debug_threads)
171 fprintf (stderr, "set pc to %08lx\n", (long) newpc);
611cb4a5 172 supply_register_by_name ("eip", &newpc);
0d62e5e8
DJ
173}
174
175static int
176i386_breakpoint_at (CORE_ADDR pc)
177{
178 unsigned char c;
179
180 read_inferior_memory (pc, &c, 1);
181 if (c == 0xCC)
182 return 1;
611cb4a5 183
0d62e5e8 184 return 0;
611cb4a5
DJ
185}
186
2ec06d2e
DJ
187struct linux_target_ops the_low_target = {
188 i386_num_regs,
189 i386_regmap,
190 i386_cannot_fetch_register,
191 i386_cannot_store_register,
0d62e5e8 192 i386_get_pc,
611cb4a5
DJ
193 i386_set_pc,
194 i386_breakpoint,
195 i386_breakpoint_len,
0d62e5e8
DJ
196 NULL,
197 1,
198 i386_breakpoint_at,
23181151
DJ
199 NULL,
200 NULL,
201 NULL,
202 NULL,
203 0,
204 "i386"
2ec06d2e 205};