libunwind-devel
[Top][All Lists]
Advanced

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

[Libunwind-devel] [patch] Fixup start_ip in unw_get_proc_info when no dw


From: Mark Wielaard
Subject: [Libunwind-devel] [patch] Fixup start_ip in unw_get_proc_info when no dwarf info
Date: Tue, 02 Oct 2007 15:42:40 +0200

Hi,

We use the following patch in frysk for unw_get_proc_info to get the
correct start_ip when dwarf_make_proc_info fails. In that case we need
to adjust the start_ip using unw_get_proc_name to get the right
procedure start. Since we are only interested in the offset this patch
also makes it so that a NULL bufp can be provided to unw_get_proc_name
(including a small documentation update). This way the base address
returned by unw_get_proc_info can always be reliably used in combination
with later offsets returned by unw_get_proc_name (without this patch
there is no way to know whether or not to use the offset because both
unw_get_proc_info and unw_get_proc_name seem to succeed just fine).

2006-09-16  Alexandre Oliva  <address@hidden>
        
        * src/x86/Gget_proc_info.c (unw_get_proc_info): Use
        unw_get_proc_name to build a proper proc_info_t.
        * src/x86_64/Gget_proc_info.c (unw_get_proc_info): Likewise.
        * src/hppa/Gget_proc_info.c (unw_get_proc_info): Likewise.

2006-09-27  Alexandre Oliva  <address@hidden>

    * src/elfxx.c (lookup_symbol): Cope with NULL buf and zero buf_len.
    * src/mi/Gget_proc_name.c (intern_string, get_proc_name): Likewise.
    * src/hppa/Gget_proc_info.c (unw_get_proc_info): Use it.
    * src/x86/Gget_proc_info.c (unw_get_proc_info): Likewise.
    * src/x86_64/Gget_proc_info.c (unw_get_proc_info): Likewise.
    * doc/unw_get_proc_name.tex: Document NULL buf and zero buf_len.
    * doc/unw_create_addr_space.tex (get_proc_name): Likewise.
    * doc/unw_get_proc_name.man: Rebuilt.
    * doc/unw_create_addr_space.man: Likewise.

This doesn't introduce any test suite regressions (x86).

Cheers,

Mark
diff -r 5b0998e37265 doc/unw_create_addr_space.man
--- a/doc/unw_create_addr_space.man     Mon Sep 24 13:00:13 2007 +0200
+++ b/doc/unw_create_addr_space.man     Tue Oct 02 15:27:25 2007 +0200
@@ -413,6 +413,19 @@ pointed to by offp
 (assuming the procedure is at least 0x80 
 bytes long). 
 .PP
+If bufp
+is NULL
+, buf_len
+is still verified to fit
+and offp
+is set.  Passing buf_len
+as zero to indicate no
+limits on the buffer length is only safe if buf
+is NULL
+,
+otherwise the callback is entitled and likely to scribble anywhere in
+the entire address space.
+.PP
 On successful completion, the get_proc_name()
 call\-back must 
 return zero. Otherwise, the negative value of one of the 
