* gdb.threads/Makefile.in (docdir): Removed.
[deliverable/binutils-gdb.git] / gdb / remote-vx.c
index 63028e257d7a9a456bee817667074ee71ae58fda..13b6c294994ca8e5feaaaafd39dbf3d8555631e4 100644 (file)
@@ -1,25 +1,24 @@
 /* Memory-access and commands for remote VxWorks processes, for GDB.
-   Copyright (C) 1990-1991  Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
    Contributed by Wind River Systems and Cygnus Support.
 
 This file is part of GDB.
 
-GDB is free software; you can redistribute it and/or modify
+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 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include "param.h"
 #include "frame.h"
 #include "inferior.h"
 #include "wait.h"
@@ -27,36 +26,46 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "command.h"
 #include "symtab.h"
-#include "symfile.h"           /* for struct complaint */
-
-#include <stdio.h>
-#include <string.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 "gdb_string.h"
 #include <errno.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <sys/types.h>
-#include <sys/time.h>
 #include <sys/socket.h>
+#define malloc bogon_malloc    /* Sun claims "char *malloc()" not void * */
 #define free bogon_free                /* Sun claims "int free()" not void */
+#define realloc bogon_realloc  /* Sun claims "char *realloc()", not void * */
 #include <rpc/rpc.h>
+#undef malloc
 #undef free
+#undef realloc
 #include <sys/time.h>          /* UTek's <rpc/rpc.h> doesn't #incl this */
 #include <netdb.h>
-#include <ptrace.h>
-#include "xdr_ptrace.h"
-#include "xdr_ld.h"
-#include "xdr_rdb.h"
-#include "dbgRpcLib.h"
-
-/* get rid of value.h if possible */
-#include <value.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
 #include <symtab.h>
-extern value call_function_by_hand ();
+
+/* 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 void add_syms_addr_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 */
@@ -70,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.  */
 
@@ -89,401 +98,97 @@ static char *find_white_space ();
  
 /* Tell the VxWorks target system to download a file.
    The load addresses of the text, data, and bss segments are
-   stored in pTextAddr, pDataAddr, and *pBssAddr (respectively).
+   stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
    Returns 0 for success, -1 for failure.  */
 
 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;
-    bzero ((char *) &ldstruct, sizeof (ldstruct));
-
-    /* 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.  
-       
-       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);
-
-    if (status == RPC_SUCCESS)
-      {
-        if (*ldstruct.name == NULL)    /* 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? */
-
-    bzero ((char *) &ptrace_in, sizeof (ptrace_in));
-    break_status = 0;
+     char *filename;
+     CORE_ADDR *pTextAddr;
+     CORE_ADDR *pDataAddr;
+     CORE_ADDR *pBssAddr;
+{
+  enum clnt_stat status;
+  struct ldfile ldstruct;
+  struct timeval load_timeout;
 
-    ptrace_in.addr = addr;
-    ptrace_in.pid = inferior_pid;
+  memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
 
-    status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
-                           &break_status);
+  /* 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.  
 
-    if (status != RPC_SUCCESS)
-       return errno;
+     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...  */
 
-    if (break_status == -1)
-      return ENOMEM;
-    return break_status;       /* probably (FIXME) zero */
-    }
+  load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
+  load_timeout.tv_usec = 0;
  
-/* returns 0 if successful, errno otherwise */
+  status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+                     &ldstruct, load_timeout);
 
