This is the mail archive of the frysk-cvs@sources.redhat.com mailing list for the frysk 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]

[SCM] master: Add debug_frame parsing.


The branch, master has been updated
       via  00b9fa35668c84c9899076d86c7e3a2ff7c6347e (commit)
      from  882c8ebdcc825139e58e50982810a0f00f1a229b (commit)

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

- Log -----------------------------------------------------------------
commit 00b9fa35668c84c9899076d86c7e3a2ff7c6347e
Author: Mark Wielaard <mwielaard@redhat.com>
Date:   Thu Jan 17 12:02:50 2008 +0100

    Add debug_frame parsing.
    
    frysk-imports/libunwind/ChangeLog
    2008-01-17  Mark Wielaard  <mwielaard@redhat.com>
    
        * include/dwarf.h (dwarf_extract_proc_info_from_fde): Pass
        table_start.
        * src/dwarf/Gfde.c (is_cie_id): Removed.
        (parse_cie): Accept debug and eh cie ids.
        (dwarf_extract_proc_info_from_fde): Accept table_start. Calculate
        correct cie_addr. Fix error reporting.
        * src/dwarf/Gfind_proc_info-lsb.c (linear_search): Don't depend
        on local address space. Pass table start for fde parsing.
        (dwarf_search_unwind_table): Handle debug_frame by linear search.
        * src/mi/Gget_unwind_table.c (get_frame_table, get_debug_table):
        new functions.
        (unw_get_unwind_table): Call either get_frame_table or
        get_debug_table depending on format.
    
    frysk-sys/lib/unwind/ChangeLog
    2008-01-17  Mark Wielaard  <mwielaard@redhat.com>
    
        * cni/UnwindH.hxx (get_eh_frame_hdr_addr): Find and return
        debug_frame address and set pi->format.
        (createProcInfoFromElfImage): Handle either debug_frame or
        eh_frame addresses.

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

Summary of changes:
 frysk-imports/libunwind/ChangeLog                  |   16 +++++
 frysk-imports/libunwind/include/dwarf.h            |    1 +
 frysk-imports/libunwind/src/dwarf/Gfde.c           |   47 ++++++++-----
 .../libunwind/src/dwarf/Gfind_proc_info-lsb.c      |   25 ++++++-
 frysk-imports/libunwind/src/mi/Gget_unwind_table.c |   58 +++++++++++++++--
 frysk-sys/lib/unwind/ChangeLog                     |    7 ++
 frysk-sys/lib/unwind/cni/UnwindH.hxx               |   69 ++++++++++++++++---
 7 files changed, 184 insertions(+), 39 deletions(-)

First 500 lines of diff:
diff --git a/frysk-imports/libunwind/ChangeLog b/frysk-imports/libunwind/ChangeLog
index 184c9e5..44d3d68 100644
--- a/frysk-imports/libunwind/ChangeLog
+++ b/frysk-imports/libunwind/ChangeLog
@@ -1,3 +1,19 @@
+2008-01-17  Mark Wielaard  <mwielaard@redhat.com>
+
+	* include/dwarf.h (dwarf_extract_proc_info_from_fde): Pass
+	table_start.
+	* src/dwarf/Gfde.c (is_cie_id): Removed.
+	(parse_cie): Accept debug and eh cie ids.
+	(dwarf_extract_proc_info_from_fde): Accept table_start. Calculate
+	correct cie_addr. Fix error reporting.
+	* src/dwarf/Gfind_proc_info-lsb.c (linear_search): Don't depend
+	on local address space. Pass table start for fde parsing.
+	(dwarf_search_unwind_table): Handle debug_frame by linear search.
+	* src/mi/Gget_unwind_table.c (get_frame_table, get_debug_table):
+	new functions.
+	(unw_get_unwind_table): Call either get_frame_table or
+	get_debug_table depending on format.
+	
 2007-12-22  Mark Wielaard  <mwielaard@redhat.com>
 
 	* include/libunwind-common.h.in (unw_get_unwind_table):
