This is the mail archive of the frysk@sources.redhat.com mailing list for the frysk project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: remote dwarf info using libunwind


On Sep 15, 2006, Alexandre Oliva <aoliva@redhat.com> wrote:

> Here's the patch that fixes line numbers for main() and addresses
> printed in backtraces for PCs in modules that don't have unwind info.
> I wonder if I should set an upper limit on the symbol name size
> instead of keeping retrying until memory is really exhausted or so.
> Thoughts?

Here's another approach I thought of, that involves a change in the
interface of the get_proc_name callback, requiring it to cope with a
NULL buf and zero buf_len.  We could do away with the latter, and pass
in ~(size_t)0 for essentially the same effect, but since it hardly
makes any difference, I thought I'd go for both.

Is this ok for frysk?  It should reduce the stack size requirements
when unwinding through ridiculously long symbol names.

Ok for frysk?

for  frysk/frysk-imports/libunwind/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* 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.

Index: frysk/frysk-imports/libunwind/src/elfxx.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/elfxx.c	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/elfxx.c	2006-09-17 03:08:36.000000000 -0300
@@ -107,9 +107,13 @@ elf_w (lookup_symbol) (unw_word_t ip, st
 		  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;
 		    }
 		}
Index: frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-17 03:08:36.000000000 -0300
@@ -36,19 +36,9 @@ 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.  */
-      int size = 128;
       unw_word_t offset;
-      int ret;
 
-      do
-	{
-	  char buf[size];
-
-	  ret = unw_get_proc_name (cursor, buf, size, &offset);
-	}
-      while (ret == -UNW_ENOMEM && (size *= 2));
-
-      if (ret != 0)
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
 	offset = 0;
 
       memset (pi, 0, sizeof (*pi));
Index: frysk/frysk-imports/libunwind/src/mi/Gget_proc_name.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/mi/Gget_proc_name.c	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/mi/Gget_proc_name.c	2006-09-17 03:08:36.000000000 -0300
@@ -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)
Index: frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-09-17 03:08:36.000000000 -0300
@@ -35,19 +35,9 @@ 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.  */
-      int size = 128;
       unw_word_t offset;
-      int ret;
 
-      do
-	{
-	  char buf[size];
-
-	  ret = unw_get_proc_name (cursor, buf, size, &offset);
-	}
-      while (ret == -UNW_ENOMEM && (size *= 2));
-
-      if (ret != 0)
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
 	offset = 0;
 
       memset (pi, 0, sizeof (*pi));
Index: frysk/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c	2006-09-17 03:08:36.000000000 -0300
@@ -38,19 +38,9 @@ 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.  */
-      int size = 128;
       unw_word_t offset;
-      int ret;
 
-      do
-	{
-	  char buf[size];
-
-	  ret = unw_get_proc_name (cursor, buf, size, &offset);
-	}
-      while (ret == -UNW_ENOMEM && (size *= 2));
-
-      if (ret != 0)
+      if (unw_get_proc_name (cursor, NULL, 0, &offset) < 0)
 	offset = 0;
 
       memset (pi, 0, sizeof (*pi));
Index: frysk/frysk-imports/libunwind/doc/unw_get_proc_name.tex
===================================================================
--- frysk.orig/frysk-imports/libunwind/doc/unw_get_proc_name.tex	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/doc/unw_get_proc_name.tex	2006-09-17 03:08:36.000000000 -0300
@@ -29,6 +29,12 @@ stack frame with an instruction-pointer 
 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
 information has been stripped from a program, procedure names may be
Index: frysk/frysk-imports/libunwind/doc/unw_create_addr_space.tex
===================================================================
--- frysk.orig/frysk-imports/libunwind/doc/unw_create_addr_space.tex	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/doc/unw_create_addr_space.tex	2006-09-17 03:08:36.000000000 -0300
@@ -229,6 +229,12 @@ at address 0x40003000, then invoking \Fu
 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.
Index: frysk/frysk-imports/libunwind/doc/unw_get_proc_name.man
===================================================================
--- frysk.orig/frysk-imports/libunwind/doc/unw_get_proc_name.man	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/doc/unw_get_proc_name.man	2006-09-17 03:08:36.000000000 -0300
@@ -54,6 +54,19 @@ return a value of 0x80 in the word point
 (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 
 information has been stripped from a program, procedure names may be 
Index: frysk/frysk-imports/libunwind/doc/unw_create_addr_space.man
===================================================================
--- frysk.orig/frysk-imports/libunwind/doc/unw_create_addr_space.man	2006-09-17 03:08:22.000000000 -0300
+++ frysk/frysk-imports/libunwind/doc/unw_create_addr_space.man	2006-09-17 03:08:36.000000000 -0300
@@ -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 
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]