* Check in Fred Fish's changes in these modules. Fred
[binutils-gdb.git] / gdb / pyr-xdep.c
1 /* Low level Pyramid interface to ptrace, for GDB when running under Unix.
2 Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include <stdio.h>
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24
25 #include <sys/param.h>
26 #include <sys/dir.h>
27 #include <signal.h>
28 #include <sys/ioctl.h>
29 /* #include <fcntl.h> Can we live without this? */
30
31 #include "gdbcore.h"
32 #include <sys/user.h> /* After a.out.h */
33 #include <sys/file.h>
34 #include <sys/stat.h>
35
36 \f
37 void
38 fetch_inferior_registers (regno)
39 int regno;
40 {
41 register int datum;
42 register unsigned int regaddr;
43 int reg_buf[NUM_REGS+1];
44 struct user u;
45 register int skipped_frames = 0;
46
47 registers_fetched ();
48
49 for (regno = 0; regno < 64; regno++) {
50 reg_buf[regno] = ptrace (3, inferior_pid, regno, 0);
51
52 #if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
53 printf ("Fetching %s from inferior, got %0x\n",
54 reg_names[regno],
55 reg_buf[regno]);
56 #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
57
58 if (reg_buf[regno] == -1 && errno == EIO) {
59 printf("fetch_interior_registers: fetching %s from inferior\n",
60 reg_names[regno]);
61 errno = 0;
62 }
63 supply_register (regno, reg_buf+regno);
64 }
65 /* that leaves regs 64, 65, and 66 */
66 datum = ptrace (3, inferior_pid,
67 ((char *)&u.u_pcb.pcb_csp) -
68 ((char *)&u), 0);
69
70
71
72 /* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
73 register (ie, NOT windowed), that gets saved in a frame iff
74 the code for that frame has a prologue (ie, "adsf N"). If
75 there is a prologue, the adsf insn saves the old cfp in
76 pr13, cfp is set to sp, and N bytes of locals are allocated
77 (sp is decremented by n).
78 This makes finding CFP hard. I guess the right way to do it
79 is:
80 - If this is the innermost frame, believe ptrace() or
81 the core area.
82 - Otherwise:
83 Find the first insn of the current frame.
84 - find the saved pc;
85 - find the call insn that saved it;
86 - figure out where the call is to;
87 - if the first insn is an adsf, we got a frame
88 pointer. */
89
90
91 /* Normal processors have separate stack pointers for user and
92 kernel mode. Getting the last user mode frame on such
93 machines is easy: the kernel context of the ptrace()'d
94 process is on the kernel stack, and the USP points to what
95 we want. But Pyramids only have a single cfp for both user and
96 kernel mode. And processes being ptrace()'d have some
97 kernel-context control frames on their stack.
98 To avoid tracing back into the kernel context of an inferior,
99 we skip 0 or more contiguous control frames where the pc is
100 in the kernel. */
101
102 while (1) {
103 register int inferior_saved_pc;
104 inferior_saved_pc = ptrace (1, inferior_pid, datum+((32+15)*4), 0);
105 if (inferior_saved_pc > 0) break;
106 #if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
107 printf("skipping kernel frame %08x, pc=%08x\n", datum,
108 inferior_saved_pc);
109 #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
110 skipped_frames++;
111 datum -= CONTROL_STACK_FRAME_SIZE;
112 }
113
114 reg_buf[CSP_REGNUM] = datum;
115 supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
116 #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
117 if (skipped_frames) {
118 fprintf (stderr,
119 "skipped %d frames from %x to %x; cfp was %x, now %x\n",
120 skipped_frames, reg_buf[CSP_REGNUM]);
121 }
122 #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
123 }
124
125 /* Store our register values back into the inferior.
126 If REGNO is -1, do this for all registers.
127 Otherwise, REGNO specifies which register (so we can save time). */
128
129 void
130 store_inferior_registers (regno)
131 int regno;
132 {
133 register unsigned int regaddr;
134 char buf[80];
135
136 if (regno >= 0)
137 {
138 if ((0 <= regno) && (regno < 64)) {
139 /*regaddr = register_addr (regno, offset);*/
140 regaddr = regno;
141 errno = 0;
142 ptrace (6, inferior_pid, regaddr, read_register (regno));
143 if (errno != 0)
144 {
145 sprintf (buf, "writing register number %d", regno);
146 perror_with_name (buf);
147 }
148 }
149 }
150 else
151 {
152 for (regno = 0; regno < NUM_REGS; regno++)
153 {
154 /*regaddr = register_addr (regno, offset);*/
155 regaddr = regno;
156 errno = 0;
157 ptrace (6, inferior_pid, regaddr, read_register (regno));
158 if (errno != 0)
159 {
160 sprintf (buf, "writing all regs, number %d", regno);
161 perror_with_name (buf);
162 }
163 }
164 }
165 \f
166 /*** Extensions to core and dump files, for GDB. */
167
168 extern unsigned int last_frame_offset;
169
170 #ifdef PYRAMID_CORE
171
172 /* Can't make definitions here static, since core.c needs them
173 to do bounds checking on the core-file areas. O well. */
174
175 /* have two stacks: one for data, one for register windows. */
176 extern CORE_ADDR reg_stack_start;
177 extern CORE_ADDR reg_stack_end;
178
179 /* need this so we can find the global registers: they never get saved. */
180 CORE_ADDR global_reg_offset;
181 static CORE_ADDR last_frame_address;
182 CORE_ADDR last_frame_offset;
183
184
185 /* Address in core file of start of register window stack area.
186 Don't know if is this any of meaningful, useful or necessary. */
187 extern int reg_stack_offset;
188
189 #endif /* PYRAMID_CORE */
190
191 \f
192 /* Work with core dump and executable files, for GDB.
193 This code would be in core.c if it weren't machine-dependent. */
194
195 void
196 core_file_command (filename, from_tty)
197 char *filename;
198 int from_tty;
199 {
200 int val;
201 extern char registers[];
202
203 /* Discard all vestiges of any previous core file
204 and mark data and stack spaces as empty. */
205
206 if (corefile)
207 free (corefile);
208 corefile = 0;
209
210 if (corechan >= 0)
211 close (corechan);
212 corechan = -1;
213
214 data_start = 0;
215 data_end = 0;
216 stack_start = STACK_END_ADDR;
217 stack_end = STACK_END_ADDR;
218
219 #ifdef PYRAMID_CORE
220 reg_stack_start = CONTROL_STACK_ADDR;
221 reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
222 #endif /* PYRAMID_CORE */
223
224 /* Now, if a new core file was specified, open it and digest it. */
225
226 if (filename)
227 {
228 filename = tilde_expand (filename);
229 make_cleanup (free, filename);
230
231 if (have_inferior_p ())
232 error ("To look at a core file, you must kill the inferior with \"kill\".");
233 corechan = open (filename, O_RDONLY, 0);
234 if (corechan < 0)
235 perror_with_name (filename);
236 /* 4.2-style (and perhaps also sysV-style) core dump file. */
237 {
238 struct user u;
239
240 unsigned int reg_offset;
241
242 val = myread (corechan, &u, sizeof u);
243 if (val < 0)
244 perror_with_name ("Not a core file: reading upage");
245 if (val != sizeof u)
246 error ("Not a core file: could only read %d bytes", val);
247 data_start = exec_data_start;
248
249 data_end = data_start + NBPG * u.u_dsize;
250 data_offset = NBPG * UPAGES;
251 stack_offset = NBPG * (UPAGES + u.u_dsize);
252
253 /* find registers in core file */
254 #ifdef PYRAMID_PTRACE
255 stack_start = stack_end - NBPG * u.u_ussize;
256 reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
257 reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
258
259 last_frame_address = ((int) u.u_pcb.pcb_csp);
260 last_frame_offset = reg_stack_offset + last_frame_address
261 - CONTROL_STACK_ADDR ;
262 global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
263
264 /* skip any control-stack frames that were executed in the
265 kernel. */
266
267 while (1) {
268 char buf[4];
269 val = lseek (corechan, last_frame_offset+(47*4), 0);
270 if (val < 0)
271 perror_with_name (filename);
272 val = myread (corechan, buf, sizeof buf);
273 if (val < 0)
274 perror_with_name (filename);
275
276 if (*(int *)buf >= 0)
277 break;
278 printf ("skipping frame %s\n", local_hex_string (last_frame_address));
279 last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
280 last_frame_address -= CONTROL_STACK_FRAME_SIZE;
281 }
282 reg_offset = last_frame_offset;
283
284 #if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
285 printf ("Control stack pointer = %s\n",
286 local_hex_string (u.u_pcb.pcb_csp));
287 printf ("offset to control stack %d outermost frame %d (%s)\n",
288 reg_stack_offset, reg_offset, local_hex_string (last_frame_address));
289 #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
290
291 #else /* not PYRAMID_CORE */
292 stack_start = stack_end - NBPG * u.u_ssize;
293 reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
294 #endif /* not PYRAMID_CORE */
295
296 #ifdef __not_on_pyr_yet
297 /* Some machines put an absolute address in here and some put
298 the offset in the upage of the regs. */
299 reg_offset = (int) u.u_ar0;
300 if (reg_offset > NBPG * UPAGES)
301 reg_offset -= KERNEL_U_ADDR;
302 #endif
303
304 /* I don't know where to find this info.
305 So, for now, mark it as not available. */
306 N_SET_MAGIC (core_aouthdr, 0);
307
308 /* Read the register values out of the core file and store
309 them where `read_register' will find them. */
310
311 {
312 register int regno;
313
314 for (regno = 0; regno < 64; regno++)
315 {
316 char buf[MAX_REGISTER_RAW_SIZE];
317
318 val = lseek (corechan, register_addr (regno, reg_offset), 0);
319 if (val < 0
320 || (val = myread (corechan, buf, sizeof buf)) < 0)
321 {
322 char * buffer = (char *) alloca (strlen (reg_names[regno])
323 + 30);
324 strcpy (buffer, "Reading register ");
325 strcat (buffer, reg_names[regno]);
326
327 perror_with_name (buffer);
328 }
329
330 if (val < 0)
331 perror_with_name (filename);
332 #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
333 printf ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
334 reg_names[regno], regno, filename,
335 register_addr(regno, reg_offset),
336 regno * 4 + last_frame_address,
337 *((int *)buf));
338 #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
339 supply_register (regno, buf);
340 }
341 }
342 }
343 if (filename[0] == '/')
344 corefile = savestring (filename, strlen (filename));
345 else
346 {
347 corefile = concat (current_directory, "/", filename, NULL);
348 }
349
350 #if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
351 printf ("Providing CSP (%s) as nominal address of current frame.\n",
352 local_hex_string(last_frame_address));
353 #endif PYRAMID_CONTROL_FRAME_DEBUGGING
354 /* FIXME: Which of the following is correct? */
355 #if 0
356 set_current_frame ( create_new_frame (read_register (FP_REGNUM),
357 read_pc ()));
358 #else
359 set_current_frame ( create_new_frame (last_frame_address,
360 read_pc ()));
361 #endif
362
363 select_frame (get_current_frame (), 0);
364 validate_files ();
365 }
366 else if (from_tty)
367 printf ("No core file now.\n");
368 }