* gdbint.texinfo: Add a cautionary note about macro use.
[deliverable/binutils-gdb.git] / gdb / i386v-nat.c
CommitLineData
c906108c 1/* Intel 386 native support for SYSV systems (pre-SVR4).
b6ba6518
KB
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
3 2000 Free Software Foundation, Inc.
c906108c 4
4e326852 5 This file is part of GDB.
c906108c 6
4e326852
JB
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
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
c906108c 11
4e326852
JB
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.
c906108c 16
4e326852
JB
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
c906108c
SS
21
22#include "defs.h"
23
24#ifdef HAVE_PTRACE_H
4e326852 25#include <ptrace.h>
c906108c 26#else
4e326852
JB
27#ifdef HAVE_SYS_PTRACE_H
28#include <sys/ptrace.h>
29#endif
c906108c
SS
30#endif
31
32#include "frame.h"
33#include "inferior.h"
34#include "language.h"
35#include "gdbcore.h"
36
37#ifdef USG
38#include <sys/types.h>
39#endif
40
41#include <sys/param.h>
42#include <sys/dir.h>
43#include <signal.h>
44#include <sys/user.h>
45#include <sys/ioctl.h>
46#include <fcntl.h>
47
48
49/* FIXME: The following used to be just "#include <sys/debugreg.h>", but
50 * the the Linux 2.1.x kernel and glibc 2.0.x are not in sync; including
51 * <sys/debugreg.h> will result in an error. With luck, these losers
52 * will get their act together and we can trash this hack in the near future.
53 * --jsm 1998-10-21
54 */
55
56#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
4e326852
JB
57#ifdef HAVE_ASM_DEBUGREG_H
58#include <asm/debugreg.h>
59#else
60#include <sys/debugreg.h>
61#endif
c906108c
SS
62#endif
63
64#include <sys/file.h>
65#include "gdb_stat.h"
66
67#ifdef HAVE_SYS_REG_H
68#include <sys/reg.h>
69#endif
70
71#include "floatformat.h"
72
73#include "target.h"
77d2aaae 74\f
4e326852 75
c906108c
SS
76/* this table must line up with REGISTER_NAMES in tm-i386v.h */
77/* symbols like 'EAX' come from <sys/reg.h> */
4e326852 78static int regmap[] =
c906108c
SS
79{
80 EAX, ECX, EDX, EBX,
81 UESP, EBP, ESI, EDI,
82 EIP, EFL, CS, SS,
83 DS, ES, FS, GS,
84};
85
86/* blockend is the value of u.u_ar0, and points to the
87 * place where GS is stored
88 */
89
90int
fba45db2 91i386_register_u_addr (int blockend, int regnum)
c906108c
SS
92{
93 struct user u;
94 int fpstate;
95 int ubase;
96
97 ubase = blockend;
98 /* FIXME: Should have better way to test floating point range */
4e326852 99 if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
c906108c 100 {
4e326852 101#ifdef KSTKSZ /* SCO, and others? */
c906108c 102 ubase += 4 * (SS + 1) - KSTKSZ;
4e326852 103 fpstate = ubase + ((char *) &u.u_fps.u_fpstate - (char *) &u);
c906108c
SS
104 return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
105#else
4e326852 106 fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
c906108c
SS
107 return (fpstate + 10 * (regnum - FP0_REGNUM));
108#endif
4e326852 109 }
c906108c
SS
110 else
111 {
112 return (ubase + 4 * regmap[regnum]);
113 }
4e326852 114
c906108c
SS
115}
116\f
117int
fba45db2 118kernel_u_size (void)
c906108c
SS
119{
120 return (sizeof (struct user));
121}
122\f
123#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
124
125#if !defined (offsetof)
126#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
127#endif
128
129/* Record the value of the debug control register. */
130static int debug_control_mirror;
131
132/* Record which address associates with which register. */
133static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
134
135static int
a14ed312 136i386_insert_aligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
c906108c
SS
137
138static int
a14ed312 139i386_insert_nonaligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
c906108c
SS
140
141/* Insert a watchpoint. */
142
143int
fba45db2 144i386_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
c906108c
SS
145{
146 return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
147}
148
149static int
fba45db2
KB
150i386_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
151 int len, int rw)
c906108c
SS
152{
153 int i;
154 int read_write_bits, len_bits;
155 int free_debug_register;
156 int register_number;
4e326852 157
c906108c
SS
158 /* Look for a free debug register. */
159 for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
160 {
161 if (address_lookup[i - DR_FIRSTADDR] == 0)
162 break;
163 }
164
165 /* No more debug registers! */
166 if (i > DR_LASTADDR)
167 return -1;
168
169 read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
170
171 if (len == 1)
172 len_bits = DR_LEN_1;
173 else if (len == 2)
174 {
175 if (addr % 2)
176 return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
177 len_bits = DR_LEN_2;
178 }
179
180 else if (len == 4)
181 {
182 if (addr % 4)
183 return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
184 len_bits = DR_LEN_4;
185 }
186 else
187 return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
4e326852 188
c906108c
SS
189 free_debug_register = i;
190 register_number = free_debug_register - DR_FIRSTADDR;
191 debug_control_mirror |=
192 ((read_write_bits | len_bits)
193 << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
194 debug_control_mirror |=
195 (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
196 debug_control_mirror |= DR_LOCAL_SLOWDOWN;
197 debug_control_mirror &= ~DR_CONTROL_RESERVED;
4e326852 198
c906108c
SS
199 ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
200 debug_control_mirror);
201 ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
202 addr);
203
204 /* Record where we came from. */
205 address_lookup[register_number] = addr;
206 return 0;
207}
208
209static int
fba45db2
KB
210i386_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
211 int len, int rw)
c906108c
SS
212{
213 int align;
214 int size;
215 int rv;
216
ceef0e30 217 static int size_try_array[4][4] =
4e326852 218 {
ceef0e30
JB
219 { 1, 1, 1, 1 }, /* trying size one */
220 { 2, 1, 2, 1 }, /* trying size two */
221 { 2, 1, 2, 1 }, /* trying size three */
222 { 4, 1, 2, 1 } /* trying size four */
c906108c
SS
223 };
224
225 rv = 0;
226 while (len > 0)
227 {
228 align = addr % 4;
229 /* Four is the maximum length for 386. */
ceef0e30 230 size = size_try_array[len > 4 ? 3 : len - 1][align];
c906108c
SS
231
232 rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
233 if (rv)
234 {
235 i386_remove_watchpoint (pid, waddr, size);
236 return rv;
237 }
238 addr += size;
239 len -= size;
240 }
241 return rv;
242}
243
244/* Remove a watchpoint. */
245
246int
fba45db2 247i386_remove_watchpoint (int pid, CORE_ADDR addr, int len)
c906108c
SS
248{
249 int i;
250 int register_number;
251
252 for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
253 {
254 register_number = i - DR_FIRSTADDR;
255 if (address_lookup[register_number] == addr)
256 {
257 debug_control_mirror &=
258 ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
259 address_lookup[register_number] = 0;
260 }
261 }
262 ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
263 debug_control_mirror);
264 ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
265
266 return 0;
267}
268
269/* Check if stopped by a watchpoint. */
270
271CORE_ADDR
fba45db2 272i386_stopped_by_watchpoint (int pid)
c906108c
SS
273{
274 int i;
275 int status;
276
277 status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
278 ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
279
280 for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
281 {
282 if (status & (1 << (i - DR_FIRSTADDR)))
283 return address_lookup[i - DR_FIRSTADDR];
284 }
285
286 return 0;
287}
288
289#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
This page took 0.159333 seconds and 4 git commands to generate.