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:
Randolph Chung 2004-06-07 02:08:07 +00:00
parent 7d9b040b53
commit d49771efb5
5 changed files with 149 additions and 1 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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);

View File

@ -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);

View File

@ -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 *);
};
/*