* magic.h: Renamed to gmagic.h to avoid <magic.h> conflict.
authorFred Fish <fnf@specifix.com>
Tue, 28 Nov 1995 19:33:22 +0000 (19:33 +0000)
committerFred Fish <fnf@specifix.com>
Tue, 28 Nov 1995 19:33:22 +0000 (19:33 +0000)
* magic.c:  Renamed to gmagic.c in sympathy.
* eval.c, gmagic.c, config/tm-magic.h:
  Include "gmagic.h" rather than "magic.h".

gdb/.Sanitize
gdb/ChangeLog
gdb/config/tm-magic.h
gdb/eval.c
gdb/gmagic.c [new file with mode: 0644]
gdb/gmagic.h [new file with mode: 0644]
gdb/magic.c
gdb/magic.h

index 12b50c4..595de2c 100644 (file)
@@ -60,7 +60,7 @@ else
        fi
 fi
 
-gm_files="magic.c magic.h"
+gm_files="gmagic.c gmagic.h"
 
 if ( echo $* | grep keep\-gm > /dev/null ) ; then
        keep_these_too="${gm_files} ${keep_these_too}"
index caaa191..9640b9d 100644 (file)
@@ -1,3 +1,10 @@
+Tue Nov 28 11:17:47 1995  Fred Fish  <fnf@cygnus.com>
+
+       * magic.h:  Renamed to gmagic.h to avoid <magic.h> conflict.
+       * magic.c:  Renamed to gmagic.c in sympathy.
+       * eval.c, gmagic.c, config/tm-magic.h:
+       Include "gmagic.h" rather than "magic.h".
+
 Sat Nov 25 02:56:38 1995  Peter Schauer  (pes@regent.e-technik.tu-muenchen.de)
 
        * mdebugread.c (handle_psymbol_enumerators, parse_symbol):
index a33230f..db709f4 100644 (file)
@@ -17,7 +17,7 @@ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include "magic.h"
+#include "gmagic.h"
 
 #define TARGET_SYMFILE_POSTREAD(OBJFILE) init_magic ()
 
index 0e24041..65c9312 100644 (file)
@@ -30,9 +30,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "language.h"  /* For CAST_IS_CONVERSION */
 #include "f-lang.h"    /* for array bound stuff */
 /* start-sanitize-gm */
-#ifdef GENERAL_MAGIC_HACKS
-#include "magic.h"
-#endif /* GENERAL_MAGIC_HACKS */
+#ifdef GENERAL_MAGIC
+#include "gmagic.h"
+#endif /* GENERAL_MAGIC */
 /* end-sanitize-gm */
 
 /* Prototypes for local functions. */
@@ -845,7 +845,7 @@ evaluate_subexp_standard (expect_type, exp, pos, noside)
        }
 
 /* start-sanitize-gm */
-#ifdef GENERAL_MAGIC_HACKS
+#ifdef GENERAL_MAGIC
     case STRUCTOP_FIELD:
       tem = longest_to_int (exp->elts[pc + 1].longconst);
       (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
@@ -871,7 +871,7 @@ evaluate_subexp_standard (expect_type, exp, pos, noside)
                                     NULL, "structure pointer");
          }
       }
-#endif /* GENERAL_MAGIC_HACKS */
+#endif /* GENERAL_MAGIC */
 /* end-sanitize-gm */
 
     case STRUCTOP_MEMBER:
