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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [hppab-nat.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 578 markom
/* Machine-dependent hooks for the unix child process stratum.  This
2
   code is for the HP PA-RISC cpu.
3
 
4
   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1998,
5
   1999, 2000, 2001 Free Software Foundation, Inc.
6
 
7
   Contributed by the Center for Software Science at the
8
   University of Utah (pa-gdb-bugs@cs.utah.edu).
9
 
10
   This file is part of GDB.
11
 
12
   This program is free software; you can redistribute it and/or modify
13
   it under the terms of the GNU General Public License as published by
14
   the Free Software Foundation; either version 2 of the License, or
15
   (at your option) any later version.
16
 
17
   This program is distributed in the hope that it will be useful,
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   GNU General Public License for more details.
21
 
22
   You should have received a copy of the GNU General Public License
23
   along with this program; if not, write to the Free Software
24
   Foundation, Inc., 59 Temple Place - Suite 330,
25
   Boston, MA 02111-1307, USA.  */
26
 
27
#include "defs.h"
28
#include "inferior.h"
29
#include "target.h"
30
#include "regcache.h"
31
#include <sys/ptrace.h>
32
 
33
/* Use an extra level of indirection for ptrace calls.
34
   This lets us breakpoint usefully on call_ptrace.   It also
35
   allows us to pass an extra argument to ptrace without
36
   using an ANSI-C specific macro.  */
37
 
38
#define ptrace call_ptrace
39
 
40
#if !defined (offsetof)
41
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
42
#endif
43
 
44
/* U_REGS_OFFSET is the offset of the registers within the u area.  */
45
#if !defined (U_REGS_OFFSET)
46
#define U_REGS_OFFSET \
47
  ptrace (PT_READ_U, PIDGET (inferior_ptid), \
48
          (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
49
    - KERNEL_U_ADDR
50
#endif
51
 
52
/* Fetch one register.  */
53
 
54
static void
55
fetch_register (int regno)
56
{
57
  register unsigned int regaddr;
58
  char buf[MAX_REGISTER_RAW_SIZE];
59
  register int i;
60
 
61
  /* Offset of registers within the u area.  */
62
  unsigned int offset;
63
 
64
  offset = U_REGS_OFFSET;
65
 
66
  regaddr = register_addr (regno, offset);
67
  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
68
    {
69
      errno = 0;
70
      *(int *) &buf[i] = ptrace (PT_RUREGS, PIDGET (inferior_ptid),
71
                                 (PTRACE_ARG3_TYPE) regaddr, 0);
72
      regaddr += sizeof (int);
73
      if (errno != 0)
74
        {
75
          /* Warning, not error, in case we are attached; sometimes the
76
             kernel doesn't let us at the registers.  */
77
          char *err = safe_strerror (errno);
78
          char *msg = alloca (strlen (err) + 128);
79
          sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
80
          warning (msg);
81
          goto error_exit;
82
        }
83
    }
84
  supply_register (regno, buf);
85
error_exit:;
86
}
87
 
88
/* Fetch all registers, or just one, from the child process.  */
89
 
90
void
91
fetch_inferior_registers (int regno)
92
{
93
  if (regno == -1)
94
    for (regno = 0; regno < NUM_REGS; regno++)
95
      fetch_register (regno);
96
  else
97
    fetch_register (regno);
98
}
99
 
100
/* Store our register values back into the inferior.
101
   If REGNO is -1, do this for all registers.
102
   Otherwise, REGNO specifies which register (so we can save time).  */
103
 
104
void
105
store_inferior_registers (int regno)
106
{
107
  register unsigned int regaddr;
108
  char buf[80];
109
  register int i;
110
  unsigned int offset = U_REGS_OFFSET;
111
  int scratch;
112
 
113
  if (regno >= 0)
114
    {
115
      if (CANNOT_STORE_REGISTER (regno))
116
        return;
117
      regaddr = register_addr (regno, offset);
118
      errno = 0;
119
      if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
120
        {
121
          scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
122
          ptrace (PT_WUREGS, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr,
123
                  scratch);
124
          if (errno != 0)
125
            {
126
              /* Error, even if attached.  Failing to write these two
127
                 registers is pretty serious.  */
128
              sprintf (buf, "writing register number %d", regno);
129
              perror_with_name (buf);
130
            }
131
        }
132
      else
133
        for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
134
          {
135
            errno = 0;
136
            ptrace (PT_WUREGS, PIDGET (inferior_ptid),
137
                    (PTRACE_ARG3_TYPE) regaddr,
138
                    *(int *) &registers[REGISTER_BYTE (regno) + i]);
139
            if (errno != 0)
140
              {
141
                /* Warning, not error, in case we are attached; sometimes the
142
                   kernel doesn't let us at the registers.  */
143
                char *err = safe_strerror (errno);
144
                char *msg = alloca (strlen (err) + 128);
145
                sprintf (msg, "writing register %s: %s",
146
                         REGISTER_NAME (regno), err);
147
                warning (msg);
148
                return;
149
              }
150
            regaddr += sizeof (int);
151
          }
152
    }
153
  else
154
    for (regno = 0; regno < NUM_REGS; regno++)
155
      store_inferior_registers (regno);
156
}
157
 
158
/* PT_PROT is specific to the PA BSD kernel and isn't documented
159
   anywhere (except here).
160
 
161
   PT_PROT allows one to enable/disable the data memory break bit
162
   for pages of memory in an inferior process.  This bit is used
163
   to cause "Data memory break traps" to occur when the appropriate
164
   page is written to.
165
 
166
   The arguments are as follows:
167
 
168
   PT_PROT -- The ptrace action to perform.
169
 
170
   INFERIOR_PID -- The pid of the process who's page table entries
171
   will be modified.
172
 
173
   PT_ARGS -- The *address* of a 3 word block of memory which has
174
   additional information:
175
 
176
   word 0 -- The start address to watch.  This should be a page-aligned
177
   address.
178
 
179
   word 1 -- The ending address to watch.  Again, this should be a
180
   page aligned address.
181
 
182
   word 2 -- Nonzero to enable the data memory break bit on the
183
   given address range or zero to disable the data memory break
184
   bit on the given address range.
185
 
186
   This call may fail if the given addresses are not valid in the inferior
187
   process.  This most often happens when restarting a program which
188
   has watchpoints inserted on heap or stack memory.  */
189
 
190
#define PT_PROT 21
191
 
192
int
193
hppa_set_watchpoint (int addr, int len, int flag)
194
{
195
  int pt_args[3];
196
  pt_args[0] = addr;
197
  pt_args[1] = addr + len;
198
  pt_args[2] = flag;
199
 
200
  /* Mask off the lower 12 bits since we want to work on a page basis.  */
201
  pt_args[0] >>= 12;
202
  pt_args[1] >>= 12;
203
 
204
  /* Rounding adjustments.  */
205
  pt_args[1] -= pt_args[0];
206
  pt_args[1]++;
207
 
208
  /* Put the lower 12 bits back as zero.  */
209
  pt_args[0] <<= 12;
210
  pt_args[1] <<= 12;
211
 
212
  /* Do it.  */
213
  return ptrace (PT_PROT, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) pt_args, 0);
214
}

powered by: WebSVN 2.1.0

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