* a29k-tdep.c (get_longjmp_target): add this function, from WRS.

* remote-vx.c: move read_register and write_register out to
        target specific files.
        * remote-vx29k.c (get_fp_contnets): add this function, from WRS.
This commit is contained in:
Kung Hsu 1995-03-01 00:01:49 +00:00
parent 33d8f4697c
commit 161520dc02
4 changed files with 241 additions and 130 deletions

View File

@ -1,5 +1,10 @@
Tue Feb 28 14:38:39 1995 Kung Hsu <kung@mexican.cygnus.com>
* a29k-tdep.c (get_longjmp_target): add this function, from WRS.
* remote-vx.c: move read_register and write_register out to
target specific files.
* remote-vx29k.c (get_fp_contnets): add this function, from WRS.
* defs.h: define SWAP_TARGET_AND_HOST macro.
* findvar.c, monitor.c, hppa-tdep.c: remove definition of
SWAP_TARGET_AND_HOST.

View File

@ -402,7 +402,7 @@ init_frame_info (innermost_frame, frame)
else
frame->frame = frame->next->frame + frame->next->rsize;
#if CALL_DUMMY_LOCATION == ON_STACK
#if 0 /* CALL_DUMMY_LOCATION == ON_STACK */
This wont work;
#else
if (PC_IN_CALL_DUMMY (p, 0, 0))
@ -825,6 +825,16 @@ push_dummy_frame ()
gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
write_register (GR1_REGNUM, gr1);
#ifdef VXWORKS_TARGET
/* We force re-reading all registers to get the new local registers set
after gr1 has been modified. This fix is due to the lack of single
register read/write operation in the RPC interface between VxGDB and
VxWorks. This really must be changed ! */
vx_read_register (-1);
#endif /* VXWORK_TARGET */
rab = read_register (RAB_REGNUM);
if (gr1 < rab)
{
@ -967,6 +977,30 @@ a29k_get_processor_type ()
fprintf_filtered (gdb_stderr, " revision %c\n", 'A' + ((cfg_reg >> 24) & 0x0f));
}
#ifdef GET_LONGJMP_TARGET
/* Figure out where the longjmp will land. We expect that we have just entered
longjmp and haven't yet setup the stack frame, so the args are still in the
output regs. lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
This routine returns true on success */
int
get_longjmp_target(pc)
CORE_ADDR *pc;
{
CORE_ADDR jb_addr;
jb_addr = read_register(LR2_REGNUM);
if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, (char *) pc,
sizeof(CORE_ADDR)))
return 0;
SWAP_TARGET_AND_HOST(pc, sizeof(CORE_ADDR));
return 1;
}
#endif /* GET_LONGJMP_TARGET */
void
_initialize_a29k_tdep ()
{

View File

@ -56,9 +56,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <symtab.h>
/* Maximum number of bytes to transfer in a single
PTRACE_{READ,WRITE}DATA request. */
#define VX_MEMXFER_MAX 4096
extern void vx_read_register ();
extern void vx_write_register ();
extern void symbol_file_command ();
extern int stop_soon_quietly; /* for wait_for_inferior */
static int net_step ();
static int net_ptrace_clnt_call (); /* Forward decl */
static enum clnt_stat net_clnt_call (); /* Forward decl */
extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration */
@ -72,7 +79,7 @@ static char *vx_running; /* Called function */
/* Nonzero means target that is being debugged remotely has a floating
point processor. */
static int target_has_fp;
int target_has_fp;
/* Default error message when the network is forking up. */
@ -340,7 +347,13 @@ net_wait (pEvent)
status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT,
pEvent);
return (status == RPC_SUCCESS)? pEvent->status: -1;
/* return (status == RPC_SUCCESS)? pEvent->status: -1; */
if (status == RPC_SUCCESS)
return ((pEvent->status) ? 1 : 0);
else if (status == RPC_TIMEDOUT)
return (1);
else
return (-1);
}
/* Suspend the remote task.
@ -368,64 +381,91 @@ net_quit ()
/* Read a register or registers from the remote system. */
static void
vx_read_register (regno)
int regno;
void
net_read_registers (reg_buf, len, procnum)
char *reg_buf;
int len;
u_long procnum;
{
int status;
Rptrace ptrace_in;
Ptrace_return ptrace_out;
C_bytes in_data;
C_bytes out_data;
extern char registers[];
char message[100];
memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
/* FIXME, eventually only get the ones we need. */
registers_fetched ();
/* Initialize RPC input argument structure. */
ptrace_in.pid = inferior_pid;
ptrace_in.info.ttype = NOINFO;
/* Initialize RPC return value structure. */
out_data.bytes = reg_buf;
out_data.len = len;
ptrace_out.info.more_data = (caddr_t) &out_data;
out_data.len = VX_NUM_REGS * REGISTER_RAW_SIZE (0);
out_data.bytes = (caddr_t) registers;
status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
/* Call RPC; take an error exit if appropriate. */
status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
{
errno = ptrace_out.errno;
perror_with_name ("net_ptrace_clnt_call(PTRACE_GETREGS)");
sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS)
? "general-purpose"
: "floating-point");
perror_with_name (message);
}
#ifdef VX_SIZE_FPREGS
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
registers[] for good measure, even though we might not
need to. */
}
if (target_has_fp)
/* Write register values to a VxWorks target. REG_BUF points to a buffer
containing the raw register values, LEN is the length of REG_BUF in
bytes, and PROCNUM is the RPC procedure number (PTRACE_SETREGS or
PTRACE_SETFPREGS). An error exit is taken if the RPC call fails or
if an error status is returned by the remote debug server. This is
a utility routine used by vx_write_register (). */
void
net_write_registers (reg_buf, len, procnum)
char *reg_buf;
int len;
u_long procnum;
{
int status;
Rptrace ptrace_in;
Ptrace_return ptrace_out;
C_bytes in_data;
char message[100];
memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
/* Initialize RPC input argument structure. */
in_data.bytes = reg_buf;
in_data.len = len;
ptrace_in.pid = inferior_pid;
ptrace_in.info.ttype = DATA;
ptrace_in.info.more_data = (caddr_t) &in_data;
/* Call RPC; take an error exit if appropriate. */
status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
{
ptrace_in.pid = inferior_pid;
ptrace_out.info.more_data = (caddr_t) &out_data;
out_data.len = VX_SIZE_FPREGS;
out_data.bytes = (caddr_t) &registers[REGISTER_BYTE (FP0_REGNUM)];
status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
{
errno = ptrace_out.errno;
perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)");
}
errno = ptrace_out.errno;
sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS)
? "general-purpose"
: "floating-point");
perror_with_name (message);
}
else
{
memset (&registers[REGISTER_BYTE (FP0_REGNUM)], '\0', VX_SIZE_FPREGS);
}
#endif /* VX_SIZE_FPREGS */
}
/* Prepare to store registers. Since we will store all of them,
@ -438,70 +478,6 @@ vx_prepare_to_store ()
read_register_bytes (0, NULL, REGISTER_BYTES);
}
/* 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). */
/* FIXME, look at REGNO to save time here */
static void
vx_write_register (regno)
int regno;
{
C_bytes in_data;
C_bytes out_data;
extern char registers[];
int status;
Rptrace ptrace_in;
Ptrace_return ptrace_out;
memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
ptrace_in.pid = inferior_pid;
ptrace_in.info.ttype = DATA;
ptrace_in.info.more_data = (caddr_t) &in_data;
in_data.bytes = registers;
in_data.len = VX_NUM_REGS * REGISTER_SIZE;
/* XXX change second param to be a proc number */
status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
{
errno = ptrace_out.errno;
perror_with_name ("net_ptrace_clnt_call(PTRACE_SETREGS)");
}
#ifdef VX_SIZE_FPREGS
/* Store floating point registers if the target has them. */
if (target_has_fp)
{
ptrace_in.pid = inferior_pid;
ptrace_in.info.ttype = DATA;
ptrace_in.info.more_data = (caddr_t) &in_data;
in_data.bytes = &registers[REGISTER_BYTE (FP0_REGNUM)];
in_data.len = VX_SIZE_FPREGS;
status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in,
&ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
{
errno = ptrace_out.errno;
perror_with_name ("net_ptrace_clnt_call(PTRACE_SETFPREGS)");
}
}
#endif /* VX_SIZE_FPREGS */
}
/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. WRITE is true if writing to the
inferior.
@ -522,6 +498,8 @@ vx_xfer_memory (memaddr, myaddr, len, write, target)
Rptrace ptrace_in;
Ptrace_return ptrace_out;
C_bytes data;
enum ptracereq request;
int nleft, nxfer;
memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
@ -537,28 +515,55 @@ vx_xfer_memory (memaddr, myaddr, len, write, target)
data.bytes = (caddr_t) myaddr; /* Where from */
data.len = len; /* How many bytes (again, for XDR) */
/* XXX change second param to be a proc number */
status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in,
&ptrace_out);
request = PTRACE_WRITEDATA;
}
else
{
ptrace_out.info.more_data = (caddr_t) &data;
data.bytes = myaddr; /* Where to */
data.len = len; /* How many (again, for XDR) */
/* XXX change second param to be a proc number */
status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
request = PTRACE_READDATA;
}
/* Loop until the entire request has been satisfied, transferring
at most VX_MEMXFER_MAX bytes per iteration. Break from the loop
if an error status is returned by the remote debug server. */
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
nleft = len;
status = 0;
while (nleft > 0 && status == 0)
{
return 0; /* No bytes moved */
nxfer = min (nleft, VX_MEMXFER_MAX);
ptrace_in.addr = (int) memaddr;
ptrace_in.data = nxfer;
data.bytes = (caddr_t) myaddr;
data.len = nxfer;
/* Request a block from the remote debug server; if RPC fails,
report an error and return to debugger command level. */
if (net_ptrace_clnt_call (request, &ptrace_in, &ptrace_out))
error (rpcerr);
status = ptrace_out.status;
if (status == 0)
{
memaddr += nxfer;
myaddr += nxfer;
nleft -= nxfer;
}
else
{
/* A target-side error has ocurred. Set errno to the error
code chosen by the target so that a later perror () will
say something meaningful. */
errno = ptrace_out.errno;
}
}
return len; /* Moved *all* the bytes */
/* Return the number of bytes transferred. */
return (len - nleft);
}
static void
@ -589,6 +594,7 @@ vx_resume (pid, step, siggnal)
int status;
Rptrace ptrace_in;
Ptrace_return ptrace_out;
CORE_ADDR cont_addr;
if (pid == -1)
pid = inferior_pid;
@ -596,15 +602,29 @@ vx_resume (pid, step, siggnal)
if (siggnal != 0 && siggnal != stop_signal)
error ("Cannot send signals to VxWorks processes");
/* Set CONT_ADDR to the address at which we are continuing,
or to 1 if we are continuing from where the program stopped.
This conforms to traditional ptrace () usage, but at the same
time has special meaning for the VxWorks remote debug server.
If the address is not 1, the server knows that the target
program is jumping to a new address, which requires special
handling if there is a breakpoint at the new address. */
cont_addr = read_register (PC_REGNUM);
if (cont_addr == stop_pc)
cont_addr = 1;
memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
ptrace_in.pid = pid;
ptrace_in.addr = 1; /* Target side insists on this, or it panics. */
ptrace_in.addr = cont_addr; /* Target side insists on this, or it panics. */
if (step)
status = net_step();
else
status = net_ptrace_clnt_call (PTRACE_CONT, &ptrace_in, &ptrace_out);
/* XXX change second param to be a proc number */
status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
&ptrace_in, &ptrace_out);
if (status)
error (rpcerr);
if (ptrace_out.status == -1)
@ -719,6 +739,18 @@ vx_load_command (arg_string, from_tty)
dont_repeat ();
/* Refuse to load the module if a debugged task is running. Doing so
can have a number of unpleasant consequences to the running task. */
if (inferior_pid != 0 && target_has_execution)
{
if (query ("You may not load a module while the target task is running.\n\
Kill the target task? "))
target_kill ();
else
error ("Load cancelled.");
}
QUIT;
immediate_quit++;
if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
@ -732,7 +764,6 @@ vx_load_command (arg_string, from_tty)
reinit_frame_cache ();
}
#ifdef FIXME /* Not ready for prime time */
/* Single step the target program at the source or machine level.
Takes an error exit if rpc fails.
Returns -1 if remote single-step operation fails, else 0. */
@ -765,7 +796,6 @@ net_step ()
else
error (rpcerr);
}
#endif
/* Emulate ptrace using RPC calls to the VxWorks target system.
Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
@ -1228,6 +1258,29 @@ vx_attach (args, from_tty)
in order for other parts of GDB to work correctly. */
inferior_pid = pid;
vx_running = 0;
#if defined (START_INFERIOR_HOOK)
START_INFERIOR_HOOK ();
#endif
mark_breakpoints_out ();
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
target_terminal_init ();
/* Install inferior's terminal modes. */
target_terminal_inferior ();
/* We will get a task spawn event immediately. */
init_wait_for_inferior ();
clear_proceed_status ();
stop_soon_quietly = 1;
wait_for_inferior ();
stop_soon_quietly = 0;
normal_stop ();
}

