Fri Sep 4 13:57:43 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
[deliverable/binutils-gdb.git] / gdb / remote-vx.c
index c8625f59088b8be3073487c52008434a7d6f4a7f..df3426382fdcd798a3906175fce804d71c88e6c9 100644 (file)
@@ -16,7 +16,7 @@ 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.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -28,8 +28,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "symtab.h"
 #include "complaints.h"
 #include "gdbcmd.h"
+#include "bfd.h" /* Required by objfiles.h.  */
+#include "symfile.h" /* Required by objfiles.h.  */
+#include "objfiles.h"
+#include "gdb-stabs.h"
 
-#include <string.h>
+#include "gdb_string.h"
 #include <errno.h>
 #include <signal.h>
 #include <fcntl.h>
@@ -52,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 */
@@ -68,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.  */
 
@@ -92,91 +103,91 @@ static char *find_white_space ();
 
 static int
 net_load (filename, pTextAddr, pDataAddr, pBssAddr)
-    char *filename;
-    CORE_ADDR *pTextAddr;
-    CORE_ADDR *pDataAddr;
-    CORE_ADDR *pBssAddr;
-    {
-    enum clnt_stat status;
-    struct ldfile ldstruct;
-    struct timeval load_timeout;
-    memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
+     char *filename;
+     CORE_ADDR *pTextAddr;
+     CORE_ADDR *pDataAddr;
+     CORE_ADDR *pBssAddr;
+{
+  enum clnt_stat status;
+  struct ldfile ldstruct;
+  struct timeval load_timeout;
 
-    /* We invoke clnt_call () here directly, instead of through
-       net_clnt_call (), because we need to set a large timeout value.
-       The load on the target side can take quite a while, easily
-       more than 10 seconds.  The user can kill this call by typing
-       CTRL-C if there really is a problem with the load.  
+  memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
 
-       Do not change the tv_sec value without checking -- select() imposes
-       a limit of 10**8 on it for no good reason that I can see...  */
+  /* We invoke clnt_call () here directly, instead of through
+     net_clnt_call (), because we need to set a large timeout value.
+     The load on the target side can take quite a while, easily
+     more than 10 seconds.  The user can kill this call by typing
+     CTRL-C if there really is a problem with the load.  
 
-    load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
-    load_timeout.tv_usec = 0;
+     Do not change the tv_sec value without checking -- select() imposes
+     a limit of 10**8 on it for no good reason that I can see...  */
+
+  load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
+  load_timeout.tv_usec = 0;
  
-    status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
-                       &ldstruct, load_timeout);
+  status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+                     &ldstruct, load_timeout);
 
-    if (status == RPC_SUCCESS)
-      {
-        if (*ldstruct.name == 0)       /* load failed on VxWorks side */
-          return -1;
-       *pTextAddr = ldstruct.txt_addr;
-       *pDataAddr = ldstruct.data_addr;
-       *pBssAddr = ldstruct.bss_addr;
-       return 0;
-      }
-    else
-        return -1;
+  if (status == RPC_SUCCESS)
+    {
+      if (*ldstruct.name == 0) /* load failed on VxWorks side */
+       return -1;
+      *pTextAddr = ldstruct.txt_addr;
+      *pDataAddr = ldstruct.data_addr;
+      *pBssAddr = ldstruct.bss_addr;
+      return 0;
     }
-      
+  else
+    return -1;
+}
+
 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
 
 static int
 net_break (addr, procnum)
-    int addr;
-    u_long procnum;
-    {
-    enum clnt_stat status;
-    int break_status;
-    Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
-                           structure.  How about something smaller? */
+     int addr;
+     u_long procnum;
+{
+  enum clnt_stat status;
+  int break_status;
+  Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
+                        structure.  How about something smaller? */
+
+  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+  break_status = 0;
 
-    memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
-    break_status = 0;
+  ptrace_in.addr = addr;
+  ptrace_in.pid = inferior_pid;
 
-    ptrace_in.addr = addr;
-    ptrace_in.pid = inferior_pid;
+  status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+                         &break_status);
 
-    status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
-                           &break_status);
+  if (status != RPC_SUCCESS)
+      return errno;
 
