This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch/rfa] hppa-linux target, 2nd try


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]