View File

@ -97,7 +97,7 @@ vx_read_register (regno)
/* PAD For now, don't care about exop register */
bzero (&registers[REGISTER_BYTE (EXO_REGNUM)], 1 * AM29K_GREG_SIZE);
memset (&registers[REGISTER_BYTE (EXO_REGNUM)], '\0', AM29K_GREG_SIZE);
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
@ -113,16 +113,16 @@ vx_read_register (regno)
/* PAD For now, don't care about registers (?) AI0 to q */
bzero (&registers[REGISTER_BYTE (161)], 21 * AM29K_FPREG_SIZE);
memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
}
else
{
bzero (&registers[REGISTER_BYTE (FPE_REGNUM)], 1 * AM29K_FPREG_SIZE);
bzero (&registers[REGISTER_BYTE (FPS_REGNUM)], 1 * AM29K_FPREG_SIZE);
memset (&registers[REGISTER_BYTE (FPE_REGNUM)], '\0', AM29K_FPREG_SIZE);
memset (&registers[REGISTER_BYTE (FPS_REGNUM)], '\0', AM29K_FPREG_SIZE);
/* PAD For now, don't care about registers (?) AI0 to q */
bzero (&registers[REGISTER_BYTE (161)], 21 * AM29K_FPREG_SIZE);
memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
}
/* Mark the register cache valid. */
@ -167,3 +167,22 @@ vx_write_register (regno)
}
}
/* VxWorks zeroes fp when the task is initialized; we use this
to terminate the frame chain. Chain means here the nominal address of
a frame, that is, the return address (lr0) address in the stack. To
obtain the frame pointer (lr1) contents, we must add 4 bytes.
Note : may be we should modify init_frame_info() to get the frame pointer
and store it into the frame_info struct rather than reading its
contents when FRAME_CHAIN_VALID is invoked. */
int
get_fp_contents (chain, thisframe)
CORE_ADDR chain;
struct frame_info *thisframe; /* not used here */
{
int fp_contents;
read_memory ((CORE_ADDR)(chain + 4), (char *) &fp_contents, 4);
return (fp_contents != 0);
}