Improve backtrace_symbols{,_fd} output when missing symbols.

This commit is contained in:
Roland McGrath 2009-08-20 15:31:08 -07:00
parent 677760a307
commit 464dc022eb
3 changed files with 89 additions and 43 deletions

View File

@ -1,3 +1,12 @@
2009-08-20 Roland McGrath <roland@redhat.com>
* sysdeps/generic/elf/backtracesyms.c (__backtrace_symbols):
Use l_addr instead of l_map_start (dli_fbase).
Print "FILE([+-]OFFSET) [ADDRESS]" with the file-relative
address when there is no proximate symbol.
* sysdeps/generic/elf/backtracesymsfd.c (__backtrace_symbols_fd):
Likewise.
2009-08-16 Ulrich Drepper <drepper@redhat.com> 2009-08-16 Ulrich Drepper <drepper@redhat.com>
* scripts/gen-as-const.awk: Fix test for 64-bit platform. * scripts/gen-as-const.awk: Fix test for 64-bit platform.

View File

@ -1,5 +1,5 @@
/* Return list with names for address in backtrace. /* Return list with names for address in backtrace.
Copyright (C) 1998,1999,2000,2001,2003 Free Software Foundation, Inc. Copyright (C) 1998,1999,2000,2001,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -48,15 +48,22 @@ __backtrace_symbols (array, size)
/* Fill in the information we can get from `dladdr'. */ /* Fill in the information we can get from `dladdr'. */
for (cnt = 0; cnt < size; ++cnt) for (cnt = 0; cnt < size; ++cnt)
{ {
status[cnt] = _dl_addr (array[cnt], &info[cnt], NULL, NULL); struct link_map *map;
status[cnt] = _dl_addr (array[cnt], &info[cnt], &map, NULL);
if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0') if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0')
/* We have some info, compute the length of the string which will be {
"<file-name>(<sym-name>) [+offset]. */ /* We have some info, compute the length of the string which will be
total += (strlen (info[cnt].dli_fname ?: "") "<file-name>(<sym-name>+offset) [address]. */
+ (info[cnt].dli_sname total += (strlen (info[cnt].dli_fname ?: "")
? strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3 + strlen (info[cnt].dli_sname ?: "")
: 1) + 3 + WORD_WIDTH + 3 + WORD_WIDTH + 5);
+ WORD_WIDTH + 5);
/* The load bias is more useful to the user than the load
address. The use of these addresses is to calculate an
address in the ELF file, so its prelinked bias is not
something we want to subtract out. */
info[cnt].dli_fbase = (void *) map->l_addr;
}
else else
total += 5 + WORD_WIDTH; total += 5 + WORD_WIDTH;
} }
@ -71,25 +78,39 @@ __backtrace_symbols (array, size)
{ {
result[cnt] = last; result[cnt] = last;
if (status[cnt] && info[cnt].dli_fname if (status[cnt]
&& info[cnt].dli_fname[0] != '\0') && info[cnt].dli_fname != NULL && info[cnt].dli_fname[0] != '\0')
{ {
char buf[20]; if (info[cnt].dli_sname == NULL)
/* We found no symbol name to use, so describe it as
relative to the file. */
info[cnt].dli_saddr = info[cnt].dli_fbase;
if (array[cnt] >= (void *) info[cnt].dli_saddr) if (info[cnt].dli_sname == NULL && info[cnt].dli_saddr == 0)
sprintf (buf, "+%#lx", last += 1 + sprintf (last, "%s(%s) [%p]",
(unsigned long)(array[cnt] - info[cnt].dli_saddr)); info[cnt].dli_fname ?: "",
info[cnt].dli_sname ?: "",
array[cnt]);
else else
sprintf (buf, "-%#lx", {
(unsigned long)(info[cnt].dli_saddr - array[cnt])); char sign;
ptrdiff_t offset;
if (array[cnt] >= (void *) info[cnt].dli_saddr)
{
sign = '+';
offset = array[cnt] - info[cnt].dli_saddr;
}
else
{
sign = '-';
offset = info[cnt].dli_saddr - array[cnt];
}
last += 1 + sprintf (last, "%s%s%s%s%s[%p]", last += 1 + sprintf (last, "%s(%s%c%#tx) [%p]",
info[cnt].dli_fname ?: "", info[cnt].dli_fname ?: "",
info[cnt].dli_sname ? "(" : "", info[cnt].dli_sname ?: "",
info[cnt].dli_sname ?: "", sign, offset, array[cnt]);
info[cnt].dli_sname ? buf : "", }
info[cnt].dli_sname ? ") " : " ",
array[cnt]);
} }
else else
last += 1 + sprintf (last, "[%p]", array[cnt]); last += 1 + sprintf (last, "[%p]", array[cnt]);

View File

@ -1,5 +1,5 @@
/* Write formatted list with names for addresses in backtrace to a file. /* Write formatted list with names for addresses in backtrace to a file.
Copyright (C) 1998, 2000, 2003, 2005 Free Software Foundation, Inc. Copyright (C) 1998,2000,2003,2005,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -46,47 +46,63 @@ __backtrace_symbols_fd (array, size, fd)
{ {
char buf[WORD_WIDTH]; char buf[WORD_WIDTH];
Dl_info info; Dl_info info;
struct link_map *map;
size_t last = 0; size_t last = 0;
if (_dl_addr (array[cnt], &info, NULL, NULL) if (_dl_addr (array[cnt], &info, &map, NULL)
&& info.dli_fname && info.dli_fname[0] != '\0') && info.dli_fname != NULL && info.dli_fname[0] != '\0')
{ {
/* Name of the file. */ /* Name of the file. */
iov[0].iov_base = (void *) info.dli_fname; iov[0].iov_base = (void *) info.dli_fname;
iov[0].iov_len = strlen (info.dli_fname); iov[0].iov_len = strlen (info.dli_fname);
last = 1; last = 1;
/* Symbol name. */ if (info.dli_sname != NULL || map->l_addr != 0)
if (info.dli_sname != NULL)
{ {
char buf2[WORD_WIDTH]; char buf2[WORD_WIDTH];
size_t diff; size_t diff;
iov[1].iov_base = (void *) "("; iov[last].iov_base = (void *) "(";
iov[1].iov_len = 1; iov[last].iov_len = 1;
iov[2].iov_base = (void *) info.dli_sname; ++last;
iov[2].iov_len = strlen (info.dli_sname);
if (info.dli_sname != NULL)
{
/* We have a symbol name. */
iov[last].iov_base = (void *) info.dli_sname;
iov[last].iov_len = strlen (info.dli_sname);
++last;
}
else
/* We have no symbol, so describe it as relative to the file.
The load bias is more useful to the user than the load
address. The use of these addresses is to calculate an
address in the ELF file, so its prelinked bias is not
something we want to subtract out. */
info.dli_saddr = (void *) map->l_addr;
if (array[cnt] >= (void *) info.dli_saddr) if (array[cnt] >= (void *) info.dli_saddr)
{ {
iov[3].iov_base = (void *) "+0x"; iov[last].iov_base = (void *) "+0x";
diff = array[cnt] - info.dli_saddr; diff = array[cnt] - info.dli_saddr;
} }
else else
{ {
iov[3].iov_base = (void *) "-0x"; iov[last].iov_base = (void *) "-0x";
diff = info.dli_saddr - array[cnt]; diff = info.dli_saddr - array[cnt];
} }
iov[3].iov_len = 3; iov[last].iov_len = 3;
++last;
iov[4].iov_base = _itoa_word ((unsigned long int) diff, iov[last].iov_base = _itoa_word ((unsigned long int) diff,
&buf2[WORD_WIDTH], 16, 0); &buf2[WORD_WIDTH], 16, 0);
iov[4].iov_len = &buf2[WORD_WIDTH] - (char *) iov[4].iov_base; iov[last].iov_len = (&buf2[WORD_WIDTH]
- (char *) iov[last].iov_base);
++last;
iov[5].iov_base = (void *) ")"; iov[last].iov_base = (void *) ")";
iov[5].iov_len = 1; iov[last].iov_len = 1;
++last;
last = 6;
} }
} }