-    if (status != RPC_SUCCESS)
-       return errno;
+  if (break_status == -1)
+    return ENOMEM;
+  return break_status; /* probably (FIXME) zero */
+}
 
-    if (break_status == -1)
-      return ENOMEM;
-    return break_status;       /* probably (FIXME) zero */
-    }
 /* returns 0 if successful, errno otherwise */
 
 static int
 vx_insert_breakpoint (addr)
-    int addr;
-    {
-    return net_break (addr, VX_BREAK_ADD);
-    }
+     int addr;
+{
+  return net_break (addr, VX_BREAK_ADD);
+}
 
 /* returns 0 if successful, errno otherwise */
 
 static int
 vx_remove_breakpoint (addr)
-    int addr;
-    {
-    return net_break (addr, VX_BREAK_DELETE);
-    }
+     int addr;
+{
+  return net_break (addr, VX_BREAK_DELETE);
+}
 
 /* Start an inferior process and sets inferior_pid to its pid.
    EXEC_FILE is the file to run.
@@ -333,9 +344,16 @@ net_wait (pEvent)
     memset ((char *) pEvent, '\0', sizeof (RDB_EVENT));
 
     pid = inferior_pid;
-    status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, 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.
@@ -344,156 +362,120 @@ net_wait (pEvent)
 static int
 net_quit ()
 {
-    int pid;
-    int quit_status;
-    enum clnt_stat status;
+  int pid;
+  int quit_status;
+  enum clnt_stat status;
 
-    quit_status = 0;
+  quit_status = 0;
 
-    /* don't let rdbTask suspend itself by passing a pid of 0 */
+  /* don't let rdbTask suspend itself by passing a pid of 0 */
 
-    if ((pid = inferior_pid) == 0)
-       return -1;
+  if ((pid = inferior_pid) == 0)
+    return -1;
 
-    status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
-                           &quit_status);
+  status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+                         &quit_status);
 
-    return (status == RPC_SUCCESS)? quit_status: -1;
+  return (status == RPC_SUCCESS)? quit_status: -1;
 }
 
 /* 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)
-    {
-      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);
-    }
-#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);
-}
-
-
-/* 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 */
+/* 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 ().  */
 
-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;
+  /* Call RPC; take an error exit if appropriate.  */
 
-  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);
+  status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
   if (status)
-      error (rpcerr);
+    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
@@ -516,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));
@@ -531,27 +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
@@ -582,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;
@@ -589,17 +602,31 @@ 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);
+    error (rpcerr);
   if (ptrace_out.status == -1)
     {
       errno = ptrace_out.errno;
@@ -615,17 +642,92 @@ vx_mourn_inferior ()
 }
 
 \f
