* testsuite/regress-demangle (failed test): Show result and
[binutils-gdb.git] / gdb / hppab-nat.c
blob29d22ebad4696afa3759bedd9672392f6e9a556c
1 /* Machine-dependent hooks for the unix child process stratum. This
2 code is for the HP PA-RISC cpu.
4 Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
6 Contributed by the Center for Software Science at the
7 University of Utah (pa-gdb-bugs@cs.utah.edu).
9 This file is part of GDB.
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.
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.
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. */
26 #include "defs.h"
27 #include "inferior.h"
28 #include "target.h"
29 #include <sys/ptrace.h>
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. */
36 #define ptrace call_ptrace
38 #if !defined (offsetof)
39 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
40 #endif
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
50 /* Fetch one register. */
52 static void
53 fetch_register (regno)
54 int regno;
56 register unsigned int regaddr;
57 char buf[MAX_REGISTER_RAW_SIZE];
58 register int i;
60 /* Offset of registers within the u area. */
61 unsigned int offset;
63 offset = U_REGS_OFFSET;
65 regaddr = register_addr (regno, offset);
66 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
68 errno = 0;
69 *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
70 (PTRACE_ARG3_TYPE) regaddr, 0);
71 regaddr += sizeof (int);
72 if (errno != 0)
74 /* Warning, not error, in case we are attached; sometimes the
75 kernel doesn't let us at the registers. */
76 char *err = safe_strerror (errno);
77 char *msg = alloca (strlen (err) + 128);
78 sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
79 warning (msg);
80 goto error_exit;
83 supply_register (regno, buf);
84 error_exit:;
87 /* Fetch all registers, or just one, from the child process. */
89 void
90 fetch_inferior_registers (regno)
91 int regno;
93 if (regno == -1)
94 for (regno = 0; regno < NUM_REGS; regno++)
95 fetch_register (regno);
96 else
97 fetch_register (regno);
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). */
104 void
105 store_inferior_registers (regno)
106 int regno;
108 register unsigned int regaddr;
109 char buf[80];
110 register int i;
111 unsigned int offset = U_REGS_OFFSET;
112 int scratch;
114 if (regno >= 0)
116 if (CANNOT_STORE_REGISTER (regno))
117 return;
118 regaddr = register_addr (regno, offset);
119 errno = 0;
120 if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
122 scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
123 ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
124 scratch);
125 if (errno != 0)
127 /* Error, even if attached. Failing to write these two
128 registers is pretty serious. */
129 sprintf (buf, "writing register number %d", regno);
130 perror_with_name (buf);
133 else
134 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
136 errno = 0;
137 ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
138 *(int *) &registers[REGISTER_BYTE (regno) + i]);
139 if (errno != 0)
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;
150 regaddr += sizeof (int);
153 else
154 for (regno = 0; regno < NUM_REGS; regno++)
155 store_inferior_registers (regno);
158 /* PT_PROT is specific to the PA BSD kernel and isn't documented
159 anywhere (except here).
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.
166 The arguments are as follows:
168 PT_PROT -- The ptrace action to perform.
170 INFERIOR_PID -- The pid of the process who's page table entries
171 will be modified.
173 PT_ARGS -- The *address* of a 3 word block of memory which has
174 additional information:
176 word 0 -- The start address to watch. This should be a page-aligned
177 address.
179 word 1 -- The ending address to watch. Again, this should be a
180 page aligned address.
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.
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 as watchpoints inserted on heap or stack memory. */
190 #define PT_PROT 21
193 hppa_set_watchpoint (addr, len, flag)
194 int addr, len, flag;
196 int pt_args[3];
197 pt_args[0] = addr;
198 pt_args[1] = addr + len;
199 pt_args[2] = flag;
201 /* Mask off the lower 12 bits since we want to work on a page basis. */
202 pt_args[0] >>= 12;
203 pt_args[1] >>= 12;
205 /* Rounding adjustments. */
206 pt_args[1] -= pt_args[0];
207 pt_args[1]++;
209 /* Put the lower 12 bits back as zero. */
210 pt_args[0] <<= 12;
211 pt_args[1] <<= 12;
213 /* Do it. */
214 return ptrace (PT_PROT, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0);