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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [gdb/] [i386v-nat.c] - Blame information for rev 1778

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

Line No. Rev Author Line
1 1181 sfurman
/* Intel 386 native support for System V systems (pre-SVR4).
2
 
3
   Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
4
   1999, 2000, 2002 Free Software Foundation, Inc.
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
10
   the Free Software Foundation; either version 2 of the License, or
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
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 59 Temple Place - Suite 330,
21
   Boston, MA 02111-1307, USA.  */
22
 
23
#include "defs.h"
24
 
25
#ifdef HAVE_PTRACE_H
26
#include <ptrace.h>
27
#else
28
#ifdef HAVE_SYS_PTRACE_H
29
#include <sys/ptrace.h>
30
#endif
31
#endif
32
 
33
#include "frame.h"
34
#include "inferior.h"
35
#include "language.h"
36
#include "gdbcore.h"
37
 
38
#ifdef USG
39
#include <sys/types.h>
40
#endif
41
 
42
#include <sys/param.h>
43
#include <sys/dir.h>
44
#include <signal.h>
45
#include <sys/user.h>
46
#include <sys/ioctl.h>
47
#include <fcntl.h>
48
 
49
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
50
#include <sys/debugreg.h>
51
#endif
52
 
53
#include <sys/file.h>
54
#include "gdb_stat.h"
55
 
56
#ifdef HAVE_SYS_REG_H
57
#include <sys/reg.h>
58
#endif
59
 
60
#include "floatformat.h"
61
 
62
#include "target.h"
63
 
64
#include "i386-tdep.h"
65
 
66
 
67
/* Mapping between the general-purpose registers in `struct user'
68
   format and GDB's register array layout.  */
69
static int regmap[] =
70
{
71
  EAX, ECX, EDX, EBX,
72
  UESP, EBP, ESI, EDI,
73
  EIP, EFL, CS, SS,
74
  DS, ES, FS, GS,
75
};
76
 
77
/* Support for the user struct.  */
78
 
79
/* Return the address of register REGNUM.  BLOCKEND is the value of
80
   u.u_ar0, and points to the place where GS is stored.  */
81
 
82
CORE_ADDR
83
register_u_addr (CORE_ADDR blockend, int regnum)
84
{
85
  struct user u;
86
  CORE_ADDR fpstate;
87
 
88
  if (FP_REGNUM_P (regnum))
89
    {
90
#ifdef KSTKSZ                   /* SCO, and others?  */
91
      blockend += 4 * (SS + 1) - KSTKSZ;
92
      fpstate = blockend + ((char *) &u.u_fps.u_fpstate - (char *) &u);
93
      return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
94
#else
95
      fpstate = blockend + ((char *) &u.i387.st_space - (char *) &u);
96
      return (fpstate + 10 * (regnum - FP0_REGNUM));
97
#endif
98
    }
99
 
100
  return (blockend + 4 * regmap[regnum]);
101
}
102
 
103
/* Return the size of the user struct.  */
104
 
105
int
106
kernel_u_size (void)
107
{
108
  return (sizeof (struct user));
109
}
110
 
111
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
112
 
113
#if !defined (offsetof)
114
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
115
#endif
116
 
117
/* Record the value of the debug control register.  */
118
static int debug_control_mirror;
119
 
120
/* Record which address associates with which register.  */
121
static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
122
 
123
static int
124
i386_insert_aligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
125
 
126
static int
127
i386_insert_nonaligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
128
 
129
/* Insert a watchpoint.  */
130
 
131
int
132
i386_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
133
{
134
  return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
135
}
136
 
137
static int
138
i386_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
139
                                int len, int rw)
140
{
141
  int i;
142
  int read_write_bits, len_bits;
143
  int free_debug_register;
144
  int register_number;
145
 
146
  /* Look for a free debug register.  */
147
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
148
    {
149
      if (address_lookup[i - DR_FIRSTADDR] == 0)
150
        break;
151
    }
152
 
153
  /* No more debug registers!  */
154
  if (i > DR_LASTADDR)
155
    return -1;
156
 
157
  read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
158
 
159
  if (len == 1)
160
    len_bits = DR_LEN_1;
161
  else if (len == 2)
162
    {
163
      if (addr % 2)
164
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
165
      len_bits = DR_LEN_2;
166
    }
167
 
168
  else if (len == 4)
169
    {
170
      if (addr % 4)
171
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
172
      len_bits = DR_LEN_4;
173
    }
174
  else
175
    return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
176
 
177
  free_debug_register = i;
178
  register_number = free_debug_register - DR_FIRSTADDR;
179
  debug_control_mirror |=
180
    ((read_write_bits | len_bits)
181
     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
182
  debug_control_mirror |=
183
    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
184
  debug_control_mirror |= DR_LOCAL_SLOWDOWN;
185
  debug_control_mirror &= ~DR_CONTROL_RESERVED;
186
 
187
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
188
          debug_control_mirror);
189
  ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
190
          addr);
191
 
192
  /* Record where we came from.  */
193
  address_lookup[register_number] = addr;
194
  return 0;
195
}
196
 
197
static int
198
i386_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
199
                                   int len, int rw)
200
{
201
  int align;
202
  int size;
203
  int rv;
204
 
205
  static int size_try_array[4][4] =
206
  {
207
    { 1, 1, 1, 1 },             /* trying size one */
208
    { 2, 1, 2, 1 },             /* trying size two */
209
    { 2, 1, 2, 1 },             /* trying size three */
210
    { 4, 1, 2, 1 }              /* trying size four */
211
  };
212
 
213
  rv = 0;
214
  while (len > 0)
215
    {
216
      align = addr % 4;
217
      /* Four is the maximum length for 386.  */
218
      size = size_try_array[len > 4 ? 3 : len - 1][align];
219
 
220
      rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
221
      if (rv)
222
        {
223
          i386_remove_watchpoint (pid, waddr, size);
224
          return rv;
225
        }
226
      addr += size;
227
      len -= size;
228
    }
229
  return rv;
230
}
231
 
232
/* Remove a watchpoint.  */
233
 
234
int
235
i386_remove_watchpoint (int pid, CORE_ADDR addr, int len)
236
{
237
  int i;
238
  int register_number;
239
 
240
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
241
    {
242
      register_number = i - DR_FIRSTADDR;
243
      if (address_lookup[register_number] == addr)
244
        {
245
          debug_control_mirror &=
246
            ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
247
          address_lookup[register_number] = 0;
248
        }
249
    }
250
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
251
          debug_control_mirror);
252
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
253
 
254
  return 0;
255
}
256
 
257
/* Check if stopped by a watchpoint.  */
258
 
259
CORE_ADDR
260
i386_stopped_by_watchpoint (int pid)
261
{
262
  int i;
263
  int status;
264
 
265
  status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
266
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
267
 
268
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
269
    {
270
      if (status & (1 << (i - DR_FIRSTADDR)))
271
        return address_lookup[i - DR_FIRSTADDR];
272
    }
273
 
274
  return 0;
275
}
276
 
277
#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.