+static void vx_add_symbols PARAMS ((char *, int, CORE_ADDR, CORE_ADDR,
+                                   CORE_ADDR));
+
+struct find_sect_args {
+  CORE_ADDR text_start;
+  CORE_ADDR data_start;
+  CORE_ADDR bss_start;
+};
+
+static void find_sect PARAMS ((bfd *, asection *, void *));
+
+static void
+find_sect (abfd, sect, obj)
+     bfd *abfd;
+     asection *sect;
+     PTR obj;
+{
+  struct find_sect_args *args = (struct find_sect_args *)obj;
+
+  if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY))
+    args->text_start = bfd_get_section_vma (abfd, sect);
+  else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
+    {
+      if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+       {
+         /* Exclude .ctor and .dtor sections which have SEC_CODE set but not
+            SEC_DATA.  */
+         if (bfd_get_section_flags (abfd, sect) & SEC_DATA)
+           args->data_start = bfd_get_section_vma (abfd, sect);
+       }
+      else
+       args->bss_start = bfd_get_section_vma (abfd, sect);
+    }
+}
+
+static void
+vx_add_symbols (name, from_tty, text_addr, data_addr, bss_addr)
+     char *name;
+     int from_tty;
+     CORE_ADDR text_addr;
+     CORE_ADDR data_addr;
+     CORE_ADDR bss_addr;
+{
+  struct section_offsets *offs;
+  struct objfile *objfile;
+  struct find_sect_args ss;
+
+  /* It might be nice to suppress the breakpoint_re_set which happens here
+     because we are going to do one again after the objfile_relocate.  */
+  objfile = symbol_file_add (name, from_tty, 0, 0, 0, 0);
+
+  /* This is a (slightly cheesy) way of superceding the old symbols.  A less
+     cheesy way would be to find the objfile with the same name and
+     free_objfile it.  */
+  objfile_to_front (objfile);
+
+  offs = (struct section_offsets *)
+    alloca (sizeof (struct section_offsets)
+           + objfile->num_sections * sizeof (offs->offsets));
+  memcpy (offs, objfile->section_offsets,
+         sizeof (struct section_offsets)
+         + objfile->num_sections * sizeof (offs->offsets));
+
+  ss.text_start = 0;
+  ss.data_start = 0;
+  ss.bss_start = 0;
+  bfd_map_over_sections (objfile->obfd, find_sect, &ss);
+
+  /* Both COFF and b.out frontends use these SECT_OFF_* values.  */
+  ANOFFSET (offs, SECT_OFF_TEXT) = text_addr - ss.text_start;
+  ANOFFSET (offs, SECT_OFF_DATA) = data_addr - ss.data_start;
+  ANOFFSET (offs, SECT_OFF_BSS) = bss_addr - ss.bss_start;
+  objfile_relocate (objfile, offs);
+}
+
 /* This function allows the addition of incrementally linked object files.  */
 
 static void
 vx_load_command (arg_string, from_tty)
-     chararg_string;
+     char *arg_string;
      int from_tty;
 {
   CORE_ADDR text_addr;
   CORE_ADDR data_addr;
   CORE_ADDR bss_addr;
-  
+
   if (arg_string == 0)
     error ("The load command takes a file name");
 
@@ -634,21 +736,31 @@ 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)
     error ("Load failed on target machine");
   immediate_quit--;
 
-  /* FIXME, for now we ignore data_addr and bss_addr.  */
-  symbol_file_add (arg_string, from_tty, text_addr, 0, 0, 0);
+  vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
   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.  */
@@ -681,7 +793,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.  */
@@ -757,10 +868,11 @@ vx_lookup_symbol (name, pAddr)
 
   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
                          xdr_SYMBOL_ADDR, &symbolAddr);
-  if (status != RPC_SUCCESS) {
+  if (status != RPC_SUCCESS)
+    {
       complain (&cant_contact_target);
       return -1;
-  }
+    }
 
   *pAddr = symbolAddr.addr;
   return symbolAddr.status;
@@ -778,7 +890,7 @@ net_check_for_fp ()
 
   status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
   if (status != RPC_SUCCESS)
-      error (rpcerr);
+    error (rpcerr);
 
    return (int) fp;
 }
@@ -793,7 +905,7 @@ net_connect (host)
   struct sockaddr_in destAddr;
   struct hostent *destHost;
   unsigned long addr;
-  
+
   /* Get the internet address for the given host.  Allow a numeric
      IP address or a hostname.  */
 
@@ -802,6 +914,9 @@ net_connect (host)
     {
       destHost = (struct hostent *) gethostbyname (host);
       if (destHost == NULL)
+       /* FIXME: Probably should include hostname here in quotes.
+          For example if the user types "target vxworks vx960 " it should
+          say "Invalid host `vx960 '." not just "Invalid hostname".  */
        error ("Invalid hostname.  Couldn't find remote host address.");
       addr = * (unsigned long *) destHost->h_addr;
     }
