libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] Some elf/maps reading changes from frysk


From: Mark Wielaard
Subject: [Libunwind-devel] Some elf/maps reading changes from frysk
Date: Mon, 28 Jan 2008 13:06:38 +0100
User-agent: Thunderbird 2.0.0.9 (X11/20071115)

Hi,

We used to carry the following patches in our libunwind copy in frysk to get elf reading from libunwind while using the remote interface. We no longer mix the remote interface with elf or symbol reading through libunwind in frysk so I removed them from our copy. But maybe someone else still finds them interesting.

These are related to the old patch to cleanup unw_get_procinfo which we changed to use a different version of unw_get_reg described in these threads: http://lists.gnu.org/archive/html/libunwind-devel/2007-10/msg00002.html
http://lists.gnu.org/archive/html/libunwind-devel/2007-11/msg00011.html

Since that patch to unw_get_reg went in we rewrote our code to not use any elf or symbol reading through libunwind since we were already using elfutils to do that. The patches below are probably good, but since we don't use these code paths anymore we dropped them to make sure our libunwind version is as close as possible to upstream as can be (I will be posting the remaining outstanding changes to the list).

Cheers,

Mark
2006-09-20  Alexandre Oliva  <address@hidden>
        
        * src/os-linux.h (maps_next): Don't error out just because
        path is missing.
        * include/tdep-hppa/libunwind_i.h (tdep_get_elf_image): Add as
        and arg to the parameter list.
        * include/tdep-ia64/libunwind_i.h (tdep_get_elf_image): Ditto.
        * include/tdep-ppc64/libunwind_i.h (tdep_get_elf_image): Ditto.
        * include/tdep-x86/libunwind_i.h (tdep_get_elf_image): Ditto.
        * include/tdep-x86_64/libunwind_i.h (tdep_get_elf_image): Ditto.
        * src/elfxx.h (get_proc_name): Ditto.
        * src/elfxx.c (get_proc_name): Ditto.  Adjust.
        * src/hppa/Ginit.c (get_static_proc_name): Adjust.
        * src/ia64/Ginit.c (get_static_proc_name): Ditto.
        * src/ppc64/Ginit.c (get_static_proc_name): Ditto.
        * src/x86/Ginit.c (get_static_proc_name): Ditto.
        * src/x86_64/Ginit.c (get_static_proc_name): Ditto.
        * src/ptrace/_UPT_find_proc_info.c (get_unwind_info): Ditto.
        * src/ptrace/_UPT_get_proc_name.c (_UPT_get_proc_name): Ditto.
        * src/os-hpux.c (tdep_get_elf_image): Ditto.
        * src/os-linux.c (tdep_get_elf_image): Ditto.  Read in 1-page
        segments that start with the ELF magic.
        (MAX_VDSO_SIZE): New.

2007-04-25  Nurdin Premji  <address@hidden>

        * src/elfxx.h (elf_map_image): map image using MAP_32BIT to
        avoid address truncation issues in cross-platform unwinding.
        * src/os-linux.h: (tdep_get_elf_image) Ditto for VDSO section.
        * src/ptrace/_UPT_find_proc_info.c (_UPTi_find_unwind_table): 
        Added dummy local address space for cross-platform unwinding.

diff --git a/frysk-imports/libunwind/include/tdep-hppa/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-hppa/libunwind_i.h
index 74bd9c0..b7b67d4 100644
--- a/frysk-imports/libunwind/include/tdep-hppa/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-hppa/libunwind_i.h
@@ -252,8 +252,10 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, 
unw_word_t ip,
                                     unw_dyn_info_t *di, unw_proc_info_t *pi,
                                     int need_unwind_info, void *arg);
 extern void *tdep_uc_addr (ucontext_t *uc, int reg);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                              pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff,