diff -r 5b0998e37265 doc/unw_create_addr_space.tex
--- a/doc/unw_create_addr_space.tex     Mon Sep 24 13:00:13 2007 +0200
+++ b/doc/unw_create_addr_space.tex     Tue Oct 02 15:27:25 2007 +0200
@@ -229,6 +229,12 @@ pointed to by \Var{offp} (assuming the p
 pointed to by \Var{offp} (assuming the procedure is at least 0x80
 bytes long).
 
+If \Var{bufp} is \Const{NULL}, \Var{buf\_len} is still verified to fit
+and \Var{offp} is set.  Passing \Var{buf\_len} as zero to indicate no
+limits on the buffer length is only safe if \Var{buf} is \Const{NULL},
+otherwise the callback is entitled and likely to scribble anywhere in
+the entire address space.
+
 On successful completion, the \Func{get\_proc\_name}() call-back must
 return zero.  Otherwise, the negative value of one of the
 \Type{unw\_error\_t} error-codes may be returned.
diff -r 5b0998e37265 doc/unw_get_proc_name.man
--- a/doc/unw_get_proc_name.man Mon Sep 24 13:00:13 2007 +0200
+++ b/doc/unw_get_proc_name.man Tue Oct 02 15:27:25 2007 +0200
@@ -53,6 +53,19 @@ return a value of 0x80 in the word point
 return a value of 0x80 in the word pointed to by offp
 (assuming 
 the procedure is at least 0x80 bytes long). 
+.PP
+If bufp
+is NULL
+, buf_len
+is still verified to fit
+and offp
+is set.  Passing buf_len
+as zero to indicate no
+limits on the buffer length is only safe if buf
+is NULL
+,
+otherwise the callback is entitled and likely to scribble anywhere in
+the entire address space.
 .PP
 Note that on some platforms there is no reliable way to distinguish 
 between procedure names and ordinary labels. Furthermore, if symbol 
diff -r 5b0998e37265 doc/unw_get_proc_name.tex
--- a/doc/unw_get_proc_name.tex Mon Sep 24 13:00:13 2007 +0200
+++ b/doc/unw_get_proc_name.tex Tue Oct 02 15:27:25 2007 +0200
@@ -28,6 +28,12 @@ stack frame with an instruction-pointer 
 stack frame with an instruction-pointer value of 0x40003080 would
 return a value of 0x80 in the word pointed to by \Var{offp} (assuming
 the procedure is at least 0x80 bytes long).
+
+If \Var{bufp} is \Const{NULL}, \Var{buf\_len} is still verified to fit
+and \Var{offp} is set.  Passing \Var{buf\_len} as zero to indicate no
+limits on the buffer length is only safe if \Var{buf} is \Const{NULL},
+otherwise the callback is entitled and likely to scribble anywhere in
+the entire address space.
 
 Note that on some platforms there is no reliable way to distinguish
 between procedure names and ordinary labels.  Furthermore, if symbol
diff -r 5b0998e37265 src/elfxx.c
--- a/src/elfxx.c       Mon Sep 24 13:00:13 2007 +0200
+++ b/src/elfxx.c       Tue Oct 02 15:27:25 2007 +0200
@@ -110,9 +110,13 @@ elf_w (lookup_symbol) (unw_addr_space_t 
                  if ((Elf_W (Addr)) (ip - val) < min_dist)
                    {
                      min_dist = (Elf_W (Addr)) (ip - val);
-                     strncpy (buf, strtab + sym->st_name, buf_len);
-                     buf[buf_len - 1] = '\0';
-                     if (strlen (strtab + sym->st_name) >= buf_len)
+                     buf_len--;
+                     if (buf)
+                       {
+                         strncpy (buf, strtab + sym->st_name, buf_len);
+                         buf[buf_len] = '\0';
+                       }
+                     if (strlen (strtab + sym->st_name) > buf_len)
                        ret = -UNW_ENOMEM;
                    }
                }
diff -r 5b0998e37265 src/hppa/Gget_proc_info.c
--- a/src/hppa/Gget_proc_info.c Mon Sep 24 13:00:13 2007 +0200
+++ b/src/hppa/Gget_proc_info.c Tue Oct 02 15:27:25 2007 +0200
@@ -36,8 +36,13 @@ unw_get_proc_info (unw_cursor_t *cursor,
         are missing DWARF unwind info.  We don't want to fail in that
         case, because those frames are uninteresting and just mark
         the end of the frame-chain anyhow.  */
+      unw_word_t offset;
+
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
+       offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 4;
       return 0;
     }
diff -r 5b0998e37265 src/mi/Gget_proc_name.c
--- a/src/mi/Gget_proc_name.c   Mon Sep 24 13:00:13 2007 +0200
+++ b/src/mi/Gget_proc_name.c   Tue Oct 02 15:27:25 2007 +0200
@@ -33,16 +33,25 @@ intern_string (unw_addr_space_t as, unw_
   size_t i;
   int ret;
 
-  for (i = 0; i < buf_len; ++i)
+  buf_len--;
+
+  for (i = 0; i <= buf_len; ++i)
     {
-      if ((ret = fetch8 (as, a, &addr, (int8_t *) buf + i, arg)) < 0)
+      int8_t c, *p = buf ? (int8_t *)buf + i : &c;
+
+      if ((ret = fetch8 (as, a, &addr, p, arg)) < 0)
        return ret;
 
-      if (buf[i] == '\0')
+      if (*p == '\0')
        return 0;               /* copied full string; return success */
     }
-  buf[buf_len - 1] = '\0';     /* ensure string is NUL terminated */
-  return -UNW_ENOMEM;
+  if (buf)
+    {
+      buf[buf_len] = '\0';     /* ensure string is NUL terminated */
+      return -UNW_ENOMEM;
+    }
+  else
+    return 0;
 }
 
 static inline int
@@ -53,7 +62,8 @@ get_proc_name (unw_addr_space_t as, unw_
   unw_proc_info_t pi;
   int ret;
 
-  buf[0] = '\0';       /* always return a valid string, even if it's empty */
+  if (buf)
+    buf[0] = '\0';     /* always return a valid string, even if it's empty */
 
   ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg);
   if (ret == 0)
diff -r 5b0998e37265 src/x86/Gget_proc_info.c
--- a/src/x86/Gget_proc_info.c  Mon Sep 24 13:00:13 2007 +0200
+++ b/src/x86/Gget_proc_info.c  Tue Oct 02 15:27:25 2007 +0200
@@ -35,8 +35,13 @@ unw_get_proc_info (unw_cursor_t *cursor,
       /* On x86, it's relatively common to be missing DWARF unwind
         info.  We don't want to fail in that case, because the
         frame-chain still would let us do a backtrace at least.  */
+      unw_word_t offset;
+
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
+       offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 1;
       return 0;
     }
diff -r 5b0998e37265 src/x86_64/Gget_proc_info.c
--- a/src/x86_64/Gget_proc_info.c       Mon Sep 24 13:00:13 2007 +0200
+++ b/src/x86_64/Gget_proc_info.c       Tue Oct 02 15:39:43 2007 +0200
@@ -38,8 +38,13 @@ unw_get_proc_info (unw_cursor_t *cursor,
         are missing DWARF unwind info.  We don't want to fail in that
         case, because those frames are uninteresting and just mark
         the end of the frame-chain anyhow.  */
+      unw_word_t offset;
+
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
+       offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 1;
       return 0;
     }

reply via email to

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