public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
* [patch] Add debug_frame parsing
@ 2008-01-17 11:12 Mark Wielaard
  2008-01-17 14:34 ` Andrew Cagney
  2008-01-20 15:08 ` Mark Wielaard
  0 siblings, 2 replies; 3+ messages in thread
From: Mark Wielaard @ 2008-01-17 11:12 UTC (permalink / raw)
  To: frysk

[-- Attachment #1: Type: text/plain, Size: 2020 bytes --]

Hi,

This patch widens out libunwind interface to accept either eh_frame or
debug_frame tables and adds support for parsing debug_frame data. It
currently does a linear search through the data to find the right fde
and corresponding cie by making the right adjustments. Although it does
find the right fde covering the ip ranges, it doesn't always run the cfi
program correctly. So for now the default is still the default and
debug_frame is only used as fallback when eh_frame data cannot be found
(that can be changed in a simple if statement, see the FIXME in UnwindH
- that will however give a couple of test failures). It also fixes a
couple of libunwind issues found when working on this (direct usage of
local memory space, error values not being negative and unw_word being
64bit != dwarf 64 format is always in use).

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.

Tested on x86_64 and x86 (fedora and centos, which both have full
eh_frame coverage, so admittedly most of the new code paths aren't hit
yet).

Cheers,

Mark

[-- Attachment #2: debug_frame.patch --]
[-- Type: text/x-patch, Size: 14394 bytes --]

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch] Add debug_frame parsing
  2008-01-17 11:12 [patch] Add debug_frame parsing Mark Wielaard
@ 2008-01-17 14:34 ` Andrew Cagney
  2008-01-20 15:08 ` Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Andrew Cagney @ 2008-01-17 14:34 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: frysk

Mark Wielaard wrote:
> Hi,
>
> This patch widens out libunwind interface to accept either eh_frame or
> debug_frame tables and adds support for parsing debug_frame data. It
> currently does a linear search through the data to find the right fde
> and corresponding cie by making the right adjustments. Although it does
> find the right fde covering the ip ranges, it doesn't always run the cfi
> program correctly. So for now the default is still the default and
> debug_frame is only used as fallback when eh_frame data cannot be found
> (that can be changed in a simple if statement, see the FIXME in UnwindH
> - that will however give a couple of test failures). It also fixes a
> couple of libunwind issues found when working on this (direct usage of
> local memory space, error values not being negative and unw_word being
> 64bit != dwarf 64 format is always in use).
>
>   
Nice work mark; this gets us to a much more reliable unwinder!

Andrew

> 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.
>
> Tested on x86_64 and x86 (fedora and centos, which both have full
> eh_frame coverage, so admittedly most of the new code paths aren't hit
> yet).
>
> Cheers,
>
> Mark
>   

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch] Add debug_frame parsing
  2008-01-17 11:12 [patch] Add debug_frame parsing Mark Wielaard
  2008-01-17 14:34 ` Andrew Cagney
@ 2008-01-20 15:08 ` Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Wielaard @ 2008-01-20 15:08 UTC (permalink / raw)
  To: frysk

[-- Attachment #1: Type: text/plain, Size: 1177 bytes --]

Hi,

On Thu, 2008-01-17 at 12:12 +0100, Mark Wielaard wrote:
> Although it does find the right fde covering the ip ranges, it doesn't
> always run the cfi program correctly.

Because it was using the wrong address space... duh.
So this small patch records and makes sure the right one is always used
(debug_frame lives in our, not in the inferior address space).

frysk-imports/libunwind/ChangeLog
2008-01-18  Mark Wielaard  <mwielaard@redhat.com>
    
       * include/dwarf.h (dwarf_cie_info): Add as and as_arg members.
       * src/dwarf/Gfde.c (dwarf_extract_proc_info_from_fde): Set dci
       as and as_arg when not local only.
       * src/dwarf/Gparser.c (run_cfi_program): Use dci as and as_arg
       when not local only.
    
frysk-sys/lib/unwind/ChangeLog
2008-01-18  Mark Wielaard  <mwielaard@redhat.com>
    
       * cni/UnwindH.hxx (get_eh_frame_hdr_addr): Prefer debug_frame.

The patch is small, but it does enable using debug_frame in preference
to eh_frame when found (but currently only in the main executable, a
follow up patch should make sure that libdwfl is always used to get at
the debug_frame). All tests now PASS with this enabled.

Cheers,

Mark

[-- Attachment #2: cfi_as.patch --]
[-- Type: text/x-patch, Size: 2533 bytes --]

diff --git a/frysk-imports/libunwind/include/dwarf.h b/frysk-imports/libunwind/include/dwarf.h
index cf8a74a..3a17c87 100644
--- a/frysk-imports/libunwind/include/dwarf.h
+++ b/frysk-imports/libunwind/include/dwarf.h
@@ -252,6 +252,10 @@ dwarf_reg_state_t;
 
 typedef struct dwarf_cie_info
   {
+#ifndef UNW_LOCAL_ONLY
+    unw_addr_space_t as;        /* reference to frame address-space */
+    void *as_arg;               /* argument to address-space callbacks */
+#endif
     unw_word_t cie_instr_start;	/* start addr. of CIE "initial_instructions" */
     unw_word_t cie_instr_end;	/* end addr. of CIE "initial_instructions" */
     unw_word_t fde_instr_start;	/* start addr. of FDE "instructions" */
diff --git a/frysk-imports/libunwind/src/dwarf/Gfde.c b/frysk-imports/libunwind/src/dwarf/Gfde.c
index de2b193..a9c36f4 100644
--- a/frysk-imports/libunwind/src/dwarf/Gfde.c
+++ b/frysk-imports/libunwind/src/dwarf/Gfde.c
@@ -351,7 +351,10 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
       else
 	dci.fde_instr_start = addr;
       dci.fde_instr_end = fde_end_addr;
-
+#ifndef UNW_LOCAL_ONLY
+      dci.as = as;
+      dci.as_arg = arg;
+#endif
       memcpy (pi->unwind_info, &dci, sizeof (dci));
     }
   return 0;
diff --git a/frysk-imports/libunwind/src/dwarf/Gparser.c b/frysk-imports/libunwind/src/dwarf/Gparser.c
index ada82d9..441cf9b 100644
--- a/frysk-imports/libunwind/src/dwarf/Gparser.c
+++ b/frysk-imports/libunwind/src/dwarf/Gparser.c
@@ -71,8 +71,13 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
   void *arg;
   int ret;
 
+#ifndef UNW_LOCAL_ONLY
+  as = dci->as;
+  arg = dci->as_arg;
+#else
   as = c->as;
   arg = c->as_arg;
+#endif
   a = unw_get_accessors (as);
   curr_ip = c->pi.start_ip;
 
diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx
index 08c8ce1..f56d16b 100644
--- a/frysk-sys/lib/unwind/cni/UnwindH.hxx
+++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx
@@ -567,11 +567,7 @@ get_eh_frame_hdr_addr(unw_proc_info_t *pi, char *image, size_t size,
   *peh_vaddr = peh_hdr.p_vaddr;
 
   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
+  if (debug_frame_data != NULL && debug_frame_data->d_buf != NULL
       && debug_frame_data->d_size != 0)
     {
       pi->format = UNW_INFO_FORMAT_TABLE;

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-01-20 15:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-17 11:12 [patch] Add debug_frame parsing Mark Wielaard
2008-01-17 14:34 ` Andrew Cagney
2008-01-20 15:08 ` Mark Wielaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).