-int
-vx_insert_breakpoint (addr)
-    int addr;
+  if (status == RPC_SUCCESS)
     {
-    return net_break (addr, VX_BREAK_ADD);
+      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 otherwise */
-
-int
-vx_remove_breakpoint (addr)
-    int addr;
-    {
-    return net_break (addr, VX_BREAK_DELETE);
-    }
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
 
-/* Call a function on the VxWorks target system.
-   ARGS is a vector of values of arguments (NARGS of them).
-   FUNCTION is a value, the function to be called.
-   Returns a struct value * representing what the function returned.
-   May fail to return, if a breakpoint or signal is hit
-   during the execution of the function.  */
-
-#ifdef FIXME
-/* FIXME, function calls are really fried.  GO back to manual method. */
-value
-vx_call_function (function, nargs, args)
-     value function;
-     int nargs;
-     value *args;
+static int
+net_break (addr, procnum)
+     int addr;
+     u_long procnum;
 {
-  register CORE_ADDR sp;
-  register int i;
-  CORE_ADDR start_sp;
-  static REGISTER_TYPE dummy[] = CALL_DUMMY;
-  REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
-  CORE_ADDR old_sp;
-  struct type *value_type;
-  unsigned char struct_return;
-  CORE_ADDR struct_addr;
-  struct inferior_status inf_status;
-  struct cleanup *old_chain;
-  CORE_ADDR funaddr;
-  int using_gcc;
-
-  save_inferior_status (&inf_status, 1);
-  old_chain = make_cleanup (restore_inferior_status, &inf_status);
-
-  /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
-     (and POP_FRAME for restoring them).  (At least on most machines)
-     they are saved on the stack in the inferior.  */
-  PUSH_DUMMY_FRAME;
-
-  old_sp = sp = read_register (SP_REGNUM);
-
-#if 1 INNER_THAN 2             /* Stack grows down */
-  sp -= sizeof dummy;
-  start_sp = sp;
-#else                          /* Stack grows up */
-  start_sp = sp;
-  sp += sizeof dummy;
-#endif
-
-  funaddr = find_function_addr (function, &value_type);
-
-  {
-    struct block *b = block_for_pc (funaddr);
-    /* If compiled without -g, assume GCC.  */
-    using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
-  }
-
-  /* Are we returning a value using a structure return or a normal
-     value return? */
-
-  struct_return = using_struct_return (function, funaddr, value_type,
-                                      using_gcc);
-
-  /* Create a call sequence customized for this function
-     and the number of arguments for it.  */
-  bcopy (dummy, dummy1, sizeof dummy);
-  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
-                 value_type, using_gcc);
-
-#if CALL_DUMMY_LOCATION == ON_STACK
-  write_memory (start_sp, dummy1, sizeof dummy);
-
-#else /* Not on stack.  */
-#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
-  /* Convex Unix prohibits executing in the stack segment. */
-  /* Hope there is empty room at the top of the text segment. */
-  {
-    static checked = 0;
-    if (!checked)
-      for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
-       if (read_memory_integer (start_sp, 1) != 0)
-         error ("text segment full -- no place to put call");
-    checked = 1;
-    sp = old_sp;
-    start_sp = text_end - sizeof dummy;
-    write_memory (start_sp, dummy1, sizeof dummy);
-  }
-#else /* After text_end.  */
-  {
-    int errcode;
-    sp = old_sp;
-    start_sp = text_end;
-    errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
-    if (errcode != 0)
-      error ("Cannot write text segment -- call_function failed");
-  }
-#endif /* After text_end.  */
-#endif /* Not on stack.  */
-
-#ifdef STACK_ALIGN
-  /* If stack grows down, we must leave a hole at the top. */
-  {
-    int len = 0;
-
-    /* Reserve space for the return structure to be written on the
-       stack, if necessary */
-
-    if (struct_return)
-      len += TYPE_LENGTH (value_type);
-    
-    for (i = nargs - 1; i >= 0; i--)
-      len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
-#ifdef CALL_DUMMY_STACK_ADJUST
-    len += CALL_DUMMY_STACK_ADJUST;
-#endif
-#if 1 INNER_THAN 2
-    sp -= STACK_ALIGN (len) - len;
-#else
-    sp += STACK_ALIGN (len) - len;
-#endif
-  }
-#endif /* STACK_ALIGN */
-
-    /* Reserve space for the return structure to be written on the
-       stack, if necessary */
-
-    if (struct_return)
-      {
-#if 1 INNER_THAN 2
-       sp -= TYPE_LENGTH (value_type);
-       struct_addr = sp;
-#else
-       struct_addr = sp;
-       sp += TYPE_LENGTH (value_type);
-#endif
-      }
-
-#if defined (REG_STRUCT_HAS_ADDR)
-  {
-    /* This is a machine like the sparc, where we need to pass a pointer
-       to the structure, not the structure itself.  */
-    if (REG_STRUCT_HAS_ADDR (using_gcc))
-      for (i = nargs - 1; i >= 0; i--)
-       if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
-         {
-           CORE_ADDR addr;
-#if !(1 INNER_THAN 2)
-           /* The stack grows up, so the address of the thing we push
-              is the stack pointer before we push it.  */
-           addr = sp;
-#endif
-           /* Push the structure.  */
-           sp = value_push (sp, args[i]);
-#if 1 INNER_THAN 2
-           /* The stack grows down, so the address of the thing we push
-              is the stack pointer after we push it.  */
-           addr = sp;
-#endif
-           /* The value we're going to pass is the address of the thing
-              we just pushed.  */
-           args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
-         }
-  }
-#endif /* REG_STRUCT_HAS_ADDR.  */
-
-#ifdef PUSH_ARGUMENTS
-  PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
-#else /* !PUSH_ARGUMENTS */
-  for (i = nargs - 1; i >= 0; i--)
-    sp = value_arg_push (sp, args[i]);
-#endif /* !PUSH_ARGUMENTS */
-
-#ifdef CALL_DUMMY_STACK_ADJUST
-#if 1 INNER_THAN 2
-  sp -= CALL_DUMMY_STACK_ADJUST;
-#else
-  sp += CALL_DUMMY_STACK_ADJUST;
-#endif
-#endif /* CALL_DUMMY_STACK_ADJUST */
-
-  /* Store the address at which the structure is supposed to be
-     written.  Note that this (and the code which reserved the space
-     above) assumes that gcc was used to compile this function.  Since
-     it doesn't cost us anything but space and if the function is pcc
-     it will ignore this value, we will make that assumption.
-
-     Also note that on some machines (like the sparc) pcc uses a 
-     convention like gcc's.  */
-
-  if (struct_return)
-    STORE_STRUCT_RETURN (struct_addr, sp);
+  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? */
 
-  /* Write the stack pointer.  This is here because the statements above
-     might fool with it.  On SPARC, this write also stores the register
-     window into the right place in the new stack frame, which otherwise
-     wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
-  write_register (SP_REGNUM, sp);
+  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+  break_status = 0;
 
-  /* Figure out the value returned by the function.  */
-  {
-    char retbuf[REGISTER_BYTES];
+  ptrace_in.addr = addr;
+  ptrace_in.pid = inferior_pid;
 
-    /* Execute the stack dummy routine, calling FUNCTION.
-       When it is done, discard the empty frame
-       after storing the contents of all regs into retbuf.  */
-    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+  status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+                         &break_status);
 
-    do_cleanups (old_chain);
+  if (status != RPC_SUCCESS)
+      return errno;
 
-    return value_being_returned (value_type, retbuf, struct_return);
-  }
+  if (break_status == -1)
+    return ENOMEM;
+  return break_status; /* probably (FIXME) zero */
 }
