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