mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-05 06:23:58 +08:00
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:
@ -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>
|
2004-06-06 Randolph Chung <tausq@debian.org>
|
||||||
|
|
||||||
* gdbarch.sh (PUSH_DUMMY_CALL): Change CORE_ADDR func_addr argument
|
* 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) \
|
hppa-linux-tdep.o: hppa-linux-tdep.c $(defs_h) $(gdbcore_h) $(osabi_h) \
|
||||||
$(target_h) $(objfiles_h) $(solib_svr4_h) $(glibc_tdep_h) \
|
$(target_h) $(objfiles_h) $(solib_svr4_h) $(glibc_tdep_h) \
|
||||||
$(frame_unwind_h) $(trad_frame_h) $(dwarf2_frame_h) $(hppa_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) \
|
hppa-linux-nat.o: hppa-linux-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
|
||||||
$(gdb_string_h) $(inferior_h)
|
$(gdb_string_h) $(inferior_h)
|
||||||
hpread.o: hpread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(hp_symtab_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 "frame-unwind.h"
|
||||||
#include "trad-frame.h"
|
#include "trad-frame.h"
|
||||||
#include "dwarf2-frame.h"
|
#include "dwarf2-frame.h"
|
||||||
|
#include "value.h"
|
||||||
#include "hppa-tdep.h"
|
#include "hppa-tdep.h"
|
||||||
|
|
||||||
|
#include "elf/common.h"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Convert DWARF register number REG to the appropriate register
|
/* Convert DWARF register number REG to the appropriate register
|
||||||
number used by GDB. */
|
number used by GDB. */
|
||||||
@ -466,6 +469,93 @@ hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
|
|||||||
return NULL;
|
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. */
|
/* Forward declarations. */
|
||||||
extern initialize_file_ftype _initialize_hppa_linux_tdep;
|
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. */
|
/* Linux is always ELF. */
|
||||||
tdep->is_elf = 1;
|
tdep->is_elf = 1;
|
||||||
|
|
||||||
|
tdep->find_global_pointer = hppa_linux_find_global_pointer;
|
||||||
|
|
||||||
set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc);
|
set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc);
|
||||||
|
|
||||||
frame_unwind_append_sniffer (gdbarch, hppa_linux_sigtramp_unwind_sniffer);
|
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,
|
/* Two passes. First pass computes the location of everything,
|
||||||
second pass writes the bytes out. */
|
second pass writes the bytes out. */
|
||||||
int write_pass;
|
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++)
|
for (write_pass = 0; write_pass < 2; write_pass++)
|
||||||
{
|
{
|
||||||
CORE_ADDR struct_ptr = 0;
|
CORE_ADDR struct_ptr = 0;
|
||||||
@ -847,6 +853,11 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||||||
if (struct_return)
|
if (struct_return)
|
||||||
write_register (28, struct_addr);
|
write_register (28, struct_addr);
|
||||||
|
|
||||||
|
gp = tdep->find_global_pointer (function);
|
||||||
|
|
||||||
|
if (gp != 0)
|
||||||
|
write_register (19, gp);
|
||||||
|
|
||||||
/* Set the return address. */
|
/* Set the return address. */
|
||||||
regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
|
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;
|
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
|
static CORE_ADDR
|
||||||
hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR 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);
|
store_unsigned_integer (buf, sizeof(tmp), tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
hppa_find_global_pointer (struct value *function)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hppa_frame_prev_register_helper (struct frame_info *next_frame,
|
hppa_frame_prev_register_helper (struct frame_info *next_frame,
|
||||||
struct trad_frame_saved_reg saved_regs[],
|
struct trad_frame_saved_reg saved_regs[],
|
||||||
@ -2410,6 +2443,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
else
|
else
|
||||||
tdep->bytes_per_address = 4;
|
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
|
/* Some parts of the gdbarch vector depend on whether we are running
|
||||||
on a 32 bits or 64 bits target. */
|
on a 32 bits or 64 bits target. */
|
||||||
switch (tdep->bytes_per_address)
|
switch (tdep->bytes_per_address)
|
||||||
@ -2469,6 +2504,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
case 4:
|
case 4:
|
||||||
set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
|
set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
|
||||||
set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
|
set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
|
||||||
|
set_gdbarch_convert_from_func_ptr_addr
|
||||||
|
(gdbarch, hppa32_convert_from_func_ptr_addr);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
|
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
|
/* Is this an ELF target? This can be 64-bit HP-UX, or a 32/64-bit GNU/Linux
|
||||||
system. */
|
system. */
|
||||||
int is_elf;
|
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 *);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user