diff --git a/frysk-imports/libunwind/include/dwarf.h b/frysk-imports/libunwind/include/dwarf.h
index 47896f6..cf8a74a 100644
--- a/frysk-imports/libunwind/include/dwarf.h
+++ b/frysk-imports/libunwind/include/dwarf.h
@@ -362,6 +362,7 @@ extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr,
 			    int *is_register);
 extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as,
 					     unw_accessors_t *a,
+					     unw_word_t table_start,
 					     unw_word_t *fde_addr,
 					     unw_proc_info_t *pi,
 					     int need_unwind_info,
diff --git a/frysk-imports/libunwind/src/dwarf/Gfde.c b/frysk-imports/libunwind/src/dwarf/Gfde.c
index 11a6433..de2b193 100644
--- a/frysk-imports/libunwind/src/dwarf/Gfde.c
+++ b/frysk-imports/libunwind/src/dwarf/Gfde.c
@@ -1,6 +1,8 @@
 /* libunwind - a platform-independent unwind library
    Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
 	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+   Copyright (c) 2008 Red Hat, Inc.
+	Contributed by Mark Wielaard <mwielaard@redhat.com>
 
 This file is part of libunwind.
 
@@ -25,15 +27,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "dwarf_i.h"
 
-static inline int
-is_cie_id (unw_word_t val)
-{
-  /* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
-     0xffffffffffffffff (for 64-bit ELF).  However, the GNU toolchain
-     uses 0.  */
-  return (val == 0 || val == - (unw_word_t) 1);
-}
-
 /* Note: we don't need to keep track of more than the first four
    characters of the augmentation string, because we (a) ignore any
    augmentation string contents once we find an unrecognized character
@@ -80,7 +73,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
       if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
 	return ret;
       /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
-      if (cie_id != 0)
+      if (cie_id != 0 && cie_id != 0xffffffff)
 	{
 	  Debug (1, "Unexpected CIE id %x\n", cie_id);
 	  return -UNW_EINVAL;
@@ -99,7 +92,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
 	return ret;
       /* DWARF says CIE id should be 0xffffffffffffffff, but in
 	 .eh_frame, it's 0 */
-      if (cie_id != 0)
+      if (cie_id != 0 && cie_id != 0xffffffffffffffff)
 	{
 	  Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id);
 	  return -UNW_EINVAL;
@@ -217,7 +210,8 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
 
 HIDDEN int
 dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
-				  unw_word_t *addrp, unw_proc_info_t *pi,
+				  unw_word_t table_start, unw_word_t *addrp,
+				  unw_proc_info_t *pi,
 				  int need_unwind_info,
 				  void *arg)
 {
@@ -252,7 +246,12 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
       if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
 	return ret;
 
-      if (is_cie_id (cie_offset))
+      /* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
+	 0xffffffffffffffff (for 64-bit ELF).  However, the GNU toolchain
+	 uses 0.  */
+      if ((pi->format != UNW_INFO_FORMAT_TABLE && cie_offset == 0)
+	  || (pi->format == UNW_INFO_FORMAT_TABLE
+	      && cie_offset == 0xffffffff))
 	/* ignore CIEs (happens during linear searches) */
 	return 0;
 
@@ -260,7 +259,10 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
 	 .debug_frame-relative offset, but the GCC-generated .eh_frame
 	 sections instead store a "pcrelative" offset, which is just
 	 as fine as it's self-contained.  */
-      cie_addr = cie_offset_addr - cie_offset;
+      if (pi->format == UNW_INFO_FORMAT_TABLE)
+	cie_addr = table_start + cie_offset;
+      else
+	cie_addr = cie_offset_addr - cie_offset;
     }
   else
     {
@@ -277,7 +279,12 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
       if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
 	return ret;
 
-      if (is_cie_id (cie_offset))
+      /* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
+	 0xffffffffffffffff (for 64-bit ELF).  However, the GNU toolchain
+	 uses 0.  */
+      if ((pi->format != UNW_INFO_FORMAT_TABLE && cie_offset == 0)
+          || (pi->format == UNW_INFO_FORMAT_TABLE
+              && cie_offset == 0xffffffffffffffff))
 	/* ignore CIEs (happens during linear searches) */
 	return 0;
 
@@ -285,7 +292,10 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
 	 .debug_frame-relative offset, but the GCC-generated .eh_frame
 	 sections instead store a "pcrelative" offset, which is just
 	 as fine as it's self-contained.  */
-      cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
+      if (pi->format == UNW_INFO_FORMAT_TABLE)
+	cie_addr = (unw_word_t) ((uint64_t) table_start + cie_offset);
+      else
+	cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
     }
 
   if ((ret = parse_cie (as, a, cie_addr, pi, &dci, arg)) < 0)
