2004-06-06 Randolph Chung <tausq@debian.org>
* hppa-tdep.h (struct value): Forward declaration. (gdbarch_tdep): Define tdep find_global_pointer method. * hppa-tdep.c (hppa32_push_dummy_call): Find the global pointer associated with the function we are trying to call, and write it to the gp register. (hppa32_convert_from_funct_ptr_addr): New function. (hppa_find_global_pointer): New function. (hppa_gdbarch_init): Set default find_global_pointer method; set convert_from_func_ptr_addr method. * hppa-linux-tdep.c (hppa_linux_find_global_pointer): New function. (hppa_linux_init_abi): Set find_global_pointer method. * Makefile.in (hppa-linux-tdep.o): Add value.h dependency.
This commit is contained in:
parent
7d9b040b53
commit
d49771efb5
@ -1,3 +1,18 @@
|
||||
2004-06-06 Randolph Chung <tausq@debian.org>
|
||||
|
||||
* hppa-tdep.h (struct value): Forward declaration.
|
||||
(gdbarch_tdep): Define tdep find_global_pointer method.
|
||||
* hppa-tdep.c (hppa32_push_dummy_call): Find the global pointer
|
||||
associated with the function we are trying to call, and write it
|
||||
to the gp register.
|
||||
(hppa32_convert_from_funct_ptr_addr): New function.
|
||||
(hppa_find_global_pointer): New function.
|
||||
(hppa_gdbarch_init): Set default find_global_pointer method; set
|
||||
convert_from_func_ptr_addr method.
|
||||
* hppa-linux-tdep.c (hppa_linux_find_global_pointer): New function.
|
||||
(hppa_linux_init_abi): Set find_global_pointer method.
|
||||
* Makefile.in (hppa-linux-tdep.o): Add value.h dependency.
|
||||
|
||||
2004-06-06 Randolph Chung <tausq@debian.org>
|
||||
|
||||
* gdbarch.sh (PUSH_DUMMY_CALL): Change CORE_ADDR func_addr argument
|
||||
|
@ -1845,7 +1845,7 @@ hppa-tdep.o: hppa-tdep.c $(defs_h) $(frame_h) $(bfd_h) $(inferior_h) \
|
||||
hppa-linux-tdep.o: hppa-linux-tdep.c $(defs_h) $(gdbcore_h) $(osabi_h) \
|
||||
$(target_h) $(objfiles_h) $(solib_svr4_h) $(glibc_tdep_h) \
|
||||
$(frame_unwind_h) $(trad_frame_h) $(dwarf2_frame_h) $(hppa_tdep_h) \
|
||||
$(elf_common_h)
|
||||
$(elf_common_h) $(value_h)
|
||||
hppa-linux-nat.o: hppa-linux-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
|
||||
$(gdb_string_h) $(inferior_h)
|
||||
hpread.o: hpread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(hp_symtab_h) \
|
||||
|
@ -28,8 +28,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "frame-unwind.h"
|
||||
#include "trad-frame.h"
|
||||
#include "dwarf2-frame.h"
|
||||
#include "value.h"
|
||||
#include "hppa-tdep.h"
|
||||
|
||||
#include "elf/common.h"
|
||||
|
||||
#if 0
|
||||
/* Convert DWARF register number REG to the appropriate register
|
||||
number used by GDB. */
|
||||
@ -466,6 +469,93 @@ hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempt to find (and return) the global pointer for the given
|
||||
function.
|
||||
|
||||
This is a rather nasty bit of code searchs for the .dynamic section
|
||||
in the objfile corresponding to the pc of the function we're trying
|
||||
to call. Once it finds the addresses at which the .dynamic section
|
||||
lives in the child process, it scans the Elf32_Dyn entries for a
|
||||
DT_PLTGOT tag. If it finds one of these, the corresponding
|
||||
d_un.d_ptr value is the global pointer. */
|
||||
|
||||
static CORE_ADDR
|
||||
hppa_linux_find_global_pointer (struct value *function)
|
||||
{
|
||||
struct obj_section *faddr_sect;
|
||||
CORE_ADDR faddr;
|
||||
|
||||
faddr = value_as_address (function);
|
||||
|
||||
/* Is this a plabel? If so, dereference it to get the gp value. */
|
||||
if (faddr & 2)
|
||||
{
|
||||
int status;
|
||||
char buf[4];
|
||||
|
||||
faddr &= ~3;
|
||||
|
||||
status = target_read_memory (faddr + 4, buf, sizeof (buf));
|
||||
if (status == 0)
|
||||
return extract_unsigned_integer (buf, sizeof (buf));
|
||||
}
|
||||
|
||||
/* If the address is in the plt section, then the real function hasn't
|
||||
yet been fixed up by the linker so we cannot determine the gp of
|
||||
that function. */
|
||||
if (in_plt_section (faddr, NULL))
|
||||
return 0;
|
||||
|
||||
faddr_sect = find_pc_section (faddr);
|
||||
if (faddr_sect != NULL)
|
||||
{
|
||||
struct obj_section *osect;
|
||||
|
||||
ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect)
|
||||
{
|
||||
if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (osect < faddr_sect->objfile->sections_end)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
|
||||
addr = osect->addr;
|
||||
while (addr < osect->endaddr)
|
||||
{
|
||||
int status;
|
||||
LONGEST tag;
|
||||
char buf[4];
|
||||
|
||||
status = target_read_memory (addr, buf, sizeof (buf));
|
||||
if (status != 0)
|
||||
break;
|
||||
tag = extract_signed_integer (buf, sizeof (buf));
|
||||
|
||||
if (tag == DT_PLTGOT)
|
||||
{
|
||||
CORE_ADDR global_pointer;
|
||||
|
||||
status = target_read_memory (addr + 4, buf, sizeof (buf));
|
||||
if (status != 0)
|
||||
break;
|
||||
global_pointer = extract_unsigned_integer (buf, sizeof (buf));
|
||||
|
||||
/* The payoff... */
|
||||
return global_pointer;
|
||||
}
|
||||
|
||||
if (tag == DT_NULL)
|
||||
break;
|
||||
|
||||
addr += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward declarations. */
|
||||
extern initialize_file_ftype _initialize_hppa_linux_tdep;
|
||||
|
||||
@ -477,6 +567,8 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
/* Linux is always ELF. */
|
||||
tdep->is_elf = 1;
|
||||
|
||||
tdep->find_global_pointer = hppa_linux_find_global_pointer;
|
||||
|
||||
set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc);
|
||||
|
||||
frame_unwind_append_sniffer (gdbarch, hppa_linux_sigtramp_unwind_sniffer);
|
||||
|
@ -727,6 +727,12 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
/* Two passes. First pass computes the location of everything,
|
||||
second pass writes the bytes out. */
|
||||
int write_pass;
|
||||
|
||||
/* Global pointer (r19) of the function we are trying to call. */
|
||||
CORE_ADDR gp;
|
||||
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
for (write_pass = 0; write_pass < 2; write_pass++)
|
||||
{
|
||||
CORE_ADDR struct_ptr = 0;
|
||||
@ -847,6 +853,11 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
if (struct_return)
|
||||
write_register (28, struct_addr);
|
||||
|
||||
gp = tdep->find_global_pointer (function);
|
||||
|
||||
if (gp != 0)
|
||||
write_register (19, gp);
|
||||
|
||||
/* Set the return address. */
|
||||
regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
|
||||
|
||||
@ -979,6 +990,22 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
return param_end + 64;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||||
CORE_ADDR addr,
|
||||
struct target_ops *targ)
|
||||
{
|
||||
if (addr & 2)
|
||||
{
|
||||
CORE_ADDR plabel;
|
||||
|
||||
plabel = addr & ~3;
|
||||
target_read_memory(plabel, (char *)&addr, 4);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
|
||||
{
|
||||
@ -2309,6 +2336,12 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
store_unsigned_integer (buf, sizeof(tmp), tmp);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
hppa_find_global_pointer (struct value *function)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hppa_frame_prev_register_helper (struct frame_info *next_frame,
|
||||
struct trad_frame_saved_reg saved_regs[],
|
||||
@ -2410,6 +2443,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
else
|
||||
tdep->bytes_per_address = 4;
|
||||
|
||||
tdep->find_global_pointer = hppa_find_global_pointer;
|
||||
|
||||
/* Some parts of the gdbarch vector depend on whether we are running
|
||||
on a 32 bits or 64 bits target. */
|
||||
switch (tdep->bytes_per_address)
|
||||
@ -2469,6 +2504,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
case 4:
|
||||
set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
|
||||
set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
|
||||
set_gdbarch_convert_from_func_ptr_addr
|
||||
(gdbarch, hppa32_convert_from_func_ptr_addr);
|
||||
break;
|
||||
case 8:
|
||||
set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
|
||||
|
@ -78,6 +78,10 @@ struct gdbarch_tdep
|
||||
/* Is this an ELF target? This can be 64-bit HP-UX, or a 32/64-bit GNU/Linux
|
||||
system. */
|
||||
int is_elf;
|
||||
|
||||
/* Given a function address, try to find the global pointer for the
|
||||
corresponding shared object. */
|
||||
CORE_ADDR (*find_global_pointer) (struct value *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user