OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [i386v-nat.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.