|
|
|
@ -67,14 +67,6 @@ |
|
|
|
extern void _initialize_hppa_hpux_tdep (void); |
|
|
|
extern initialize_file_ftype _initialize_hppa_hpux_tdep; |
|
|
|
|
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
struct minimal_symbol *msym; |
|
|
|
CORE_ADDR solib_handle; |
|
|
|
CORE_ADDR return_val; |
|
|
|
} |
|
|
|
args_for_find_stub; |
|
|
|
|
|
|
|
static int |
|
|
|
in_opd_section (CORE_ADDR pc) |
|
|
|
{ |
|
|
|
@ -571,562 +563,6 @@ hppa_skip_permanent_breakpoint (struct regcache *regcache) |
|
|
|
/* We can leave the tail's space the same, since there's no jump. */ |
|
|
|
} |
|
|
|
|
|
|
|
/* Exception handling support for the HP-UX ANSI C++ compiler.
|
|
|
|
The compiler (aCC) provides a callback for exception events; |
|
|
|
GDB can set a breakpoint on this callback and find out what |
|
|
|
exception event has occurred. */ |
|
|
|
|
|
|
|
/* The name of the hook to be set to point to the callback function. */ |
|
|
|
static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook"; |
|
|
|
/* The name of the function to be used to set the hook value. */ |
|
|
|
static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value"; |
|
|
|
/* The name of the callback function in end.o */ |
|
|
|
static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback"; |
|
|
|
/* Name of function in end.o on which a break is set (called by above). */ |
|
|
|
static char HP_ACC_EH_break[] = "__d_eh_break"; |
|
|
|
/* Name of flag (in end.o) that enables catching throws. */ |
|
|
|
static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw"; |
|
|
|
/* Name of flag (in end.o) that enables catching catching. */ |
|
|
|
static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch"; |
|
|
|
/* The enum used by aCC. */ |
|
|
|
typedef enum |
|
|
|
{ |
|
|
|
__EH_NOTIFY_THROW, |
|
|
|
__EH_NOTIFY_CATCH |
|
|
|
} |
|
|
|
__eh_notification; |
|
|
|
|
|
|
|
/* Is exception-handling support available with this executable? */ |
|
|
|
static int hp_cxx_exception_support = 0; |
|
|
|
/* Has the initialize function been run? */ |
|
|
|
static int hp_cxx_exception_support_initialized = 0; |
|
|
|
/* Address of __eh_notify_hook */ |
|
|
|
static CORE_ADDR eh_notify_hook_addr = 0; |
|
|
|
/* Address of __d_eh_notify_callback */ |
|
|
|
static CORE_ADDR eh_notify_callback_addr = 0; |
|
|
|
/* Address of __d_eh_break */ |
|
|
|
static CORE_ADDR eh_break_addr = 0; |
|
|
|
/* Address of __d_eh_catch_catch */ |
|
|
|
static CORE_ADDR eh_catch_catch_addr = 0; |
|
|
|
/* Address of __d_eh_catch_throw */ |
|
|
|
static CORE_ADDR eh_catch_throw_addr = 0; |
|
|
|
/* Sal for __d_eh_break */ |
|
|
|
static struct symtab_and_line *break_callback_sal = 0; |
|
|
|
|
|
|
|
/* Code in end.c expects __d_pid to be set in the inferior,
|
|
|
|
otherwise __d_eh_notify_callback doesn't bother to call |
|
|
|
__d_eh_break! So we poke the pid into this symbol |
|
|
|
ourselves. |
|
|
|
0 => success |
|
|
|
1 => failure */ |
|
|
|
static int |
|
|
|
setup_d_pid_in_inferior (void) |
|
|
|
{ |
|
|
|
CORE_ADDR anaddr; |
|
|
|
struct minimal_symbol *msymbol; |
|
|
|
char buf[4]; /* FIXME 32x64? */ |
|
|
|
|
|
|
|
/* Slam the pid of the process into __d_pid; failing is only a warning! */ |
|
|
|
msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile); |
|
|
|
if (msymbol == NULL) |
|
|
|
{ |
|
|
|
warning (_("Unable to find __d_pid symbol in object file.\n" |
|
|
|
"Suggest linking executable with -g (links in /opt/langtools/lib/end.o).")); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
anaddr = SYMBOL_VALUE_ADDRESS (msymbol); |
|
|
|
store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */ |
|
|
|
if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */ |
|
|
|
{ |
|
|
|
warning (_("Unable to write __d_pid.\n" |
|
|
|
"Suggest linking executable with -g (links in /opt/langtools/lib/end.o).")); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* elz: Used to lookup a symbol in the shared libraries.
|
|
|
|
This function calls shl_findsym, indirectly through a |
|
|
|
call to __d_shl_get. __d_shl_get is in end.c, which is always |
|
|
|
linked in by the hp compilers/linkers. |
|
|
|
The call to shl_findsym cannot be made directly because it needs |
|
|
|
to be active in target address space. |
|
|
|
inputs: - minimal symbol pointer for the function we want to look up |
|
|
|
- address in target space of the descriptor for the library |
|
|
|
where we want to look the symbol up. |
|
|
|
This address is retrieved using the |
|
|
|
som_solib_get_solib_by_pc function (somsolib.c). |
|
|
|
output: - real address in the library of the function. |
|
|
|
note: the handle can be null, in which case shl_findsym will look for |
|
|
|
the symbol in all the loaded shared libraries. |
|
|
|
files to look at if you need reference on this stuff: |
|
|
|
dld.c, dld_shl_findsym.c |
|
|
|
end.c |
|
|
|
man entry for shl_findsym */ |
|
|
|
|
|
|
|
static CORE_ADDR |
|
|
|
find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle) |
|
|
|
{ |
|
|
|
struct symbol *get_sym, *symbol2; |
|
|
|
struct minimal_symbol *buff_minsym, *msymbol; |
|
|
|
struct type *ftype; |
|
|
|
struct value **args; |
|
|
|
struct value *funcval; |
|
|
|
struct value *val; |
|
|
|
|
|
|
|
int x, namelen, err_value, tmp = -1; |
|
|
|
CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr; |
|
|
|
CORE_ADDR stub_addr; |
|
|
|
|
|
|
|
|
|
|
|
args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */ |
|
|
|
funcval = find_function_in_inferior ("__d_shl_get"); |
|
|
|
get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL); |
|
|
|
buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL); |
|
|
|
msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL); |
|
|
|
symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL); |
|
|
|
endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym); |
|
|
|
namelen = strlen (DEPRECATED_SYMBOL_NAME (function)); |
|
|
|
value_return_addr = endo_buff_addr + namelen; |
|
|
|
ftype = check_typedef (SYMBOL_TYPE (get_sym)); |
|
|
|
|
|
|
|
/* do alignment */ |
|
|
|
if ((x = value_return_addr % 64) != 0) |
|
|
|
value_return_addr = value_return_addr + 64 - x; |
|
|
|
|
|
|
|
errno_return_addr = value_return_addr + 64; |
|
|
|
|
|
|
|
|
|
|
|
/* set up stuff needed by __d_shl_get in buffer in end.o */ |
|
|
|
|
|
|
|
target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen); |
|
|
|
|
|
|
|
target_write_memory (value_return_addr, (char *) &tmp, 4); |
|
|
|
|
|
|
|
target_write_memory (errno_return_addr, (char *) &tmp, 4); |
|
|
|
|
|
|
|
target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol), |
|
|
|
(char *) &handle, 4); |
|
|
|
|
|
|
|
/* now prepare the arguments for the call */ |
|
|
|
|
|
|
|
args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12); |
|
|
|
args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol)); |
|
|
|
args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr); |
|
|
|
args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), 3 /* TYPE_PROCEDURE */); |
|
|
|
args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr); |
|
|
|
args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr); |
|
|
|
|
|
|
|
/* now call the function */ |
|
|
|
|
|
|
|
val = call_function_by_hand (funcval, 6, args); |
|
|
|
|
|
|
|
/* now get the results */ |
|
|
|
|
|
|
|
target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value)); |
|
|
|
|
|
|
|
target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr)); |
|
|
|
if (stub_addr <= 0) |
|
|
|
error (_("call to __d_shl_get failed, error code is %d"), err_value); |
|
|
|
|
|
|
|
return (stub_addr); |
|
|
|
} |
|
|
|
|
|
|
|
/* Cover routine for find_stub_with_shl_get to pass to catch_errors */ |
|
|
|
static int |
|
|
|
cover_find_stub_with_shl_get (void *args_untyped) |
|
|
|
{ |
|
|
|
args_for_find_stub *args = args_untyped; |
|
|
|
args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Initialize exception catchpoint support by looking for the
|
|
|
|
necessary hooks/callbacks in end.o, etc., and set the hook value |
|
|
|
to point to the required debug function. |
|
|
|
|
|
|
|
Return 0 => failure |
|
|
|
1 => success */ |
|
|
|
|
|
|
|
static int |
|
|
|
initialize_hp_cxx_exception_support (void) |
|
|
|
{ |
|
|
|
struct symtabs_and_lines sals; |
|
|
|
struct cleanup *old_chain; |
|
|
|
struct cleanup *canonical_strings_chain = NULL; |
|
|
|
int i; |
|
|
|
char *addr_start; |
|
|
|
char *addr_end = NULL; |
|
|
|
char **canonical = (char **) NULL; |
|
|
|
int thread = -1; |
|
|
|
struct symbol *sym = NULL; |
|
|
|
struct minimal_symbol *msym = NULL; |
|
|
|
struct objfile *objfile; |
|
|
|
asection *shlib_info; |
|
|
|
|
|
|
|
/* Detect and disallow recursion. On HP-UX with aCC, infinite
|
|
|
|
recursion is a possibility because finding the hook for exception |
|
|
|
callbacks involves making a call in the inferior, which means |
|
|
|
re-inserting breakpoints which can re-invoke this code. */ |
|
|
|
|
|
|
|
static int recurse = 0; |
|
|
|
if (recurse > 0) |
|
|
|
{ |
|
|
|
hp_cxx_exception_support_initialized = 0; |
|
|
|
deprecated_exception_support_initialized = 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
hp_cxx_exception_support = 0; |
|
|
|
|
|
|
|
/* First check if we have seen any HP compiled objects; if not,
|
|
|
|
it is very unlikely that HP's idiosyncratic callback mechanism |
|
|
|
for exception handling debug support will be available! |
|
|
|
This will percolate back up to breakpoint.c, where our callers |
|
|
|
will decide to try the g++ exception-handling support instead. */ |
|
|
|
if (!deprecated_hp_som_som_object_present) |
|
|
|
return 0; |
|
|
|
|
|
|
|
/* We have a SOM executable with SOM debug info; find the hooks. */ |
|
|
|
|
|
|
|
/* First look for the notify hook provided by aCC runtime libs */ |
|
|
|
/* If we find this symbol, we conclude that the executable must
|
|
|
|
have HP aCC exception support built in. If this symbol is not |
|
|
|
found, even though we're a HP SOM-SOM file, we may have been |
|
|
|
built with some other compiler (not aCC). This results percolates |
|
|
|
back up to our callers in breakpoint.c which can decide to |
|
|
|
try the g++ style of exception support instead. |
|
|
|
If this symbol is found but the other symbols we require are |
|
|
|
not found, there is something weird going on, and g++ support |
|
|
|
should *not* be tried as an alternative. |
|
|
|
|
|
|
|
ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined. |
|
|
|
ASSUMPTION: HP aCC and g++ modules cannot be linked together. */ |
|
|
|
|
|
|
|
/* libCsup has this hook; it'll usually be non-debuggable */ |
|
|
|
msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL); |
|
|
|
if (msym) |
|
|
|
{ |
|
|
|
eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Unable to find exception callback hook (%s).\n\ |
|
|
|
Executable may not have been compiled debuggable with HP aCC.\n\ |
|
|
|
GDB will be unable to intercept exception events."), |
|
|
|
HP_ACC_EH_notify_hook); |
|
|
|
eh_notify_hook_addr = 0; |
|
|
|
hp_cxx_exception_support = 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Next look for the notify callback routine in end.o */ |
|
|
|
/* This is always available in the SOM symbol dictionary if end.o is
|
|
|
|
linked in. */ |
|
|
|
msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL); |
|
|
|
if (msym) |
|
|
|
{ |
|
|
|
eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Unable to find exception callback routine (%s).\n\ |
|
|
|
Suggest linking executable with -g (links in /opt/langtools/lib/end.o).\n\ |
|
|
|
GDB will be unable to intercept exception events."), |
|
|
|
HP_ACC_EH_notify_callback); |
|
|
|
eh_notify_callback_addr = 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (!gdbarch_tdep (current_gdbarch)->is_elf) |
|
|
|
{ |
|
|
|
/* Check whether the executable is dynamically linked or archive bound */ |
|
|
|
/* With an archive-bound executable we can use the raw addresses we find
|
|
|
|
for the callback function, etc. without modification. For an executable |
|
|
|
with shared libraries, we have to do more work to find the plabel, which |
|
|
|
can be the target of a call through $$dyncall from the aCC runtime |
|
|
|
support library (libCsup) which is linked shared by default by aCC. */ |
|
|
|
/* This test below was copied from somsolib.c/somread.c. It may not be a very
|
|
|
|
reliable one to test that an executable is linked shared. |
|
|
|
pai/1997-07-18 */ |
|
|
|
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$"); |
|
|
|
if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0)) |
|
|
|
{ |
|
|
|
/* The minsym we have has the local code address, but that's not
|
|
|
|
the plabel that can be used by an inter-load-module call. */ |
|
|
|
/* Find solib handle for main image (which has end.o), and use
|
|
|
|
that and the min sym as arguments to __d_shl_get() (which |
|
|
|
does the equivalent of shl_findsym()) to find the plabel. */ |
|
|
|
|
|
|
|
args_for_find_stub args; |
|
|
|
|
|
|
|
args.solib_handle = gdbarch_tdep (current_gdbarch)->solib_get_solib_by_pc (eh_notify_callback_addr); |
|
|
|
args.msym = msym; |
|
|
|
args.return_val = 0; |
|
|
|
|
|
|
|
recurse++; |
|
|
|
catch_errors (cover_find_stub_with_shl_get, &args, |
|
|
|
_("Error while finding exception callback hook:\n"), |
|
|
|
RETURN_MASK_ALL); |
|
|
|
eh_notify_callback_addr = args.return_val; |
|
|
|
recurse--; |
|
|
|
|
|
|
|
deprecated_exception_catchpoints_are_fragile = 1; |
|
|
|
|
|
|
|
if (!eh_notify_callback_addr) |
|
|
|
{ |
|
|
|
/* We can get here either if there is no plabel in the export list
|
|
|
|
for the main image, or if something strange happened (?) */ |
|
|
|
warning (_("\
|
|
|
|
Couldn't find a plabel (indirect function label) for the exception callback.\n\ |
|
|
|
GDB will not be able to intercept exception events.")); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
deprecated_exception_catchpoints_are_fragile = 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Now, look for the breakpointable routine in end.o */ |
|
|
|
/* This should also be available in the SOM symbol dict. if end.o linked in */ |
|
|
|
msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL); |
|
|
|
if (msym) |
|
|
|
{ |
|
|
|
eh_break_addr = SYMBOL_VALUE_ADDRESS (msym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Unable to find exception callback routine to set breakpoint (%s).\n\ |
|
|
|
Suggest linking executable with -g (link in /opt/langtools/lib/end.o).\n\ |
|
|
|
GDB will be unable to intercept exception events."), |
|
|
|
HP_ACC_EH_break); |
|
|
|
eh_break_addr = 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Next look for the catch enable flag provided in end.o */ |
|
|
|
sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL, |
|
|
|
VAR_DOMAIN, 0, (struct symtab **) NULL); |
|
|
|
if (sym) /* sometimes present in debug info */ |
|
|
|
{ |
|
|
|
eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
/* otherwise look in SOM symbol dict. */ |
|
|
|
{ |
|
|
|
msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL); |
|
|
|
if (msym) |
|
|
|
{ |
|
|
|
eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Unable to enable interception of exception catches.\n\ |
|
|
|
Executable may not have been compiled debuggable with HP aCC.\n\ |
|
|
|
Suggest linking executable with -g (link in /opt/langtools/lib/end.o).")); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Next look for the catch enable flag provided end.o */ |
|
|
|
sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL, |
|
|
|
VAR_DOMAIN, 0, (struct symtab **) NULL); |
|
|
|
if (sym) /* sometimes present in debug info */ |
|
|
|
{ |
|
|
|
eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
/* otherwise look in SOM symbol dict. */ |
|
|
|
{ |
|
|
|
msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL); |
|
|
|
if (msym) |
|
|
|
{ |
|
|
|
eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym); |
|
|
|
hp_cxx_exception_support = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Unable to enable interception of exception throws.\n\ |
|
|
|
Executable may not have been compiled debuggable with HP aCC.\n\ |
|
|
|
Suggest linking executable with -g (link in /opt/langtools/lib/end.o).")); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Set the flags */ |
|
|
|
hp_cxx_exception_support = 2; /* everything worked so far */ |
|
|
|
hp_cxx_exception_support_initialized = 1; |
|
|
|
deprecated_exception_support_initialized = 1; |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Target operation for enabling or disabling interception of
|
|
|
|
exception events. |
|
|
|
KIND is either EX_EVENT_THROW or EX_EVENT_CATCH |
|
|
|
ENABLE is either 0 (disable) or 1 (enable). |
|
|
|
Return value is NULL if no support found; |
|
|
|
-1 if something went wrong, |
|
|
|
or a pointer to a symtab/line struct if the breakpointable |
|
|
|
address was found. */ |
|
|
|
|
|
|
|
struct symtab_and_line * |
|
|
|
child_enable_exception_callback (enum exception_event_kind kind, int enable) |
|
|
|
{ |
|
|
|
char buf[4]; |
|
|
|
|
|
|
|
if (!deprecated_exception_support_initialized |
|
|
|
|| !hp_cxx_exception_support_initialized) |
|
|
|
if (!initialize_hp_cxx_exception_support ()) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
switch (hp_cxx_exception_support) |
|
|
|
{ |
|
|
|
case 0: |
|
|
|
/* Assuming no HP support at all */ |
|
|
|
return NULL; |
|
|
|
case 1: |
|
|
|
/* HP support should be present, but something went wrong */ |
|
|
|
return (struct symtab_and_line *) -1; /* yuck! */ |
|
|
|
/* there may be other cases in the future */ |
|
|
|
} |
|
|
|
|
|
|
|
/* Set the EH hook to point to the callback routine. */ |
|
|
|
store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */ |
|
|
|
/* pai: (temp) FIXME should there be a pack operation first? */ |
|
|
|
if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */ |
|
|
|
{ |
|
|
|
warning (_("\
|
|
|
|
Could not write to target memory for exception event callback.\n\ |
|
|
|
Interception of exception events may not work.")); |
|
|
|
return (struct symtab_and_line *) -1; |
|
|
|
} |
|
|
|
if (enable) |
|
|
|
{ |
|
|
|
/* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */ |
|
|
|
if (PIDGET (inferior_ptid) > 0) |
|
|
|
{ |
|
|
|
if (setup_d_pid_in_inferior ()) |
|
|
|
return (struct symtab_and_line *) -1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
warning (_("Internal error: Invalid inferior pid? Cannot intercept exception events.")); |
|
|
|
return (struct symtab_and_line *) -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
switch (kind) |
|
|
|
{ |
|
|
|
case EX_EVENT_THROW: |
|
|
|
store_unsigned_integer (buf, 4, enable ? 1 : 0); |
|
|
|
if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */ |
|
|
|
{ |
|
|
|
warning (_("Couldn't enable exception throw interception.")); |
|
|
|
return (struct symtab_and_line *) -1; |
|
|
|
} |
|
|
|
break; |
|
|
|
case EX_EVENT_CATCH: |
|
|
|
store_unsigned_integer (buf, 4, enable ? 1 : 0); |
|
|
|
if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */ |
|
|
|
{ |
|
|
|
warning (_("Couldn't enable exception catch interception.")); |
|
|
|
return (struct symtab_and_line *) -1; |
|
|
|
} |
|
|
|
break; |
|
|
|
default: |
|
|
|
error (_("Request to enable unknown or unsupported exception event.")); |
|
|
|
} |
|
|
|
|
|
|
|
/* Copy break address into new sal struct, malloc'ing if needed. */ |
|
|
|
if (!break_callback_sal) |
|
|
|
break_callback_sal = XMALLOC (struct symtab_and_line); |
|
|
|
init_sal (break_callback_sal); |
|
|
|
break_callback_sal->symtab = NULL; |
|
|
|
break_callback_sal->pc = eh_break_addr; |
|
|
|
break_callback_sal->line = 0; |
|
|
|
break_callback_sal->end = eh_break_addr; |
|
|
|
|
|
|
|
return break_callback_sal; |
|
|
|
} |
|
|
|
|
|
|
|
/* Record some information about the current exception event */ |
|
|
|
static struct exception_event_record current_ex_event; |
|
|
|
|
|
|
|
/* Report current exception event. Returns a pointer to a record
|
|
|
|
that describes the kind of the event, where it was thrown from, |
|
|
|
and where it will be caught. More information may be reported |
|
|
|
in the future */ |
|
|
|
struct exception_event_record * |
|
|
|
child_get_current_exception_event (void) |
|
|
|
{ |
|
|
|
CORE_ADDR event_kind; |
|
|
|
CORE_ADDR throw_addr; |
|
|
|
CORE_ADDR catch_addr; |
|
|
|
struct frame_info *fi, *curr_frame; |
|
|
|
int level = 1; |
|
|
|
|
|
|
|
curr_frame = get_current_frame (); |
|
|
|
if (!curr_frame) |
|
|
|
return (struct exception_event_record *) NULL; |
|
|
|
|
|
|
|
/* Go up one frame to __d_eh_notify_callback, because at the
|
|
|
|
point when this code is executed, there's garbage in the |
|
|
|
arguments of __d_eh_break. */ |
|
|
|
fi = find_relative_frame (curr_frame, &level); |
|
|
|
if (level != 0) |
|
|
|
return (struct exception_event_record *) NULL; |
|
|
|
|
|
|
|
select_frame (fi); |
|
|
|
|
|
|
|
/* Read in the arguments */ |
|
|
|
/* __d_eh_notify_callback() is called with 3 arguments:
|
|
|
|
1. event kind catch or throw |
|
|
|
2. the target address if known |
|
|
|
3. a flag -- not sure what this is. pai/1997-07-17 */ |
|
|
|
event_kind = read_register (HPPA_ARG0_REGNUM); |
|
|
|
catch_addr = read_register (HPPA_ARG1_REGNUM); |
|
|
|
|
|
|
|
/* Now go down to a user frame */ |
|
|
|
/* For a throw, __d_eh_break is called by
|
|
|
|
__d_eh_notify_callback which is called by |
|
|
|
__notify_throw which is called |
|
|
|
from user code. |
|
|
|
For a catch, __d_eh_break is called by |
|
|
|
__d_eh_notify_callback which is called by |
|
|
|
<stackwalking stuff> which is called by |
|
|
|
__throw__<stuff> or __rethrow_<stuff> which is called |
|
|
|
from user code. */ |
|
|
|
/* FIXME: Don't use such magic numbers; search for the frames */ |
|
|
|
level = (event_kind == EX_EVENT_THROW) ? 3 : 4; |
|
|
|
fi = find_relative_frame (curr_frame, &level); |
|
|
|
if (level != 0) |
|
|
|
return (struct exception_event_record *) NULL; |
|
|
|
|
|
|
|
select_frame (fi); |
|
|
|
throw_addr = get_frame_pc (fi); |
|
|
|
|
|
|
|
/* Go back to original (top) frame */ |
|
|
|
select_frame (curr_frame); |
|
|
|
|
|
|
|
current_ex_event.kind = (enum exception_event_kind) event_kind; |
|
|
|
current_ex_event.throw_sal = find_pc_line (throw_addr, 1); |
|
|
|
current_ex_event.catch_sal = find_pc_line (catch_addr, 1); |
|
|
|
|
|
|
|
return ¤t_ex_event; |
|
|
|
} |
|
|
|
|
|
|
|
/* Signal frames. */ |
|
|
|
struct hppa_hpux_sigtramp_unwind_cache |
|
|
|
@ -1967,15 +1403,6 @@ hppa_hpux_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty) |
|
|
|
{ |
|
|
|
/* Some HP-UX related globals to clear when a new "main"
|
|
|
|
symbol file is loaded. HP-specific. */ |
|
|
|
deprecated_hp_som_som_object_present = 0; |
|
|
|
hp_cxx_exception_support_initialized = 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Given the current value of the pc, check to see if it is inside a stub, and
|
|
|
|
if so, change the value of the pc to point to the caller of the stub. |
|
|
|
NEXT_FRAME is the next frame in the current list of frames. |
|
|
|
@ -2043,8 +1470,6 @@ hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
|
|
|
(gdbarch, hppa_hpux_regset_from_core_section); |
|
|
|
|
|
|
|
frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer); |
|
|
|
|
|
|
|
observer_attach_inferior_created (hppa_hpux_inferior_created); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
|