diff options
author | Stan Shebs <shebs@codesourcery.com> | 1993-10-30 00:16:25 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1993-10-30 00:16:25 +0000 |
commit | 9bebe5008136deb7bed1667f637bb47b0fc1580b (patch) | |
tree | 442fabe583d366eeae77d06ee971070718483f15 /gdb/sparcly-nat.c | |
parent | 762df61d4c38314139a7f518e96f747586d45f7c (diff) | |
download | gdb-9bebe5008136deb7bed1667f637bb47b0fc1580b.zip gdb-9bebe5008136deb7bed1667f637bb47b0fc1580b.tar.gz gdb-9bebe5008136deb7bed1667f637bb47b0fc1580b.tar.bz2 |
More LynxOS support
Diffstat (limited to 'gdb/sparcly-nat.c')
-rw-r--r-- | gdb/sparcly-nat.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/gdb/sparcly-nat.c b/gdb/sparcly-nat.c new file mode 100644 index 0000000..193fa1e --- /dev/null +++ b/gdb/sparcly-nat.c @@ -0,0 +1,363 @@ +/* Native-dependent code for Sparc running LynxOS. + Copyright (C) 1989, 1992, Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "target.h" + +#include <signal.h> +#include <sys/ptrace.h> +#include <sys/wait.h> +#if 0 +#include <machine/reg.h> +#endif + +/* We don't store all registers immediately when requested, since they + get sent over in large chunks anyway. Instead, we accumulate most + of the changes and send them over once. "deferred_stores" keeps + track of which sets of registers we have locally-changed copies of, + so we only need send the groups that have changed. */ + +#define INT_REGS 1 +#define STACK_REGS 2 +#define FP_REGS 4 + +/* Fetch one or more registers from the inferior. REGNO == -1 to get + them all. We actually fetch more than requested, when convenient, + marking them as valid so we won't fetch them again. */ + +void +fetch_inferior_registers (regno) + int regno; +{ +#if 0 + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + int i; + + /* We should never be called with deferred stores, because a prerequisite + for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh. */ + if (deferred_stores) abort(); + + DO_DEFERRED_STORES; + + /* Global and Out regs are fetched directly, as well as the control + registers. If we're getting one of the in or local regs, + and the stack pointer has not yet been fetched, + we have to do that first, since they're found in memory relative + to the stack pointer. */ + if (regno < O7_REGNUM /* including -1 */ + || regno >= Y_REGNUM + || (!register_valid[SP_REGNUM] && regno < I7_REGNUM)) + { + if (0 != ptrace (PTRACE_GETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0)) + perror("ptrace_getregs"); + + registers[REGISTER_BYTE (0)] = 0; + memcpy (®isters[REGISTER_BYTE (1)], &inferior_registers.r_g1, + 15 * REGISTER_RAW_SIZE (G0_REGNUM)); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc; + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y; + + for (i = G0_REGNUM; i <= O7_REGNUM; i++) + register_valid[i] = 1; + register_valid[Y_REGNUM] = 1; + register_valid[PS_REGNUM] = 1; + register_valid[PC_REGNUM] = 1; + register_valid[NPC_REGNUM] = 1; + /* If we don't set these valid, read_register_bytes() rereads + all the regs every time it is called! FIXME. */ + register_valid[WIM_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[TBR_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[FPS_REGNUM] = 1; /* Not true yet, FIXME */ + register_valid[CPS_REGNUM] = 1; /* Not true yet, FIXME */ + } + + /* Floating point registers */ + if (regno == -1 || (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31)) + { + if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_fp_registers, + 0)) + perror("ptrace_getfpregs"); + memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers, + sizeof inferior_fp_registers.fpu_fr); + /* memcpy (®isters[REGISTER_BYTE (FPS_REGNUM)], + &inferior_fp_registers.Fpu_fsr, + sizeof (FPU_FSR_TYPE)); FIXME??? -- gnu@cyg */ + for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++) + register_valid[i] = 1; + register_valid[FPS_REGNUM] = 1; + } + + /* These regs are saved on the stack by the kernel. Only read them + all (16 ptrace calls!) if we really need them. */ + if (regno == -1) + { + target_xfer_memory (*(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)], + ®isters[REGISTER_BYTE (L0_REGNUM)], + 16*REGISTER_RAW_SIZE (L0_REGNUM), 0); + for (i = L0_REGNUM; i <= I7_REGNUM; i++) + register_valid[i] = 1; + } + else if (regno >= L0_REGNUM && regno <= I7_REGNUM) + { + CORE_ADDR sp = *(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)]; + i = REGISTER_BYTE (regno); + if (register_valid[regno]) + printf("register %d valid and read\n", regno); + target_xfer_memory (sp + i - REGISTER_BYTE (L0_REGNUM), + ®isters[i], REGISTER_RAW_SIZE (regno), 0); + register_valid[regno] = 1; + } +#endif +} + +/* Store our register values back into the inferior. + If REGNO is -1, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +void +store_inferior_registers (regno) + int regno; +{ +#if 0 + struct regs inferior_registers; + struct fp_status inferior_fp_registers; + int wanna_store = INT_REGS + STACK_REGS + FP_REGS; + + /* First decide which pieces of machine-state we need to modify. + Default for regno == -1 case is all pieces. */ + if (regno >= 0) + if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32) + { + wanna_store = FP_REGS; + } + else + { + if (regno == SP_REGNUM) + wanna_store = INT_REGS + STACK_REGS; + else if (regno < L0_REGNUM || regno > I7_REGNUM) + wanna_store = INT_REGS; + else + wanna_store = STACK_REGS; + } + + /* See if we're forcing the stores to happen now, or deferring. */ + if (regno == -2) + { + wanna_store = deferred_stores; + deferred_stores = 0; + } + else + { + if (wanna_store == STACK_REGS) + { + /* Fall through and just store one stack reg. If we deferred + it, we'd have to store them all, or remember more info. */ + } + else + { + deferred_stores |= wanna_store; + return; + } + } + + if (wanna_store & STACK_REGS) + { + CORE_ADDR sp = *(CORE_ADDR *)®isters[REGISTER_BYTE (SP_REGNUM)]; + + if (regno < 0 || regno == SP_REGNUM) + { + if (!register_valid[L0_REGNUM+5]) abort(); + target_xfer_memory (sp, + ®isters[REGISTER_BYTE (L0_REGNUM)], + 16*REGISTER_RAW_SIZE (L0_REGNUM), 1); + } + else + { + if (!register_valid[regno]) abort(); + target_xfer_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM), + ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (regno), 1); + } + + } + + if (wanna_store & INT_REGS) + { + if (!register_valid[G1_REGNUM]) abort(); + + memcpy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (G1_REGNUM)], + 15 * REGISTER_RAW_SIZE (G1_REGNUM)); + + inferior_registers.r_ps = + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; + inferior_registers.r_pc = + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; + inferior_registers.r_npc = + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)]; + inferior_registers.r_y = + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)]; + + if (0 != ptrace (PTRACE_SETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0)) + perror("ptrace_setregs"); + } + + if (wanna_store & FP_REGS) + { + if (!register_valid[FP0_REGNUM+9]) abort(); + /* Initialize inferior_fp_registers members that gdb doesn't set + by reading them from the inferior. */ + if (0 != + ptrace (PTRACE_GETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0)) + perror("ptrace_getfpregs"); + memcpy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof inferior_fp_registers.fpu_fr); + +/* memcpy (&inferior_fp_registers.Fpu_fsr, + ®isters[REGISTER_BYTE (FPS_REGNUM)], sizeof (FPU_FSR_TYPE)); +****/ + if (0 != + ptrace (PTRACE_SETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0)) + perror("ptrace_setfpregs"); + } +#endif +} + + +void +fetch_core_registers (core_reg_sect, core_reg_size, which, ignore) + char *core_reg_sect; + unsigned core_reg_size; + int which; + unsigned int ignore; /* reg addr, unused in this version */ +{ +#if 0 + if (which == 0) { + + /* Integer registers */ + +#define gregs ((struct regs *)core_reg_sect) + /* G0 *always* holds 0. */ + *(int *)®isters[REGISTER_BYTE (0)] = 0; + + /* The globals and output registers. */ + memcpy (®isters[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1, + 15 * REGISTER_RAW_SIZE (G1_REGNUM)); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc; + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc; + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y; + + /* My best guess at where to get the locals and input + registers is exactly where they usually are, right above + the stack pointer. If the core dump was caused by a bus error + from blowing away the stack pointer (as is possible) then this + won't work, but it's worth the try. */ + { + int sp; + + sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)]; + if (0 != target_read_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)], + 16 * REGISTER_RAW_SIZE (L0_REGNUM))) + { + /* fprintf so user can still use gdb */ + fprintf (stderr, + "Couldn't read input and local registers from core file\n"); + } + } + } else if (which == 2) { + + /* Floating point registers */ + +#define fpuregs ((struct fpu *) core_reg_sect) + if (core_reg_size >= sizeof (struct fpu)) + { + memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], fpuregs->fpu_regs, + sizeof (fpuregs->fpu_regs)); + memcpy (®isters[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr, + sizeof (FPU_FSR_TYPE)); + } + else + fprintf (stderr, "Couldn't read float regs from core file\n"); + } +#endif +} + +/* Wait for child to do something. Return pid of child, or -1 in case + of error; store status through argument pointer STATUS. */ + +int +child_wait (pid, status) + int pid; + int *status; +{ + int save_errno; + int thread; + + while (1) + { + int sig; + + if (attach_flag) + set_sigint_trap(); /* Causes SIGINT to be passed on to the + attached process. */ + pid = wait (status); + save_errno = errno; + + if (attach_flag) + clear_sigint_trap(); + + if (pid == -1) + { + if (save_errno == EINTR) + continue; + fprintf (stderr, "Child process unexpectedly missing: %s.\n", + safe_strerror (save_errno)); + *status = 42; /* Claim it exited with signal 42 */ + return -1; + } + + if (pid != PIDGET (inferior_pid)) /* Some other process?!? */ + continue; + +/* thread = WIFTID (*status);*/ + thread = *status >> 16; + + /* Initial thread value can only be acquired via wait, so we have to + resort to this hack. */ + + if (TIDGET (inferior_pid) == 0) + { + inferior_pid = BUILDPID (inferior_pid, thread); + add_thread (inferior_pid); + } + + pid = BUILDPID (pid, thread); + + return pid; + } +} |