]> Git Repo - binutils.git/blob - gdb/hppab-nat.c
Phase 1 of the ptid_t changes.
[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, 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 ([email protected]).
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 }
This page took 0.03603 seconds and 4 git commands to generate.