This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [patch/rfa] hppa-linux target, 2nd try
- From: Randolph Chung <randolph at tausq dot org>
- To: Joel Brobecker <brobecker at gnat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Sat, 24 Apr 2004 23:08:15 -0700
- Subject: Re: [patch/rfa] hppa-linux target, 2nd try
- References: <20040424192614.GD2923@tausq.org> <20040425002520.GP2811@gnat.com>
- Reply-to: Randolph Chung <randolph at tausq dot org>
> I actually started looking at that about 10 days ago, but it is hard for
> me to figure out what is going wrong, because I don't know too well the
> machinery for calling functions inside shared libraries. And then I got
> pre-empted by something else.
>
> It's something that's on my reasonably-near-future list.
Something like this (derived from ia64) works for hppa-linux, but I have
no idea how to do this for som.
2004-04-24 Randolph Chung <tausq@debian.org>
* hppa-tdep.h (find_global_pointer): Add target-specific method
to find a gp given a function address.
(FIND_GLOBAL_POINTER): Convenience wrapper for find_global_pointer.
* hppa-tdep.c (hppa32_push_dummy_call): Try to fill in the gp
with the correct value when calling a function in a shared lib.
* hppa-linux-tdep.c (generic_elf_find_global_pointer): New function.
(hppa_linux_init_abi): Set find_global_pointer.
Index: hppa-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.h,v
retrieving revision 1.4
diff -u -p -r1.4 hppa-tdep.h
--- hppa-tdep.h 23 Apr 2004 02:54:21 -0000 1.4
+++ hppa-tdep.h 25 Apr 2004 06:01:42 -0000
@@ -33,7 +33,12 @@ 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;
+
+ CORE_ADDR (*find_global_pointer) (CORE_ADDR);
};
+
+#define FIND_GLOBAL_POINTER \
+ (gdbarch_tdep (current_gdbarch)->find_global_pointer)
/*
* Unwind table and descriptor.
Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.151
diff -u -p -r1.151 hppa-tdep.c
--- hppa-tdep.c 24 Apr 2004 06:13:32 -0000 1.151
+++ hppa-tdep.c 25 Apr 2004 06:01:37 -0000
@@ -856,7 +856,12 @@ hppa32_push_dummy_call (struct gdbarch *
if (struct_return)
write_register (28, struct_addr);
+ gp = FIND_GLOBAL_POINTER (func_addr);
+
+ if (gp != 0)
+ write_register (19, gp);
+
/* Set the return address. */
regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
/* Update the Stack Pointer. */
diff -u hppa-linux-tdep.c hppa-linux-tdep.c
--- hppa-linux-tdep.c 2004-04-24 11:39:03.211793064 -0700
+++ hppa-linux-tdep.c 2004-04-24 20:28:40.486912952 -0700
@@ -30,6 +30,8 @@
#include "dwarf2-frame.h"
#include "hppa-tdep.h"
+#include "elf/common.h"
+
#if 0
/* Convert DWARF register number REG to the appropriate register
number used by GDB. */
@@ -456,6 +458,71 @@
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
+generic_elf_find_global_pointer (CORE_ADDR faddr)
+{
+ struct obj_section *faddr_sect;
+
+ 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;
@@ -467,6 +534,8 @@
/* Linux is always ELF. */
tdep->is_elf = 1;
+ tdep->find_global_pointer = generic_elf_find_global_pointer;
+
set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc);
frame_unwind_append_sniffer (gdbarch, hppa_linux_sigtramp_unwind_sniffer);
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/