diff options
author | Joel Brobecker <brobecker@gnat.com> | 2011-01-13 16:24:42 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2011-01-13 16:24:42 +0000 |
commit | c4de7027e3081f32895dc41d121a96e9e6717128 (patch) | |
tree | 36730eec41334dadc4705ab54af4423421b65833 /gdb/ia64-tdep.h | |
parent | 77ca787b12516ebb1b0d23710021b26b9c81b018 (diff) | |
download | gdb-c4de7027e3081f32895dc41d121a96e9e6717128.zip gdb-c4de7027e3081f32895dc41d121a96e9e6717128.tar.gz gdb-c4de7027e3081f32895dc41d121a96e9e6717128.tar.bz2 |
[ia64-hpux] inferior function call support
We have two stacks to deal with on ia64, when making a function call.
The first is the usual stack frame, and the second is the register
stack frame. On ia64-linux, the register frame is setup by adjusting
the BSP register. Unfortunately for us, the HP-UX kernel does not allow
the debugger to change the value of the BSP.
To work around that limitation, the method I am using here is to push
some assembly code on the stack. This assembly code contains, among
other things, a call to the alloc insn, which sets up our frame for us.
An extensive comment in ia64-hpux-tdep.c explains the entire procedure.
Despite this approach, most of the code in ia64-tdep.c which sets up
the function call is still applicable - and only a few things need
to be done differently: For instance, instead of changing the BSP,
we do nothing. We store the parameters at a different location, etc.
So this patch also adjusts the inf-call code in ia64-tdep.c to make it
a little more extensible: I create a new ia64_infcall_ops structure
which allows an ABI to define how the few things that need to be
differentiated.
Another element that turned out to be necessary but is more of a detail
is that the computation of the linkage pointer needs to be handled
specially for symbols inside shared libraries. This is especially
visible when calling malloc, which happens everytime memory needs to
be allocated in inferior memory... The special treatment included
again the necessity to use some routines only available on the host.
So another target object TARGET_OBJECT_HPUX_SOLIB_GOT was created for
that purpose.
gdb/ChangeLog:
* ia64-tdep.h (struct regcache): Forward declare.
(struct ia64_infcall_ops): New struct type.
(struct gdbarch_tdep): New fields "find_global_pointer_from_solib"
and "infcall_ops".
* ia64-tdep.c (ia64_find_global_pointer_from_dynamic_section):
Renames ia64_find_global_pointer.
(ia64_find_global_pointer, ia64_allocate_new_rse_frame)
(ia64_store_argument_in_slot, ia64_set_function_addr: New function.
(ia64_push_dummy_call): Adjust to use the new tdep ia64_infocall_ops
methods.
(ia64_infcall_ops): New static global constant.
(ia64_gdbarch_init): Set tdep->infcall_ops.
* ia64-hpux-nat.c (ia64_hpux_xfer_solib_got): New function.
(ia64_hpux_xfer_partial): Add TARGET_OBJECT_HPUX_SOLIB_GOT handing.
* ia64-hpux-tdep.c: Include "regcache.h", "gdbcore.h" and "inferior.h".
(ia64_hpux_dummy_code): New static global constant.
(ia64_hpux_push_dummy_code, ia64_hpux_allocate_new_rse_frame)
(ia64_hpux_store_argument_in_slot, ia64_hpux_set_function_addr)
(ia64_hpux_dummy_id, ia64_hpux_find_global_pointer_from_solib):
New function.
(ia64_hpux_infcall_ops): New static global constant.
(ia64_hpux_init_abi): Install gdbarch and tdep methods needed
for inferior function calls to work properly on ia64-hpux.
Diffstat (limited to 'gdb/ia64-tdep.h')
-rw-r--r-- | gdb/ia64-tdep.h | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/gdb/ia64-tdep.h b/gdb/ia64-tdep.h index 384cb14..df0b4bb 100644 --- a/gdb/ia64-tdep.h +++ b/gdb/ia64-tdep.h @@ -196,6 +196,32 @@ #define IA64_NAT127_REGNUM (IA64_NAT0_REGNUM + 127) struct frame_info; +struct regcache; + +/* A struction containing pointers to all the target-dependent operations + performed to setup an inferior function call. */ + +struct ia64_infcall_ops +{ + /* Allocate a new register stack frame starting after the output + region of the current frame. The new frame will contain SOF + registers, all in the output region. This is one way of protecting + the stacked registers of the current frame. + + Should do nothing if this operation is not permitted by the OS. */ + void (*allocate_new_rse_frame) (struct regcache *regcache, ULONGEST bsp, + int sof); + + /* Store the argument stored in BUF into the appropriate location + given the BSP and the SLOTNUM. */ + void (*store_argument_in_slot) (struct regcache *regcache, CORE_ADDR bsp, + int slotnum, gdb_byte *buf); + + /* For targets where we cannot call the function directly, store + the address of the function we want to call at the location + expected by the calling sequence. */ + void (*set_function_addr) (struct regcache *regcache, CORE_ADDR func_addr); +}; struct gdbarch_tdep { @@ -209,8 +235,18 @@ struct gdbarch_tdep extracting the lowest 7 bits ("cfm & 0x7f"). */ int (*size_of_register_frame) (struct frame_info *this_frame, ULONGEST cfm); + /* Determine the function address FADDR belongs to a shared library. + If it does, then return the associated global pointer. If no shared + library was found to contain that function, then return zero. + + This pointer may be NULL. */ + CORE_ADDR (*find_global_pointer_from_solib) (struct gdbarch *gdbarch, + CORE_ADDR faddr); + /* ISA-specific data types. */ struct type *ia64_ext_type; + + struct ia64_infcall_ops infcall_ops; }; extern void ia64_write_pc (struct regcache *, CORE_ADDR); |