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