aboutsummaryrefslogtreecommitdiff
path: root/gdb/magic.c
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1995-10-27 17:48:36 +0000
committerStu Grossman <grossman@cygnus>1995-10-27 17:48:36 +0000
commitcd10c7e3886bd28dc6ada58dcd5d93685a3ce865 (patch)
treec80e120745cd9901b95aba08398fb4e6cecff5df /gdb/magic.c
parentd6d44ef984d15d089277de11f176ce0775cabc31 (diff)
downloadgdb-cd10c7e3886bd28dc6ada58dcd5d93685a3ce865.zip
gdb-cd10c7e3886bd28dc6ada58dcd5d93685a3ce865.tar.gz
gdb-cd10c7e3886bd28dc6ada58dcd5d93685a3ce865.tar.bz2
* breakpoint.c (breakpoint_re_set): #ifdef GET_LONGJMP_TARGET
around calls to create_longjmp_breakpoint. Why install the breakpoints if we can't find the longjmp target? * infrun.c (wait_for_inferior): Cleanup comments near call test. * remote-mips.c: Fixed a bunch of prototypes to avoid char/int complaint from picky compilers. Add comment to mips_expect. Replace all instances of sr_get_debug with remote_debug. * (mips_readchar): Don't jam init string to monitor. mips_initialize() handles that. * (mips_receive_header): Print better message when we get too much garbage. * (mips_request): Allow caller to pass in buff to allow them to analyze the returned message. * (mips_initialize): Re-do initialization to try sending a BREAK, a ^C, and then a download escape sequence. Cleanup protocol startup. Eliminate sleeps. Clear breakpoints (if using monitor breakpoints). Re-init frame. * (mips_detach): Close down target. start-sanitize-gm * (mips_resume): Pass signal down to target. * (mips_create_inferior): Start target with TARGET_SIGNAL_PWR. end-sanitize-gm * (mips_wait): Handle return status with registers, or breakpoint stuff. * (mips_kill): Add ^C handling. * (mips_insert_breakpoint mips_remove_breakpoint): Call new breakpoint stuff if enabled. * (calculate_mask remote_mips_set_watchpoint remote_mips_remove_watchpoint remote_mips_stopped_by_watchpoint): Hardware watchpoint/breakpoint stuff. * (common_breakpoint): Common code for new monitor breakpoint commands. * (mips_load): Don't use `prompt'. It's a global variable. * top.c (dont_repeat_command): New command for use in user-defined commands to suppress auto-repeat (by hittin return key). start-sanitize-gm * utils.c (request_quit): Call target_kill here. Good idea. Needs a better implementation. end-sanitize-gm * valops.c: Add start of auto function-call abandonment capability. start-sanitize-gm * c-exp.y: Add code (currently disabled) to handle GM dynamic structures (it conflicts with @!). * eval.c (evaluate_subexp_standard): ditto. * expprint.c (print_subexp dump_expression): ditto. * expression.h (enum exp_opcode): ditto. * parse.c (length_of_subexp): ditto. * configure, configure.in: Add mip*-*-magic* target. * magic.c magic.h: Special routines to handle GM stuff (like stepping through dispatcher). end-sanitize-gm
Diffstat (limited to 'gdb/magic.c')
-rw-r--r--gdb/magic.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/gdb/magic.c b/gdb/magic.c
new file mode 100644
index 0000000..6576e23
--- /dev/null
+++ b/gdb/magic.c
@@ -0,0 +1,420 @@
+#include "defs.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "value.h"
+#include <ctype.h>
+#include <string.h>
+#ifdef DYNAMIC_COMMAND_SUPPORT
+#include <dlfcn.h>
+#endif
+
+typedef unsigned long ulong;
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+static void
+dlopen_command PARAMS ((char *, int));
+#endif
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+/* ARGSUSED */
+static void
+dlopen_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char *p;
+ void *hdl;
+ void (*sym)();
+
+ if (arg == 0) {
+ error ("No arguments specified.");
+ return;
+ }
+ p = arg;
+ while(*p != ' ' && *p != '\0')
+ p++;
+ if (*p != ' ') {
+ error ("Not enough arguments.");
+ return;
+ }
+ *p++ = '\0';
+
+ hdl = dlopen(arg, RTLD_NOW);
+ if (hdl == NULL) {
+ fprintf(stderr, "%s: %s\n", arg, dlerror());
+ return;
+ }
+ sym = dlsym(hdl, p);
+
+ if (sym == NULL) {
+ fprintf(stderr, "%s: %s\n", p, dlerror());
+ return;
+ }
+
+ sym();
+}
+#endif
+
+static void
+local_shell_escape (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. */
+}
+
+static void
+GetClassName(long objectID, char* name)
+{
+ register value_ptr val;
+ register struct symbol *sym;
+ struct minimal_symbol *msymbol;
+ struct type *type;
+ value_ptr blocklen;
+ LONGEST maddr;
+
+ /* Find the address of RemoteGetClassName in the inferior. */
+
+ sym = lookup_symbol ("RemoteGetClassName", 0, VAR_NAMESPACE, 0, NULL);
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error ("\"RemoteGetClassName\" exists in this program but is not a function.");
+ }
+ val = value_of_variable (sym, NULL);
+ }
+ else
+ {
+ msymbol = lookup_minimal_symbol ("RemoteGetClassName", "", (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol);
+ val = value_from_longest (type, maddr);
+ }
+ else
+ {
+ error ("evaluation of this expression requires the program to have a function \"RemoteGetClassName\".");
+ }
+ }
+
+ blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID);
+ val = call_function_by_hand (val, 1, &blocklen);
+ if (value_logical_not (val))
+ {
+ error ("Could not get class name.");
+ }
+ read_memory(value_as_pointer(val), name, 32);
+
+}
+
+static CORE_ADDR
+GetBasePtr(long objectID)
+{
+ register value_ptr val;
+ register struct symbol *sym;
+ struct minimal_symbol *msymbol;
+ struct type *type;
+ value_ptr blocklen;
+ LONGEST maddr;
+
+ /* Find the address of RemoteGetBasePtr in the inferior. */
+
+ sym = lookup_symbol ("RemoteGetBasePtr", 0, VAR_NAMESPACE, 0, NULL);
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error ("\"RemoteGetBasePtr\" exists in this program but is not a function.");
+ }
+ val = value_of_variable (sym, NULL);
+ }
+ else
+ {
+ msymbol = lookup_minimal_symbol ("RemoteGetBasePtr", "", (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol);
+ val = value_from_longest (type, maddr);
+ }
+ else
+ {
+ error ("evaluation of this expression requires the program to have a function \"RemoteGetBasePtr\".");
+ }
+ }
+
+ blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID);
+ val = call_function_by_hand (val, 1, &blocklen);
+ if (value_logical_not (val))
+ {
+ error ("Could not get base pointer to object.");
+ }
+ return value_as_pointer(val);
+}
+
+static void
+dump_extra_data(CORE_ADDR addr, ulong length)
+{
+ ulong buf[5], chunk, i;
+ char *p;
+
+ while (length > 3) {
+ chunk = (length > 16) ? 16 : length;
+
+ memset(buf, 0, 5*sizeof(long));
+ read_memory(addr, &buf, chunk);
+ fprintf(gdb_stdout, "%08lx %08lx %08lx %08lx | ", buf[0],
+ buf[1], buf[2], buf[3]);
+ for (i = 0, p = (char*)buf; i < chunk; i++, p++) {
+ if (!isprint(*p))
+ *p = '.';
+ }
+ fprintf(gdb_stdout, "%s |\n", buf);
+ addr += chunk;
+ length -= chunk;
+ }
+}
+
+struct type *type_of_object(CORE_ADDR object)
+{
+ char className[32], classAllFieldsName[128];
+ struct type *type = NULL;
+ GetClassName(object, className);
+ sprintf(classAllFieldsName, "%s_AllFields", className);
+
+ type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0);
+ return lookup_pointer_type(type);
+}
+
+CORE_ADDR baseptr_of_object(ulong object)
+{
+ return GetBasePtr(object) + 12;
+}
+
+/* ARGSUSED */
+static void
+print_object (arg, dump)
+ char *arg;
+ int dump;
+{
+ CORE_ADDR addr;
+ ulong object, objectLength, typeLength = 0;
+ char className[32], classAllFieldsName[128];
+ struct type* type = NULL;
+
+ object = parse_and_eval_address(arg);
+
+ GetClassName(object, className);
+ sprintf(classAllFieldsName, "%s_AllFields", className);
+
+ type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0);
+ typeLength = TYPE_LENGTH(type);
+ addr = GetBasePtr(object);
+ read_memory(addr, &objectLength, 4);
+ objectLength -= 12;
+ addr += 12;
+ if (TYPE_CODE(type) != TYPE_CODE_UNDEF && !(TYPE_FLAGS(type)&TYPE_FLAG_STUB)) {
+ if (dump) {
+ value_ptr valptr = value_at_lazy(type, addr);
+ int histindex = record_latest_value(valptr);
+ printf_filtered("Object 0x%08lx at address 0x%08lx of class %s\n",
+ object, addr, className);
+ if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+ value_print(valptr, gdb_stdout, 0, Val_prettyprint);
+ objectLength -= typeLength;
+ addr += typeLength;
+ printf_filtered("\n");
+ dump_extra_data(addr, objectLength);
+ printf_filtered("\n");
+ } else {
+ value_ptr valptr = value_from_longest(lookup_pointer_type(type), addr);
+ int histindex = record_latest_value(valptr);
+ if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+ value_print(valptr, gdb_stdout, 0, Val_prettyprint);
+ printf_filtered("\n");
+ }
+ }
+}
+
+/* ARGSUSED */
+static void
+dobj_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ print_object(arg, 1);
+}
+
+/* ARGSUSED */
+static void
+pobj_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ print_object(arg, 0);
+}
+
+/* ARGSUSED */
+static void
+getint_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char shellCommand[128];
+
+ sprintf(shellCommand, "getint %s", arg);
+ local_shell_escape(shellCommand);
+}
+
+/* ARGSUSED */
+static void
+getindexical_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char shellCommand[128];
+
+ sprintf(shellCommand, "getindexical %s", arg);
+ local_shell_escape(shellCommand);
+}
+
+/* ARGSUSED */
+static void
+exc_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char shellCommand[128];
+ ulong exception;
+
+ sprintf(shellCommand, "getexc %s", arg);
+ local_shell_escape(shellCommand);
+}
+
+static CORE_ADDR dispatch_method_addr = -1, dispatch_inherited_addr = -1, dispatch_delegated_addr = -1, dispatch_intrinsic_addr = -1;
+CORE_ADDR do_dispatch_method_addr = -1, do_dispatch_intrinsic_addr = -1;
+
+static CORE_ADDR
+lookup_address(const char *name)
+{
+ struct symbol *sym = lookup_symbol(name, NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym)
+ return BLOCK_START(SYMBOL_BLOCK_VALUE(sym));
+ else
+ {
+/* printf("Couldn't find %s!\n", name); */
+ return -1;
+ }
+}
+
+void
+init_magic()
+{
+ dispatch_method_addr = lookup_address("__DispatchMethod");
+ dispatch_inherited_addr = lookup_address("__DispatchInherited");
+ dispatch_delegated_addr = lookup_address("__DispatchDelegated");
+ dispatch_intrinsic_addr = lookup_address("__DispatchIntrinsic");
+ do_dispatch_method_addr = lookup_address("__DoTheDispatch");
+ do_dispatch_intrinsic_addr = lookup_address("__DoDispatchIntrinsic");
+}
+
+int
+is_dispatch(CORE_ADDR pc)
+{
+ return (pc == dispatch_method_addr) || (pc == dispatch_inherited_addr) || (pc == dispatch_delegated_addr);
+}
+
+int
+is_dispatch_intrinsic(CORE_ADDR pc)
+{
+ return pc == dispatch_intrinsic_addr;
+}
+
+/* If we are stopped at one of the entry points to the dispatcher, we want to continue until just
+ before we jump to the implementation. If we are at that point, we want to continue until we
+ actually get to the implementation. Likewise for the intrinsic dispatcher
+ */
+CORE_ADDR
+deal_with_dispatch(CORE_ADDR stop_pc)
+{
+ if (is_dispatch(stop_pc))
+ return do_dispatch_method_addr;
+ else if (is_dispatch_intrinsic(stop_pc))
+ return do_dispatch_intrinsic_addr;
+ else if (stop_pc == do_dispatch_method_addr)
+ /* This assumes that we branch through t6 */
+ return read_register(14);
+ else if (stop_pc == do_dispatch_intrinsic_addr)
+ /* This assumes that we branch through t0 */
+ return read_register(8);
+ else
+ return 0;
+}
+
+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, &errorDebugger, 4);
+ }
+
+ init_magic ();
+}
+
+
+_initialize_magic ()
+{
+ add_com ("dobj", class_support, dobj_command, "Display Object Contents");
+ add_com ("pobj", class_support, pobj_command, "Print object base pointer");
+ add_com ("getint", class_support, getint_command, "Convert intrinsic name to number or vice versa.");
+ add_com ("getindexical", class_support, getindexical_command, "Convert indexical name to number or vice versa.");
+ add_com ("exc", class_support, exc_command, "Convert exception name to number or vice versa.");
+
+#ifdef DYNAMIC_COMMAND_SUPPORT
+ add_com ("dlopen", class_support, dlopen_command,
+ "Load the dynamic library specified and execute the specified symbol");
+#endif
+}