-/* should return a value of some sort */
-value
-vx_call_function (funcAddr, nargs, args, valueType)
-    char *funcAddr;
-    int nargs;
-    value *args;
-    struct type * valueType;
-{
-    int i;
-    func_call funcInfo;
-    arg_value *argValue;
-    enum clnt_stat status;
-    register int len;
-    arg_value funcReturn;
-    value gdbValue;
-
-    argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
-
-    bzero (argValue, nargs * sizeof (arg_value));
-    bzero (&funcReturn, sizeof (funcReturn));
-
-    for (i = nargs - 1; i >= 0; i--)
-       {
-       len = TYPE_LENGTH (VALUE_TYPE (args [i]));
 
-       switch (TYPE_CODE (VALUE_TYPE (args[i])))
-           {
-           /* XXX put other types here.  Where's CHAR, etc??? */
-
-           case TYPE_CODE_FLT:
-               argValue[i].type = T_FLOAT;
-               break;
-           case TYPE_CODE_INT:
-           case TYPE_CODE_PTR:
-           case TYPE_CODE_ENUM:
-           case TYPE_CODE_FUNC:
-               argValue[i].type = T_INT;
-               break;
-
-           case TYPE_CODE_UNDEF:
-           case TYPE_CODE_ARRAY:
-           case TYPE_CODE_STRUCT:
-           case TYPE_CODE_UNION:
-           case TYPE_CODE_VOID:
-           case TYPE_CODE_SET:
-           case TYPE_CODE_RANGE:
-           case TYPE_CODE_PASCAL_ARRAY:
-           case TYPE_CODE_MEMBER:          /* C++ */
-           case TYPE_CODE_METHOD:          /* C++ */
-           case TYPE_CODE_REF:             /* C++ */
-           default:
-               error ("No corresponding VxWorks type for %d.  CHECK IT OUT!!!\n",
-                       TYPE_CODE(VALUE_TYPE(args[i])));
-           } /* switch */
-       if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
-           argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
-       else
-           bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
-                  len);
-       }
+/* returns 0 if successful, errno otherwise */
 
-    /* XXX what should the type of this function addr be?
-     * XXX Both in gdb and vxWorks
-     */
-    funcInfo.func_addr = (int) funcAddr;
-    funcInfo.args.args_len = nargs;
-    funcInfo.args.args_val = argValue;
+static int
+vx_insert_breakpoint (addr)
+     int addr;
+{
+  return net_break (addr, VX_BREAK_ADD);
+}
 
-    status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
-                           xdr_arg_value, &funcReturn);
+/* returns 0 if successful, errno otherwise */
 
-    free ((char *) argValue);
+static int
+vx_remove_breakpoint (addr)
+     int addr;
+{
+  return net_break (addr, VX_BREAK_DELETE);
+}
 
-    if (status == RPC_SUCCESS)
-       {
-       /* XXX this assumes that vxWorks ALWAYS returns an int, and that
-        * XXX gdb isn't expecting anything more
-        */
-
-       /*******************
-       if (funcReturn.type == T_UNKNOWN)
-           return YYYXXX...;
-       *******************/
-       gdbValue = allocate_value (valueType);
-       bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
-               sizeof (int));
-        return gdbValue;
-       }
-    else 
-       error (rpcerr);
-    }
-#endif /* FIXME */
 /* Start an inferior process and sets inferior_pid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
@@ -491,7 +196,7 @@ vx_call_function (funcAddr, nargs, args, valueType)
    Returns process id.  Errors reported with error().
    On VxWorks, we ignore exec_file.  */
  
-void
+static void
 vx_create_inferior (exec_file, args, env)
      char *exec_file;
      char *args;
@@ -501,8 +206,8 @@ vx_create_inferior (exec_file, args, env)
   arg_array passArgs;
   TASK_START taskStart;
 
-  bzero ((char *) &passArgs, sizeof (passArgs));
-  bzero ((char *) &taskStart, sizeof (taskStart));
+  memset ((char *) &passArgs, '\0', sizeof (passArgs));
+  memset ((char *) &taskStart, '\0', sizeof (taskStart));
 
   /* parse arguments, put them in passArgs */
 
@@ -521,17 +226,9 @@ vx_create_inferior (exec_file, args, env)
   vx_running = savestring (passArgs.arg_array_val[0],
                           strlen (passArgs.arg_array_val[0]));
 
-#ifdef CREATE_INFERIOR_HOOK
-  CREATE_INFERIOR_HOOK (pid);
-#endif  
-
   push_target (&vx_run_ops);
   inferior_pid = taskStart.pid;
 
-#if defined (START_INFERIOR_HOOK)
-  START_INFERIOR_HOOK ();
-#endif
-
   /* We will get a trace trap after one instruction.
      Insert breakpoints and continue.  */
 
@@ -544,14 +241,12 @@ vx_create_inferior (exec_file, args, env)
   /* Install inferior's terminal modes.  */
   target_terminal_inferior ();
 
