This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
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}