@@ -818,8 +933,9 @@ net_connect (host)
 
   ptraceSock = RPC_ANYSOCK;
   pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
-  /* FIXME, here is where we deal with different version numbers of the proto */
-  
+  /* FIXME, here is where we deal with different version numbers of the
+     proto */
+
   if (pClient == NULL)
     {
       clnt_pcreateerror ("\tnet_connect");
@@ -843,24 +959,13 @@ sleep_ms (ms)
   select_timeout.tv_sec = 0;
   select_timeout.tv_usec = ms * 1000;
 
-  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
+  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0,
+                  &select_timeout);
 
   if (status < 0 && errno != EINTR)
     perror_with_name ("select");
 }
 
-/* Wait for control to return from inferior to debugger.
-   If inferior gets a signal, we may decide to start it up again
-   instead of returning.  That is why there is a loop in this function.
-   When this function actually returns it means the inferior
-   should be left stopped and GDB should read more commands.  */
-
-/* For network debugging with VxWorks.
- * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
- * so vx_wait() receives this information directly from
- * VxWorks instead of trying to figure out what happenned via a wait() call.
- */
-
 static int
 vx_wait (pid_to_wait_for, status)
      int pid_to_wait_for;
@@ -984,7 +1089,8 @@ add_symbol_stub (arg)
   struct ldfile *pLoadFile = (struct ldfile *)arg;
 
   printf_unfiltered("\t%s: ", pLoadFile->name);
-  symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0, 0, 0);
+  vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
+                 pLoadFile->data_addr, pLoadFile->bss_addr);
   printf_unfiltered ("ok\n");
   return 1;
 }
@@ -1042,13 +1148,19 @@ vx_open (args, from_tty)
   bootFile = NULL;
   if (!net_get_boot_file (&bootFile))
     {
-      if (*bootFile) {
-       printf_filtered ("\t%s: ", bootFile);
-       if (catch_errors
-           (symbol_stub, bootFile,
-            "Error while reading symbols from boot file:\n", RETURN_MASK_ALL))
-         puts_filtered ("ok\n");
-      } else if (from_tty)
+      if (*bootFile)
+       {
+         printf_filtered ("\t%s: ", bootFile);
+         /* This assumes that the kernel is never relocated.  Hope that is an
+            accurate assumption.  */
+         if (catch_errors
+             (symbol_stub,
+              bootFile,
+              "Error while reading symbols from boot file:\n",
+              RETURN_MASK_ALL))
+           puts_filtered ("ok\n");
+       }
+      else if (from_tty)
        printf_unfiltered ("VxWorks kernel symbols not loaded.\n");
     }
   else
@@ -1079,9 +1191,10 @@ vx_open (args, from_tty)
     do_cleanups (old_chain);
   }
 #else
-      /* Botches, FIXME:
-        (1)  Searches the PATH, not the source path.
-        (2)  data and bss are assumed to be at the usual offsets from text.  */
+      /* FIXME: Is there something better to search than the PATH? (probably
+        not the source path, since source might be in different directories
+        than objects.  */
+
       if (catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0,
                        RETURN_MASK_ALL))
        symbols_added = 1;
@@ -1136,15 +1249,15 @@ vx_attach (args, from_tty)
     }
 
   /* It worked... */
-  push_target (&vx_run_ops);
-  /* The unsigned long pid will get turned into a signed int here,
-     but it doesn't seem to matter.  inferior_pid must be signed
-     in order for other parts of GDB to work correctly.  */
+
   inferior_pid = pid;
+  push_target (&vx_run_ops);
+
+  if (vx_running)
+    free (vx_running);
   vx_running = 0;
 }
 
-
 /* detach_command --
    takes a program previously attached to and detaches it.
    The program resumes execution and will no longer stop
@@ -1281,66 +1394,114 @@ vx_proc_open (name, from_tty)
 
 /* Target ops structure for accessing memory and such over the net */
 