-  /* remote_start(args); */
-  /* trap_expected = 0; */
   stop_soon_quietly = 1;
   wait_for_inferior ();                /* Get the task spawn event */
   stop_soon_quietly = 0;
 
   /* insert_step_breakpoint ();  FIXME, do we need this?  */
-  proceed(-1, -1, 0);
+  proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
 }
 
 /* Fill ARGSTRUCT in argc/argv form with the arguments from the
@@ -566,7 +261,7 @@ parse_args (arg_string, arg_struct)
   register int arg_index = 0;
   register char *p0;
  
-  bzero ((char *) arg_struct, sizeof (arg_array));
+  memset ((char *) arg_struct, '\0', sizeof (arg_array));
  
   /* first count how many arguments there are */
 
@@ -639,255 +334,148 @@ find_white_space (p)
    to the debugged task.
    Returns -1 if remote wait failed, task status otherwise.  */
 
-int
+static int
 net_wait (pEvent)
     RDB_EVENT *pEvent;
 {
     int pid;
     enum clnt_stat status;
 
-    bzero ((char *) pEvent, sizeof (RDB_EVENT));
+    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.
    Returns -1 if suspend fails on target system, 0 otherwise.  */
 
-int
+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.  */
 
-int
-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;
-  struct regs inferior_registers;
-  struct fp_status inferior_fp_registers;
-  extern char registers[];
+  C_bytes out_data;
+  char message[100];
 
-  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
-  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+  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 ();
-  
-  ptrace_in.pid = inferior_pid;
-  ptrace_out.info.more_data = (caddr_t) &inferior_registers;
-  status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
-  if (status)
-    error (rpcerr);
-  if (ptrace_out.status == -1)
-    {
-      errno = ptrace_out.errno;
-      return -1;
-    }
-  
-#ifdef I80960
+  /* Initialize RPC input argument structure.  */
 
-      bcopy ((char *) inferior_registers.r_lreg,
-            &registers[REGISTER_BYTE (R0_REGNUM)], 16 * sizeof (int));
-      bcopy ((char *) inferior_registers.r_greg,
-            &registers[REGISTER_BYTE (G0_REGNUM)], 16 * sizeof (int));
-
-      /* Don't assume that a location in registers[] is properly aligned.  */
-
-      bcopy ((char *) &inferior_registers.r_pcw,
-            &registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
-      bcopy ((char *) &inferior_registers.r_acw,
-            &registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
-      bcopy ((char *) &inferior_registers.r_lreg[2],   /* r2 (RIP) -> IP */
-            &registers[REGISTER_BYTE (IP_REGNUM)], sizeof (int));
-      bcopy ((char *) &inferior_registers.r_tcw,
-            &registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
+  ptrace_in.pid = inferior_pid;
+  ptrace_in.info.ttype = NOINFO;
 
-      /* 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.  */
+  /* Initialize RPC return value structure.  */
 
-      if (target_has_fp)
-       {
-         ptrace_in.pid = inferior_pid;
-         ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
-         status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
-         if (status)
-           error (rpcerr);
-         if (ptrace_out.status == -1)
-           {
-             errno = ptrace_out.errno;
-             return -1;
-           }
-         
-         bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
-                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
-       }
-      else
-       {
-         bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
-                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
-       }
+  out_data.bytes = reg_buf;
+  out_data.len = len;
+  ptrace_out.info.more_data = (caddr_t) &out_data;
 
-#else  /* not 960, thus must be 68000:  FIXME!  */
+  /* Call RPC; take an error exit if appropriate.  */
 
-  bcopy (&inferior_registers, registers, 16 * 4);
-  *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
-  *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
-
-  if (target_has_fp)
-    {
-      ptrace_in.pid = inferior_pid;
-      ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
-      status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
-      if (status)
-       error (rpcerr);
-      if (ptrace_out.status == -1)
-       {
-         errno = ptrace_out.errno;
-         return -1;
-       }
-      
-      bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
-            sizeof inferior_fp_registers.fps_regs);
-      bcopy (&inferior_fp_registers.fps_control,
-        &registers[REGISTER_BYTE (FPC_REGNUM)],
-        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
-    }
-  else
+  status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
+  if (status)
+    error (rpcerr);
+  if (ptrace_out.status == -1)
     {
-      bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
-            sizeof inferior_fp_registers.fps_regs);
-      bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
-        sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+      errno = ptrace_out.errno;
+      sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS)
+                                                ? "general-purpose"
+                                                : "floating-point");
+      perror_with_name (message);
     }
-#endif  /* various architectures */
-
-  return 0;
 }
 
-/* Prepare to store registers.  Since we will store all of them,
-   read out their current values now.  */
+/* 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
-vx_prepare_to_store ()
-{
-  vx_read_register (-1);
-}
-
-
-/* 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 */
-
-vx_write_register (regno)
-     int regno;
+net_write_registers (reg_buf, len, procnum)
+     char *reg_buf;
+     int len;
+     u_long procnum;
 {
-  struct regs inferior_registers;
-  struct fp_status inferior_fp_registers;
-  extern char registers[];
   int status;
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
+  C_bytes in_data;
+  char message[100];
 
-  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
-  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
-
-#ifdef I80960
-
-  bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
-        (char *) inferior_registers.r_lreg, 16 * sizeof (int));
-  bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
-        (char *) inferior_registers.r_greg, 16 * sizeof (int));
-
-  /* Don't assume that a location in registers[] is properly aligned.  */
+  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
 
