import gdb-1999-06-14 snapshot
[deliverable/binutils-gdb.git] / gdb / hppab-nat.c
CommitLineData
c906108c
SS
1/* 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 Free Software Foundation, Inc.
5
6 Contributed by the Center for Software Science at the
7 University of Utah (pa-gdb-bugs@cs.utah.edu).
8
9This file is part of GDB.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#include "defs.h"
26#include "inferior.h"
27#include "target.h"
28#include <sys/ptrace.h>
29
30/* Use an extra level of indirection for ptrace calls.
31 This lets us breakpoint usefully on call_ptrace. It also
32 allows us to pass an extra argument to ptrace without
33 using an ANSI-C specific macro. */
34
35#define ptrace call_ptrace
36
37#if !defined (offsetof)
38#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
39#endif
40
41/* U_REGS_OFFSET is the offset of the registers within the u area. */
42#if !defined (U_REGS_OFFSET)
43#define U_REGS_OFFSET \
44 ptrace (PT_READ_U, inferior_pid, \
45 (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
46 - KERNEL_U_ADDR
47#endif
48
49/* Fetch one register. */
50
51static void
52fetch_register (regno)
53 int regno;
54{
55 register unsigned int regaddr;
56 char buf[MAX_REGISTER_RAW_SIZE];
57 register int i;
58
59 /* Offset of registers within the u area. */
60 unsigned int offset;
61
62 offset = U_REGS_OFFSET;
63
64 regaddr = register_addr (regno, offset);
65 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
66 {
67 errno = 0;
68 *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
69 (PTRACE_ARG3_TYPE) regaddr, 0);
70 regaddr += sizeof (int);
71 if (errno != 0)
72 {
73 /* Warning, not error, in case we are attached; sometimes the
74 kernel doesn't let us at the registers. */
75 char *err = safe_strerror (errno);
76 char *msg = alloca (strlen (err) + 128);
77 sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
78 warning (msg);
79 goto error_exit;
80 }
81 }
82 supply_register (regno, buf);
83 error_exit:;
84}
85
86/* Fetch all registers, or just one, from the child process. */
87
88void
89fetch_inferior_registers (regno)
90 int regno;
91{
92 if (regno == -1)
93 for (regno = 0; regno < NUM_REGS; regno++)
94 fetch_register (regno);
95 else
96 fetch_register (regno);
97}
98
99/* Store our register values back into the inferior.
100 If REGNO is -1, do this for all registers.
101 Otherwise, REGNO specifies which register (so we can save time). */
102
103void
104store_inferior_registers (regno)
105 int regno;
106{
107 register unsigned int regaddr;
108 char buf[80];
c906108c
SS
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, inferior_pid, (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, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
137 *(int *) &registers[REGISTER_BYTE (regno) + i]);
138 if (errno != 0)
139 {
140 /* Warning, not error, in case we are attached; sometimes the
141 kernel doesn't let us at the registers. */
142 char *err = safe_strerror (errno);
143 char *msg = alloca (strlen (err) + 128);
144 sprintf (msg, "writing register %s: %s",
145 REGISTER_NAME (regno), err);
146 warning (msg);
147 return;
148 }
149 regaddr += sizeof(int);
150 }
151 }
152 else
153 for (regno = 0; regno < NUM_REGS; regno++)
154 store_inferior_registers (regno);
155}
156
157/* PT_PROT is specific to the PA BSD kernel and isn't documented
158 anywhere (except here).
159
160 PT_PROT allows one to enable/disable the data memory break bit
161 for pages of memory in an inferior process. This bit is used
162 to cause "Data memory break traps" to occur when the appropriate
163 page is written to.
164
165 The arguments are as follows:
166
167 PT_PROT -- The ptrace action to perform.
168
169 INFERIOR_PID -- The pid of the process who's page table entries
170 will be modified.
171
172 PT_ARGS -- The *address* of a 3 word block of memory which has
173 additional information:
174
175 word 0 -- The start address to watch. This should be a page-aligned
176 address.
177
178 word 1 -- The ending address to watch. Again, this should be a
179 page aligned address.
180
181 word 2 -- Nonzero to enable the data memory break bit on the
182 given address range or zero to disable the data memory break
183 bit on the given address range.
184
185 This call may fail if the given addresses are not valid in the inferior
186 process. This most often happens when restarting a program which
187 as watchpoints inserted on heap or stack memory. */
188
189#define PT_PROT 21
190
191int
192hppa_set_watchpoint (addr, len, flag)
193 int addr, len, 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, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0);
214}
This page took 0.034453 seconds and 4 git commands to generate.