Hi people,

This patch adds the function address needed by PowerPC64.
I tried to make a generic implementation in src/mi/get_func_addr.c
I hope that David can have an ideia of its implementation.

regards,
-- 
Jose Flavio Aguilar Paulino
([EMAIL PROTECTED])
System / Software Engineer

Toolchain Team
LTC, Linux Technology Center
IBM Brazil
Index: libunwind/src/elfxx.c
===================================================================
--- libunwind/src/elfxx.c.orig
+++ libunwind/src/elfxx.c
@@ -1,7 +1,8 @@
 /* libunwind - a platform-independent unwind library
    Copyright (C) 2003-2005 Hewlett-Packard Co
 	Contributed by David Mosberger-Tang <[EMAIL PROTECTED]>
-
+	Aug-2007 - Updated by
+	Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
 This file is part of libunwind.
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -39,7 +40,8 @@ elf_w (valid_object) (struct elf_image *
 
 
 static int
-elf_w (lookup_symbol) (unw_word_t ip, struct elf_image *ei,
+elf_w (lookup_symbol) (unw_addr_space_t as,
+                       unw_word_t ip, struct elf_image *ei,
 		       Elf_W (Addr) load_offset,
 		       char *buf, size_t buf_len, unw_word_t *offp)
 {
@@ -48,7 +50,8 @@ elf_w (lookup_symbol) (unw_word_t ip, st
   Elf_W (Sym) *sym, *symtab, *symtab_end;
   Elf_W (Off) soff, str_soff;
   Elf_W (Shdr) *shdr, *str_shdr;
-  Elf_W (Addr) val, min_dist = ~(Elf_W (Addr))0;
+  Elf_W (Addr) func_addr, sym_val, min_dist = ~(Elf_W (Addr))0;
+  Elf_W (Addr) cur_dist;
   int i, ret = 0;
   char *strtab;
 
@@ -98,18 +101,35 @@ elf_w (lookup_symbol) (unw_word_t ip, st
 	      if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
 		  && sym->st_shndx != SHN_UNDEF)
 		{
-		  val = sym->st_value;
-		  if (sym->st_shndx != SHN_ABS)
-		    val += load_offset;
-		  Debug (16, "0x%016lx info=0x%02x %s\n",
-			 (long) val, sym->st_info, strtab + sym->st_name);
+		  /* On some architectures, the symbol value doesn't point
+                     directly at the function, but to a function descriptor
+                     in a table (TOC, opd section) instead.
+                     This is true for PowerPC64. */
+                  sym_val = sym->st_value;
+                  ret = tdep_get_func_addr(as, sym_val, &func_addr);
+                  if (ret != 0)
+                    continue;
+
+                  if (sym->st_shndx != SHN_ABS)
+                    func_addr += load_offset;
+
+                  /* Just some checks to see if the function address is
+                     in a valid range */
+	          cur_dist = (Elf_W (Addr)) (ip - func_addr);
+                  if (unlikely (cur_dist < 0))
+                    continue;
+                  if (unlikely (sym->st_size && ip >= func_addr + sym->st_size))
+                    continue;
+
+		  Debug (16, "sym_val: 0x%016lx  func_addr: 0x%016lx  info=0x%02x %s\n",
+			 (long) sym_val, func_addr, sym->st_info, strtab + sym->st_name);
 
-		  if ((Elf_W (Addr)) (ip - val) < min_dist)
+		  if (cur_dist < min_dist)
 		    {
-		      min_dist = (Elf_W (Addr)) (ip - val);
+		      min_dist = cur_dist;
 		      strncpy (buf, strtab + sym->st_name, buf_len);
 		      buf[buf_len - 1] = '\0';
-		      if (strlen (strtab + sym->st_name) >= buf_len)
+	      	      if (strlen (strtab + sym->st_name) >= buf_len)
 			ret = -UNW_ENOMEM;
 		    }
 		}
@@ -125,6 +145,7 @@ elf_w (lookup_symbol) (unw_word_t ip, st
     return -UNW_ENOINFO;		/* not found */
   if (offp)
     *offp = min_dist;
+  //printf("buf_p: %p\n", buf);
   return ret;
 }
 