+                              void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t *valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/include/tdep-ia64/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-ia64/libunwind_i.h
index b851a03..edf3f9f 100644
--- a/frysk-imports/libunwind/include/tdep-ia64/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-ia64/libunwind_i.h
@@ -244,8 +244,10 @@ extern void tdep_put_unwind_info (unw_addr_space_t as,
                                  unw_proc_info_t *pi, void *arg);
 extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
                           uint8_t *nat_bitnr);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                              pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff,
+                              void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t *valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/include/tdep-ppc32/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-ppc32/libunwind_i.h
index d88ab4c..9011538 100644
--- a/frysk-imports/libunwind/include/tdep-ppc32/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-ppc32/libunwind_i.h
@@ -288,8 +288,10 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, 
unw_word_t ip,
                                     unw_proc_info_t * pi,
                                     int need_unwind_info, void *arg);
 extern void *tdep_uc_addr (ucontext_t * uc, int reg);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                              pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff,
+                              void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t * valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/include/tdep-ppc64/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-ppc64/libunwind_i.h
index 710fdd6..74dfe2b 100644
--- a/frysk-imports/libunwind/include/tdep-ppc64/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-ppc64/libunwind_i.h
@@ -288,8 +288,9 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, 
unw_word_t ip,
                                     unw_proc_info_t * pi,
                                     int need_unwind_info, void *arg);
 extern void *tdep_uc_addr (ucontext_t * uc, int reg);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei, 
pid_t pid,
+                              unw_word_t ip, unsigned long *segbase,
+                              unsigned long *mapoff, void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t * valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/include/tdep-x86/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-x86/libunwind_i.h
index ac6df2f..55ccb27 100644
--- a/frysk-imports/libunwind/include/tdep-x86/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-x86/libunwind_i.h
@@ -256,8 +256,10 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, 
unw_word_t ip,
                                     unw_dyn_info_t *di, unw_proc_info_t *pi,
                                     int need_unwind_info, void *arg);
 extern void *tdep_uc_addr (ucontext_t *uc, int reg);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                              pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff,
+                              void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t *valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/include/tdep-x86_64/libunwind_i.h 
b/frysk-imports/libunwind/include/tdep-x86_64/libunwind_i.h
index 9aeb425..4ba8915 100644
--- a/frysk-imports/libunwind/include/tdep-x86_64/libunwind_i.h
+++ b/frysk-imports/libunwind/include/tdep-x86_64/libunwind_i.h
@@ -182,8 +182,10 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, 
unw_word_t ip,
                                     unw_dyn_info_t *di, unw_proc_info_t *pi,
                                     int need_unwind_info, void *arg);
 extern void *tdep_uc_addr (ucontext_t *uc, int reg);
-extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                              unsigned long *segbase, unsigned long *mapoff);
+extern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                              pid_t pid, unw_word_t ip,
+                              unsigned long *segbase, unsigned long *mapoff,
+                              void *arg);
 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
                            unw_word_t *valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
diff --git a/frysk-imports/libunwind/src/elfxx.c 
b/frysk-imports/libunwind/src/elfxx.c
index 05b9943..6b32305 100644
--- a/frysk-imports/libunwind/src/elfxx.c
+++ b/frysk-imports/libunwind/src/elfxx.c
@@ -138,7 +138,7 @@ elf_w (lookup_symbol) (unw_addr_space_t as,
 
 HIDDEN int
 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)
+                      char *buf, size_t buf_len, unw_word_t *offp, void *arg)
 {
   unsigned long segbase, mapoff;
   Elf_W (Addr) load_offset = 0;
@@ -147,7 +147,7 @@ elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, 
unw_word_t ip,
   Elf_W (Phdr) *phdr;
   int i, ret;
 
-  ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff);
+  ret = tdep_get_elf_image (as, &ei, pid, ip, &segbase, &mapoff, arg);
   if (ret < 0)
     return ret;
 
diff --git a/frysk-imports/libunwind/src/elfxx.h 
b/frysk-imports/libunwind/src/elfxx.h
index 7742806..205b49f 100644
--- a/frysk-imports/libunwind/src/elfxx.h
+++ b/frysk-imports/libunwind/src/elfxx.h
@@ -2,6 +2,7 @@
    Copyright (C) 2003, 2005 Hewlett-Packard Co
    Copyright (C) 2007 David Mosberger-Tang
        Contributed by David Mosberger-Tang <address@hidden>
+   Copyright Red Hat 2007
 
 This file is part of libunwind.
 
@@ -43,6 +44,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 # define elf_w(x)      _Uelf64_##x
 #endif
 
+#ifndef MAP_32BIT
+# define MAP_32BIT 0
+#endif
+
 static inline int
 elf_map_image (struct elf_image *ei, const char *path)
 {
@@ -60,7 +65,7 @@ elf_map_image (struct elf_image *ei, const char *path)
     }
 
   ei->size = stat.st_size;
-  ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0);
+  ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE | MAP_32BIT, fd, 0);
   close (fd);
   if (ei->image == MAP_FAILED)
     return -1;
@@ -72,4 +77,4 @@ extern int elf_w (valid_object) (struct elf_image *ei);
 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);
+                                 unw_word_t *offp, void *arg);
diff --git a/frysk-imports/libunwind/src/hppa/Ginit.c 
b/frysk-imports/libunwind/src/hppa/Ginit.c
index 5326b82..39f1d1a 100644
--- a/frysk-imports/libunwind/src/hppa/Ginit.c
+++ b/frysk-imports/libunwind/src/hppa/Ginit.c
@@ -172,7 +172,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
diff --git a/frysk-imports/libunwind/src/ia64/Ginit.c 
b/frysk-imports/libunwind/src/ia64/Ginit.c
index 5afa9ab..3c5f7ad 100644
--- a/frysk-imports/libunwind/src/ia64/Ginit.c
+++ b/frysk-imports/libunwind/src/ia64/Ginit.c
@@ -348,7 +348,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
diff --git a/frysk-imports/libunwind/src/os-hpux.c 
b/frysk-imports/libunwind/src/os-hpux.c
index 586ace2..b34851a 100644
--- a/frysk-imports/libunwind/src/os-hpux.c
+++ b/frysk-imports/libunwind/src/os-hpux.c
@@ -33,8 +33,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 #include "elf64.h"
 
 HIDDEN int
-tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                   unsigned long *segbase, unsigned long *mapoff)
+tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                   pid_t pid, unw_word_t ip,
+                   unsigned long *segbase, unsigned long *mapoff,
+                   void *arg)
 {
   struct load_module_desc lmd;
   const char *path;
diff --git a/frysk-imports/libunwind/src/os-linux.c 
b/frysk-imports/libunwind/src/os-linux.c
index ae37d8f..f0b4142 100644
--- a/frysk-imports/libunwind/src/os-linux.c
+++ b/frysk-imports/libunwind/src/os-linux.c
@@ -1,6 +1,7 @@
 /* libunwind - a platform-independent unwind library
    Copyright (C) 2003-2005 Hewlett-Packard Co
        Contributed by David Mosberger-Tang <address@hidden>
+   Copyright Red Hat 2007
 
 This file is part of libunwind.
 
@@ -31,14 +32,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 #include "libunwind_i.h"
 #include "os-linux.h"
 
+#ifndef MAX_VDSO_SIZE
+# define MAX_VDSO_SIZE ((size_t) sysconf (_SC_PAGESIZE))
+#endif
+
+#ifndef MAP_32BIT
+# define MAP_32BIT 0
+#endif
+
 PROTECTED int
-tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
-                   unsigned long *segbase, unsigned long *mapoff)
+tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
+                   pid_t pid, unw_word_t ip,
+                   unsigned long *segbase, unsigned long *mapoff,
+                   void *arg)
 {
   struct map_iterator mi;
   char path[PATH_MAX];
   int found = 0;
   unsigned long hi;
+  unw_accessors_t *a;
+  unw_word_t magic;
 
   maps_init (&mi, pid);
   while (maps_next (&mi, segbase, &hi, mapoff, path, sizeof (path)))
@@ -52,7 +65,65 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, 
unw_word_t ip,
   if (!found)
     return -1;
 
-  return elf_map_image (ei, path);
+  found = elf_map_image (ei, path);
+  if (found != -1)
+    return found;
+
+  /* If the above failed, try to bring in page-sized segments directly
+     from process memory.  This enables us to locate VDSO unwind
+     tables.  */
+  ei->size = hi - *segbase;
+  if (ei->size > MAX_VDSO_SIZE)
+    return found;
+
+  a = unw_get_accessors (as);
+  if (! a->access_mem)
+    return found;
+
+  /* Try to decide whether it's an ELF image before bringing it all
+     in.  */
+  if (ei->size <= EI_CLASS || ei->size <= sizeof (magic))
+    return found;
+
+  if (sizeof (magic) >= SELFMAG)
+    {
+      int ret = (*a->access_mem) (as, *segbase, &magic, 0, arg);
+      if (ret < 0)
+       return ret;
+
+      if (memcmp (&magic, ELFMAG, SELFMAG) != 0)
+       return found;
+    }
+
+  ei->image = mmap (0, ei->size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+  if (ei->image == MAP_FAILED)
+    return found;
+
+  if (sizeof (magic) >= SELFMAG)
+    {
+      *(unw_word_t *)ei->image = magic;
+      hi = sizeof (magic);
+    }
+  else
+    hi = 0;
+
+  for (; hi < ei->size; hi += sizeof (unw_word_t))
+    {
+      found = (*a->access_mem) (as, *segbase + hi, ei->image + hi,
+                               0, arg);
+      if (found < 0)
+       {
+         munmap (ei->image, ei->size);
+         return found;
+       }
+    }
+
+  if (*segbase == *mapoff
+      && (*path == 0 || strcmp (path, "[vdso]") == 0))
+    *mapoff = 0;
+
+  return 0;
 }
 
 #endif /* UNW_REMOTE_ONLY */
diff --git a/frysk-imports/libunwind/src/os-linux.h 
b/frysk-imports/libunwind/src/os-linux.h
index b2c9a8b..dba788e 100644
--- a/frysk-imports/libunwind/src/os-linux.h
+++ b/frysk-imports/libunwind/src/os-linux.h
@@ -294,8 +294,12 @@ maps_next (struct map_iterator *mi,
       cp = scan_char (cp, &colon);
       cp = scan_hex (cp, &minor);
       cp = scan_dec (cp, &inum);
+      if (!cp)
+       continue;
       cp = scan_string (cp, path, path_size);
-      if (!cp || dash != '-' || colon != ':')
+      if (!cp)
+       *path = 0;
+      if (dash != '-' || colon != ':')
        continue;       /* skip line with unknown or bad format */
       return 1;
     }
diff --git a/frysk-imports/libunwind/src/ppc32/Ginit.c 
b/frysk-imports/libunwind/src/ppc32/Ginit.c
index 47c66f1..98034ab 100644
--- a/frysk-imports/libunwind/src/ppc32/Ginit.c
+++ b/frysk-imports/libunwind/src/ppc32/Ginit.c
@@ -199,7 +199,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
diff --git a/frysk-imports/libunwind/src/ppc64/Ginit.c 
b/frysk-imports/libunwind/src/ppc64/Ginit.c
index 97c9d78..e53a343 100644
--- a/frysk-imports/libunwind/src/ppc64/Ginit.c
+++ b/frysk-imports/libunwind/src/ppc64/Ginit.c
@@ -208,7 +208,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
diff --git a/frysk-imports/libunwind/src/ptrace/_UPT_find_proc_info.c 
b/frysk-imports/libunwind/src/ptrace/_UPT_find_proc_info.c
index 9f4ed38..c06e456 100644
--- a/frysk-imports/libunwind/src/ptrace/_UPT_find_proc_info.c
+++ b/frysk-imports/libunwind/src/ptrace/_UPT_find_proc_info.c
@@ -1,6 +1,7 @@
 /* libunwind - a platform-independent unwind library
    Copyright (C) 2003-2004 Hewlett-Packard Co
        Contributed by David Mosberger-Tang <address@hidden>
+   Copyright Red Hat 2007
 
 This file is part of libunwind.
 
@@ -170,7 +171,6 @@ _UPTi_find_unwind_table (struct UPT_info *ui, 
unw_addr_space_t as,
   unw_word_t addr, eh_frame_start, fde_count, load_base;
   struct dwarf_eh_frame_hdr *hdr;
   unw_proc_info_t pi;
-  unw_accessors_t *a;
   Elf_W(Ehdr) *ehdr;
   int i, ret;
 
@@ -236,8 +236,7 @@ _UPTi_find_unwind_table (struct UPT_info *ui, 
unw_addr_space_t as,
             path, hdr->version);
       return 0;
     }
-
-  a = unw_get_accessors (unw_local_addr_space);
+ 
   addr = (unw_word_t) (hdr + 1);
 
   /* Fill in a dummy proc_info structure.  We just need to fill in
@@ -247,14 +246,37 @@ _UPTi_find_unwind_table (struct UPT_info *ui, 
unw_addr_space_t as,
   memset (&pi, 0, sizeof (pi));
   pi.gp = ui->di_cache.gp;
 
+//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) 
+  {    
+       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);
+       }
+       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 (unw_local_addr_space, a,
+  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 NULL;
 
   /* (Optionally) read fde_count: */
-  if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
+  if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, 
&temp_local_accessors,
                                         &addr, hdr->fde_count_enc, &pi,
                                         &fde_count, NULL)) < 0)
     return NULL;
@@ -337,7 +359,7 @@ get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, 
unw_word_t ip)
       ui->di_cache.start_ip = ui->di_cache.end_ip = 0;
     }
 
-  if (tdep_get_elf_image (&ui->ei, ui->pid, ip, &segbase, &mapoff) < 0)
+  if (tdep_get_elf_image (as, &ui->ei, ui->pid, ip, &segbase, &mapoff, ui) < 0)
     return NULL;
 
   /* Here, SEGBASE is the starting-address of the (mmap'ped) segment
diff --git a/frysk-imports/libunwind/src/ptrace/_UPT_get_proc_name.c 
b/frysk-imports/libunwind/src/ptrace/_UPT_get_proc_name.c
index 6ac85a0..2d718fc 100644
--- a/frysk-imports/libunwind/src/ptrace/_UPT_get_proc_name.c
+++ b/frysk-imports/libunwind/src/ptrace/_UPT_get_proc_name.c
@@ -33,9 +33,9 @@ _UPT_get_proc_name (unw_addr_space_t as, unw_word_t ip,
   struct UPT_info *ui = arg;
 
 #if ELF_CLASS == ELFCLASS64
-  return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp, arg);
 #elif ELF_CLASS == ELFCLASS32
-  return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp, arg);
 #else
   return -UNW_ENOINFO;
 #endif
diff --git a/frysk-imports/libunwind/src/x86/Ginit.c 
b/frysk-imports/libunwind/src/x86/Ginit.c
index abc9e61..21453a4 100644
--- a/frysk-imports/libunwind/src/x86/Ginit.c
+++ b/frysk-imports/libunwind/src/x86/Ginit.c
@@ -187,7 +187,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
diff --git a/frysk-imports/libunwind/src/x86_64/Ginit.c 
b/frysk-imports/libunwind/src/x86_64/Ginit.c
index 026e8d2..7fb311e 100644
--- a/frysk-imports/libunwind/src/x86_64/Ginit.c
+++ b/frysk-imports/libunwind/src/x86_64/Ginit.c
@@ -234,7 +234,7 @@ get_static_proc_name (unw_addr_space_t as, unw_word_t ip,
                      char *buf, size_t buf_len, unw_word_t *offp,
                      void *arg)
 {
-  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
+  return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
 }
 
 HIDDEN void
           2006-12-10  Jan Kratochvil  <address@hidden>
    
           * src/elfxx.c (lookup_symbol): Avoid returning irrelevant symbols
           defined as the last ones before the address in different
           section.
    
           2006-12-10  Jan Kratochvil  <address@hidden>
    
           * src/elfxx.c (lookup_symbol): Fixed excessive buffer
           size requirement.

git diff f409de5e8b94142diff --git a/frysk-imports/libunwind/ChangeLog 
b/frysk-imports/libunwind/ChangeLog
diff --git a/frysk-imports/libunwind/src/elfxx.c 
b/frysk-imports/libunwind/src/elfxx.c
index 6b32305..ae1ef34 100644
--- a/frysk-imports/libunwind/src/elfxx.c
+++ b/frysk-imports/libunwind/src/elfxx.c
@@ -51,12 +51,15 @@ elf_w (lookup_symbol) (unw_addr_space_t as,
   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) val_max_below = 0;
   int i, ret = 0;
   char *strtab;
 
   if (!elf_w (valid_object) (ei))
     return -UNW_ENOINFO;
 
+  buf_len--;   /* Terminating 0. */
+
   soff = ehdr->e_shoff;
   if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
     {
@@ -100,10 +103,58 @@ elf_w (lookup_symbol) (unw_addr_space_t as,
              if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
                  && sym->st_shndx != SHN_UNDEF)
                {
+                 Elf_W (Shdr) *shdr2;
+                 int i2;
+
                  if (tdep_get_func_addr (as, sym->st_value, &val) < 0)
                    continue;
                  if (sym->st_shndx != SHN_ABS)
                    val += load_offset;
+
+                 if (ip < val)
+                   continue;
+                 if (val + sym->st_size < val_max_below)
+                   continue;
+                 val_max_below = val + sym->st_size;
+                 if (sym->st_size && ip >= val + sym->st_size)
+                   continue;
+
+                 if ((Elf_W (Addr)) (ip - val) >= min_dist)
+                   continue;
+
+                 /* Check both the address and the symbol belong to the same
+                    section.  */
+                 shdr2 = (Elf_W (Shdr) *) ((char *) ei->image + soff);
+                 for (i2 = 0; i2 < ehdr->e_shnum; ++i2,
+                      shdr2 = (Elf_W (Shdr) *) (((char *) shdr2) + 
ehdr->e_shentsize))
+                   {
+                     unw_word_t addr_start;
+
+                     if (shdr2->sh_type != SHT_PROGBITS)
+                       continue;
+                     /* `load_offset' is no absolute address.
+                        `shdr2->sh_addr' is address where the library was 
prelink(8)ed to.
+                        `load_offset + shdr2->sh_addr' will give the loaded 
address.
+                        `shdr2->sh_addr == 0' is for sections not in the 
memory image.
+                        prelink(8) at offset 0x0:
+                               
load_offset=0x360000,segbase=0x360000,p_vaddr=0x0,p_paddr=0x0
+                               
segbase=0x360000,load_offset=0x360000,shdr2->sh_addr=0x1b4,shdr2->sh_offset=0x1b4,ip=0x3601c5
+                        prelink(8) at offset 0x8048000:
+                               
load_offset=0xf80c9000,segbase=0x111000,p_vaddr=0x8048000,p_paddr=0x8048000
+                               
segbase=0x111000,load_offset=0xf80c9000,shdr2->sh_addr=0x80481b4,shdr2->sh_offset=0x1b4,ip=0x1111c5
+                        */
+                     if (shdr2->sh_addr == 0)
+                       continue;
+                     addr_start = load_offset + shdr2->sh_addr;
+                     if (ip >= addr_start
+                         && ip < addr_start + shdr2->sh_size
+                         && val >= addr_start
+                         && val < addr_start + shdr2->sh_size)
+                       break;
+                   }
+                 if (i2 >= ehdr->e_shnum)
+                   continue;
+
                  Debug (16, "0x%016lx info=0x%02x %s\n",
                         (long) val, sym->st_info, strtab + sym->st_name);
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]