@@ -320,11 +330,12 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
 
   if (need_unwind_info)
     {
-      pi->format = UNW_INFO_FORMAT_TABLE;
+      // FRYSK LOCAL - we already set this.
+      // pi->format = UNW_INFO_FORMAT_TABLE;
       pi->unwind_info_size = sizeof (dci);
       pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool);
       if (!pi->unwind_info)
-	return UNW_ENOMEM;
+	return -UNW_ENOMEM;
 
       if (dci.have_abi_marker)
 	{
diff --git a/frysk-imports/libunwind/src/dwarf/Gfind_proc_info-lsb.c b/frysk-imports/libunwind/src/dwarf/Gfind_proc_info-lsb.c
index a8a3b69..be22e3e 100644
--- a/frysk-imports/libunwind/src/dwarf/Gfind_proc_info-lsb.c
+++ b/frysk-imports/libunwind/src/dwarf/Gfind_proc_info-lsb.c
@@ -1,6 +1,8 @@
 /* libunwind - a platform-independent unwind library
    Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
 	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+   Copyright (c) 2008, Red Hat, Inc.
+	Contributed by Mark Wielaard <mwielaard@redhat.com>
 
 This file is part of libunwind.
 
@@ -52,20 +54,23 @@ struct callback_data
     unw_dyn_info_t di;		/* table info (if single_fde is false) */
   };
 
+#endif /* !UNW_REMOTE_ONLY */
+
 static int
 linear_search (unw_addr_space_t as, unw_word_t ip,
 	       unw_word_t eh_frame_start, unw_word_t eh_frame_end,
 	       unw_word_t fde_count,
 	       unw_proc_info_t *pi, int need_unwind_info, void *arg)
 {
-  unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
+  unw_accessors_t *a = unw_get_accessors (as);
   unw_word_t i = 0, fde_addr, addr = eh_frame_start;
   int ret;
 
   while (i++ < fde_count && addr < eh_frame_end)
     {
       fde_addr = addr;
-      if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, arg))
+      if ((ret = dwarf_extract_proc_info_from_fde (as, a, eh_frame_start,
+						   &addr, pi, 0, arg))
 	  < 0)
 	return ret;
 
@@ -74,7 +79,8 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
 	  if (!need_unwind_info)
 	    return 1;
 	  addr = fde_addr;
-	  if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
+	  if ((ret = dwarf_extract_proc_info_from_fde (as, a, eh_frame_start,
+						       &addr, pi,
 						       need_unwind_info, arg))
 	      < 0)
 	    return ret;
@@ -84,6 +90,8 @@ linear_search (unw_addr_space_t as, unw_word_t ip,
   return -UNW_ENOINFO;
 }
 
+#ifndef UNW_REMOTE_ONLY
+
 /* Info is a pointer to a unw_dyn_info_t structure and, on entry,
    member u.rti.segbase contains the instruction-pointer we're looking
    for.  */
@@ -361,6 +369,15 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
 #endif
   int ret;
 
+  if (di->format == UNW_INFO_FORMAT_TABLE)
+    {
+      ret = linear_search (as, ip, di->u.rti.table_data,
+			   di->u.rti.table_data
+			   + di->u.rti.table_len * sizeof (unw_word_t),
+			   ~0UL, pi, need_unwind_info, arg);
+      return ret;
+    }
+
   assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
 	  && (ip >= di->start_ip && ip < di->end_ip));
 
