* lynx-nat.c: Add Sparc support.
* sparcly-nat.c: Remove. It's useless. * config/sparc/nm-sparclynx.h: Rewrite. * config/sparc/sparclynx.mh (NATDEPFILES): Replace sparcly-nat.o with lynx-nat.o * config/sparc/tm-sparclynx.h: Rewrite.
This commit is contained in:
parent
24845456a3
commit
d575ddc0ef
|
@ -1,3 +1,12 @@
|
||||||
|
Fri Jan 21 17:49:28 1994 Stu Grossman (grossman at cygnus.com)
|
||||||
|
|
||||||
|
* lynx-nat.c: Add Sparc support.
|
||||||
|
* sparcly-nat.c: Remove. It's useless.
|
||||||
|
* config/sparc/nm-sparclynx.h: Rewrite.
|
||||||
|
* config/sparc/sparclynx.mh (NATDEPFILES): Replace sparcly-nat.o
|
||||||
|
with lynx-nat.o
|
||||||
|
* config/sparc/tm-sparclynx.h: Rewrite.
|
||||||
|
|
||||||
Fri Jan 21 19:08:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
Fri Jan 21 19:08:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
||||||
|
|
||||||
* rs6000-pinsn.c: Use the new disassembler in the opcodes
|
* rs6000-pinsn.c: Use the new disassembler in the opcodes
|
||||||
|
|
|
@ -20,45 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#ifndef NM_SPARCLYNX_H
|
#ifndef NM_SPARCLYNX_H
|
||||||
#define NM_SPARCLYNX_H
|
#define NM_SPARCLYNX_H
|
||||||
|
|
||||||
#include <sys/conf.h>
|
#include "nm-lynx.h"
|
||||||
#include <sys/kernel.h>
|
|
||||||
#include <sys/mem.h>
|
|
||||||
#include <sys/signal.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/itimer.h>
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#include "thread.h"
|
|
||||||
|
|
||||||
/* This is the amount to subtract from u.u_ar0 to get the offset in
|
|
||||||
the core file of the register values. */
|
|
||||||
|
|
||||||
#define KERNEL_U_ADDR USRSTACK
|
|
||||||
|
|
||||||
#undef FLOAT_INFO /* No float info yet */
|
|
||||||
|
|
||||||
#define PTRACE_ARG3_TYPE char*
|
|
||||||
|
|
||||||
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
|
|
||||||
#define FETCH_INFERIOR_REGISTERS
|
|
||||||
|
|
||||||
/* Thread ID of stopped thread. */
|
|
||||||
|
|
||||||
#define WIFTID(x) (((union wait *)&x)->w_tid)
|
|
||||||
|
|
||||||
#define CHILD_WAIT
|
|
||||||
|
|
||||||
extern int child_wait PARAMS ((int pid, int *status));
|
|
||||||
|
|
||||||
#if 0 /* need sparcly-nat.c to define this */
|
|
||||||
/* Lynx needs a special definition of this so that we can
|
|
||||||
print out the pid and thread number seperatly. */
|
|
||||||
|
|
||||||
#undef target_pid_to_str
|
|
||||||
#define target_pid_to_str(PID) sparclynx_pid_to_str (PID)
|
|
||||||
|
|
||||||
extern char *sparclynx_pid_to_str PARAMS ((int pid));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* NM_SPARCLYNX_H */
|
#endif /* NM_SPARCLYNX_H */
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
XM_FILE= xm-sparclynx.h
|
XM_FILE= xm-sparclynx.h
|
||||||
XDEPFILES=
|
XDEPFILES=
|
||||||
NAT_FILE= nm-sparclynx.h
|
NAT_FILE= nm-sparclynx.h
|
||||||
NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparcly-nat.o
|
NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o
|
||||||
REGEX=regex.o
|
REGEX=regex.o
|
||||||
REGEX1=regex.o
|
REGEX1=regex.o
|
||||||
GDBSERVER_LIBS= -lbsd
|
GDBSERVER_LIBS= -lbsd
|
||||||
|
|
|
@ -20,12 +20,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#ifndef TM_SPARCLYNX_H
|
#ifndef TM_SPARCLYNX_H
|
||||||
#define TM_SPARCLYNX_H
|
#define TM_SPARCLYNX_H
|
||||||
|
|
||||||
/* Use generic Sparc definitions. */
|
#include "tm-lynx.h"
|
||||||
|
|
||||||
|
/* Use generic Sparc definitions. */
|
||||||
#include "sparc/tm-sparc.h"
|
#include "sparc/tm-sparc.h"
|
||||||
|
|
||||||
/* Include COFF shared library support. */
|
|
||||||
|
|
||||||
#include "coff-solib.h"
|
|
||||||
|
|
||||||
#endif /* TM_SPARCLYNX_H */
|
#endif /* TM_SPARCLYNX_H */
|
||||||
|
|
294
gdb/lynx-nat.c
294
gdb/lynx-nat.c
|
@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/fpp.h>
|
||||||
|
|
||||||
static unsigned long registers_addr PARAMS ((int pid));
|
static unsigned long registers_addr PARAMS ((int pid));
|
||||||
|
|
||||||
|
@ -95,6 +96,287 @@ static int regmap[] =
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SPARC
|
||||||
|
/* Mappings from tm-sparc.h */
|
||||||
|
|
||||||
|
#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
|
||||||
|
|
||||||
|
static int regmap[] =
|
||||||
|
{
|
||||||
|
-1, /* g0 */
|
||||||
|
X(g1),
|
||||||
|
X(g2),
|
||||||
|
X(g3),
|
||||||
|
X(g4),
|
||||||
|
-1, /* g5->g7 aren't saved by Lynx */
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
|
||||||
|
X(o[0]),
|
||||||
|
X(o[1]),
|
||||||
|
X(o[2]),
|
||||||
|
X(o[3]),
|
||||||
|
X(o[4]),
|
||||||
|
X(o[5]),
|
||||||
|
X(o[6]), /* sp */
|
||||||
|
X(o[7]), /* ra */
|
||||||
|
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
|
||||||
|
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
|
||||||
|
|
||||||
|
FX(f.fregs[0]), /* f0 */
|
||||||
|
FX(f.fregs[1]),
|
||||||
|
FX(f.fregs[2]),
|
||||||
|
FX(f.fregs[3]),
|
||||||
|
FX(f.fregs[4]),
|
||||||
|
FX(f.fregs[5]),
|
||||||
|
FX(f.fregs[6]),
|
||||||
|
FX(f.fregs[7]),
|
||||||
|
FX(f.fregs[8]),
|
||||||
|
FX(f.fregs[9]),
|
||||||
|
FX(f.fregs[10]),
|
||||||
|
FX(f.fregs[11]),
|
||||||
|
FX(f.fregs[12]),
|
||||||
|
FX(f.fregs[13]),
|
||||||
|
FX(f.fregs[14]),
|
||||||
|
FX(f.fregs[15]),
|
||||||
|
FX(f.fregs[16]),
|
||||||
|
FX(f.fregs[17]),
|
||||||
|
FX(f.fregs[18]),
|
||||||
|
FX(f.fregs[19]),
|
||||||
|
FX(f.fregs[20]),
|
||||||
|
FX(f.fregs[21]),
|
||||||
|
FX(f.fregs[22]),
|
||||||
|
FX(f.fregs[23]),
|
||||||
|
FX(f.fregs[24]),
|
||||||
|
FX(f.fregs[25]),
|
||||||
|
FX(f.fregs[26]),
|
||||||
|
FX(f.fregs[27]),
|
||||||
|
FX(f.fregs[28]),
|
||||||
|
FX(f.fregs[29]),
|
||||||
|
FX(f.fregs[30]),
|
||||||
|
FX(f.fregs[31]),
|
||||||
|
|
||||||
|
X(y),
|
||||||
|
X(psr),
|
||||||
|
X(wim),
|
||||||
|
X(tbr),
|
||||||
|
X(pc),
|
||||||
|
X(npc),
|
||||||
|
FX(fsr), /* fpsr */
|
||||||
|
-1, /* cpsr */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SPARC
|
||||||
|
|
||||||
|
/* This routine handles some oddball cases for Sparc registers and LynxOS.
|
||||||
|
In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
|
||||||
|
It also handles knows where to find the I & L regs on the stack. */
|
||||||
|
|
||||||
|
void
|
||||||
|
fetch_inferior_registers (regno)
|
||||||
|
int regno;
|
||||||
|
{
|
||||||
|
int whatregs = 0;
|
||||||
|
|
||||||
|
#define WHATREGS_FLOAT 1
|
||||||
|
#define WHATREGS_GEN 2
|
||||||
|
#define WHATREGS_STACK 4
|
||||||
|
|
||||||
|
if (regno == -1)
|
||||||
|
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
|
||||||
|
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||||
|
whatregs = WHATREGS_STACK;
|
||||||
|
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
|
||||||
|
whatregs = WHATREGS_FLOAT;
|
||||||
|
else
|
||||||
|
whatregs = WHATREGS_GEN;
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_GEN)
|
||||||
|
{
|
||||||
|
struct econtext ec; /* general regs */
|
||||||
|
char buf[MAX_REGISTER_RAW_SIZE];
|
||||||
|
int retval;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
|
||||||
|
0);
|
||||||
|
if (errno)
|
||||||
|
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||||
|
|
||||||
|
memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
|
||||||
|
supply_register (G0_REGNUM, buf);
|
||||||
|
supply_register (TBR_REGNUM, (char *)&ec.tbr);
|
||||||
|
|
||||||
|
memcpy (®isters[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
|
||||||
|
4 * REGISTER_RAW_SIZE (G1_REGNUM));
|
||||||
|
for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
|
||||||
|
register_valid[i] = 1;
|
||||||
|
|
||||||
|
supply_register (PS_REGNUM, (char *)&ec.psr);
|
||||||
|
supply_register (Y_REGNUM, (char *)&ec.y);
|
||||||
|
supply_register (PC_REGNUM, (char *)&ec.pc);
|
||||||
|
supply_register (NPC_REGNUM, (char *)&ec.npc);
|
||||||
|
supply_register (WIM_REGNUM, (char *)&ec.wim);
|
||||||
|
|
||||||
|
memcpy (®isters[REGISTER_BYTE (O0_REGNUM)], ec.o,
|
||||||
|
8 * REGISTER_RAW_SIZE (O0_REGNUM));
|
||||||
|
for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
|
||||||
|
register_valid[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_STACK)
|
||||||
|
{
|
||||||
|
CORE_ADDR sp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sp = read_register (SP_REGNUM);
|
||||||
|
|
||||||
|
target_xfer_memory (sp, ®isters[REGISTER_BYTE(I0_REGNUM)],
|
||||||
|
8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
|
||||||
|
for (i = I0_REGNUM; i <= I7_REGNUM; i++)
|
||||||
|
register_valid[i] = 1;
|
||||||
|
|
||||||
|
sp += 8 * REGISTER_RAW_SIZE (I0_REGNUM);
|
||||||
|
|
||||||
|
target_xfer_memory (sp, ®isters[REGISTER_BYTE(L0_REGNUM)],
|
||||||
|
8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
|
||||||
|
for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
|
||||||
|
register_valid[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_FLOAT)
|
||||||
|
{
|
||||||
|
struct fcontext fc; /* fp regs */
|
||||||
|
int retval;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||||
|
0);
|
||||||
|
if (errno)
|
||||||
|
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||||
|
|
||||||
|
memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
|
||||||
|
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
||||||
|
for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
|
||||||
|
register_valid[i] = 1;
|
||||||
|
|
||||||
|
supply_register (FPS_REGNUM, (char *)&fc.fsr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine handles storing of the I & L regs for the Sparc. The trick
|
||||||
|
here is that they actually live on the stack. The really tricky part is
|
||||||
|
that when changing the stack pointer, the I & L regs must be written to
|
||||||
|
where the new SP points, otherwise the regs will be incorrect when the
|
||||||
|
process is started up again. We assume that the I & L regs are valid at
|
||||||
|
this point. */
|
||||||
|
|
||||||
|
void
|
||||||
|
store_inferior_registers (regno)
|
||||||
|
int regno;
|
||||||
|
{
|
||||||
|
int whatregs = 0;
|
||||||
|
|
||||||
|
if (regno == -1)
|
||||||
|
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
|
||||||
|
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||||
|
whatregs = WHATREGS_STACK;
|
||||||
|
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
|
||||||
|
whatregs = WHATREGS_FLOAT;
|
||||||
|
else if (regno == SP_REGNUM)
|
||||||
|
whatregs = WHATREGS_STACK | WHATREGS_GEN;
|
||||||
|
else
|
||||||
|
whatregs = WHATREGS_GEN;
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_GEN)
|
||||||
|
{
|
||||||
|
struct econtext ec; /* general regs */
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
ec.tbr = read_register (TBR_REGNUM);
|
||||||
|
memcpy (&ec.g1, ®isters[REGISTER_BYTE (G1_REGNUM)],
|
||||||
|
4 * REGISTER_RAW_SIZE (G1_REGNUM));
|
||||||
|
|
||||||
|
ec.psr = read_register (PS_REGNUM);
|
||||||
|
ec.y = read_register (Y_REGNUM);
|
||||||
|
ec.pc = read_register (PC_REGNUM);
|
||||||
|
ec.npc = read_register (NPC_REGNUM);
|
||||||
|
ec.wim = read_register (WIM_REGNUM);
|
||||||
|
|
||||||
|
memcpy (ec.o, ®isters[REGISTER_BYTE (O0_REGNUM)],
|
||||||
|
8 * REGISTER_RAW_SIZE (O0_REGNUM));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
|
||||||
|
0);
|
||||||
|
if (errno)
|
||||||
|
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_STACK)
|
||||||
|
{
|
||||||
|
int regoffset;
|
||||||
|
CORE_ADDR sp;
|
||||||
|
|
||||||
|
sp = read_register (SP_REGNUM);
|
||||||
|
|
||||||
|
if (regno == -1 || regno == SP_REGNUM)
|
||||||
|
{
|
||||||
|
if (!register_valid[L0_REGNUM+5])
|
||||||
|
abort();
|
||||||
|
target_xfer_memory (sp, ®isters[REGISTER_BYTE (I0_REGNUM)],
|
||||||
|
8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
|
||||||
|
sp += 8 * REGISTER_RAW_SIZE (I0_REGNUM);
|
||||||
|
target_xfer_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)],
|
||||||
|
8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
|
||||||
|
}
|
||||||
|
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||||
|
{
|
||||||
|
if (!register_valid[regno])
|
||||||
|
abort();
|
||||||
|
if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
|
||||||
|
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
|
||||||
|
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM);
|
||||||
|
else
|
||||||
|
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM);
|
||||||
|
target_xfer_memory (sp + regoffset, ®isters[REGISTER_BYTE (regno)],
|
||||||
|
REGISTER_RAW_SIZE (regno), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whatregs & WHATREGS_FLOAT)
|
||||||
|
{
|
||||||
|
struct fcontext fc; /* fp regs */
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/* We read fcontext first so that we can get good values for fq_t... */
|
||||||
|
errno = 0;
|
||||||
|
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||||
|
0);
|
||||||
|
if (errno)
|
||||||
|
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||||
|
|
||||||
|
memcpy (fc.f.fregs, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||||
|
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
||||||
|
|
||||||
|
fc.fsr = read_register (FPS_REGNUM);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||||
|
0);
|
||||||
|
if (errno)
|
||||||
|
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPARC
|
||||||
|
|
||||||
/* Return the offset relative to the start of the per-thread data to the
|
/* Return the offset relative to the start of the per-thread data to the
|
||||||
saved context block. */
|
saved context block. */
|
||||||
|
|
||||||
|
@ -142,7 +424,7 @@ fetch_inferior_registers (regno)
|
||||||
|
|
||||||
ecp = registers_addr (inferior_pid);
|
ecp = registers_addr (inferior_pid);
|
||||||
|
|
||||||
for (regno = reglo; regno <= reghi; regno++)
|
for (regno = reglo; regno <= reghi && regmap[regno] != -1; regno++)
|
||||||
{
|
{
|
||||||
char buf[MAX_REGISTER_RAW_SIZE];
|
char buf[MAX_REGISTER_RAW_SIZE];
|
||||||
int ptrace_fun = PTRACE_PEEKTHREAD;
|
int ptrace_fun = PTRACE_PEEKTHREAD;
|
||||||
|
@ -189,7 +471,7 @@ store_inferior_registers (regno)
|
||||||
|
|
||||||
ecp = registers_addr (inferior_pid);
|
ecp = registers_addr (inferior_pid);
|
||||||
|
|
||||||
for (regno = reglo; regno <= reghi; regno++)
|
for (regno = reglo; regno <= reghi && regmap[regno] != -1; regno++)
|
||||||
{
|
{
|
||||||
int ptrace_fun = PTRACE_POKEUSER;
|
int ptrace_fun = PTRACE_POKEUSER;
|
||||||
|
|
||||||
|
@ -211,6 +493,7 @@ store_inferior_registers (regno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* ifndef SPARC */
|
||||||
|
|
||||||
/* Wait for child to do something. Return pid of child, or -1 in case
|
/* Wait for child to do something. Return pid of child, or -1 in case
|
||||||
of error; store status through argument pointer OURSTATUS. */
|
of error; store status through argument pointer OURSTATUS. */
|
||||||
|
@ -231,7 +514,12 @@ child_wait (pid, ourstatus)
|
||||||
if (attach_flag)
|
if (attach_flag)
|
||||||
set_sigint_trap(); /* Causes SIGINT to be passed on to the
|
set_sigint_trap(); /* Causes SIGINT to be passed on to the
|
||||||
attached process. */
|
attached process. */
|
||||||
pid = wait (status);
|
pid = wait (&status);
|
||||||
|
#ifdef SPARC
|
||||||
|
/* Swap halves of status so that the rest of GDB can understand it */
|
||||||
|
status = (status << 16) | ((unsigned)status >> 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
save_errno = errno;
|
save_errno = errno;
|
||||||
|
|
||||||
if (attach_flag)
|
if (attach_flag)
|
||||||
|
|
|
@ -1,370 +0,0 @@
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
/* FIXME: Not sparc-specific. Should be using lynx-nat.c instead; the
|
|
||||||
child_wait's are identical. */
|
|
||||||
|
|
||||||
int
|
|
||||||
child_wait (pid, status)
|
|
||||||
int pid;
|
|
||||||
struct target_waitstatus *ourstatus;
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
/* Claim it exited with unknown signal. */
|
|
||||||
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
|
||||||
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
|
|
||||||
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);
|
|
||||||
|
|
||||||
store_waitstatus (ourstatus, status);
|
|
||||||
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue