[SCM] master: Add new libunwind get_unwind_table interface.

mark@sourceware.org mark@sourceware.org
Tue Dec 11 14:35:00 GMT 2007


The branch, master has been updated
       via  2579d604e2b8ce0bc583e872642ecdfefb957cfa (commit)
      from  5f078697788883be959202a9643d29430587e182 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 2579d604e2b8ce0bc583e872642ecdfefb957cfa
Author: Mark Wielaard <mwielaard@redhat.com>
Date:   Tue Dec 11 15:35:01 2007 +0100

    Add new libunwind get_unwind_table interface.
    
    frysk-imports/libunwind/ChangeLog
    2007-12-11  Mark Wielaard  <mwielaard@redhat.com>
    
            * include/libunwind-common.h.in (unw_get_unwind_table): Add
            unw_accessor_t, remove elf image arguments.
            * src/mi/Gget_unwind_table.c (unw_get_unwind_table): Likewise.
            Rewrite to use unw_accessor_t for reading all data.
    
    frysk-sys/lib/unwind/ChangeLog
    2007-12-11  Mark Wielaard  <mwielaard@redhat.com>
    
            * ElfImage.java (name): New field.
            (ElfImage): Set name.
            (toString): Add name.
            * cni/ElfImage.cxx (mapElfImage): Pass in name.
            * cni/UnwindH.hxx (access_mem): Handle memory holes.
            (get_eh_frame_hdr_addr): New static function.
            (local_access_mem): Likewise.
            (createProcInfoFromElfImage): Use get_eh_frame_hdr_addr and
            local_access_mem.
            (createElfImageFromVDSO): Set name to [vdso].

-----------------------------------------------------------------------

Summary of changes:
 frysk-imports/libunwind/ChangeLog                  |    7 +
 .../libunwind/include/libunwind-common.h.in        |    8 +-
 frysk-imports/libunwind/src/mi/Gget_unwind_table.c |  229 ++++++--------------
 frysk-sys/lib/unwind/ChangeLog                     |   13 ++
 frysk-sys/lib/unwind/ElfImage.java                 |    8 +-
 frysk-sys/lib/unwind/cni/ElfImage.cxx              |    2 +-
 frysk-sys/lib/unwind/cni/UnwindH.hxx               |  194 +++++++++++++++--
 7 files changed, 273 insertions(+), 188 deletions(-)

First 500 lines of diff:
diff --git a/frysk-imports/libunwind/ChangeLog b/frysk-imports/libunwind/ChangeLog
index f7af421..3e02b0d 100644
--- a/frysk-imports/libunwind/ChangeLog
+++ b/frysk-imports/libunwind/ChangeLog
@@ -1,3 +1,10 @@
+2007-12-11  Mark Wielaard  <mwielaard@redhat.com>
+
+	* include/libunwind-common.h.in (unw_get_unwind_table): Add
+	unw_accessor_t, remove elf image arguments.
+	* src/mi/Gget_unwind_table.c (unw_get_unwind_table): Likewise.
+	Rewrite to use unw_accessor_t for reading all data.
+	
 2007-11-28  Mark Wielaard  <mwielaard@redhat.com>
 
 	* src/mi/Gget_unwind_table.c (unw_get_unwind_table): Make addr a
diff --git a/frysk-imports/libunwind/include/libunwind-common.h.in b/frysk-imports/libunwind/include/libunwind-common.h.in
index 497a7b4..a837055 100644
--- a/frysk-imports/libunwind/include/libunwind-common.h.in
+++ b/frysk-imports/libunwind/include/libunwind-common.h.in
@@ -252,8 +252,10 @@ extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
 extern const char *unw_strerror (int);
 extern int unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, 
 				unw_proc_info_t *pi, int need_unwind_info,
-				void *image, size_t size, 
-				unsigned long segbase, unsigned long mapoff,
-				void *arg);
+				void *arg,
+				unw_accessors_t *eh_frame_accessors,
+				unw_word_t eh_frame_hdr_address,
+				void *eh_frame_arg,
+				unw_word_t peh_vaddr);
 
 extern unw_addr_space_t unw_local_addr_space;
diff --git a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
index 2acb947..1d905b6 100644
--- a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
+++ b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
@@ -22,177 +22,72 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
-//#include "remote.h"
+#include "dwarf_i.h"
 #include "dwarf-eh.h"
 
 int
-unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
-			int need_unwind_info, void *image, size_t size, 
-			unsigned long segbase, unsigned long mapoff, void *arg)
+unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip,
+		     unw_proc_info_t *pi, int need_unwind_info, void *arg,
+		     unw_accessors_t *eh_frame_accessors,
+		     unw_word_t eh_frame_hdr_address,
+		     void *eh_frame_arg,
+		     unw_word_t peh_vaddr)
 {
-	Debug(99, "Entering get_unwind_table\n");
-	Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
-	unw_word_t eh_frame_start, fde_count, load_base;
-	char *addr;
-	struct dwarf_eh_frame_hdr *hdr;	
-	Elf_W(Ehdr) *ehdr;
-	int i, ret;
-	unw_dyn_info_t di_cache;
-	
-	 if (size <= EI_CLASS)
-    		return -1;
-
-	Debug(99, "Checking elf size\n");
- 	if (!(memcmp (image, ELFMAG, SELFMAG) == 0
-	  && ((uint8_t *) image)[EI_CLASS] == ELF_CLASS))
-	  	return -1;
-    		
-    	Debug(99, "Checked elf class\n");
-    	ehdr = image;
-	phdr = (Elf_W(Phdr) *) ((char *) image + ehdr->e_phoff);
-	for (i = 0; i < ehdr->e_phnum; ++i)
-    {
-      switch (phdr[i].p_type)
-	{
-	case PT_LOAD:
-	  if (phdr[i].p_offset == mapoff)
-	    ptxt = phdr + i;
-	  break;
-
-	case PT_GNU_EH_FRAME:
-	  peh_hdr = phdr + i;
-	  break;
-
-	case PT_DYNAMIC:
-	  pdyn = phdr + i;
-	  break;
-
-	default:
-	  break;
-	}
-    }
-    
-    	Debug(99, "Traversed headers\n");
-	if (!ptxt || !peh_hdr)
-    		return -UNW_ENOINFO;
-    		    
-    	if (pdyn)
-    {
-    	Debug(99, "Got dynamic header\n");
-      /* For dynamicly linked executables and shared libraries,
-	 DT_PLTGOT is the value that data-relative addresses are
-	 relative to for that object.  We call this the "gp".  */
-	    Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset
-					     + (char *) image);
-      for (; dyn->d_tag != DT_NULL; ++dyn)
-	if (dyn->d_tag == DT_PLTGOT)
-	  {
-	    /* Assume that _DYNAMIC is writable and GLIBC has
-	       relocated it (true for x86 at least).  */
-	    di_cache.gp = dyn->d_un.d_ptr;
-	    break;
-	  }
-    }
-     else
-    /* Otherwise this is a static executable with no _DYNAMIC.  Assume
-       that data-relative addresses are relative to 0, i.e.,
-       absolute.  */
-    	di_cache.gp = 0;
-    	
-    	Debug(99, "Got eh_frame_hdr\n");
-    	 hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset
-				       + (char *) image);
-  if (hdr->version != DW_EH_VERSION)
-    {
-      Debug (1, "table has unexpected version %d\n",
-	    hdr->version);
-      return 0;
-    }
-
-	Debug(99, "EH_VERSION is correct\n");
-
-  addr = hdr + 1;
-  Debug (99, "Got addr\n");
-  /* Fill in a dummy proc_info structure.  We just need to fill in
-     enough to ensure that dwarf_read_encoded_pointer() can do it's
-     job.  Since we don't have a procedure-context at this point, all
-     we have to do is fill in the global-pointer.  */
-  memset (pi, 0, sizeof (*pi));  
-  Debug(99, "cleared pi\n");
-  pi->gp = di_cache.gp;
-
-  Debug(99, "set pi gp\n");
-
-// The following is a local address space memory accessor used by
-// dwarf_read_encoded_pointer.  The arg pointer is the base address,
-// addr is the offset from the base address.
-  int 
-  local_access_mem (unw_addr_space_t as, unw_word_t addr,
-		    unw_word_t *val, int write, void *arg) 
-  {
-    Debug(99, "entering local_access_mem, reading addr: 0x%lx into: %p\n", 
-	  (long) addr, val);
-    if (write)
-      {
-	// Writing is not supported
-	return -UNW_EINVAL;
-      }
-    else
-      {
-	*val = *(unw_word_t *) (addr + (char *) arg);
-	Debug (16, "mem[%x] -> %x\n", (addr + (char *) arg), *val);
-      }
-    Debug(99, "leaving local_access_mem\n");
-    return 0;
-  }
-  
-  unw_accessors_t local_accessors = {NULL, NULL, NULL, local_access_mem, 
-				     NULL, NULL, NULL, NULL, NULL};
-  unw_addr_space_t local_addr_space
-    = unw_create_addr_space(&local_accessors, 0);
-
-  unw_word_t start = 0;
+  int ret;
+  unw_word_t start = eh_frame_hdr_address;
+
+  // Version
+  unsigned char version;
+  if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start,
+			   &version, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
+
+  if (version != DW_EH_VERSION)
+    return -UNW_ENOINFO;
+
+  unsigned char eh_frame_ptr_enc;
+  if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start,
+			   &eh_frame_ptr_enc, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
+
+  unsigned char fde_count_enc;
+  if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start,
+			   &fde_count_enc, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
+
+  unsigned char table_enc;
+  if ((ret = dwarf_readu8 (as, eh_frame_accessors, &start,
+			   &table_enc, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
   	
-   /* (Optionally) read eh_frame_ptr: */
-  if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors,
-					 &start, hdr->eh_frame_ptr_enc, pi,
-					 &eh_frame_start, addr)) < 0)
-    return -1;
-    
-  Debug(99, "read eh_frame_start: 0x%lx\n", (long) eh_frame_start);
-
-  /* (Optionally) read fde_count: */
-  if ((ret = dwarf_read_encoded_pointer (local_addr_space, &local_accessors,
-					 &start, hdr->fde_count_enc, pi,
-					 &fde_count, addr)) < 0)
-    return -1;
-
-  Debug(99, "read fde_count: 0x%lx\n", (long) fde_count);
-  if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
-    {
-      return -1;
-    }
+  if (table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+    return -UNW_ENOINFO;
+
+  unw_word_t eh_frame_start;
+  if ((ret = dwarf_read_encoded_pointer (as, eh_frame_accessors,
+					 &start, eh_frame_ptr_enc, pi,
+					 &eh_frame_start, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
     
-  addr += start;
-
-  load_base = segbase - ptxt->p_vaddr;
-
-  di_cache.start_ip = segbase;
-  di_cache.end_ip = di_cache.start_ip + ptxt->p_memsz;
-  di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE;
-  di_cache.u.rti.name_ptr = 0;
-  /* two 32-bit values (ip_offset/fde_offset) per table-entry: */
-  di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
-  di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
-				   + (addr - (unw_word_t) image
-				      - peh_hdr->p_offset));
-
-  /* For the binary-search table in the eh_frame_hdr, data-relative
-     means relative to the start of that section... */
-  di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
-				+ ((unw_word_t) hdr - (unw_word_t) image
-				   - peh_hdr->p_offset));
-
-	Debug(99, "Leaving get_unwind_table\n");
-  return tdep_search_unwind_table (as, ip, &di_cache, pi, need_unwind_info, arg);
+  unw_word_t fde_count;
+  if ((ret = dwarf_read_encoded_pointer (as, eh_frame_accessors,
+					 &start, fde_count_enc, pi,
+					 &fde_count, eh_frame_arg)) < 0)
+    return -UNW_ENOINFO;
+
+  unw_dyn_info_t di;
+  di.start_ip = pi->start_ip;
+  di.end_ip = pi->end_ip;
+  di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
+  di.gp = pi->gp;
+  di.u.rti.name_ptr = 0;
+  /* two 32-bit values (ip_offset/fde_offset) per table-entry:
+     For the binary-search table in the eh_frame_hdr, data-relative
+     means relative to the start of that section...
+     So for now we pass in peh_vaddr and use the main as for access. */
+  di.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
+  di.u.rti.table_data = peh_vaddr + 12;
+  di.u.rti.segbase = peh_vaddr;
+
+  return tdep_search_unwind_table (as, ip, &di, pi, need_unwind_info, arg);
 }
diff --git a/frysk-sys/lib/unwind/ChangeLog b/frysk-sys/lib/unwind/ChangeLog
index 1078b4a..933bca8 100644
--- a/frysk-sys/lib/unwind/ChangeLog
+++ b/frysk-sys/lib/unwind/ChangeLog
@@ -1,3 +1,16 @@
+2007-12-11  Mark Wielaard  <mwielaard@redhat.com>
+
+	* ElfImage.java (name): New field.
+	(ElfImage): Set name.
+	(toString): Add name.
+	* cni/ElfImage.cxx (mapElfImage): Pass in name.
+	* cni/UnwindH.hxx (access_mem): Handle memory holes.
+	(get_eh_frame_hdr_addr): New static function.
+	(local_access_mem): Likewise.
+	(createProcInfoFromElfImage): Use get_eh_frame_hdr_addr and
+	local_access_mem.
+	(createElfImageFromVDSO): Set name to [vdso].
+	
 2007-12-10  Andrew Cagney  <cagney@redhat.com>
 
 	* cni/UnwindH.hxx (access_fpreg): Allocate a buffer big enough for
diff --git a/frysk-sys/lib/unwind/ElfImage.java b/frysk-sys/lib/unwind/ElfImage.java
index 7707f09..e938c96 100644
--- a/frysk-sys/lib/unwind/ElfImage.java
+++ b/frysk-sys/lib/unwind/ElfImage.java
@@ -43,6 +43,8 @@ package lib.unwind;
 public class ElfImage
 {
 
+  final String name;
+
   long elfImage;
 
   long size;
@@ -53,8 +55,9 @@ public class ElfImage
 
   int ret = 0;
   
-  public ElfImage (long elfImage, long size, long segbase, long mapoff)
+  public ElfImage (String name, long elfImage, long size, long segbase, long mapoff)
   {
+    this.name = name;
     this.elfImage = elfImage;
     this.size = size;
     this.segbase = segbase;
@@ -63,6 +66,7 @@ public class ElfImage
 
   public ElfImage (int ret)
   {
+    this.name = "ERROR: " + Integer.toString(ret);
     this.ret = ret;
   }
 
@@ -71,7 +75,7 @@ public class ElfImage
     if (ret != 0)
       return "Bad Elf Image, ret: " + ret;
 
-    return "Elf Image: 0x" + Long.toHexString(elfImage) + " size: " + size
+    return "Elf Image (" + name + "): 0x" + Long.toHexString(elfImage) + " size: " + size
 	   + " segbase: 0x" + Long.toHexString(segbase) + " mapoff: 0x"
 	   + Long.toHexString(mapoff);
   }
diff --git a/frysk-sys/lib/unwind/cni/ElfImage.cxx b/frysk-sys/lib/unwind/cni/ElfImage.cxx
index d521643..3f7fdd3 100644
--- a/frysk-sys/lib/unwind/cni/ElfImage.cxx
+++ b/frysk-sys/lib/unwind/cni/ElfImage.cxx
@@ -80,7 +80,7 @@ lib::unwind::ElfImage::mapElfImage(jstring elfImageName, jlong segbase, jlong hi
     return new lib::unwind::ElfImage((jint) -1);
 
   lib::unwind::ElfImage* elfImage
-  = new lib::unwind::ElfImage((jlong) image, (jlong) size,
+    = new lib::unwind::ElfImage(elfImageName, (jlong) image, (jlong) size,
                               (jlong) segbase, (jlong) mapoff);
 
   return elfImage;
diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx
index 1d13156..e1cc430 100644
--- a/frysk-sys/lib/unwind/cni/UnwindH.hxx
+++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx
@@ -47,7 +47,9 @@
 
 #include <libdwfl.h>
 #include LIBUNWIND_TARGET_H
-#include <dwarf.h>
+
+#include <libelf.h>
+#include <gelf.h>
 
 #include <gcj/cni.h>
 
@@ -135,11 +137,22 @@ static int
 access_mem (::unw_addr_space_t as, ::unw_word_t addr,
 	    ::unw_word_t *valp, int write, void *arg)
 {
-  jbyteArray tmp = JvNewByteArray (sizeof (unw_word_t));
-  memcpy (elements(tmp), valp, JvGetArrayLength(tmp));
-  int ret = addressSpace(arg)->accessMem((jlong) addr, tmp, (jboolean) write);
-  memcpy(valp, elements(tmp), JvGetArrayLength(tmp));
-  return ret;
+  try
+    {
+      jbyteArray tmp = JvNewByteArray (sizeof (unw_word_t));
+      memcpy (elements(tmp), valp, JvGetArrayLength(tmp));
+      int ret = addressSpace(arg)->accessMem((jlong) addr,
+					     tmp, (jboolean) write);
+      memcpy(valp, elements(tmp), JvGetArrayLength(tmp));
+      return ret;
+    }
+  catch (java::lang::RuntimeException *t)
+    {
+      // We have to catch all RuntimeExceptions here since there
+      // is no indicator for just "invalid memory location".
+      // Core files might have "holes" in their memory.
+      return -UNW_EINVAL;
+    }
 }
 
 /*
@@ -429,26 +442,177 @@ lib::unwind::TARGET::getProcInfo(gnu::gcj::RawDataManaged* cursor)
   return myInfo;
 }
 
+// Return NULL when eh_frame_hdr cannot be found.
+// Also fills in ip->start_ip, ip->end_ip and ip->gp.
+// peh_vaddr will point to the address of the eh_frame_hdr in the main
+// address space of the inferior.
+static void *
+get_eh_frame_hdr_addr(unw_proc_info_t *pi, char *image, size_t size,
+		      unsigned long segbase, unw_word_t *peh_vaddr)
+{
+  if (elf_version(EV_CURRENT) == EV_NONE)
+    return NULL;
+
+  Elf *elf = elf_memory(image, size);
+  if (elf == NULL)
+    return NULL;
+
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr(elf, &ehdr) == NULL)
+    return NULL;
+  
+  GElf_Phdr phdr;
+  int ptxt_ndx = -1, peh_hdr_ndx = -1, pdyn_ndx = -1;
+  for (int i = 0; i < ehdr.e_phnum; i++)
+    {
+      if (gelf_getphdr (elf, i, &phdr) == NULL)
+	return NULL;
+      
+      switch (phdr.p_type)
+        {
+        case PT_LOAD:
+          if (phdr.p_vaddr == segbase)
+            ptxt_ndx = i;
+          break;
+	  
+        case PT_GNU_EH_FRAME:
+          peh_hdr_ndx = i;
+          break;
+	  
+        case PT_DYNAMIC:
+          pdyn_ndx = i;
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  if (ptxt_ndx == -1 || peh_hdr_ndx == -1)
+    return NULL;
+
+  GElf_Phdr ptxt, peh_hdr;
+  if (gelf_getphdr (elf, ptxt_ndx, &ptxt) == NULL)
+    return NULL;
+
+  if (gelf_getphdr (elf, peh_hdr_ndx, &peh_hdr) == NULL)
+    return NULL;
+
+  if (pdyn_ndx != -1)
+    {
+      /* For dynamicly linked executables and shared libraries,
+	 DT_PLTGOT is the value that data-relative addresses are
+	 relative to for that object.  We call this the "gp". */
+      GElf_Phdr pdyn;
+      if (gelf_getphdr (elf, pdyn_ndx, &pdyn) == NULL)
+	return NULL;
+
+      Elf_Scn *pdyn_scn = gelf_offscn(elf, pdyn.p_offset);
+      if (pdyn_scn == NULL)
+	return NULL;
+
+      Elf_Data *pdyn_data;
+      pdyn_data = elf_getdata (pdyn_scn, NULL);
+      if (pdyn_data == NULL)
+	return NULL;
+
+      GElf_Shdr pdyn_shdr;
+      if (gelf_getshdr (pdyn_scn, &pdyn_shdr) == NULL)
+	return NULL;
+
+      for (unsigned int i = 0;
+	   i < pdyn_shdr.sh_size / pdyn_shdr.sh_entsize; i++)
+	{
+	  GElf_Dyn dyn;
+	  if (gelf_getdyn (pdyn_data, i, &dyn) == NULL)
+	    return NULL;
+
+	  if (dyn.d_tag == DT_PLTGOT)
+	    {
+	      /* Assume that _DYNAMIC is writable and GLIBC has
+		 relocated it (true for x86 at least). */
+	      pi->gp = dyn.d_un.d_ptr;
+	      break;
+	    }
+	}
+    }
+  else
+    /* Otherwise this is a static executable with no _DYNAMIC.  Assume
+       that data-relative addresses are relative to 0, i.e.,
+       absolute. */
+    pi->gp = 0;
+
+  pi->start_ip = segbase;


hooks/post-receive
--
frysk system monitor/debugger



More information about the Frysk-cvs mailing list