* a29k-tdep.c (get_longjmp_target): add this function, from WRS.
authorKung Hsu <kung@cygnus>
Wed, 1 Mar 1995 00:01:49 +0000 (00:01 +0000)
committerKung Hsu <kung@cygnus>
Wed, 1 Mar 1995 00:01:49 +0000 (00:01 +0000)
        * 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
gdb/a29k-tdep.c
gdb/remote-vx.c
gdb/remote-vx29k.c

index 77befe587ead8e128761d223b076cf4025a2c14f..918f0360dd61cc2640563965af36cdcf01e4708e 100644 (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.
index 591afbdc415edc759ccf9f8dcd010962d3121759..dbcd60b0ad3e6221fb4f440efeb1642e70089f51 100644 (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 ()
 {
index 2de3bc5f98b9bd3fd23720bb277a408ddc506635..4e142c735c7d39acb51cf65c9c6473520e4d84b4 100644 (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,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) &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)");
-       }
-    }
-  else
-    {
-      memset (&registers[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 = &registers[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 ();
 }
 
 
index 519d9300eb3934b6753e55ebfe478862f0841b34..5621bcebb96fd12bc9fbddb41d45eb9622fbd297 100644 (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);
+}
+