]> Git Repo - binutils.git/blob - gdb/hppab-nat.c
* nlm/gdbserve.c: conditionalize header file inclusion for either
[binutils.git] / gdb / hppab-nat.c
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 ([email protected]).
8
9 This file is part of GDB.
10
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.
15
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.
20
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., 675 Mass Ave, Cambridge, MA 02139, 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
51 static void
52 fetch_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", reg_names[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
88 void
89 fetch_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
103 void
104 store_inferior_registers (regno)
105      int regno;
106 {
107   register unsigned int regaddr;
108   extern char registers[];
109   register int i;
110
111   unsigned int offset = U_REGS_OFFSET;
112
113   if (regno >= 0)
114     {
115       regaddr = register_addr (regno, offset);
116       for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
117         {
118           errno = 0;
119           ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
120                   *(int *) &registers[REGISTER_BYTE (regno) + i]);
121           if (errno != 0)
122             {
123               char *err = safe_strerror (errno);
124               char *msg = alloca (strlen (err) + 128);
125               sprintf (msg, "writing register %s: %s", reg_names[regno], err);
126               warning (msg);
127             }
128           regaddr += sizeof(int);
129         }
130     }
131   else
132     {
133       for (regno = 0; regno < NUM_REGS; regno++)
134         {
135           if (CANNOT_STORE_REGISTER (regno))
136             continue;
137           store_inferior_registers (regno);
138         }
139     }
140   return;
141 }
142
143
144 /* PT_PROT is specific to the PA BSD kernel and isn't documented
145    anywhere (except here).  
146
147    PT_PROT allows one to enable/disable the data memory break bit
148    for pages of memory in an inferior process.  This bit is used
149    to cause "Data memory break traps" to occur when the appropriate
150    page is written to.
151
152    The arguments are as follows:
153
154       PT_PROT -- The ptrace action to perform.
155
156       INFERIOR_PID -- The pid of the process who's page table entries
157       will be modified.
158
159       PT_ARGS -- The *address* of a 3 word block of memory which has
160       additional information:
161
162         word 0 -- The start address to watch.  This should be a page-aligned
163         address.
164
165         word 1 -- The ending address to watch.  Again, this should be a 
166         page aligned address.
167
168         word 2 -- Nonzero to enable the data memory break bit on the
169         given address range or zero to disable the data memory break
170         bit on the given address range.
171
172   This call may fail if the given addresses are not valid in the inferior
173   process.  This most often happens when restarting a program which
174   as watchpoints inserted on heap or stack memory.  */
175         
176 #define PT_PROT 21
177
178 int
179 hppa_set_watchpoint (addr, len, flag)
180      int addr, len, flag;
181 {
182   int pt_args[3];
183   pt_args[0] = addr;
184   pt_args[1] = addr + len;
185   pt_args[2] = flag;
186
187   /* Mask off the lower 12 bits since we want to work on a page basis.  */
188   pt_args[0] >>= 12; 
189   pt_args[1] >>= 12; 
190
191   /* Rounding adjustments.  */
192   pt_args[1] -= pt_args[0]; 
193   pt_args[1]++; 
194
195   /* Put the lower 12 bits back as zero.  */
196   pt_args[0] <<= 12; 
197   pt_args[1] <<= 12; 
198
199   /* Do it.  */
200   return ptrace (PT_PROT, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0);
201 }
This page took 0.03796 seconds and 4 git commands to generate.