-  bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
-        (char *) &inferior_registers.r_pcw, sizeof (int));
-  bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
-        (char *) &inferior_registers.r_acw, sizeof (int));
-  bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
-        (char *) &inferior_registers.r_tcw, sizeof (int));
+  /* Initialize RPC input argument structure.  */
 
-#else  /* not 960 -- assume 68k -- FIXME */
-
-  bcopy (registers, &inferior_registers, 16 * 4);
-  inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
-  inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
-
-#endif  /* Different register sets */
+  in_data.bytes = reg_buf;
+  in_data.len = len;
 
   ptrace_in.pid = inferior_pid;
-  ptrace_in.info.ttype     = REGS;
-  ptrace_in.info.more_data = (caddr_t) &inferior_registers;
+  ptrace_in.info.ttype = DATA;
+  ptrace_in.info.more_data = (caddr_t) &in_data;
+
+  /* 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);
+    error (rpcerr);
   if (ptrace_out.status == -1)
     {
       errno = ptrace_out.errno;
-      return -1;
+      sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS)
+                                                ? "general-purpose"
+                                                : "floating-point");
+      perror_with_name (message);
     }
+}
 
-  /* Store floating point registers if the target has them.  */
-
-  if (target_has_fp)
-    {
-#ifdef I80960
-
-      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
-            sizeof inferior_fp_registers.fps_regs);
-
-#else  /* not 960 -- assume 68k -- FIXME */
-
-      bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
-            sizeof inferior_fp_registers.fps_regs);
-      bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
-        &inferior_fp_registers.fps_control,
-         sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
-
-#endif  /* Different register sets */
-
-      ptrace_in.pid = inferior_pid;
-      ptrace_in.info.ttype     = FPREGS;
-      ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
+/* 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;
-         return -1;
-       }
-    }
-  return 0;
+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
@@ -898,19 +486,23 @@ vx_write_register (regno)
    handle the current address but can handle one N bytes further, but
    vxworks doesn't give us that information.  */
 
-int
-vx_xfer_memory (memaddr, myaddr, len, write)
+static int
+vx_xfer_memory (memaddr, myaddr, len, write, target)
      CORE_ADDR memaddr;
      char *myaddr;
      int len;
+     int write;
+     struct target_ops *target;                        /* ignored */
 {
   int status;
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
   C_bytes data;
+  enum ptracereq request;
+  int nleft, nxfer;
 
-  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
-  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
 
   ptrace_in.pid = inferior_pid;                /* XXX pid unnecessary for READDATA */
   ptrace_in.addr = (int) memaddr;      /* Where from */
@@ -923,71 +515,118 @@ vx_xfer_memory (memaddr, myaddr, len, write)
 
       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);
 }
 
-void
+static void
 vx_files_info ()
 {
-  printf ("\tAttached to host `%s'", vx_host);
-  printf (", which has %sfloating point", target_has_fp? "": "no ");
-  printf (".\n");
+  printf_unfiltered ("\tAttached to host `%s'", vx_host);
+  printf_unfiltered (", which has %sfloating point", target_has_fp? "": "no ");
+  printf_unfiltered (".\n");
 }
 
-void
+static void
 vx_run_files_info ()
 {
-  printf ("\tRunning %s VxWorks process 0x%x", 
-         vx_running? "child": "attached",
-         inferior_pid);
+  printf_unfiltered ("\tRunning %s VxWorks process %s", 
+                    vx_running ? "child" : "attached",
+                    local_hex_string (inferior_pid));
   if (vx_running)
-    printf (", function `%s'", vx_running);
-  printf(".\n");
+    printf_unfiltered (", function `%s'", vx_running);
+  printf_unfiltered(".\n");
 }
 
-void
-vx_resume (step, siggnal)
+static void
+vx_resume (pid, step, siggnal)
+     int pid;
      int step;
-     int siggnal;
+     enum target_signal siggnal;
 {
   int status;
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
+  CORE_ADDR cont_addr;
+
+  if (pid == -1)
+    pid = inferior_pid;
 
   if (siggnal != 0 && siggnal != stop_signal)
     error ("Cannot send signals to VxWorks processes");
 
-  bzero ((char *) &ptrace_in, sizeof (ptrace_in));
-  bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+  /* 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.  */
 
-  ptrace_in.pid = inferior_pid;
-  ptrace_in.addr = 1;  /* Target side insists on this, or it panics.  */
+  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 = 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;
@@ -995,7 +634,7 @@ vx_resume (step, siggnal)
     }
 }
 
-void
+static void
 vx_mourn_inferior ()
 {
   pop_target ();               /* Pop back to no-child state */
@@ -1003,17 +642,95 @@ 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);
+
+  /* Need to do this *after* things are relocated.  */
+  breakpoint_re_set ();
+}
+
 /* This function allows the addition of incrementally linked object files.  */
 
-void
+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");
 
@@ -1022,17 +739,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);
+  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.  */
@@ -1065,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.  */
@@ -1093,7 +823,7 @@ net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
    NULL, memory for the buffer will be allocated by XDR.
    Returns -1 if rpc failed, 0 otherwise.  */
 
-int
+static int
 net_get_boot_file (pBootFile)
      char **pBootFile;
 {
@@ -1109,13 +839,13 @@ net_get_boot_file (pBootFile)
    There's no way to check if the returned loadTable is correct.
    VxWorks doesn't check it.  */
 
-int
+static int
 net_get_symbols (pLoadTable)
      ldtabl *pLoadTable;               /* return pointer to ldtabl here */
 {
   enum clnt_stat status;
 
-  bzero ((char *) pLoadTable, sizeof (struct ldtabl));
+  memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl));
 
   status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
   return (status == RPC_SUCCESS) ? 0 : -1;