@@ -134,7 +155,8 @@ elf_w (lookup_symbol) (unw_word_t ip, st
    sensitive to the performance of this routine, why bother...  */
 
 HIDDEN int
-elf_w (get_proc_name) (pid_t pid, unw_word_t ip, char *buf, size_t buf_len,
+elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
+                       char *buf, size_t buf_len,
 		       unw_word_t *offp)
 {
   unsigned long segbase, mapoff;
@@ -158,7 +180,7 @@ elf_w (get_proc_name) (pid_t pid, unw_wo
 	break;
       }
 
-  ret = elf_w (lookup_symbol) (ip, &ei, load_offset, buf, buf_len, offp);
+  ret = elf_w (lookup_symbol) (as, ip, &ei, load_offset, buf, buf_len, offp);
 
   munmap (ei.image, ei.size);
   ei.image = NULL;
Index: libunwind/src/ppc64/Ginit.c
===================================================================
--- libunwind/src/ppc64/Ginit.c.orig
+++ libunwind/src/ppc64/Ginit.c
@@ -208,7 +208,7 @@ get_static_proc_name (unw_addr_space_t a
 		      char *buf, size_t buf_len, unw_word_t *offp,
 		      void *arg)
 {
-  return _Uelf64_get_proc_name (getpid (), ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
 }
 
 HIDDEN void
Index: libunwind/src/ptrace/_UPT_get_proc_name.c
===================================================================
--- libunwind/src/ptrace/_UPT_get_proc_name.c.orig
+++ libunwind/src/ptrace/_UPT_get_proc_name.c
@@ -32,9 +32,9 @@ _UPT_get_proc_name (unw_addr_space_t as,
   struct UPT_info *ui = arg;
 
 #if ELF_CLASS == ELFCLASS64
-  return _Uelf64_get_proc_name (ui->pid, ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
 #elif ELF_CLASS == ELFCLASS32
-  return _Uelf32_get_proc_name (ui->pid, ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
 #else
   return -UNW_ENOINFO;
 #endif
Index: libunwind/src/elfxx.h
===================================================================
--- libunwind/src/elfxx.h.orig
+++ libunwind/src/elfxx.h
@@ -68,6 +68,7 @@ elf_map_image (struct elf_image *ei, con
 }
 
 extern int elf_w (valid_object) (struct elf_image *ei);
-extern int elf_w (get_proc_name) (pid_t pid, unw_word_t ip,
+extern int elf_w (get_proc_name) (unw_addr_space_t as,
+                                  pid_t pid, unw_word_t ip,
 				  char *buf, size_t len,
 				  unw_word_t *offp);
Index: libunwind/include/tdep-ppc64/libunwind_i.h
===================================================================
--- libunwind/include/tdep-ppc64/libunwind_i.h.orig
+++ libunwind/include/tdep-ppc64/libunwind_i.h
@@ -255,7 +255,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf
 #define tdep_get_elf_image		UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg			UNW_OBJ(access_reg)
 #define tdep_access_fpreg		UNW_OBJ(access_fpreg)
-#define tdep_access_vreg		UNW_OBJ(access_vreg)
+
+#define tdep_get_func_addr		UNW_OBJ(get_func_addr)
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)				\
@@ -294,4 +295,7 @@ extern int tdep_access_reg (struct curso
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
 			      unw_fpreg_t * valp, int write);
 
+extern int tdep_get_func_addr(unw_addr_space_t as, unw_word_t addr,
+                              unw_word_t *func_addr);
+
 #endif /* PPC64_LIBUNWIND_I_H */
Index: libunwind/src/Makefile.am
===================================================================
--- libunwind/src/Makefile.am.orig
+++ libunwind/src/Makefile.am
@@ -154,7 +154,7 @@ libunwind_la_SOURCES_x86_common = $(libu
 	$(dwarf_SOURCES_common)						\
 	elf32.c elf32.h							\
 	x86/init.h x86/offsets.h x86/unwind_i.h				\
-	x86/is_fpreg.c x86/regname.c
+	x86/is_fpreg.c x86/regname.c mi/get_func_addr.c
 
 # The list of files that go into libunwind:
 libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common)		\
@@ -209,7 +209,7 @@ libunwind_la_SOURCES_ppc64_common = $(li
         $(dwarf_SOURCES_common)                                         \
         elf64.c elf64.h                                                 \
         ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h		\
-        ppc64/is_fpreg.c ppc64/regname.c
+        ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c
 
 # The list of files that go into libunwind:
 libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common)       \
Index: libunwind/src/ppc64/get_func_addr.c
===================================================================
--- /dev/null
+++ libunwind/src/ppc64/get_func_addr.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2006-2007 IBM
+   Contributed by
+     Corey Ashford <[EMAIL PROTECTED]>
+     Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
+
+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 "unwind_i.h"
+
+int
+tdep_get_func_addr(unw_addr_space_t as, unw_word_t addr,
+                   unw_word_t *func_addr)
+{
+  unw_word_t offset;
+  unw_accessors_t *a;
+
+  /*
+   * This really is a fixed offset of zero, so this code is here in the
+   * event that someone decides to change the position of the entry
+   * component within the func_descr_t structure.  (very unlikely)
+   */
+  offset = 0; //((void *) &dummy.entry - (void *) &dummy);
+
+  a = unw_get_accessors (as);
+  return (a->access_mem) (as, addr + offset, func_addr, 0, NULL) < 0;
+}
Index: libunwind/src/x86/Ginit.c
===================================================================
--- libunwind/src/x86/Ginit.c.orig
+++ libunwind/src/x86/Ginit.c
@@ -186,7 +186,7 @@ get_static_proc_name (unw_addr_space_t a
 		      char *buf, size_t buf_len, unw_word_t *offp,
 		      void *arg)
 {
-  return _Uelf32_get_proc_name (getpid (), ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
 }
 
 HIDDEN void
Index: libunwind/src/x86_64/Ginit.c
===================================================================
--- libunwind/src/x86_64/Ginit.c.orig
+++ libunwind/src/x86_64/Ginit.c
@@ -233,7 +233,7 @@ get_static_proc_name (unw_addr_space_t a
 		      char *buf, size_t buf_len, unw_word_t *offp,
 		      void *arg)
 {
-  return _Uelf64_get_proc_name (getpid (), ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
 }
 
 HIDDEN void
Index: libunwind/src/mi/get_func_addr.c
===================================================================
--- /dev/null
+++ libunwind/src/mi/get_func_addr.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+   Copyright (C) 2006-2007 IBM
+   Contributed by
+     Corey Ashford <[EMAIL PROTECTED]>
+     Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
+
+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"
+
+int
+tdep_get_func_addr(unw_addr_space_t as, unw_word_t sym_value,
+                   unw_word_t *func_addr)
+{
+
+  /* Trivial implementation, for many archs the address of
+     a function is just the value of the symbol */
+  *func_addr = sym_value;
+
+  /* Its always well succedd, maybe in future, some sanity check */
+  return 0;
+
+}
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to