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 13, 2006, Alexandre Oliva <aoliva@redhat.com> wrote:

> there's still something broken in the way compute addresses for
> stack traces.

> The internal computations are carried out correctly, but when
> frysk::rt::StackFrame::initialize() calls unw_get_proc_info(), it
> often gets back a fake procedure spec because we can't find unwind
> info for it (apparently because of the lack for dyn_list_addr or some
> such), so it returns proc_info with a one-byte range covering only the
> given IP, but when it calls unw_get_proc_name(), it uses a difference
> piece of code that succeeds in locating information about the
> procedure, and then it sets offset according to that base address, so
> we end up adding the offset to the wrong base address and get wrong
> info printed out.

> It still fails to print line numbers for main and for kernel vdso
> syscalls and their callers, but other than that, it's much better than
> before.

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?


Fixing vdso will take new code in libunwind to fetch the vdso ELF
image from the target process memory.  It doesn't look hard, I'll take
a stab at it in my next hacking session.


Meanwhile, ok to install in the frysk tree?

This patch fixes offsets printed in backtraces.  The problem is that
unw_get_proc_info doesn't find unwind info, so machine-specific code
returns a proc_info data structure whose start_ip is the one passed to
unw_get_proc_info, but then unw_get_proc_name succeeds in finding a
symbol name corresponding to that address, and so it sets offset
accordingly.  Then, when we add the offset with the start_ip in the
proc_info data structure, we end up with a bogus address.

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

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

Index: frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-15 06:33:16.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-15 06:34:35.000000000 -0300
@@ -36,8 +36,23 @@ 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)
+	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;
     }
Index: frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-05-31 16:04:20.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-09-15 06:34:12.000000000 -0300
@@ -35,8 +35,23 @@ 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)
+	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;
     }
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-05-31 16:04:20.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c	2006-09-15 06:34:40.000000000 -0300
@@ -38,8 +38,23 @@ 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)
+	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;
     }
-- 
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]