aboutsummaryrefslogtreecommitdiff
path: root/gdb/magic.c
diff options
context:
space:
mode:
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
+}