@@ -397,7 +414,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
   Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
 	 (long) ip, (long) (e->start_ip_offset + segbase));
   fde_addr = e->fde_offset + segbase;
-  if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
+  if ((ret = dwarf_extract_proc_info_from_fde (as, a, segbase, &fde_addr, pi,
 					       need_unwind_info, arg)) < 0)
     return ret;
 
diff --git a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
index fc46269..0223013 100644
--- a/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
+++ b/frysk-imports/libunwind/src/mi/Gget_unwind_table.c
@@ -1,4 +1,4 @@
-// Copyright 2007, Red Hat Inc.
+// Copyright 2007, 2008, Red Hat Inc.
 
 /* This file is part of libunwind.
 
@@ -25,11 +25,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "dwarf_i.h"
 #include "dwarf-eh.h"
 
-int
-unw_get_unwind_table(unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info,
-		     unw_accessors_t *eh_frame_accessors,
-		     unw_word_t eh_frame_hdr_address,
-		     void *eh_frame_arg)
+#include <stdio.h>
+
+static int
+get_frame_table(unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info,
+		unw_accessors_t *eh_frame_accessors,
+		unw_word_t eh_frame_hdr_address,
+		void *eh_frame_arg)
 {
   int ret;
   unw_addr_space_t as = unw_create_addr_space (eh_frame_accessors, 0);
@@ -87,7 +89,51 @@ unw_get_unwind_table(unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info,
   di.u.rti.table_data = eh_frame_hdr_address + 12;
   di.u.rti.segbase = eh_frame_hdr_address;
 
+  pi->start_ip = 0;
+  pi->end_ip = 0;
   ret = tdep_search_unwind_table (as, ip, &di, pi, need_unwind_info,
 				  eh_frame_arg);
   return ret;
 }
+
+static int
+get_debug_table(unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info,
+                unw_accessors_t *accessors,
+                unw_word_t address,
+                void *arg)
+{
+  unw_addr_space_t as = unw_create_addr_space (accessors, 0);
+
+  unw_dyn_info_t di;
+  di.start_ip = pi->start_ip;
+  di.end_ip = pi->end_ip;
+  di.format = UNW_INFO_FORMAT_TABLE;
+  di.gp = pi->gp;
+
+  // XXX Should we use the ti struct of the union?
+  di.u.rti.name_ptr = 0;
+  di.u.rti.segbase = address;
+  di.u.rti.table_data = address;
+  di.u.rti.table_len = pi->unwind_info_size;
+  
+  pi->start_ip = 0;
+  pi->end_ip = 0;
+  return tdep_search_unwind_table (as, ip, &di, pi, need_unwind_info, arg);
+}
+
+int
+unw_get_unwind_table(unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info,
+		     unw_accessors_t *accessors,
+		     unw_word_t address,
+		     void *arg)
+{
+  if (pi->format == UNW_INFO_FORMAT_TABLE)
+    return get_debug_table(ip, pi, need_unwind_info, accessors,
+			   address, arg);
+
+  if (pi->format == UNW_INFO_FORMAT_REMOTE_TABLE)
+    return get_frame_table(ip, pi, need_unwind_info, accessors,
+			   address, arg);
+
+  return -UNW_EINVAL;
+}
diff --git a/frysk-sys/lib/unwind/ChangeLog b/frysk-sys/lib/unwind/ChangeLog
index 28fa70b..4677847 100644
--- a/frysk-sys/lib/unwind/ChangeLog
+++ b/frysk-sys/lib/unwind/ChangeLog
@@ -1,3 +1,10 @@
+2008-01-17  Mark Wielaard  <mwielaard@redhat.com>
+
+	* cni/UnwindH.hxx (get_eh_frame_hdr_addr): Find and return
+	debug_frame address and set pi->format.
+	(createProcInfoFromElfImage): Handle either debug_frame or
+	eh_frame addresses.
+	
 2007-12-22  Mark Wielaard  <mwielaard@redhat.com>
 
 	* cni/UnwindH.hxx (get_eh_frame_hdr_addr): Return char*.
diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx
index e69e031..08c8ce1 100644
--- a/frysk-sys/lib/unwind/cni/UnwindH.hxx
+++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2007, Red Hat Inc.
+// Copyright 2007, 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -488,7 +488,26 @@ get_eh_frame_hdr_addr(unw_proc_info_t *pi, char *image, size_t size,
         }
     }
 
-  if (ptxt_ndx == -1 || peh_hdr_ndx == -1)
+  Elf_Data *debug_frame_data = NULL;
+  size_t shstrndx;
+  if (elf_getshstrndx (elf, &shstrndx) >= 0)
+    {
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL
+	     && debug_frame_data == NULL)
+	{
+	  GElf_Shdr shdr;
+	  if (gelf_getshdr (scn, &shdr) != NULL
+	      && shdr.sh_type == SHT_PROGBITS)
+	    {
+	      const char *name = elf_strptr (elf, shstrndx, shdr.sh_name);
+	      if (strcmp (name, ".debug_frame") == 0)
+		debug_frame_data = elf_getdata (scn, NULL);
+	    }
+	}
+    }
+
+  if (ptxt_ndx == -1 || (peh_hdr_ndx == -1 && debug_frame_data == NULL))
     return NULL;
 
   GElf_Phdr ptxt, peh_hdr;
@@ -547,7 +566,23 @@ get_eh_frame_hdr_addr(unw_proc_info_t *pi, char *image, size_t size,
 
   *peh_vaddr = peh_hdr.p_vaddr;
 
-  char *hdr = image + peh_hdr.p_offset;
+  char *hdr;
+  // FIXME. Currently we prefer eh_frame, but we should switch to
+  // prefer debug_frame when all bugs have been squashed out of that
+  // in libunwind.
+  if (peh_hdr_ndx == -1
+      && debug_frame_data != NULL && debug_frame_data->d_buf != NULL
+      && debug_frame_data->d_size != 0)
+    {
+      pi->format = UNW_INFO_FORMAT_TABLE;
+      pi->unwind_info_size = debug_frame_data->d_size / sizeof (unw_word_t);
+      hdr = (char *) debug_frame_data->d_buf;
+    }
+  else
+    {
+      pi->format = UNW_INFO_FORMAT_REMOTE_TABLE;
+      hdr = image + peh_hdr.p_offset;
+    }
   return hdr;
 }
 
@@ -600,14 +635,26 @@ lib::unwind::TARGET::createProcInfoFromElfImage(lib::unwind::AddressSpace* addre
   if (eh_table_hdr == NULL)
     return new lib::unwind::ProcInfo(-UNW_ENOINFO);
 
-  int ret = unw_get_unwind_table((unw_word_t) ip,
-				 procInfo,
-				 (int) needUnwindInfo,
-				 &local_accessors,
-				 // virtual address
-				 peh_vaddr,
-				 // address adjustment
-				 eh_table_hdr - peh_vaddr);
+  int ret;
+  if (procInfo->format == UNW_INFO_FORMAT_REMOTE_TABLE)
+    ret = unw_get_unwind_table((unw_word_t) ip,
+			       procInfo,
+			       (int) needUnwindInfo,
+			       &local_accessors,
+			       // virtual address
+			       peh_vaddr,
+			       // address adjustment
+			       eh_table_hdr - peh_vaddr);
+  else
+    ret = unw_get_unwind_table((unw_word_t) ip,
+                               procInfo,
+                               (int) needUnwindInfo,
+                               &local_accessors,
+                               // virtual address
+                               0,
+                               // address adjustment
+                               eh_table_hdr);
+  
   
   logFine(this, logger, "Post unw_get_unwind_table");
   lib::unwind::ProcInfo *myInfo;


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


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