aboutsummaryrefslogtreecommitdiff
path: root/gdb/lynx-nat.c
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1993-11-17 07:17:45 +0000
committerStu Grossman <grossman@cygnus>1993-11-17 07:17:45 +0000
commitd3225ea0acbf8000c86126e1196cf1ed25516041 (patch)
treedbc4e34e8093afe1a93d31dc8a5538d093367ffe /gdb/lynx-nat.c
parente63e7f9f22cf5630c46b617f8bedf003b780af77 (diff)
downloadfsf-binutils-gdb-d3225ea0acbf8000c86126e1196cf1ed25516041.zip
fsf-binutils-gdb-d3225ea0acbf8000c86126e1196cf1ed25516041.tar.gz
fsf-binutils-gdb-d3225ea0acbf8000c86126e1196cf1ed25516041.tar.bz2
* i386ly-nat.c, i386lynx-nat.c, m68kly-nat.c: Remove. Move
common code into lynx-nat.c. * lynx-nat.c: New module. Contains portable code for Lynx native stuff (mostly ptrace related). * config/i386/i386lynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o * config/m68k/m68klynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o * config/nm-lynx.h, config/tm-lynx.h: New files to contain non-architecture specific native and target defs. * config/i386/nm-i386lynx.h, config/i386/tm-i386lynx.h, config/m68k/nm-m68klynx.h, config/m68k/tm-m68klynx.h: Move all (arch) portable stuff into ../{tm nm}-lynx.h.
Diffstat (limited to 'gdb/lynx-nat.c')
-rw-r--r--gdb/lynx-nat.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/gdb/lynx-nat.c b/gdb/lynx-nat.c
new file mode 100644
index 0000000..8b2c7c8
--- /dev/null
+++ b/gdb/lynx-nat.c
@@ -0,0 +1,310 @@
+/* Native-dependent code for LynxOS.
+ Copyright 1993 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 "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#include <sys/ptrace.h>
+#include "/usr/include/sys/wait.h"
+
+static unsigned long registers_addr PARAMS ((int pid));
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY))
+
+#ifdef I386
+/* Mappings from tm-i386v.h */
+
+static int regmap[] =
+{
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp), /* sp */
+ X(ebp), /* fp */
+ X(esi),
+ X(edi),
+ X(eip), /* pc */
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault), /* we just substitute these two in the hopes
+ that they are useful. */
+};
+#endif
+
+#ifdef M68K
+/* Mappings from tm-m68k.h */
+
+static int regmap[] =
+{
+ X(regs[0]), /* d0 */
+ X(regs[1]), /* d1 */
+ X(regs[2]), /* d2 */
+ X(regs[3]), /* d3 */
+ X(regs[4]), /* d4 */
+ X(regs[5]), /* d5 */
+ X(regs[6]), /* d6 */
+ X(regs[7]), /* d7 */
+ X(regs[8]), /* a0 */
+ X(regs[9]), /* a1 */
+ X(regs[10]), /* a2 */
+ X(regs[11]), /* a3 */
+ X(regs[12]), /* a4 */
+ X(regs[13]), /* a5 */
+ X(regs[14]), /* fp */
+ offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
+ X(status), /* ps */
+ X(pc),
+
+ X(fregs[0*3]), /* fp0 */
+ X(fregs[1*3]), /* fp1 */
+ X(fregs[2*3]), /* fp2 */
+ X(fregs[3*3]), /* fp3 */
+ X(fregs[4*3]), /* fp4 */
+ X(fregs[5*3]), /* fp5 */
+ X(fregs[6*3]), /* fp6 */
+ X(fregs[7*3]), /* fp7 */
+
+ X(fcregs[0]), /* fpcontrol */
+ X(fcregs[1]), /* fpstatus */
+ X(fcregs[2]), /* fpiaddr */
+ X(ssw), /* fpcode */
+ X(fault), /* fpflags */
+};
+#endif
+
+/* Return the offset relative to the start of the per-thread data to the
+ saved context block. */
+
+static unsigned long
+registers_addr(pid)
+ int pid;
+{
+ CORE_ADDR stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE)0,
+ 0);
+ if (errno)
+ perror_with_name ("registers_addr(PTRACE_THREADUSER)");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE)ecpoff,
+ 0);
+ if (errno)
+ perror_with_name ("registers_addr(PTRACE_PEEKTHREAD)");
+
+ return ecp - stblock;
+}
+
+/* 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;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int ptrace_fun = PTRACE_PEEKTHREAD;
+
+#ifdef PTRACE_PEEKUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ errno = 0;
+ reg = ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
+ if (errno)
+ perror_with_name ("fetch_inferior_registers(ptrace)");
+
+ *(int *)&buf[i] = reg;
+ }
+ supply_register (regno, buf);
+ }
+}
+
+/* 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;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ int ptrace_fun = PTRACE_POKEUSER;
+
+#ifdef PTRACE_POKEUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ reg = *(unsigned int *)&registers[REGISTER_BYTE (regno) + i];
+
+ errno = 0;
+ ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
+ if (errno)
+ perror_with_name ("PTRACE_POKEUSER");
+ }
+ }
+}
+
+/* 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_unfiltered (gdb_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;
+ }
+}
+
+/* Convert a Lynx process ID to a string. Returns the string in a static
+ buffer. */
+
+char *
+lynx_pid_to_str (pid)
+ int pid;
+{
+ static char buf[40];
+
+ sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
+
+ return buf;
+}
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into memory.
+ CORE_REG_SIZE is the size of that area.
+ WHICH says which set of registers we are handling (0 = int, 2 = float
+ on machines where they are discontiguous).
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to
+ locate the registers in a large upage-plus-stack ".reg" section.
+ Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned reg_addr;
+{
+ struct st_entry s;
+ unsigned int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ supply_register (regno, core_reg_sect + offsetof (st_t, ec)
+ + regmap[regno]);
+}