Browse Source
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-gmgdb-4_18-branch
15 changed files with 1235 additions and 215 deletions
@ -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 |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
/* magic.h - Interface to the General Magic debugger extras */ |
|||
|
|||
extern void init_magic(); |
|||
extern CORE_ADDR deal_with_dispatch(CORE_ADDR pc); |
|||
extern struct type *type_of_object(CORE_ADDR object); |
|||
extern CORE_ADDR baseptr_of_object(CORE_ADDR object); |
|||
Loading…
Reference in new issue