@@ -1128,7 +858,7 @@ net_get_symbols (pLoadTable)
 struct complaint cant_contact_target =
   {"Lost contact with VxWorks target", 0, 0};
 
-int
+static int
 vx_lookup_symbol (name, pAddr)
      char *name;               /* symbol name */
      CORE_ADDR *pAddr;
@@ -1137,14 +867,15 @@ vx_lookup_symbol (name, pAddr)
   SYMBOL_ADDR symbolAddr;
 
   *pAddr = 0;
-  bzero ((char *) &symbolAddr, sizeof (symbolAddr));
+  memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr));
 
   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
                          xdr_SYMBOL_ADDR, &symbolAddr);
-  if (status != RPC_SUCCESS) {
-      complain (&cant_contact_target, 0);
+  if (status != RPC_SUCCESS)
+    {
+      complain (&cant_contact_target);
       return -1;
-  }
+    }
 
   *pAddr = symbolAddr.addr;
   return symbolAddr.status;
@@ -1154,7 +885,7 @@ vx_lookup_symbol (name, pAddr)
    Returns 1 if target has floating point processor, 0 otherwise.
    Calls error() if rpc fails.  */
 
-int
+static int
 net_check_for_fp ()
 {
   enum clnt_stat status;
@@ -1162,7 +893,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;
 }
@@ -1170,21 +901,32 @@ net_check_for_fp ()
 /* Establish an RPC connection with the VxWorks target system.
    Calls error () if unable to establish connection.  */
 
-void
+static void
 net_connect (host)
      char *host;
 {
   struct sockaddr_in destAddr;
   struct hostent *destHost;
+  unsigned long addr;
 
-  /* get the internet address for the given host */
+  /* Get the internet address for the given host.  Allow a numeric
+     IP address or a hostname.  */
 
-  if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
-      error ("Invalid hostname.  Couldn't find remote host address.");
+  addr = inet_addr (host);
+  if (addr == -1)
+    {
+      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;
+    }
 
-  bzero (&destAddr, sizeof (destAddr));
+  memset (&destAddr, '\0', sizeof (destAddr));
 
-  destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
+  destAddr.sin_addr.s_addr = addr;
   destAddr.sin_family      = AF_INET;
   destAddr.sin_port        = 0;        /* set to actual port that remote
                                   ptrace is listening on.  */
@@ -1194,8 +936,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");
@@ -1219,30 +962,19 @@ 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 (status)
-     int *status;
+vx_wait (pid_to_wait_for, status)
+     int pid_to_wait_for;
+     struct target_waitstatus *status;
 {
   register int pid;
-  WAITTYPE w;
   RDB_EVENT rdbEvent;
   int quit_failed;
 
@@ -1287,74 +1019,82 @@ vx_wait (status)
          sleep_ms (200);       /* FIXME Don't kill the network too badly */
        }
       else if (pid != inferior_pid)
-       fatal ("Bad pid for debugged task: 0x%x\n", pid);
+       fatal ("Bad pid for debugged task: %s\n",
+              local_hex_string((unsigned long) pid));
     } while (pid == 0);
 
-  /* FIXME, eventually do more then SIGTRAP on everything...  */
+  /* The mostly likely kind.  */
+  status->kind = TARGET_WAITKIND_STOPPED;
+
   switch (rdbEvent.eventType)
     {
     case EVENT_EXIT:
-      WSETEXIT (w, 0);
+      status->kind = TARGET_WAITKIND_EXITED;
       /* FIXME is it possible to distinguish between a
-        XXX   normal vs abnormal exit in VxWorks? */
+        normal vs abnormal exit in VxWorks? */
+      status->value.integer = 0;
       break;
 
-    case EVENT_START:          /* Task was just started. */
-      WSETSTOP (w, SIGTRAP);
+    case EVENT_START:
+      /* Task was just started. */
+      status->value.sig = TARGET_SIGNAL_TRAP;
       break;
 
     case EVENT_STOP:
-      WSETSTOP (w, SIGTRAP);
+      status->value.sig = TARGET_SIGNAL_TRAP;
       /* XXX was it stopped by a signal?  act accordingly */
       break;
 
     case EVENT_BREAK:          /* Breakpoint was hit. */
-      WSETSTOP (w, SIGTRAP);
+      status->value.sig = TARGET_SIGNAL_TRAP;
       break;
 
     case EVENT_SUSPEND:                /* Task was suspended, probably by ^C. */
-      WSETSTOP (w, SIGINT);
+      status->value.sig = TARGET_SIGNAL_INT;
       break;
 
     case EVENT_BUS_ERR:                /* Task made evil nasty reference. */
-      WSETSTOP (w, SIGBUS);
+      status->value.sig = TARGET_SIGNAL_BUS;
       break;
 
     case EVENT_ZERO_DIV:       /* Division by zero */
-      WSETSTOP (w, SIGFPE);    /* Like Unix, call it a float exception. */
+      status->value.sig = TARGET_SIGNAL_FPE;
+      break;
 
     case EVENT_SIGNAL:
-      /* The target is not running Unix, and its
-        faults/traces do not map nicely into Unix signals.
-        Make sure they do not get confused with Unix signals
-        by numbering them with values higher than the highest
-        legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
-        routine will interpret the value for wait_for_inferior.  */
-      WSETSTOP (w, rdbEvent.sigType + NSIG);
+#ifdef I80960
+      status->value.sig = i960_fault_to_signal (rdbEvent.sigType);
+#else
+      /* Back in the old days, before enum target_signal, this code used
+        to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL
+        would take care of it.  But PRINT_RANDOM_SIGNAL has never been
+        defined except on the i960, so I don't really know what we are
+        supposed to do on other architectures.  */
+      status->value.sig = TARGET_SIGNAL_UNKNOWN;
+#endif
       break;
     } /* switch */