diff --git a/gdb/gmagic.c b/gdb/gmagic.c
new file mode 100644 (file)
index 0000000..4598218
--- /dev/null
@@ -0,0 +1,1242 @@
+#include "defs.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "gmagic.h"
+#include <ctype.h>
+#include <string.h>
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+#include <dlfcn.h>
+#endif
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+
+/* Maximum number of bytes of extra data to print, or UINT_MAX for no limit.
+   Note that "set extra-data-max 0" stores UINT_MAX in extra_data_max, which
+   displays in a show command as "unlimited."  */
+
+static unsigned int extra_data_max;
+#define EXTRA_DATA_MAX_DEFAULT         1024
+
+/* Return the number of elements in ARRAY.  */
+
+#define ARRAY_NELEMENTS(array)         (sizeof (array) / sizeof (array[0]))
+
+/* Basic information about a text label */
+
+struct text_label
+{
+  char *name;          /* label name */
+  CORE_ADDR addr;      /* label value or 0 if label not found */
+};
+
+/* Labels within the Magic Cap dispatcher that we need to know about
+   in order to implement "magic stepping" (that is, stepping over
+   Magic Cap method dispatches).  The label addresses are refreshed
+   whenever a new symbol table is loaded.  */
+
+struct text_label dispatch_labels[] =
+{
+  {"__DispatchMethod",         0},     /* normal dispatch entry point */
+  {"__DispatchInherited",      0},     /* inherited dispatch entry point */
+  {"__DispatchDelegated",      0},     /* delegated dispatch entry point */
+  {"__DispatchIntrinsic",      0},     /* intrinsic dispatch entry point */
+  {"__DoDispatchMethodBpSite", 0},     /* do dispatch site */
+};
+
+/* Accessors for the array above.  */
+
+#define DISPATCH_METHOD_ADDR           dispatch_labels[0].addr
+#define DISPATCH_INHERITED_ADDR                dispatch_labels[1].addr
+#define DISPATCH_DELEGATED_ADDR                dispatch_labels[2].addr
+#define DISPATCH_INTRINSIC_ADDR                dispatch_labels[3].addr
+#define DO_DISPATCH_METHOD_ADDR                dispatch_labels[4].addr
+
+/* Cached value objects describing functions in the target program that
+   we call frequently.  These are refreshed whenever a new symbol table
+   is loaded.  */
+
+static value_ptr remote_get_class_name_val;
+static value_ptr remote_get_base_ptr_val;
+
+/* Nonzero means that "magic step" (stepping through the Magic Cap method
+   dispatcher to the dispatch target) is enabled.  */
+
+static int magic_step_enabled;
+
+/* function prototypes */
+
+static void
+print_object PARAMS ((char *args, int dump));
+
+static void
+get_class_name PARAMS ((unsigned long objectID, char **name, int *is_scripted));
+
+static CORE_ADDR
+get_base_ptr PARAMS ((unsigned long objectID));
+
+static int
+should_dump_extra_data PARAMS ((char *class_name));
+
+static void
+dump_extra_data PARAMS ((CORE_ADDR addr, unsigned long length));
+
+static value_ptr
+call_function_by_name PARAMS ((char *function_name, int nargs, ...));
+
+static value_ptr
+call_function_by_value PARAMS ((value_ptr function_value, int nargs, ...));
+
+static value_ptr
+vcall_function_by_value PARAMS ((value_ptr function_value, int nargs,
+                                va_list args));
+static void
+local_shell_escape PARAMS ((char *arg));
+
+static CORE_ADDR
+lookup_text_label PARAMS ((char *name, value_ptr *val_ptrptr));
+
+static int
+is_dispatcher_entry PARAMS ((CORE_ADDR pc));
+
+static int
+is_dispatcher_exit PARAMS ((CORE_ADDR pc));
+
+
+/* This is the GDB handler for the "dobj" command, which prints a
+   verbose description of an object.  ARGS is a string containing an
+   expression for the object ID, and FROM_TTY is nonzero if the 
+   command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+dobj_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (remote_get_class_name_val == NULL)
+    error ("This version of Magic Cap lacks the runtime support for \"dobj\".");
+
+  print_object (args, 1);
+}
+
+/* This is the GDB handler for the "pobj" command, which prints a 
+   brief description of an object.  ARGS is a string containing an
+   expression for the object ID, and FROM_TTY is nonzero if the 
+   command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+pobj_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (remote_get_class_name_val == NULL)
+    error ("This version of Magic Cap lacks the runtime support for \"pobj\".");
+
+  print_object (args, 0);
+}
+
+/* This is the GDB handler for the "cdump" command, which prints a
+   description of a cluster.  ARGS is a string containing a cluster
+   selector, and FROM_TTY is nonzero if the command was issued
+   interactively.  
+   
+   cdump <contextSlot> [/l[ocked]] [/s[tartAddr] <expr>]
+                      [/c[lass] <className> | <classNumber>] */
+
+/* ARGSUSED */
+static void
+cdump_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *token;
+  unsigned long cluster;
+  CORE_ADDR min_object;
+  long display_only_locked;
+  long filter_classes;
+  long display_only_class_number;
+  char *display_only_class_name;
+
+  if (args == NULL)
+    error_no_arg ("expression for context slot to dump");
+
+  token = strtok (args, " \t");
+  if (token[0] == '/')
+    error ("The first argument to cdump must be an expression for the context slot to dump.");
+
+  cluster = parse_and_eval_address (token);
+
+  /* Initialize option values.  Note that we assume that
+     sizeof (long) == sizeof (void *) here, in that we pass
+     min_object as a long, even though it is a pointer.  */
+
+  min_object                   = 0;
+  display_only_locked          = 0;
+  filter_classes               = 0;
+  display_only_class_name      = NULL;
+  display_only_class_number    = 0;
+
+  while ((token = strtok (NULL, " \t")) != NULL)
+    {
+      if (token[0] != '/')
+       goto bad_option;
+
+      switch (token[1])
+       {
+       case 'l':
+         if (token[2] && strcmp (token + 1, "locked"))
+           goto bad_option;
+
+         display_only_locked = 1;
+         break;
+
+       case 's':
+         if (token[2] && strcmp (token + 1, "startAddr"))
+           goto bad_option;
+
+         if ((token = strtok (NULL, " \t")) == NULL)
+           error ("Missing start address expression for `/s' option.");
+
+         min_object = parse_and_eval_address (token);
+         break;
+
+       case 'c':
+         if (token[2] && strcmp (token + 1, "class"))
+           goto bad_option;
+
+         if ((token = strtok (NULL, " \t")) == NULL)
+           error ("Missing class name or number for `/c' option.");
+
+         filter_classes = 1;
+         if (isdigit (token[0]))
+           display_only_class_number = parse_and_eval_address (token);
+         else
+           display_only_class_name = token;
+
+         break;
+       
+       default:
+         goto bad_option;
+       }
+    }
+
+  if (display_only_class_name != NULL)
+    error ("Sorry, `/c <className>' isn't supported yet.");
+
+  (void)call_function_by_name ("cdump", 6, cluster, min_object,
+                              display_only_locked,
+                              filter_classes, display_only_class_number,
+                              display_only_class_name);
+  return;
+
+bad_option:
+  error ("Invalid option: `%s'.", token);
+}
+
+/* This is the GDB handler for the "esc" command, which lists the
+   exception handlers for a given actor.  ARGS is a string containing
+   an expression for the objectID of the actor in question, and FROM_TTY
+   is nonzero if the command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+esc_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  unsigned long object;
+
+  if (args == NULL)
+    error_no_arg ("expression for actor's object ID");
+
+  object = parse_and_eval_address (args);
+  (void)call_function_by_name ("esc", 1, object);
+}
+
+/* This is the GDB handler for the "cnum" command, which converts
+   a class number to a class name.  ARGS is a string containing an
+   expression for the class number, and FROM_TTY is nonzero if the
+   command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+cnum_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  unsigned long cnum;
+
+  if (args == NULL)
+    error_no_arg ("expression for class number");
+
+  cnum = parse_and_eval_address (args);
+  (void)call_function_by_name ("cnum", 1, cnum);
+}
+
+/* This is the GDB handler for the "getint" command, which converts an
+   intrinsic operation number to the corresponding intrinsic operation name,
+   or vice-versa.  ARGS is a string containing the intrinsic number or name,
+   and FROM_TTY is nonzero if the command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+getint_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char shell_command[256];
+
+  if (args == NULL)
+    error_no_arg ("intrinsic operation number or name");
+
+  if (isdigit (args[0]))
+    sprintf (shell_command, "getint %ld", parse_and_eval_address (args));
+  else
+    sprintf (shell_command, "getint %s", args);
+
+  local_shell_escape (shell_command);
+}
+
+/* This is the GDB handler for the "getop" command, which converts an
+   operation number to the corresponding operation name, or vice-versa.
+   ARGS is a string containing the operation number or name, and FROM_TTY
+   is nonzero if the command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+getop_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char shell_command[256];
+  CORE_ADDR op_number;
+
+  if (args == NULL)
+    error_no_arg ("operation number or name");
+
+  if (isdigit (args[0]))
+    sprintf (shell_command, "getop %ld", parse_and_eval_address (args));
+  else
+    sprintf (shell_command, "getop %s", args);
+
+  local_shell_escape (shell_command);
+}
+
+/* This is the GDB handler for the "getindexical" command, which converts
+   an indexical number to the corresponding indexical name, or vice-versa.
+   ARGS is a string containing the indexical number or name, and FROM_TTY
+   is nonzero if the command was issued interactively.  */
+
+/* ARGSUSED */
+static void
+getindexical_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char shell_command[256];
+
+  if (args == NULL)
+    error_no_arg ("indexical number or name");
+
+  if (isdigit (args[0]))
+    sprintf (shell_command, "getindexical 0x%lx",
+            parse_and_eval_address (args));
+  else
+    sprintf (shell_command, "getindexical %s", args);
+
+  local_shell_escape (shell_command);
+}
+
+/* This is the GDB handler for the "exc" command, which converts an
+   exception number to the corresponding exception name, or vice-versa.
+   ARGS is a string containing the exception number or name, and FROM_TTY
+   is nonzero if the command was issued interactively.
+
+   FIXME why is this one "exc" instead of "getexc?" (inconsistent naming).  */
+
+/* ARGSUSED */
+static void
+exc_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char shell_command[256];
+
+  if (args == NULL)
+    error_no_arg ("exception number or name");
+       
+  if (isdigit (args[0]))
+    sprintf (shell_command, "getexc %ld", parse_and_eval_address (args));
+  else
+    sprintf (shell_command, "getexc %s", args);
+
+  local_shell_escape (shell_command);
+}
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+/* Open a dynamic library and invoke an entry point within it.
+   ARGS is a string containing the names of the dynamic library
+   and the symbolic entry point, separated by whitespace.  */
+
+/* ARGSUSED */
+static void
+dlopen_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *p;
+  void *hdl;
+  void (*sym)();
+
+  if (args == 0)
+    {
+      error ("No arguments specified.");
+      return;
+    }
+
+  p = args;
+  while (*p != ' ' && *p != '\0')
+    p++;
+
+  if (*p != ' ')
+    {
+      error ("Not enough arguments.");
+      return;
+    }
+  *p++ = '\0';
+
+  hdl = dlopen (args, RTLD_NOW);
+  if (hdl == NULL)
+    {
+      fprintf (stderr, "%s: %s\n", args, dlerror ());
+      return;
+    }
+
+  sym = dlsym (hdl, p);
+  if (sym == NULL)
+    {
+      fprintf (stderr, "%s: %s\n", p, dlerror ());
+      return;
+    }
+
+  sym();
+}
+#endif /* DYNAMIC_COMMAND_SUPPORT */
+
+/* Given an object ID OBJECT, return a pointer to a type structure
+   representing the GDB type that describes the layout of the object's
+   fields in memory (i.e., the "_AllFields" structure corresponding 
+   to the object's class).  */
+
+struct type *
+type_of_object (object)
+     CORE_ADDR object;
+{
+  char *class_name = NULL;
+  char classAllFieldsName[128];
+  struct type *type = NULL;
+  int is_scripted;
+
+  get_class_name (object, &class_name, &is_scripted);
+  sprintf (classAllFieldsName, "%s_AllFields", class_name);
+  free (class_name);
+
+  type = lookup_typename (classAllFieldsName, (struct block *)NULL, 0);
+  return lookup_pointer_type (type);
+}
+
+/* Given OBJECT, an object ID, return the address of the object's
+   fixed fields.  */
+
+CORE_ADDR
+baseptr_of_object (object)
+     unsigned long object;
+{
+  return get_base_ptr (object) + kSizeOfObjectHeader;
+}
+
+/* Given an expression for an object ID, ARGS, print information about
+   the object--including its class, the values of its fixed fields, and
+   the values in its extra data block.  */
+
+/* ARGSUSED */
+static void
+print_object (args, dump)
+     char *args;
+     int dump;
+{
+  CORE_ADDR addr;
+  unsigned long object, object_length;
+  char *class_name = NULL;
+  char class_all_fields_name[128];
+  struct type *type;
+  int is_scripted;
+  struct cleanup *old_chain;
+
+  if (args == NULL)
+    error_no_arg ("expression for object ID");
+
+  object = parse_and_eval_address (args);
+
+  /* check for nilObject */
+
+  if (!object)
+    {
+      printf_filtered ("\"%s\" evaluates to nilObject.\n", args);
+      return;
+    }
+
+  /* allow shortcut for system object ids */
+
+  if (IsObjectID (object))
+    object |= 1 << kIDBitUsable;
+  else if (object < 0x5000)
+    object |= (1 << kIDBitObject) | (1 << kIDBitUsable); /* 0x84000000 */
+
+  /* Get the name of the object's class, as well as the GDB type that
+     describes the layout of the object's fixed fields.  */
+   
+  get_class_name (object, &class_name, &is_scripted);
+  old_chain = make_cleanup (free_current_contents, &class_name);
+
+  sprintf (class_all_fields_name, "%s_AllFields", class_name);
+  type = lookup_typename (class_all_fields_name, (struct block *)NULL, 1);
+
+  /* Get pointer to object's fields.
+     FIXME: ADDR is actually an (ObjectHeader *); should use normal expression
+     evaluator to extract the length member, rather than hardwiring the 
+     format of the structure in this code.  */
+
+  addr = get_base_ptr (object);
+  object_length = read_memory_unsigned_integer (addr, 4);
+  object_length -= kSizeOfObjectHeader;
+  addr += kSizeOfObjectHeader;
+
+  if (type == NULL || (TYPE_CODE (type) != TYPE_CODE_UNDEF
+                      && !(TYPE_FLAGS (type) & TYPE_FLAG_STUB)))
+    {
+      if (dump)
+       {
+         unsigned long fixed_length;
+
+         printf_filtered ("Object 0x%08lx%s at address 0x%08lx of class %s\n", 
+                          object, (is_scripted) ? " (scripted)" : "",
+                          addr, class_name);
+
+         /* If the object has fixed fields, dump them.  */
+
+         if (type != NULL)
+           {
+             value_ptr valptr = value_at_lazy (type, addr);
+             int histindex = record_latest_value (valptr);
+
+             if (histindex >= 0)
+               printf_filtered ("$%d = ", histindex);
+
+             value_print (valptr, gdb_stdout, 0, Val_prettyprint);
+             puts_filtered ("\n");
+             fixed_length = TYPE_LENGTH (type);
+           }
+         else
+           fixed_length = 0;
+
+         /* If the object's length is less than that of its fixed fields,
+            warn the user.  */
+
+         if (object_length < fixed_length)
+           {
+             error ("Warning: object is too small (should be at least %d bytes, is %d bytes).",
+                    fixed_length, object_length);
+           }
+
+         /* Dump the object's extra data, if any.  should_dump_extra_data ()
+            filters out classes (e.g. Cluster) that have too much extra data
+            to be dumped usefully in this format.  */
+
+         if (should_dump_extra_data (class_name))
+           {
+             dump_extra_data (addr + fixed_length,
+                              object_length - fixed_length);
+           }
+       }
+      else
+       {
+         struct type *pointer_type;
+         value_ptr valptr;
+         int histindex;
+
+         pointer_type = lookup_pointer_type ((type == NULL) ?
+                                             builtin_type_void : type);
+         valptr = value_from_longest (pointer_type, addr);
+                                               
+         histindex = record_latest_value (valptr);
+         if (histindex >= 0)
+           printf_filtered ("$%d = ", histindex);
+
+         value_print (valptr, gdb_stdout, 0, Val_prettyprint);
+         puts_filtered ("\n");
+       }
+    }
+  do_cleanups (old_chain);
+}
+
+/* Get the name of the class of the object referenced by OBJECTID.
+   *NAME is set to a pointer to the string containing the class
+   name; it is the caller's responsibility to free the memory for
+   the string.  *IS_SCRIPTED is set to nonzero if the object is
+   scripted, zero otherwise.  */
+
+static void
+get_class_name (objectID, name, is_scripted)
+     unsigned long objectID;
+     char **name;
+     int *is_scripted;
+{
+  value_ptr val;
+  int errno_val;
+
+  val = call_function_by_value (remote_get_class_name_val, 1, objectID);
+
+  /* As RemoteGetClassName() is currently (9/21/95) written, an empty string,
+     rather than a nil pointer, is returned upon failure.  I'm leaving the
+     value_logical_not test in anyway, though, just for added robustness.  */
+     
+  if (!value_logical_not (val))
+    {
+      (void)target_read_string (value_as_pointer (val), name, 256, &errno_val);
+      if (errno_val)
+       error ("Can't read class name for object 0x%08lx.", objectID);
+
+      if (**name)
+       {
+         char *scripted_suffix;
+
+         if ((scripted_suffix = strstr (*name, " (scripted)")) != NULL)
+           {
+             *scripted_suffix = '\0';
+             *is_scripted = 1;
+           }
+         else
+           *is_scripted = 0;
+
+          return;
+       }
+      else
+       free (*name);
+    }
+
+  error ("Bad object ID: 0x%08lx.", objectID);
+}
+
+/* Given an object ID, return a pointer to the object's data.  */
+
+static CORE_ADDR
+get_base_ptr (objectID)
+     unsigned long objectID;
+{
+  register value_ptr val;
+
+  val = call_function_by_value (remote_get_base_ptr_val, 1, objectID);
+
+  if (value_logical_not (val))
+    error ("Could not get base pointer to object.");
+
+  return value_as_pointer (val);
+}
+
+/* Return nonzero if we should dump the extra data for an object 
+   of class CLASS_NAME.
+
+   FIXME this only works for explicitly named classes, and doesn't
+   handle subclasses.  */
+
+static int
+should_dump_extra_data (class_name)
+     char *class_name;
+{
+  int i;
+  char **name;
+  static char *dont_dump_extra_classes[] =
+    {
+      "Cluster"
+    };
+
+  for (i = 0, name = dont_dump_extra_classes;
+       i < ARRAY_NELEMENTS(dont_dump_extra_classes);
+       i++, name++)
+    {
+      if (!strcmp (class_name, *name))
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Given ADDR, the address of an object's extra data block, and LENGTH,
+   the length of that block in bytes, dump the object's extra data to
+   standard output.  */
+
+static void
+dump_extra_data (addr, length)
+     CORE_ADDR addr;
+     unsigned long length;
+{
+  unsigned long buf[5];
+  int chunk;
+  int chunk_longs;
+  int i;
+  int bytes_printed;
+  char *p;
+
+  bytes_printed = 0;
+
+  while (length > 3 && bytes_printed < extra_data_max)
+    {
+      QUIT;            /* allow user to interrupt dump */
+
+      /* read a chunk of extra data */
+
+      chunk = (length > 16) ? 16 : length;
+      memset (buf, 0, sizeof (buf));
+      read_memory (addr, (char *) &buf, chunk);
+
+      /* format data as hex longwords */
+
+      chunk_longs = chunk >> 2;
+      for (i = 0; i < chunk_longs; i++)
+       printf_filtered ("%08lx ",
+                        extract_unsigned_integer (buf + i, sizeof (long)));
+
+      /* pad to 4 longs */
+
+      for (i = chunk_longs; i < 4; i++)
+       puts_filtered ("         ");
+
+      puts_filtered ("| ");
+
+      /* format data as ascii bytes */
+
+      for (i = 0, p = (char*)buf; i < chunk; i++, p++)
+       {
+         if (!isprint (*p))
+           *p = '.';
+       }
+      printf_filtered ("%s |\n", buf);
+
+      addr += chunk;
+      length -= chunk;
+      bytes_printed += chunk;
+    }
+
+  if (length > 0)
+    printf_filtered ("(%d bytes of extra data remaining but not displayed.)\n",
+                    length);
+}
+
+/* Given the name of a function in the target program and a list of
+   long arguments, call the function and return a pointer to a value
+   object describing the function's return value.  NAME is a string
+   containing the name of the function to be called; NARGS is the
+   number of arguments to the function; and the remaining parameters
+   are the arguments to passed to the function, all assumed to be of
+   type long.  */
+
+static value_ptr
+#ifdef ANSI_PROTOTYPES
+call_function_by_name (char *function_name, int nargs, ...)
+#else
+call_function_by_name (va_alist)
+     va_dcl
+#endif
+{
+  va_list args;
+  value_ptr return_value;
+  value_ptr function_value;
+#ifndef ANSI_PROTOTYPES
+  char *function_name;
+  int nargs;
+
+  va_start (args);
+  function_name = va_arg (args, char *);
+  nargs = va_arg (args, int);
+#else
+  va_start (args, nargs);
+#endif
+
+  /* Find the address of function NAME in the inferior.  */
+
+  if (!lookup_text_label (function_name, &function_value))
+    error ("Execution of this command requires the debugged program to have a function \"%s.\"",
+          function_name);
+
+  /* Call the function.  */
+
+  return_value = vcall_function_by_value (function_value, nargs, args);
+  va_end (args);
+
+  return return_value;
+}
+
+/* Given a value object describing a function in the target program and
+   a list of long arguments, call the function and return a pointer to a
+   value object describing the function's return value.  FUNCTION_VALUE
+   is a pointer to a value struct describing the function; NARGS is the
+   number of arguments to the function; and the remaining parameters are
+   the arguments to passed to the function, all assumed to be of type long.  */
+
+static value_ptr
+#ifdef ANSI_PROTOTYPES
+call_function_by_value (value_ptr function_value, int nargs, ...)
+#else
+call_function_by_value (va_alist)
+     va_dcl
+#endif
+{
+  va_list args;
+  value_ptr return_value;
+#ifndef ANSI_PROTOTYPES
+  value_ptr function_value;
+  int nargs;
+
+  va_start (args);
+  function_value = va_arg (args, value_ptr);
+  nargs = va_arg (args, int);
+#else
+  va_start (args, nargs);
+#endif
+
+  /* Call the function and return its return value.  */
+
+  return_value = vcall_function_by_value (function_value, nargs, args);
+  va_end (args);
+
+  return return_value;
+}
+
+/* Helper routine for call_function_by_name and call_function_by_value 
+   above.  This function does the work of collecting the function
+   arguments into an array of value objects, and then invoking 
+   call_function_by_hand to do the real work.  FUNCTION_VALUE is a 
+   pointer to a value object describing the function to be called,
+   NARGS is the number of arguments to the function, and ARGS is a
+   list (va_list) of the arguments to the function, all assumed to
+   be of type long.
+
+   Returns a pointer to a value object describing the return value
+   of the function.  */
+
+static value_ptr
+vcall_function_by_value (function_value, nargs, args)
+     value_ptr function_value;
+     int nargs;
+     va_list args;
+{
+  value_ptr *arg_values;
+  value_ptr return_value;
+  struct cleanup *old_chain;
+  int i;
+
+  /* Construct a vector of value objects describing the arguments
+     to the function to be called.  */
+
+  arg_values = (value_ptr *) xmalloc (nargs * sizeof (value_ptr));
+  old_chain = make_cleanup (free_current_contents, &arg_values);
+
+  for (i = 0; i < nargs; i++)
+    arg_values[i] = value_from_longest (builtin_type_long,
+                                       (LONGEST) va_arg (args, unsigned long));
+
+  /* Call the function and return its return value.  */
+
+  return_value = call_function_by_hand (function_value, nargs, arg_values);
+  do_cleanups (old_chain);
+  return return_value;
+}
+
+/* Invoke a shell, supplying ARG as the command to be executed.  */
+
+static void
+local_shell_escape (arg)
+     char *arg;
+{
+#ifdef CANT_FORK
+  /* FIXME: what about errors (I don't know how GO32 system() handles
+     them)?  */
+  system (arg);
+#else /* Can fork.  */
+  int rc, status, pid;
+  char *p, *user_shell;
+
+  if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+    user_shell = "/bin/sh";
+
+  /* Get the name of the shell for arg0 */
+  if ((p = strrchr (user_shell, '/')) == NULL)
+    p = user_shell;
+  else
+    p++;                       /* Get past '/' */
+
+  if ((pid = fork()) == 0)
+    {
+      if (!arg)
+       execl (user_shell, p, 0);
+      else
+       execl (user_shell, p, "-c", arg, 0);
+
+      fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
+                         safe_strerror (errno));
+      gdb_flush (gdb_stderr);
+      _exit (0177);
+    }
+
+  if (pid != -1)
+    while ((rc = wait (&status)) != pid && rc != -1)
+      ;
+  else
+    error ("Fork failed");
+#endif /* Can fork.  */
+}
+
+/* Lookup NAME as a text label in the target program.  If NAME is the
+   name of a function, and VAL_PTRPTR is not NULL, a pointer to a value
+   object describing the function is stored at VAL_PTRPTR.
+
+   Returns the text address to which the label refers, or 0 if the
+   label is not found in the target program.  */
+
+static CORE_ADDR
+lookup_text_label (name, val_ptrptr)
+     char *name;
+     value_ptr *val_ptrptr;
+{
+  struct symbol *sym;
+  CORE_ADDR addr;
+
+  addr = 0;
+
+  /* Try looking up NAME as a first-class symbol.  */
+
+  sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+  if (sym != NULL)
+    {
+      switch (SYMBOL_CLASS (sym))
+       {
+       case LOC_BLOCK:
+         addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+         if (val_ptrptr != NULL)
+           *val_ptrptr = value_of_variable (sym, NULL);
+
+         break;
+
+       case LOC_STATIC:
+       case LOC_LABEL:
+         addr = SYMBOL_VALUE_ADDRESS (sym);
+         break;
+       }
+    }
+  else
+    {
+      struct minimal_symbol *msymbol;
+      struct type *type;
+
+      /* Try to find a minimal symbol for NAME.  */
+
+      msymbol = lookup_minimal_symbol (name, "", (struct objfile *) NULL);
+      if (msymbol != NULL)
+       {
+         addr = SYMBOL_VALUE_ADDRESS (msymbol);
+         if (val_ptrptr != NULL)
+           {
+             type = lookup_pointer_type (builtin_type_char);
+             type = lookup_function_type (type);
+             type = lookup_pointer_type (type);
+             *val_ptrptr = value_from_longest (type, addr);
+           }
+       }
+    }
+  return addr;
+}
+
+/* The following two routines adapt GDB's framework for stepping over
+   shared library trampoline code to the problem of stepping over the
+   Magic Cap method dispatcher.  While the method dispatcher is not a
+   shared library trampoline, we can use the interfaces for controlling
+   stepping over trampolines to do what we want.  */
+
+/* Return nonzero if STOP_PC is within the Magic Cap method dispatcher.
+   NAME is unused.  This function serves as the implementation of both
+   IN_SOLIB_CALL_TRAMPOLINE() and IN_SOLIB_RETURN_TRAMPOLINE() when GDB
+   is configured to target Magic Cap.  We don't need to distinguish
+   between the two types of trampolines (because they're not really
+   trampolines); we just need to tell GDB to set a breakpoint at the
+   site of the next "hop" on our way through the dispatcher, and to
+   keep going.  */
+
+int
+magic_in_dispatcher (stop_pc, name)
+     CORE_ADDR stop_pc;
+     char *name;
+{
+  return magic_step_enabled
+        && (is_dispatcher_entry (stop_pc) || is_dispatcher_exit (stop_pc));
+}
+
+/* Determine if STOP_PC is an address within the Magic Cap method
+   dispatcher, and if so, return the address at which GDB should set
+   a step resume breakpoint in order to skip over the dispatcher code.
+   In fact, we have to skip over the dispatcher in two separate "hops:"
+   the first hop gets us from a dispatcher entry point to the dispatcher
+   exit site; the second hop gets us from this exit site to the first
+   instruction of the method.
+
+   This function serves as the implementation of SKIP_TRAMPOLINE_CODE()
+   when GDB is configured to target Magic Cap.  */
+
+CORE_ADDR 
+magic_skip_dispatcher (stop_pc)
+     CORE_ADDR stop_pc;
+{
+  /* If magic stepping is disabled, return 0, indicating that GDB should
+     process this step event normally.  This will have the effect of
+     allowing the user to step through the dispatcher code itself.  */
+
+  if (!magic_step_enabled)
+    return 0;
+
+  /* If the program is stopped at an entry point to the dispatcher,
+     tell GDB to set a breakpoint at a well-known label in the
+     dispatcher where we will be able to determine the address of
+     the method to which we are dispatching.  Note that the dispatcher
+     has hair to ensure that the code at this label is executed when we
+     are completing a top-level dispatch; recursive dispatches generated
+     from within the dispatcher do not exit through this code.  */
+
+  if (is_dispatcher_entry (stop_pc))
+    return DO_DISPATCH_METHOD_ADDR;
+
+  /* If we have hit the breakpoint set previously at a dispatcher exit site,
+     determine the method address and tell GDB to set a breakpoint there.  */
+
+  else if (is_dispatcher_exit (stop_pc))
+    return read_register (14); /* assumes that we branch through t6 */
+  else
+    return 0;
+}
+
+/* Return nonzero if PC is an entry point to the Magic Cap method
+   dispatcher.  */
+
+static int
+is_dispatcher_entry (pc)
+     CORE_ADDR pc;
+{
+  return pc == DISPATCH_METHOD_ADDR
+        || pc == DISPATCH_INTRINSIC_ADDR
+        || pc == DISPATCH_INHERITED_ADDR
+        || pc == DISPATCH_DELEGATED_ADDR;
+}
+
+/* Return nonzero if PC is an exit site from the Magic Cap method
+   dispatcher.  */
+
+static int
+is_dispatcher_exit (pc)
+     CORE_ADDR pc;
+{
+  return pc == DO_DISPATCH_METHOD_ADDR;
+}
+
+/* Store away addresses in the inferior we need to control single-stepping
+   through Magic Cap method dispatches, as well as other addresses of
+   interest in Magic Cap.  */
+
+void
+init_magic ()
+{
+  struct text_label *label;
+  int i;
+
+  /* Cache method dispatch label addresses.  */
+
+  for (i = 0, label = dispatch_labels;
+       i < ARRAY_NELEMENTS (dispatch_labels);
+       i++, label++)
+    {
+      if (!(label->addr = lookup_text_label (label->name, NULL)))
+       {
+         /* If we can't find all of the dispatcher addresses, don't attempt
+            to do magic stepping.  */
+
+         magic_step_enabled = 0;
+         break;
+       }
+    }
+
+  /* Cache value objects for RemoteGetClassName () and RemoteGetBasePtr (),
+     which are used to implement the "dobj" and "pobj" commands.  Note that
+     we must call release_value () on these values to prevent GDB from freeing
+     them automatically.  */
+
+  if (remote_get_class_name_val != NULL)
+    {
+      value_free (remote_get_class_name_val);
+      remote_get_class_name_val = NULL;
+    }
+
+  if (remote_get_base_ptr_val != NULL)
+    {
+      value_free (remote_get_base_ptr_val);
+      remote_get_base_ptr_val = NULL;
+    }
+
+  if (lookup_text_label ("RemoteGetClassName", &remote_get_class_name_val))
+    {
+      release_value (remote_get_class_name_val);
+
+      if (lookup_text_label ("RemoteGetBasePtr", &remote_get_base_ptr_val))
+       release_value (remote_get_base_ptr_val);
+    }
+} 
+
+/* Hook routine called when an inferior (i.e., debugged) process is
+   created.  */
+
+void
+magic_create_inferior_hook ()
+{
+  struct symbol *sym = lookup_symbol ("gHandleError", NULL, VAR_NAMESPACE,
+                                     NULL, NULL);
+  if (sym)
+    {
+      CORE_ADDR addr = SYMBOL_VALUE (sym);
+      unsigned long errorDebugger = 2;
+
+      target_write_memory (addr, (char *) &errorDebugger, 4);
+    }
+}
+
+/* Initialization routine for magic.c.  This is where we define debugger
+   commands specific to Magic Cap.  */
+
+void
+_initialize_magic ()
+{
+  add_com ("dobj", class_support, dobj_command,
+          "Display object contents.\n\
+Usage: dobj <objectID>\n\
+Where: <objectID> is an expression for the object ID to dump.");
+
+  add_com ("pobj", class_support, pobj_command,
+          "Print object base pointer.\n\
+Usage: pobj <objectID>\n\
+Where: <objectID> is an expression for the object ID to examine.");
+
+  add_com ("cdump", class_support, cdump_command,
+          concat ("Display the contents of a cluster.\n\
+Usage: cdump <contextSlot> [/l[ocked]] [/s[tartAddr] <addr>]\n\
+                          [/c[lass] <classNumber>]\n\
+Where: <contextSlot> is an expression describing the cluster to dump;\n\
+           if <contextSlot> is a number between 0x8 and 0xf, it is \n\
+           interpreted as the high-order nibble of an object ID\n\
+           belonging to the cluster to dump, with the second highest-\n\
+           order nibble assumed to be 0.  (For example, \"cdump 8\" and \n\
+           \"cdump 0xa\" dump the System Persistent and Persistent RAM\n\
+           clusters, respectively.)\n",
+                   "\n\
+           if <contextSlot> is a number between 0xf0 and 0x100, it is\n\
+           interpreted as the high-order byte of an object ID belonging to\n\
+           the cluster to dump.  (For example, \"cdump 0x88\" and \n\
+           \"cdump 0xa8\" dump the Locked Persistent and Transient RAM\n\
+           clusters, respectively.)\n",
+                   "\n\
+       /locked or /l indicates that only locked objects are to be displayed.\n\
+\n\
+       /startAddr or /s indicates that only objects whose base pointers are\n\
+           greater than or equal to the address specified by the following\n\
+           expression (<startAddr>) are to be displayed.\n\
+\n\
+       /class or /c indicates that only objects of the class specified by\n\
+           the following expression <classNumber> are to be displayed.",
+                  NULL));
+
+  add_com ("esc", class_support, esc_command,
+          "List all the exception handlers for a given actor.\n\
+Usage: esc <objectID>\n\
+Where: <objectID> is an expression for the object ID of the actor\n\
+           whose exception handlers are to be listed.");
+
+  add_com ("cnum", class_support, cnum_command,
+          "Convert class number to name.\n\
+Usage: cnum <classNumber>\n\
+Where: <classNumber> is an expression for the class number to convert.");
+
+  add_com ("getint", class_support, getint_command,
+          "Convert intrinsic name to number or vice versa.\n\
+Usage: getint <intrinsicName> | <intrinsicNumber>\n\
+Where: <intrinsicName> | <intrinsicNumber> is an intrinsic operation name\n\
+           to be converted to an operation number, or an intrinsic operation\n\
+           number to be converted to an operation name.");
+
+  add_com ("getop", class_support, getop_command,
+          "Convert operation name to number or vice versa.\n\
+Usage: getop <operationName> | <operationNumber>\n\
+Where: <operationName> | <operationNumber> is an operation name to be\n\
+           converted to an operation number, or an operation number to\n\
+           be converted to an operation name.");
+
+  add_com ("getindexical", class_support, getindexical_command,
+          "Convert indexical name to number or vice versa.\n\
+Usage: getindexical <indexicalName> | <indexicalNumber>\n\
+Where: <indexicalName> | <indexicalNumber> is an indexical name to be\n\
+           converted to an an indexical number, or an indexical number\n\
+           to be converted to an indexical name.");
+
+  add_com ("exc", class_support, exc_command,
+          "Convert exception name to number or vice versa.\n\
+Usage: exc <exceptionName> | <exceptionNumber>\n\
+Where: <exceptionName> | <exceptionNumber> is an exception name to be\n\
+           converted to an an exception number, or an exception number\n\
+           to be converted to an exception name.");
+
+  add_show_from_set
+    (add_set_cmd ("extra-data-max", class_support, var_uinteger,
+                 (char *) &extra_data_max,
+                 "Set limit on number of bytes of extra data to print.\n\
+This command sets an upper limit on the number of bytes of extra\n\
+data displayed by the \"dobj\" command when dumping a Magic Cap\n\
+object.  \"set extra-data-max 0\" causes there to be no limit.",
+                 &setlist),
+     &showlist);
+
+  extra_data_max = EXTRA_DATA_MAX_DEFAULT;
+
+  add_show_from_set
+    (add_set_cmd ("magic-step", class_support, var_boolean,
+                 (char *) &magic_step_enabled,
+                 "Set stepping over Magic Cap method dispatches.\n\
+When set to \"on\" (the default), issuing a \"step\" command at a Magic Cap\n\
+operation call site will cause the program to stop at the first line of\n\
+the corresponding method.  Set this to \"off\" only if you need to debug\n\
+the dispatcher itself.",
+                 &setlist),
+     &showlist);
+
+  magic_step_enabled = 1;
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+  add_com ("dlopen", class_support, dlopen_command,
+        "Load the dynamic library specified and execute the specified symbol");
+#endif
+}
diff --git a/gdb/gmagic.h b/gdb/gmagic.h
new file mode 100644 (file)
index 0000000..63e8e20
--- /dev/null
@@ -0,0 +1,32 @@
+/* gmagic.h - Interface to the General Magic debugger extras */
+
+/* object framework definitions, from FrameworkDefines.asm.h and Generic.h */
+
+#define        kIDBitObject            31      /* set for valid object IDs */
+#define        kIDBitUsable            26      /* set if objectID is usable */
+
+/* Return nonzero if <object> is a valid ObjectID */
+
+#define IsObjectID(object)     (((unsigned long)(object) & 0x80000000) != 0)
+
+#define kSizeOfObjectHeader    12      /* size of object header in bytes */
+
+/* public interfaces */
+
+extern void
+init_magic PARAMS ((void));
+
+extern void
+magic_create_inferior_hook PARAMS ((void));
+
+extern struct type *
+type_of_object PARAMS ((CORE_ADDR object));
+
+extern CORE_ADDR
+baseptr_of_object PARAMS ((CORE_ADDR object));
+
+extern int
+magic_in_dispatcher PARAMS ((CORE_ADDR stop_pc, char *name));
+
+extern CORE_ADDR
+magic_skip_dispatcher PARAMS ((CORE_ADDR stop_pc));
index d8812cd..e69de29 100644 (file)
-#include "defs.h"
-#include "gdbcmd.h"
-#include "symtab.h"
-#include "value.h"
-#include "frame.h"
-#include "breakpoint.h"
-#include "inferior.h"
-#include "gdbcore.h"
-#include "magic.h"
-#include <ctype.h>
-#include <string.h>
-
-#ifdef DYNAMIC_COMMAND_SUPPORT
-#include <dlfcn.h>
-#endif
-
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-
-/* Maximum number of bytes of extra data to print, or UINT_MAX for no limit.
-   Note that "set extra-data-max 0" stores UINT_MAX in extra_data_max, which
-   displays in a show command as "unlimited."  */
-
-static unsigned int extra_data_max;
-#define EXTRA_DATA_MAX_DEFAULT         1024
-
-/* Return the number of elements in ARRAY.  */
-
-#define ARRAY_NELEMENTS(array)         (sizeof (array) / sizeof (array[0]))
-
-/* Basic information about a text label */
-
-struct text_label
-{
-  char *name;          /* label name */
-  CORE_ADDR addr;      /* label value or 0 if label not found */
-};
-
-/* Labels within the Magic Cap dispatcher that we need to know about
-   in order to implement "magic stepping" (that is, stepping over
-   Magic Cap method dispatches).  The label addresses are refreshed
-   whenever a new symbol table is loaded.  */
-
-struct text_label dispatch_labels[] =
-{
-  {"__DispatchMethod",         0},     /* normal dispatch entry point */
-  {"__DispatchInherited",      0},     /* inherited dispatch entry point */
-  {"__DispatchDelegated",      0},     /* delegated dispatch entry point */
-  {"__DispatchIntrinsic",      0},     /* intrinsic dispatch entry point */
-  {"__DoDispatchMethodBpSite", 0},     /* do dispatch site */
-};
-
-/* Accessors for the array above.  */
-
-#define DISPATCH_METHOD_ADDR           dispatch_labels[0].addr
-#define DISPATCH_INHERITED_ADDR                dispatch_labels[1].addr
-#define DISPATCH_DELEGATED_ADDR                dispatch_labels[2].addr
-#define DISPATCH_INTRINSIC_ADDR                dispatch_labels[3].addr
-#define DO_DISPATCH_METHOD_ADDR                dispatch_labels[4].addr
-
-/* Cached value objects describing functions in the target program that
-   we call frequently.  These are refreshed whenever a new symbol table
-   is loaded.  */
-
-static value_ptr remote_get_class_name_val;
-static value_ptr remote_get_base_ptr_val;
-
-/* Nonzero means that "magic step" (stepping through the Magic Cap method
-   dispatcher to the dispatch target) is enabled.  */
-
-static int magic_step_enabled;
-
-/* function prototypes */
-
-static void
-print_object PARAMS ((char *args, int dump));
-
-static void
-get_class_name PARAMS ((unsigned long objectID, char **name, int *is_scripted));
-
-static CORE_ADDR
-get_base_ptr PARAMS ((unsigned long objectID));
-
-static int
-should_dump_extra_data PARAMS ((char *class_name));
-
-static void
-dump_extra_data PARAMS ((CORE_ADDR addr, unsigned long length));
-
-static value_ptr
-call_function_by_name PARAMS ((char *function_name, int nargs, ...));
-
-static value_ptr
-call_function_by_value PARAMS ((value_ptr function_value, int nargs, ...));
-
-static value_ptr
-vcall_function_by_value PARAMS ((value_ptr function_value, int nargs,
-                                va_list args));
-static void
-local_shell_escape PARAMS ((char *arg));
-
-static CORE_ADDR
-lookup_text_label PARAMS ((char *name, value_ptr *val_ptrptr));
-
-static int
-is_dispatcher_entry PARAMS ((CORE_ADDR pc));
-
-static int
-is_dispatcher_exit PARAMS ((CORE_ADDR pc));
-
-
-/* This is the GDB handler for the "dobj" command, which prints a
-   verbose description of an object.  ARGS is a string containing an
-   expression for the object ID, and FROM_TTY is nonzero if the 
-   command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-dobj_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  if (remote_get_class_name_val == NULL)
-    error ("This version of Magic Cap lacks the runtime support for \"dobj\".");
-
-  print_object (args, 1);
-}
-
-/* This is the GDB handler for the "pobj" command, which prints a 
-   brief description of an object.  ARGS is a string containing an
-   expression for the object ID, and FROM_TTY is nonzero if the 
-   command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-pobj_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  if (remote_get_class_name_val == NULL)
-    error ("This version of Magic Cap lacks the runtime support for \"pobj\".");
-
-  print_object (args, 0);
-}
-
-/* This is the GDB handler for the "cdump" command, which prints a
-   description of a cluster.  ARGS is a string containing a cluster
-   selector, and FROM_TTY is nonzero if the command was issued
-   interactively.  
-   
-   cdump <contextSlot> [/l[ocked]] [/s[tartAddr] <expr>]
-                      [/c[lass] <className> | <classNumber>] */
-
-/* ARGSUSED */
-static void
-cdump_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char *token;
-  unsigned long cluster;
-  CORE_ADDR min_object;
-  long display_only_locked;
-  long filter_classes;
-  long display_only_class_number;
-  char *display_only_class_name;
-
-  if (args == NULL)
-    error_no_arg ("expression for context slot to dump");
-
-  token = strtok (args, " \t");
-  if (token[0] == '/')
-    error ("The first argument to cdump must be an expression for the context slot to dump.");
-
-  cluster = parse_and_eval_address (token);
-
-  /* Initialize option values.  Note that we assume that
-     sizeof (long) == sizeof (void *) here, in that we pass
-     min_object as a long, even though it is a pointer.  */
-
-  min_object                   = 0;
-  display_only_locked          = 0;
-  filter_classes               = 0;
-  display_only_class_name      = NULL;
-  display_only_class_number    = 0;
-
-  while ((token = strtok (NULL, " \t")) != NULL)
-    {
-      if (token[0] != '/')
-       goto bad_option;
-
-      switch (token[1])
-       {
-       case 'l':
-         if (token[2] && strcmp (token + 1, "locked"))
-           goto bad_option;
-
-         display_only_locked = 1;
-         break;
-
-       case 's':
-         if (token[2] && strcmp (token + 1, "startAddr"))
-           goto bad_option;
-
-         if ((token = strtok (NULL, " \t")) == NULL)
-           error ("Missing start address expression for `/s' option.");
-
-         min_object = parse_and_eval_address (token);
-         break;
-
-       case 'c':
-         if (token[2] && strcmp (token + 1, "class"))
-           goto bad_option;
-
-         if ((token = strtok (NULL, " \t")) == NULL)
-           error ("Missing class name or number for `/c' option.");
-
-         filter_classes = 1;
-         if (isdigit (token[0]))
-           display_only_class_number = parse_and_eval_address (token);
-         else
-           display_only_class_name = token;
-
-         break;
-       
-       default:
-         goto bad_option;
-       }
-    }
-
-  if (display_only_class_name != NULL)
-    error ("Sorry, `/c <className>' isn't supported yet.");
-
-  (void)call_function_by_name ("cdump", 6, cluster, min_object,
-                              display_only_locked,
-                              filter_classes, display_only_class_number,
-                              display_only_class_name);
-  return;
-
-bad_option:
-  error ("Invalid option: `%s'.", token);
-}
-
-/* This is the GDB handler for the "esc" command, which lists the
-   exception handlers for a given actor.  ARGS is a string containing
-   an expression for the objectID of the actor in question, and FROM_TTY
-   is nonzero if the command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-esc_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  unsigned long object;
-
-  if (args == NULL)
-    error_no_arg ("expression for actor's object ID");
-
-  object = parse_and_eval_address (args);
-  (void)call_function_by_name ("esc", 1, object);
-}
-
-/* This is the GDB handler for the "cnum" command, which converts
-   a class number to a class name.  ARGS is a string containing an
-   expression for the class number, and FROM_TTY is nonzero if the
-   command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-cnum_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  unsigned long cnum;
-
-  if (args == NULL)
-    error_no_arg ("expression for class number");
-
-  cnum = parse_and_eval_address (args);
-  (void)call_function_by_name ("cnum", 1, cnum);
-}
-
-/* This is the GDB handler for the "getint" command, which converts an
-   intrinsic operation number to the corresponding intrinsic operation name,
-   or vice-versa.  ARGS is a string containing the intrinsic number or name,
-   and FROM_TTY is nonzero if the command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-getint_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char shell_command[256];
-
-  if (args == NULL)
-    error_no_arg ("intrinsic operation number or name");
-
-  if (isdigit (args[0]))
-    sprintf (shell_command, "getint %ld", parse_and_eval_address (args));
-  else
-    sprintf (shell_command, "getint %s", args);
-
-  local_shell_escape (shell_command);
-}
-
-/* This is the GDB handler for the "getop" command, which converts an
-   operation number to the corresponding operation name, or vice-versa.
-   ARGS is a string containing the operation number or name, and FROM_TTY
-   is nonzero if the command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-getop_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char shell_command[256];
-  CORE_ADDR op_number;
-
-  if (args == NULL)
-    error_no_arg ("operation number or name");
-
-  if (isdigit (args[0]))
-    sprintf (shell_command, "getop %ld", parse_and_eval_address (args));
-  else
-    sprintf (shell_command, "getop %s", args);
-
-  local_shell_escape (shell_command);
-}
-
-/* This is the GDB handler for the "getindexical" command, which converts
-   an indexical number to the corresponding indexical name, or vice-versa.
-   ARGS is a string containing the indexical number or name, and FROM_TTY
-   is nonzero if the command was issued interactively.  */
-
-/* ARGSUSED */
-static void
-getindexical_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char shell_command[256];
-
-  if (args == NULL)
-    error_no_arg ("indexical number or name");
-
-  if (isdigit (args[0]))
-    sprintf (shell_command, "getindexical 0x%lx",
-            parse_and_eval_address (args));
-  else
-    sprintf (shell_command, "getindexical %s", args);
-
-  local_shell_escape (shell_command);
-}
-
-/* This is the GDB handler for the "exc" command, which converts an
-   exception number to the corresponding exception name, or vice-versa.
-   ARGS is a string containing the exception number or name, and FROM_TTY
-   is nonzero if the command was issued interactively.
-
-   FIXME why is this one "exc" instead of "getexc?" (inconsistent naming).  */
-
-/* ARGSUSED */
-static void
-exc_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char shell_command[256];
-
-  if (args == NULL)
-    error_no_arg ("exception number or name");
-       
-  if (isdigit (args[0]))
-    sprintf (shell_command, "getexc %ld", parse_and_eval_address (args));
-  else
-    sprintf (shell_command, "getexc %s", args);
-
-  local_shell_escape (shell_command);
-}
-
-#ifdef DYNAMIC_COMMAND_SUPPORT
-/* Open a dynamic library and invoke an entry point within it.
-   ARGS is a string containing the names of the dynamic library
-   and the symbolic entry point, separated by whitespace.  */
-
-/* ARGSUSED */
-static void
-dlopen_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  char *p;
-  void *hdl;
-  void (*sym)();
-
-  if (args == 0)
-    {
-      error ("No arguments specified.");
-      return;
-    }
-
-  p = args;
-  while (*p != ' ' && *p != '\0')
-    p++;
-
-  if (*p != ' ')
-    {
-      error ("Not enough arguments.");
-      return;
-    }
-  *p++ = '\0';
-
-  hdl = dlopen (args, RTLD_NOW);
-  if (hdl == NULL)
-    {
-      fprintf (stderr, "%s: %s\n", args, dlerror ());
-      return;
-    }
-
-  sym = dlsym (hdl, p);
-  if (sym == NULL)
-    {
-      fprintf (stderr, "%s: %s\n", p, dlerror ());
-      return;
-    }
-
-  sym();
-}
-#endif /* DYNAMIC_COMMAND_SUPPORT */
-
-/* Given an object ID OBJECT, return a pointer to a type structure
-   representing the GDB type that describes the layout of the object's
-   fields in memory (i.e., the "_AllFields" structure corresponding 
-   to the object's class).  */
-
-struct type *
-type_of_object (object)
-     CORE_ADDR object;
-{
-  char *class_name = NULL;
-  char classAllFieldsName[128];
-  struct type *type = NULL;
-  int is_scripted;
-
-  get_class_name (object, &class_name, &is_scripted);
-  sprintf (classAllFieldsName, "%s_AllFields", class_name);
-  free (class_name);
-
-  type = lookup_typename (classAllFieldsName, (struct block *)NULL, 0);
-  return lookup_pointer_type (type);
-}
-
-/* Given OBJECT, an object ID, return the address of the object's
-   fixed fields.  */
-
-CORE_ADDR
-baseptr_of_object (object)
-     unsigned long object;
-{
-  return get_base_ptr (object) + kSizeOfObjectHeader;
-}
-
-/* Given an expression for an object ID, ARGS, print information about
-   the object--including its class, the values of its fixed fields, and
-   the values in its extra data block.  */
-
-/* ARGSUSED */
-static void
-print_object (args, dump)
-     char *args;
-     int dump;
-{
-  CORE_ADDR addr;
-  unsigned long object, object_length;
-  char *class_name = NULL;
-  char class_all_fields_name[128];
-  struct type *type;
-  int is_scripted;
-  struct cleanup *old_chain;
-
-  if (args == NULL)
-    error_no_arg ("expression for object ID");
-
-  object = parse_and_eval_address (args);
-
-  /* check for nilObject */
-
-  if (!object)
-    {
-      printf_filtered ("\"%s\" evaluates to nilObject.\n", args);
-      return;
-    }
-
-  /* allow shortcut for system object ids */
-
-  if (IsObjectID (object))
-    object |= 1 << kIDBitUsable;
-  else if (object < 0x5000)
-    object |= (1 << kIDBitObject) | (1 << kIDBitUsable); /* 0x84000000 */
-
-  /* Get the name of the object's class, as well as the GDB type that
-     describes the layout of the object's fixed fields.  */
-   
-  get_class_name (object, &class_name, &is_scripted);
-  old_chain = make_cleanup (free_current_contents, &class_name);
-
-  sprintf (class_all_fields_name, "%s_AllFields", class_name);
-  type = lookup_typename (class_all_fields_name, (struct block *)NULL, 1);
-
-  /* Get pointer to object's fields.
-     FIXME: ADDR is actually an (ObjectHeader *); should use normal expression
-     evaluator to extract the length member, rather than hardwiring the 
-     format of the structure in this code.  */
-
-  addr = get_base_ptr (object);
-  object_length = read_memory_unsigned_integer (addr, 4);
-  object_length -= kSizeOfObjectHeader;
-  addr += kSizeOfObjectHeader;
-
-  if (type == NULL || (TYPE_CODE (type) != TYPE_CODE_UNDEF
-                      && !(TYPE_FLAGS (type) & TYPE_FLAG_STUB)))
-    {
-      if (dump)
-       {
-         unsigned long fixed_length;
-
-         printf_filtered ("Object 0x%08lx%s at address 0x%08lx of class %s\n", 
-                          object, (is_scripted) ? " (scripted)" : "",
-                          addr, class_name);
-
-         /* If the object has fixed fields, dump them.  */
-
-         if (type != NULL)
-           {
-             value_ptr valptr = value_at_lazy (type, addr);
-             int histindex = record_latest_value (valptr);
-
-             if (histindex >= 0)
-               printf_filtered ("$%d = ", histindex);
-
-             value_print (valptr, gdb_stdout, 0, Val_prettyprint);
-             puts_filtered ("\n");
-             fixed_length = TYPE_LENGTH (type);
-           }
-         else
-           fixed_length = 0;
-
-         /* If the object's length is less than that of its fixed fields,
-            warn the user.  */
-
-         if (object_length < fixed_length)
-           {
-             error ("Warning: object is too small (should be at least %d bytes, is %d bytes).",
-                    fixed_length, object_length);
-           }
-
-         /* Dump the object's extra data, if any.  should_dump_extra_data ()
-            filters out classes (e.g. Cluster) that have too much extra data
-            to be dumped usefully in this format.  */
-
-         if (should_dump_extra_data (class_name))
-           {
-             dump_extra_data (addr + fixed_length,
-                              object_length - fixed_length);
-           }
-       }
-      else
-       {
-         struct type *pointer_type;
-         value_ptr valptr;
-         int histindex;
-
-         pointer_type = lookup_pointer_type ((type == NULL) ?
-                                             builtin_type_void : type);
-         valptr = value_from_longest (pointer_type, addr);
-                                               
-         histindex = record_latest_value (valptr);
-         if (histindex >= 0)
-           printf_filtered ("$%d = ", histindex);
-
-         value_print (valptr, gdb_stdout, 0, Val_prettyprint);
-         puts_filtered ("\n");
-       }
-    }
-  do_cleanups (old_chain);
-}
-
-/* Get the name of the class of the object referenced by OBJECTID.
-   *NAME is set to a pointer to the string containing the class
-   name; it is the caller's responsibility to free the memory for
-   the string.  *IS_SCRIPTED is set to nonzero if the object is
-   scripted, zero otherwise.  */
-
-static void
-get_class_name (objectID, name, is_scripted)
-     unsigned long objectID;
-     char **name;
-     int *is_scripted;
-{
-  value_ptr val;
-  int errno_val;
-
-  val = call_function_by_value (remote_get_class_name_val, 1, objectID);
-
-  /* As RemoteGetClassName() is currently (9/21/95) written, an empty string,
-     rather than a nil pointer, is returned upon failure.  I'm leaving the
-     value_logical_not test in anyway, though, just for added robustness.  */
-     
-  if (!value_logical_not (val))
-    {
-      (void)target_read_string (value_as_pointer (val), name, 256, &errno_val);
-      if (errno_val)
-       error ("Can't read class name for object 0x%08lx.", objectID);
-
-      if (**name)
-       {
-         char *scripted_suffix;
-
-         if ((scripted_suffix = strstr (*name, " (scripted)")) != NULL)
-           {
-             *scripted_suffix = '\0';
-             *is_scripted = 1;
-           }
-         else
-           *is_scripted = 0;
-
-          return;
-       }
-      else
-       free (*name);
-    }
-
-  error ("Bad object ID: 0x%08lx.", objectID);
-}
-
-/* Given an object ID, return a pointer to the object's data.  */
-
-static CORE_ADDR
-get_base_ptr (objectID)
-     unsigned long objectID;
-{
-  register value_ptr val;
-
-  val = call_function_by_value (remote_get_base_ptr_val, 1, objectID);
-
-  if (value_logical_not (val))
-    error ("Could not get base pointer to object.");
-
-  return value_as_pointer (val);
-}
-
-/* Return nonzero if we should dump the extra data for an object 
-   of class CLASS_NAME.
-
-   FIXME this only works for explicitly named classes, and doesn't
-   handle subclasses.  */
-
-static int
-should_dump_extra_data (class_name)
-     char *class_name;
-{
-  int i;
-  char **name;
-  static char *dont_dump_extra_classes[] =
-    {
-      "Cluster"
-    };
-
-  for (i = 0, name = dont_dump_extra_classes;
-       i < ARRAY_NELEMENTS(dont_dump_extra_classes);
-       i++, name++)
-    {
-      if (!strcmp (class_name, *name))
-       return 0;
-    }
-
-  return 1;
-}
-
-/* Given ADDR, the address of an object's extra data block, and LENGTH,
-   the length of that block in bytes, dump the object's extra data to
-   standard output.  */
-
-static void
-dump_extra_data (addr, length)
-     CORE_ADDR addr;
-     unsigned long length;
-{
-  unsigned long buf[5];
-  int chunk;
-  int chunk_longs;
-  int i;
-  int bytes_printed;
-  char *p;
-
-  bytes_printed = 0;
-
-  while (length > 3 && bytes_printed < extra_data_max)
-    {
-      QUIT;            /* allow user to interrupt dump */
-
-      /* read a chunk of extra data */
-
-      chunk = (length > 16) ? 16 : length;
-      memset (buf, 0, sizeof (buf));
-      read_memory (addr, (char *) &buf, chunk);
-
-      /* format data as hex longwords */
-
-      chunk_longs = chunk >> 2;
-      for (i = 0; i < chunk_longs; i++)
-       printf_filtered ("%08lx ",
-                        extract_unsigned_integer (buf + i, sizeof (long)));
-
-      /* pad to 4 longs */
-
-      for (i = chunk_longs; i < 4; i++)
-       puts_filtered ("         ");
-
-      puts_filtered ("| ");
-
-      /* format data as ascii bytes */
-
-      for (i = 0, p = (char*)buf; i < chunk; i++, p++)
-       {
-         if (!isprint (*p))
-           *p = '.';
-       }
-      printf_filtered ("%s |\n", buf);
-
-      addr += chunk;
-      length -= chunk;
-      bytes_printed += chunk;
-    }
-
-  if (length > 0)
-    printf_filtered ("(%d bytes of extra data remaining but not displayed.)\n",
-                    length);
-}
-
-/* Given the name of a function in the target program and a list of
-   long arguments, call the function and return a pointer to a value
-   object describing the function's return value.  NAME is a string
-   containing the name of the function to be called; NARGS is the
-   number of arguments to the function; and the remaining parameters
-   are the arguments to passed to the function, all assumed to be of
-   type long.  */
-
-static value_ptr
-#ifdef ANSI_PROTOTYPES
-call_function_by_name (char *function_name, int nargs, ...)
-#else
-call_function_by_name (va_alist)
-     va_dcl
-#endif
-{
-  va_list args;
-  value_ptr return_value;
-  value_ptr function_value;
-#ifndef ANSI_PROTOTYPES
-  char *function_name;
-  int nargs;
-
-  va_start (args);
-  function_name = va_arg (args, char *);
-  nargs = va_arg (args, int);
-#else
-  va_start (args, nargs);
-#endif
-
-  /* Find the address of function NAME in the inferior.  */
-
-  if (!lookup_text_label (function_name, &function_value))
-    error ("Execution of this command requires the debugged program to have a function \"%s.\"",
-          function_name);
-
-  /* Call the function.  */
-
-  return_value = vcall_function_by_value (function_value, nargs, args);
-  va_end (args);
-
-  return return_value;
-}
-
-/* Given a value object describing a function in the target program and
-   a list of long arguments, call the function and return a pointer to a
-   value object describing the function's return value.  FUNCTION_VALUE
-   is a pointer to a value struct describing the function; NARGS is the
-   number of arguments to the function; and the remaining parameters are
-   the arguments to passed to the function, all assumed to be of type long.  */
-
-static value_ptr
-#ifdef ANSI_PROTOTYPES
-call_function_by_value (value_ptr function_value, int nargs, ...)
-#else
-call_function_by_value (va_alist)
-     va_dcl
-#endif
-{
-  va_list args;
-  value_ptr return_value;
-#ifndef ANSI_PROTOTYPES
-  value_ptr function_value;
-  int nargs;
-
-  va_start (args);
-  function_value = va_arg (args, value_ptr);
-  nargs = va_arg (args, int);
-#else
-  va_start (args, nargs);
-#endif
-
-  /* Call the function and return its return value.  */
-
-  return_value = vcall_function_by_value (function_value, nargs, args);
-  va_end (args);
-
-  return return_value;
-}
-
-/* Helper routine for call_function_by_name and call_function_by_value 
-   above.  This function does the work of collecting the function
-   arguments into an array of value objects, and then invoking 
-   call_function_by_hand to do the real work.  FUNCTION_VALUE is a 
-   pointer to a value object describing the function to be called,
-   NARGS is the number of arguments to the function, and ARGS is a
-   list (va_list) of the arguments to the function, all assumed to
-   be of type long.
-
-   Returns a pointer to a value object describing the return value
-   of the function.  */
-
-static value_ptr
-vcall_function_by_value (function_value, nargs, args)
-     value_ptr function_value;
-     int nargs;
-     va_list args;
-{
-  value_ptr *arg_values;
-  value_ptr return_value;
-  struct cleanup *old_chain;
-  int i;
-
-  /* Construct a vector of value objects describing the arguments
-     to the function to be called.  */
-
-  arg_values = (value_ptr *) xmalloc (nargs * sizeof (value_ptr));
-  old_chain = make_cleanup (free_current_contents, &arg_values);
-
-  for (i = 0; i < nargs; i++)
-    arg_values[i] = value_from_longest (builtin_type_long,
-                                       (LONGEST) va_arg (args, unsigned long));
-
-  /* Call the function and return its return value.  */
-
-  return_value = call_function_by_hand (function_value, nargs, arg_values);
-  do_cleanups (old_chain);
-  return return_value;
-}
-
-/* Invoke a shell, supplying ARG as the command to be executed.  */
-
-static void
-local_shell_escape (arg)
-     char *arg;
-{
-#ifdef CANT_FORK
-  /* FIXME: what about errors (I don't know how GO32 system() handles
-     them)?  */
-  system (arg);
-#else /* Can fork.  */
-  int rc, status, pid;
-  char *p, *user_shell;
-
-  if ((user_shell = (char *) getenv ("SHELL")) == NULL)
-    user_shell = "/bin/sh";
-
-  /* Get the name of the shell for arg0 */
-  if ((p = strrchr (user_shell, '/')) == NULL)
-    p = user_shell;
-  else
-    p++;                       /* Get past '/' */
-
-  if ((pid = fork()) == 0)
-    {
-      if (!arg)
-       execl (user_shell, p, 0);
-      else
-       execl (user_shell, p, "-c", arg, 0);
-
-      fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
-                         safe_strerror (errno));
-      gdb_flush (gdb_stderr);
-      _exit (0177);
-    }
-
-  if (pid != -1)
-    while ((rc = wait (&status)) != pid && rc != -1)
-      ;
-  else
-    error ("Fork failed");
-#endif /* Can fork.  */
-}
-
-/* Lookup NAME as a text label in the target program.  If NAME is the
-   name of a function, and VAL_PTRPTR is not NULL, a pointer to a value
-   object describing the function is stored at VAL_PTRPTR.
-
-   Returns the text address to which the label refers, or 0 if the
-   label is not found in the target program.  */
-
-static CORE_ADDR
-lookup_text_label (name, val_ptrptr)
-     char *name;
-     value_ptr *val_ptrptr;
-{
-  struct symbol *sym;
-  CORE_ADDR addr;
-
-  addr = 0;
-
-  /* Try looking up NAME as a first-class symbol.  */
-
-  sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
-  if (sym != NULL)
-    {
-      switch (SYMBOL_CLASS (sym))
-       {
-       case LOC_BLOCK:
-         addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-         if (val_ptrptr != NULL)
-           *val_ptrptr = value_of_variable (sym, NULL);
-
-         break;
-
-       case LOC_STATIC:
-       case LOC_LABEL:
-         addr = SYMBOL_VALUE_ADDRESS (sym);
-         break;
-       }
-    }
-  else
-    {
-      struct minimal_symbol *msymbol;
-      struct type *type;
-
-      /* Try to find a minimal symbol for NAME.  */
-
-      msymbol = lookup_minimal_symbol (name, "", (struct objfile *) NULL);
-      if (msymbol != NULL)
-       {
-         addr = SYMBOL_VALUE_ADDRESS (msymbol);
-         if (val_ptrptr != NULL)
-           {
-             type = lookup_pointer_type (builtin_type_char);
-             type = lookup_function_type (type);
-             type = lookup_pointer_type (type);
-             *val_ptrptr = value_from_longest (type, addr);
-           }
-       }
-    }
-  return addr;
-}
-
-/* The following two routines adapt GDB's framework for stepping over
-   shared library trampoline code to the problem of stepping over the
-   Magic Cap method dispatcher.  While the method dispatcher is not a
-   shared library trampoline, we can use the interfaces for controlling
-   stepping over trampolines to do what we want.  */
-
-/* Return nonzero if STOP_PC is within the Magic Cap method dispatcher.
-   NAME is unused.  This function serves as the implementation of both
-   IN_SOLIB_CALL_TRAMPOLINE() and IN_SOLIB_RETURN_TRAMPOLINE() when GDB
-   is configured to target Magic Cap.  We don't need to distinguish
-   between the two types of trampolines (because they're not really
-   trampolines); we just need to tell GDB to set a breakpoint at the
-   site of the next "hop" on our way through the dispatcher, and to
-   keep going.  */
-
-int
-magic_in_dispatcher (stop_pc, name)
-     CORE_ADDR stop_pc;
-     char *name;
-{
-  return magic_step_enabled
-        && (is_dispatcher_entry (stop_pc) || is_dispatcher_exit (stop_pc));
-}
-
-/* Determine if STOP_PC is an address within the Magic Cap method
-   dispatcher, and if so, return the address at which GDB should set
-   a step resume breakpoint in order to skip over the dispatcher code.
-   In fact, we have to skip over the dispatcher in two separate "hops:"
-   the first hop gets us from a dispatcher entry point to the dispatcher
-   exit site; the second hop gets us from this exit site to the first
-   instruction of the method.
-
-   This function serves as the implementation of SKIP_TRAMPOLINE_CODE()
-   when GDB is configured to target Magic Cap.  */
-
-CORE_ADDR 
-magic_skip_dispatcher (stop_pc)
-     CORE_ADDR stop_pc;
-{
-  /* If magic stepping is disabled, return 0, indicating that GDB should
-     process this step event normally.  This will have the effect of
-     allowing the user to step through the dispatcher code itself.  */
-
-  if (!magic_step_enabled)
-    return 0;
-
-  /* If the program is stopped at an entry point to the dispatcher,
-     tell GDB to set a breakpoint at a well-known label in the
-     dispatcher where we will be able to determine the address of
-     the method to which we are dispatching.  Note that the dispatcher
-     has hair to ensure that the code at this label is executed when we
-     are completing a top-level dispatch; recursive dispatches generated
-     from within the dispatcher do not exit through this code.  */
-
-  if (is_dispatcher_entry (stop_pc))
-    return DO_DISPATCH_METHOD_ADDR;
-
-  /* If we have hit the breakpoint set previously at a dispatcher exit site,
-     determine the method address and tell GDB to set a breakpoint there.  */
-
-  else if (is_dispatcher_exit (stop_pc))
-    return read_register (14); /* assumes that we branch through t6 */
-  else
-    return 0;
-}
-
-/* Return nonzero if PC is an entry point to the Magic Cap method
-   dispatcher.  */
-
-static int
-is_dispatcher_entry (pc)
-     CORE_ADDR pc;
-{
-  return pc == DISPATCH_METHOD_ADDR
-        || pc == DISPATCH_INTRINSIC_ADDR
-        || pc == DISPATCH_INHERITED_ADDR
-        || pc == DISPATCH_DELEGATED_ADDR;
-}
-
-/* Return nonzero if PC is an exit site from the Magic Cap method
-   dispatcher.  */
-
-static int
-is_dispatcher_exit (pc)
-     CORE_ADDR pc;
-{
-  return pc == DO_DISPATCH_METHOD_ADDR;
-}
-
-/* Store away addresses in the inferior we need to control single-stepping
-   through Magic Cap method dispatches, as well as other addresses of
-   interest in Magic Cap.  */
-
-void
-init_magic ()
-{
-  struct text_label *label;
-  int i;
-
-  /* Cache method dispatch label addresses.  */
-
-  for (i = 0, label = dispatch_labels;
-       i < ARRAY_NELEMENTS (dispatch_labels);
-       i++, label++)
-    {
-      if (!(label->addr = lookup_text_label (label->name, NULL)))
-       {
-         /* If we can't find all of the dispatcher addresses, don't attempt
-            to do magic stepping.  */
-
-         magic_step_enabled = 0;
-         break;
-       }
-    }
-
-  /* Cache value objects for RemoteGetClassName () and RemoteGetBasePtr (),
-     which are used to implement the "dobj" and "pobj" commands.  Note that
-     we must call release_value () on these values to prevent GDB from freeing
-     them automatically.  */
-
-  if (remote_get_class_name_val != NULL)
-    {
-      value_free (remote_get_class_name_val);
-      remote_get_class_name_val = NULL;
-    }
-
-  if (remote_get_base_ptr_val != NULL)
-    {
-      value_free (remote_get_base_ptr_val);
-      remote_get_base_ptr_val = NULL;
-    }
-
-  if (lookup_text_label ("RemoteGetClassName", &remote_get_class_name_val))
-    {
-      release_value (remote_get_class_name_val);
-
-      if (lookup_text_label ("RemoteGetBasePtr", &remote_get_base_ptr_val))
-       release_value (remote_get_base_ptr_val);
-    }
-} 
-
-/* Hook routine called when an inferior (i.e., debugged) process is
-   created.  */
-
-void
-magic_create_inferior_hook ()
-{
-  struct symbol *sym = lookup_symbol ("gHandleError", NULL, VAR_NAMESPACE,
-                                     NULL, NULL);
-  if (sym)
-    {
-      CORE_ADDR addr = SYMBOL_VALUE (sym);
-      unsigned long errorDebugger = 2;
-
-      target_write_memory (addr, (char *) &errorDebugger, 4);
-    }
-}
-
-/* Initialization routine for magic.c.  This is where we define debugger
-   commands specific to Magic Cap.  */
-
-void
-_initialize_magic ()
-{
-  add_com ("dobj", class_support, dobj_command,
-          "Display object contents.\n\
-Usage: dobj <objectID>\n\
-Where: <objectID> is an expression for the object ID to dump.");
-
-  add_com ("pobj", class_support, pobj_command,
-          "Print object base pointer.\n\
-Usage: pobj <objectID>\n\
-Where: <objectID> is an expression for the object ID to examine.");
-
-  add_com ("cdump", class_support, cdump_command,
-          concat ("Display the contents of a cluster.\n\
-Usage: cdump <contextSlot> [/l[ocked]] [/s[tartAddr] <addr>]\n\
-                          [/c[lass] <classNumber>]\n\
-Where: <contextSlot> is an expression describing the cluster to dump;\n\
-           if <contextSlot> is a number between 0x8 and 0xf, it is \n\
-           interpreted as the high-order nibble of an object ID\n\
-           belonging to the cluster to dump, with the second highest-\n\
-           order nibble assumed to be 0.  (For example, \"cdump 8\" and \n\
-           \"cdump 0xa\" dump the System Persistent and Persistent RAM\n\
-           clusters, respectively.)\n",
-                   "\n\
-           if <contextSlot> is a number between 0xf0 and 0x100, it is\n\
-           interpreted as the high-order byte of an object ID belonging to\n\
-           the cluster to dump.  (For example, \"cdump 0x88\" and \n\
-           \"cdump 0xa8\" dump the Locked Persistent and Transient RAM\n\
-           clusters, respectively.)\n",
-                   "\n\
-       /locked or /l indicates that only locked objects are to be displayed.\n\
-\n\
-       /startAddr or /s indicates that only objects whose base pointers are\n\
-           greater than or equal to the address specified by the following\n\
-           expression (<startAddr>) are to be displayed.\n\
-\n\
-       /class or /c indicates that only objects of the class specified by\n\
-           the following expression <classNumber> are to be displayed.",
-                  NULL));
-
-  add_com ("esc", class_support, esc_command,
-          "List all the exception handlers for a given actor.\n\
-Usage: esc <objectID>\n\
-Where: <objectID> is an expression for the object ID of the actor\n\
-           whose exception handlers are to be listed.");
-
-  add_com ("cnum", class_support, cnum_command,
-          "Convert class number to name.\n\
-Usage: cnum <classNumber>\n\
-Where: <classNumber> is an expression for the class number to convert.");
-
-  add_com ("getint", class_support, getint_command,
-          "Convert intrinsic name to number or vice versa.\n\
-Usage: getint <intrinsicName> | <intrinsicNumber>\n\
-Where: <intrinsicName> | <intrinsicNumber> is an intrinsic operation name\n\
-           to be converted to an operation number, or an intrinsic operation\n\
-           number to be converted to an operation name.");
-
-  add_com ("getop", class_support, getop_command,
-          "Convert operation name to number or vice versa.\n\
-Usage: getop <operationName> | <operationNumber>\n\
-Where: <operationName> | <operationNumber> is an operation name to be\n\
-           converted to an operation number, or an operation number to\n\
-           be converted to an operation name.");
-
-  add_com ("getindexical", class_support, getindexical_command,
-          "Convert indexical name to number or vice versa.\n\
-Usage: getindexical <indexicalName> | <indexicalNumber>\n\
-Where: <indexicalName> | <indexicalNumber> is an indexical name to be\n\
-           converted to an an indexical number, or an indexical number\n\
-           to be converted to an indexical name.");
-
-  add_com ("exc", class_support, exc_command,
-          "Convert exception name to number or vice versa.\n\
-Usage: exc <exceptionName> | <exceptionNumber>\n\
-Where: <exceptionName> | <exceptionNumber> is an exception name to be\n\
-           converted to an an exception number, or an exception number\n\
-           to be converted to an exception name.");
-
-  add_show_from_set
-    (add_set_cmd ("extra-data-max", class_support, var_uinteger,
-                 (char *) &extra_data_max,
-                 "Set limit on number of bytes of extra data to print.\n\
-This command sets an upper limit on the number of bytes of extra\n\
-data displayed by the \"dobj\" command when dumping a Magic Cap\n\
-object.  \"set extra-data-max 0\" causes there to be no limit.",
-                 &setlist),
-     &showlist);
-
-  extra_data_max = EXTRA_DATA_MAX_DEFAULT;
-
-  add_show_from_set
-    (add_set_cmd ("magic-step", class_support, var_boolean,
-                 (char *) &magic_step_enabled,
-                 "Set stepping over Magic Cap method dispatches.\n\
-When set to \"on\" (the default), issuing a \"step\" command at a Magic Cap\n\
-operation call site will cause the program to stop at the first line of\n\
-the corresponding method.  Set this to \"off\" only if you need to debug\n\
-the dispatcher itself.",
-                 &setlist),
-     &showlist);
-
-  magic_step_enabled = 1;
-
-#ifdef DYNAMIC_COMMAND_SUPPORT
-  add_com ("dlopen", class_support, dlopen_command,
-        "Load the dynamic library specified and execute the specified symbol");
-#endif
-}
index ef8cf2e..e69de29 100644 (file)
@@ -1,32 +0,0 @@
-/* magic.h - Interface to the General Magic debugger extras */
-
-/* object framework definitions, from FrameworkDefines.asm.h and Generic.h */
-
-#define        kIDBitObject            31      /* set for valid object IDs */
-#define        kIDBitUsable            26      /* set if objectID is usable */
-
-/* Return nonzero if <object> is a valid ObjectID */
-
-#define IsObjectID(object)     (((unsigned long)(object) & 0x80000000) != 0)
-
-#define kSizeOfObjectHeader    12      /* size of object header in bytes */
-
-/* public interfaces */
-
-extern void
-init_magic PARAMS ((void));
-
-extern void
-magic_create_inferior_hook PARAMS ((void));
-
-extern struct type *
-type_of_object PARAMS ((CORE_ADDR object));
-
-extern CORE_ADDR
-baseptr_of_object PARAMS ((CORE_ADDR object));
-
-extern int
-magic_in_dispatcher PARAMS ((CORE_ADDR stop_pc, char *name));
-
-extern CORE_ADDR
-magic_skip_dispatcher PARAMS ((CORE_ADDR stop_pc));