From 161520dc02c71146c4bcb352c7bd06ac59398e4f Mon Sep 17 00:00:00 2001 From: Kung Hsu Date: Wed, 1 Mar 1995 00:01:49 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 5 + gdb/a29k-tdep.c | 36 +++++- gdb/remote-vx.c | 281 +++++++++++++++++++++++++++------------------ gdb/remote-vx29k.c | 29 ++++- 4 files changed, 231 insertions(+), 120 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 77befe587ea..918f0360dd6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ Tue Feb 28 14:38:39 1995 Kung Hsu + * 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. diff --git a/gdb/a29k-tdep.c b/gdb/a29k-tdep.c index 591afbdc415..dbcd60b0ad3 100644 --- a/gdb/a29k-tdep.c +++ b/gdb/a29k-tdep.c @@ -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 () { diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c index 2de3bc5f98b..4e142c735c7 100644 --- a/gdb/remote-vx.c +++ b/gdb/remote-vx.c @@ -56,9 +56,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +/* 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,138 +381,101 @@ 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)"); - } - -#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) - { - 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) ®isters[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)"); - } - } - else - { - memset (®isters[REGISTER_BYTE (FP0_REGNUM)], '\0', VX_SIZE_FPREGS); + sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS) + ? "general-purpose" + : "floating-point"); + perror_with_name (message); } -#endif /* VX_SIZE_FPREGS */ -} - -/* Prepare to store registers. Since we will store all of them, - read out their current values now. */ - -static void -vx_prepare_to_store () -{ - /* Fetch all registers, if any of them are not yet fetched. */ - read_register_bytes (0, NULL, REGISTER_BYTES); } +/* 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 (). */ -/* 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; +void +net_write_registers (reg_buf, len, procnum) + char *reg_buf; + int len; + u_long procnum; { - C_bytes in_data; - C_bytes out_data; - extern char registers[]; 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.ttype = DATA; ptrace_in.info.more_data = (caddr_t) &in_data; - in_data.bytes = registers; - - in_data.len = VX_NUM_REGS * REGISTER_SIZE; + /* Call RPC; take an error exit if appropriate. */ - /* XXX change second param to be a proc number */ - status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out); + 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_SETREGS)"); + sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS) + ? "general-purpose" + : "floating-point"); + perror_with_name (message); } +} -#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 = ®isters[REGISTER_BYTE (FP0_REGNUM)]; - in_data.len = VX_SIZE_FPREGS; +/* Prepare to store registers. Since we will store all of them, + read out their current values now. */ - 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 */ +static void +vx_prepare_to_store () +{ + /* Fetch all registers, if any of them are not yet fetched. */ + read_register_bytes (0, NULL, REGISTER_BYTES); } /* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR @@ -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 (); } diff --git a/gdb/remote-vx29k.c b/gdb/remote-vx29k.c index 519d9300eb3..5621bcebb96 100644 --- a/gdb/remote-vx29k.c +++ b/gdb/remote-vx29k.c @@ -97,7 +97,7 @@ vx_read_register (regno) /* PAD For now, don't care about exop register */ - bzero (®isters[REGISTER_BYTE (EXO_REGNUM)], 1 * AM29K_GREG_SIZE); + memset (®isters[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 (®isters[REGISTER_BYTE (161)], 21 * AM29K_FPREG_SIZE); + memset (®isters[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE); } else { - bzero (®isters[REGISTER_BYTE (FPE_REGNUM)], 1 * AM29K_FPREG_SIZE); - bzero (®isters[REGISTER_BYTE (FPS_REGNUM)], 1 * AM29K_FPREG_SIZE); + memset (®isters[REGISTER_BYTE (FPE_REGNUM)], '\0', AM29K_FPREG_SIZE); + memset (®isters[REGISTER_BYTE (FPS_REGNUM)], '\0', AM29K_FPREG_SIZE); /* PAD For now, don't care about registers (?) AI0 to q */ - bzero (®isters[REGISTER_BYTE (161)], 21 * AM29K_FPREG_SIZE); + memset (®isters[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); +} + -- 2.30.2