-struct target_ops vx_ops = {
-       "vxworks", "VxWorks target memory via RPC over TCP/IP",
-       "Use VxWorks target memory.  \n\
+struct target_ops vx_ops ;
+
+static void init_vx_ops(void)
+{
+  vx_ops.to_shortname =   "vxworks";
+  vx_ops.to_longname =   "VxWorks target memory via RPC over TCP/IP";
+  vx_ops.to_doc =   "Use VxWorks target memory.  \n\
 Specify the name of the machine to connect to.",
-       vx_open, vx_close, vx_attach, 0, /* vx_detach, */
-       0, 0, /* resume, wait */
-       0, 0, /* read_reg, write_reg */
-       0, /* prep_to_store, */
-       vx_xfer_memory, vx_files_info,
-       0, 0, /* insert_breakpoint, remove_breakpoint */
-       0, 0, 0, 0, 0,  /* terminal stuff */
-       0, /* vx_kill, */
-       vx_load_command,
-       vx_lookup_symbol,
-       vx_create_inferior, 0,  /* mourn_inferior */
-       0, /* can_run */
-       0, /* notice_signals */
-       core_stratum, 0, /* next */
-       1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
-       0, 0,                   /* Section pointers */
-       OPS_MAGIC,              /* Always the last thing */
+    vx_ops.to_open =   vx_open;
+  vx_ops.to_close =   vx_close;
+  vx_ops.to_attach =   vx_attach;
+  vx_ops.to_detach =   0; /* vx_detach, */
+  vx_ops.to_resume =   0;
+  vx_ops.to_wait  =   0; /* resume, wait */
+  vx_ops.to_fetch_registers  =   0;
+  vx_ops.to_store_registers  =   0; /* read_reg, write_reg */
+  vx_ops.to_prepare_to_store =   0; /* prep_to_store, */
+  vx_ops.to_xfer_memory  =   vx_xfer_memory;
+  vx_ops.to_files_info  =   vx_files_info;
+  vx_ops.to_insert_breakpoint =   0;
+  vx_ops.to_remove_breakpoint =   0; /* insert_breakpoint, remove_breakpoint */
+  vx_ops.to_terminal_init  =   0;
+  vx_ops.to_terminal_inferior =   0;
+  vx_ops.to_terminal_ours_for_output =   0;
+  vx_ops.to_terminal_ours  =   0;
+  vx_ops.to_terminal_info  =   0;      /* terminal stuff */
+  vx_ops.to_kill  =   0; /* vx_kill, */
+  vx_ops.to_load  =   vx_load_command;
+  vx_ops.to_lookup_symbol =   vx_lookup_symbol;
+  vx_ops.to_create_inferior =   vx_create_inferior;
+  vx_ops.to_mourn_inferior =   0;  /* mourn_inferior */
+  vx_ops.to_can_run  =   0; /* can_run */
+  vx_ops.to_notice_signals =   0; /* notice_signals */
+  vx_ops.to_thread_alive  =   0; /* thread_alive */
+  vx_ops.to_stop  =   0;                               /* to_stop */
+  vx_ops.to_stratum =   core_stratum;
+  vx_ops.DONT_USE =   0; /* next */
+  vx_ops.to_has_all_memory =   1;
+  vx_ops.to_has_memory =   1;
+  vx_ops.to_has_stack =   0;
+  vx_ops.to_has_registers =   0;
+  vx_ops.to_has_execution =   0;       /* all mem, mem, stack, regs, exec */
+  vx_ops.to_sections =   0;
+  vx_ops.to_sections_end =   0;
+  vx_ops.to_magic =   OPS_MAGIC;               /* Always the last thing */
 };
 
 /* Target ops structure for accessing VxWorks child processes over the net */
 
-struct target_ops vx_run_ops = {
-       "vxprocess", "VxWorks process",
-       "VxWorks process, started by the \"run\" command.",
-       vx_proc_open, vx_proc_close, 0, vx_detach, /* vx_attach */
-       vx_resume, vx_wait,
-       vx_read_register, vx_write_register,
-       vx_prepare_to_store,
-       vx_xfer_memory, vx_run_files_info,
-       vx_insert_breakpoint, vx_remove_breakpoint,
-       0, 0, 0, 0, 0,  /* terminal stuff */
-       vx_kill,
-       vx_load_command,
-       vx_lookup_symbol,
-       0, vx_mourn_inferior,
-       0,  /* can_run */
-       0, /* notice_signals */
-       process_stratum, 0, /* next */
-       0, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
-                       /* all_mem is off to avoid spurious msg in "i files" */
-       0, 0,                   /* Section pointers */
-       OPS_MAGIC,              /* Always the last thing */
-};
+struct target_ops vx_run_ops ;
+
+static void init_vx_run_ops(void)
+{
+  vx_run_ops.to_shortname =   "vxprocess";
+  vx_run_ops.to_longname =   "VxWorks process";
+  vx_run_ops.to_doc =   "VxWorks process; started by the \"run\" command.",
+    vx_run_ops.to_open =   vx_proc_open;
+  vx_run_ops.to_close =   vx_proc_close;
+  vx_run_ops.to_attach =   0;
+  vx_run_ops.to_detach =   vx_detach; 
+  vx_run_ops.to_resume =   vx_resume;
+  vx_run_ops.to_wait  =   vx_wait;
+  vx_run_ops.to_fetch_registers  =   vx_read_register;
+  vx_run_ops.to_store_registers  =   vx_write_register;
+  vx_run_ops.to_prepare_to_store =   vx_prepare_to_store;
+  vx_run_ops.to_xfer_memory  =   vx_xfer_memory;
+  vx_run_ops.to_files_info  =   vx_run_files_info;
+  vx_run_ops.to_insert_breakpoint =   vx_insert_breakpoint;
+  vx_run_ops.to_remove_breakpoint =   vx_remove_breakpoint;
+  vx_run_ops.to_terminal_init  =   0;
+  vx_run_ops.to_terminal_inferior =   0;
+  vx_run_ops.to_terminal_ours_for_output =   0;
+  vx_run_ops.to_terminal_ours  =   0;
+  vx_run_ops.to_terminal_info  =   0;
+  vx_run_ops.to_kill  =   vx_kill;
+  vx_run_ops.to_load  =   vx_load_command;
+  vx_run_ops.to_lookup_symbol =   vx_lookup_symbol;
+  vx_run_ops.to_create_inferior =   0;
+  vx_run_ops.to_mourn_inferior =   vx_mourn_inferior ;
+  vx_run_ops.to_can_run =   0; 
+  vx_run_ops.to_notice_signals  =   0; 
+  vx_run_ops.to_thread_alive =   0; 
+  vx_run_ops.to_stop  =   0;   
+  vx_run_ops.to_stratum  =   process_stratum;
+  vx_run_ops.DONT_USE =   0; 
+  vx_run_ops.to_has_all_memory =   0; 
+  vx_run_ops.to_has_memory =   1;
+  vx_run_ops.to_has_stack =   1;
+  vx_run_ops.to_has_registers =   1;
+  vx_run_ops.to_has_execution =   1;   
+  vx_run_ops.to_sections =   0;
+  vx_run_ops.to_sections_end =   0;    
+  vx_run_ops.to_magic =   OPS_MAGIC;   
+}
 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
 \f
 void
 _initialize_vx ()
 {
-  
- add_show_from_set
+  init_vx_ops() ;
+  init_vx_run_ops() ;
+  add_show_from_set
     (add_set_cmd ("vxworks-timeout", class_support, var_uinteger,
                  (char *) &rpcTimeout.tv_sec,
                  "Set seconds to wait for rpc calls to return.\n\
 Set the number of seconds to wait for rpc calls to return.", &setlist),
      &showlist);
 
-   add_target (&vx_ops);
+  add_target (&vx_ops);
   add_target (&vx_run_ops);
 }
This page took 0.034186 seconds and 4 git commands to generate.