Hi David, this small patch adds the function that is needed for Frysk
(the code in Frysk cvs).
If you could take a look at it and say your opnion, I would be glad!
I dont know if it makes sense to you add this function, but it is needed
for Frysk.

-- José Flávio Aguilar Paulino
Index: libunwind/src/mi/Gget_unwind_table.c
===================================================================
--- /dev/null
+++ libunwind/src/mi/Gget_unwind_table.c
@@ -0,0 +1,192 @@
+// Copyright 2007, Red Hat Inc.
+
+/* This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+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-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)
+{
+	Debug(99, "Entering get_unwind_table\n");
+	Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
+	unw_word_t addr, eh_frame_start, fde_count, load_base;
+	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 = (unw_word_t) (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 dummy local address space used by dwarf_read_encoded_pointer.
+  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)
+    	{
+     	  Debug (16, "mem[%x] <- %x\n", addr, *val);
+          *(unw_word_t *) addr = *val;
+    	}
+  	else
+    	{
+          *val = *(unw_word_t *) addr;
+          Debug (16, "mem[%x] -> %x\n", addr, *val);
+    	}
+    	Debug(99, "leaving local_access_mem\n");
+  	return 0;
+  }
+  
+  unw_accessors_t temp_local_accessors = {NULL, NULL, NULL, local_access_mem, 
+  					  NULL, NULL,	NULL, NULL, NULL};
+  unw_addr_space_t temp_local_addr_space 
+  	= unw_create_addr_space(&temp_local_accessors, 0);
+  	
+   /* (Optionally) read eh_frame_ptr: */
+  if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, &temp_local_accessors,
+					 &addr, hdr->eh_frame_ptr_enc, pi,
+					 &eh_frame_start, NULL)) < 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 (temp_local_addr_space, &temp_local_accessors,
+					 &addr, hdr->fde_count_enc, pi,
+					 &fde_count, NULL)) < 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;
+    }
+    
+    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);
+}
Index: libunwind/include/libunwind-common.h.in
===================================================================
--- libunwind.orig/include/libunwind-common.h.in
+++ libunwind/include/libunwind-common.h.in
@@ -225,6 +225,7 @@ unw_save_loc_t;
 #define unw_regname		UNW_ARCH_OBJ(regname)
 #define unw_flush_cache		UNW_ARCH_OBJ(flush_cache)
 #define unw_strerror		UNW_ARCH_OBJ(strerror)
+#define unw_get_unwind_table    UNW_ARCH_OBJ(get_unwind_table)
 
 extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
 extern void unw_destroy_addr_space (unw_addr_space_t);
@@ -248,5 +249,10 @@ extern int unw_get_save_loc (unw_cursor_
 extern int unw_is_signal_frame (unw_cursor_t *);
 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);
 
 extern unw_addr_space_t unw_local_addr_space;
Index: libunwind/src/Makefile.am
===================================================================
--- libunwind.orig/src/Makefile.am
+++ libunwind/src/Makefile.am
@@ -56,7 +56,7 @@ libunwind_la_SOURCES_generic =						\
 	mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c		\
 	mi/Gget_reg.c mi/Gset_reg.c					\
 	mi/Gget_fpreg.c mi/Gset_fpreg.c					\
-	mi/Gset_caching_policy.c
+	mi/Gset_caching_policy.c mi/Gget_unwind_table.c
 
 # List of arch-independent files needed by local-only library (libunwind):
 libunwind_la_SOURCES_local =						\
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to