-  *status = *(int *)&w;                /* Grumble union wait crap Grumble */
   return pid;
 }
 \f
 static int
 symbol_stub (arg)
-     int arg;
+     char *arg;
 {
-  char *bootFile = (char *)arg;
-  symbol_file_command (bootFile, 0);
+  symbol_file_command (arg, 0);
   return 1;
 }
 
 static int
 add_symbol_stub (arg)
-     int arg;
+     char *arg;
 {
   struct ldfile *pLoadFile = (struct ldfile *)arg;
 
-  printf("\t%s: ", pLoadFile->name);
-  symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
-  printf ("ok\n");
+  printf_unfiltered("\t%s: ", pLoadFile->name);
+  vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
+                 pLoadFile->data_addr, pLoadFile->bss_addr);
+  printf_unfiltered ("ok\n");
   return 1;
 }
 /* Target command for VxWorks target systems.
@@ -1375,13 +1115,16 @@ vx_open (args, from_tty)
   struct ldfile *pLoadFile;
   int i;
   extern CLIENT *pClient;
+  int symbols_added = 0;
 
   if (!args)
     error_no_arg ("target machine name");
 
+  target_preopen (from_tty);
+  
   unpush_target (&vx_ops);
-  printf ("Attaching remote machine across net...\n");
-  fflush (stdout);
+  printf_unfiltered ("Attaching remote machine across net...\n");
+  gdb_flush (gdb_stdout);
 
   /* Allow the user to kill the connect attempt by typing ^C.
      Wait until the call to target_has_fp () completes before
@@ -1408,13 +1151,20 @@ 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, (int)bootFile,
-               "Error reading symbols from boot file"))
-         puts_filtered ("ok\n");
-      } else if (from_tty)
-       printf ("VxWorks kernel symbols not loaded.\n");
+      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
     error ("Can't retrieve boot file name from target machine.");
@@ -1444,19 +1194,26 @@ 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.  */
-      catch_errors (add_symbol_stub, (int)pLoadFile, (char *)0);
+      /* 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;
 #endif
     }
   printf_filtered ("Done.\n");
 
   clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+
+  /* Getting new symbols may change our opinion about what is
+     frameless.  */
+  if (symbols_added)
+    reinit_frame_cache ();
 }
 \f
-/* attach_command --
-   takes a task started up outside of gdb and ``attaches'' to it.
+/* Takes a task started up outside of gdb and ``attaches'' to it.
    This stops it cold in its tracks and allows us to start tracing it.  */
 
 static void
@@ -1464,26 +1221,25 @@ vx_attach (args, from_tty)
      char *args;
      int from_tty;
 {
-  int pid;
+  unsigned long pid;
   char *cptr = 0;
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
   int status;
 
-  dont_repeat();
-
   if (!args)
     error_no_arg ("process-id to attach");
 
-  pid = strtol (args, &cptr, 0);
+  pid = strtoul (args, &cptr, 0);
   if ((cptr == args) || (*cptr != '\0'))
     error ("Invalid process-id -- give a single number in decimal or 0xhex");
 
   if (from_tty)
-      printf ("Attaching pid 0x%x.\n", pid);
+    printf_unfiltered ("Attaching pid %s.\n",
+                      local_hex_string((unsigned long) pid));
 
-  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
-  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  memset ((char *)&ptrace_in,  '\0', sizeof (ptrace_in));
+  memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
   ptrace_in.pid = pid;
 
   status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
@@ -1497,9 +1253,11 @@ 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;
   vx_running = 0;
-
 #if defined (START_INFERIOR_HOOK)
   START_INFERIOR_HOOK ();
 #endif
@@ -1508,12 +1266,15 @@ vx_attach (args, from_tty)
 
   /* 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;
@@ -1546,13 +1307,14 @@ vx_detach (args, from_tty)
     error ("Argument given to VxWorks \"detach\".");
 
   if (from_tty)
-      printf ("Detaching pid 0x%x.\n", inferior_pid);
+      printf_unfiltered ("Detaching pid %s.\n",
+             local_hex_string((unsigned long) inferior_pid));
 
   if (args)            /* FIXME, should be possible to leave suspended */
     signal = atoi (args);
   
-  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
-  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  memset ((char *)&ptrace_in,  '\0', sizeof (ptrace_in));
+  memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
   ptrace_in.pid = inferior_pid;
 
   status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
@@ -1571,41 +1333,36 @@ vx_detach (args, from_tty)
 /* vx_kill -- takes a running task and wipes it out.  */
 
 static void
-vx_kill (args, from_tty)
-     char *args;
-     int from_tty;
+vx_kill ()
 {
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
   int status;
 
-  if (args)
-    error ("Argument given to VxWorks \"kill\".");
-
-  if (from_tty)
-      printf ("Killing pid 0x%x.\n", inferior_pid);
+  printf_unfiltered ("Killing pid %s.\n", local_hex_string((unsigned long) inferior_pid));
 
-  bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
-  bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+  memset ((char *)&ptrace_in,  '\0', sizeof (ptrace_in));
+  memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
   ptrace_in.pid = inferior_pid;
 
   status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
   if (status == -1)
-    error (rpcerr);
-  if (ptrace_out.status == -1)
+    warning (rpcerr);
+  else if (ptrace_out.status == -1)
     {
       errno = ptrace_out.errno;
       perror_with_name ("Killing VxWorks process");
     }
 
-  /* If it gives good status, the process is *gone*, no events remain.  */
+  /* If it gives good status, the process is *gone*, no events remain.
+     If the kill failed, assume the process is gone anyhow.  */
   inferior_pid = 0;
   pop_target ();       /* go back to non-executing VxWorks connection */
 }
 
 /* Clean up from the VxWorks process target as it goes away.  */
 
-void
+static void
 vx_proc_close (quitting)
      int quitting;
 {
@@ -1615,77 +1372,6 @@ vx_proc_close (quitting)
   vx_running = 0;
 }
 \f
-/* Cross-net conversion of floats to and from extended form.
-   (This is needed because different target machines have different
-    extended floating point formats.)  */
-
-/* Convert from an extended float to a double.
-
-   The extended float is stored as raw data pointed to by FROM.
-   Return the converted value as raw data in the double pointed to by TO.
-*/
-
-static void
-vx_convert_to_virtual (regno, from, to)
-    int regno;
-    char *from;
-    char *to;
-{
-  enum clnt_stat status;
-
-  if (REGISTER_CONVERTIBLE (regno)) 
-    {
-      if (!target_has_fp) {
-       *(double *)to = 0.0;    /* Skip the trouble if no float anyway */
-       return;
-      }
-
-      status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, from,
-                             xdr_double, to);
-
-      if (status == RPC_SUCCESS)
-         return;
-      else
-         error (rpcerr);
-    }
-  else
-    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
-}
-
-
-/* The converse:  convert from a double to an extended float.
-
-   The double is stored as raw data pointed to by FROM.
-   Return the converted value as raw data in the extended
-   float pointed to by TO.
-*/
-
-static void
-vx_convert_from_virtual (regno, from, to)
-    int regno;
-    char *from;
-    char *to;
-{
-  enum clnt_stat status;
-
-  if (REGISTER_CONVERTIBLE (regno)) 
-    {
-      if (!target_has_fp) {
-       bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM));     /* Shrug */
-       return;
-      }
-
-      status = net_clnt_call (VX_CONV_TO_68881, xdr_double, from,
-                             xdr_ext_fp, to);
-      if (status == RPC_SUCCESS)
-         return;
-      else
-         error (rpcerr);
-    }
-  else
-    bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
-}
-\f
 /* Make an RPC call to the VxWorks target.
    Returns RPC status.  */
 
@@ -1709,7 +1395,7 @@ net_clnt_call (procNum, inProc, in, outProc, out)
 
 /* Clean up before losing control.  */
 
-void
+static void
 vx_close (quitting)
      int quitting;
 {
@@ -1722,54 +1408,81 @@ vx_close (quitting)
   vx_host = 0;
 }
 
+/* A vxprocess target should be started via "run" not "target".  */
+/*ARGSUSED*/
+static void
+vx_proc_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  error ("Use the \"run\" command to start a VxWorks process.");
+}
 
 /* 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",
-       vx_open, vx_close, vx_attach, 0, /* vx_detach, */
-       0, 0, /* resume, wait */
-       0, 0, /* read_reg, write_reg */
-       0, vx_convert_to_virtual, vx_convert_from_virtual,  /* 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, add_syms_addr_command,
-       0,  /* call_function */
-       vx_lookup_symbol,
-       vx_create_inferior, 0,  /* mourn_inferior */
-       core_stratum, 0, /* next */
-       1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
-       OPS_MAGIC,              /* Always the last thing */
+  "vxworks", "VxWorks target memory via RPC over TCP/IP",
+  "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 */
+  0, /* thread_alive */
+  0,                           /* to_stop */
+  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 */
 };
 
 /* Target ops structure for accessing VxWorks child processes over the net */
 
 struct target_ops vx_run_ops = {
-       "vxprocess", "VxWorks process",
-       vx_open, vx_proc_close, 0, vx_detach, /* vx_attach */
-       vx_resume, vx_wait,
-       vx_read_register, vx_write_register,
-       vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
-       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, add_syms_addr_command,
-       call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
-       vx_lookup_symbol,
-       0, vx_mourn_inferior,
-       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" */
-       OPS_MAGIC,              /* Always the last thing */
+  "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 */
+  0, /* thread_alive */
+  0,                           /* to_stop */
+  process_stratum, 0, /* next */
+  0, /* all_mem--off to avoid spurious msg in "i files" */
+  1, 1, 1, 1,  /* mem, stack, regs, exec */
+  0, 0,                        /* Section pointers */
+  OPS_MAGIC,           /* Always the last thing */
 };
 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
 \f
 void
 _initialize_vx ()
 {
+  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_run_ops);
 }
This page took 0.044147 seconds and 4 git commands to generate.