Skip to content

Commit

Permalink
Improve backtrace_symbols{,_fd} output when missing symbols.
Browse files Browse the repository at this point in the history
  • Loading branch information
Roland McGrath committed Aug 20, 2009
1 parent 677760a commit 464dc02
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 46 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* scripts/gen-as-const.awk: Fix test for 64-bit platform.
Expand Down
71 changes: 46 additions & 25 deletions sysdeps/generic/elf/backtracesyms.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Expand Down Expand Up @@ -48,15 +48,22 @@ __backtrace_symbols (array, size)
/* Fill in the information we can get from `dladdr'. */
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')
/* We have some info, compute the length of the string which will be
"<file-name>(<sym-name>) [+offset]. */
total += (strlen (info[cnt].dli_fname ?: "")
+ (info[cnt].dli_sname
? strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3
: 1)
+ WORD_WIDTH + 5);
{
/* We have some info, compute the length of the string which will be
"<file-name>(<sym-name>+offset) [address]. */
total += (strlen (info[cnt].dli_fname ?: "")
+ strlen (info[cnt].dli_sname ?: "")
+ 3 + WORD_WIDTH + 3 + 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
total += 5 + WORD_WIDTH;
}
Expand All @@ -71,25 +78,39 @@ __backtrace_symbols (array, size)
{
result[cnt] = last;

if (status[cnt] && info[cnt].dli_fname
&& info[cnt].dli_fname[0] != '\0')
if (status[cnt]
&& 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)
sprintf (buf, "+%#lx",
(unsigned long)(array[cnt] - info[cnt].dli_saddr));
if (info[cnt].dli_sname == NULL && info[cnt].dli_saddr == 0)
last += 1 + sprintf (last, "%s(%s) [%p]",
info[cnt].dli_fname ?: "",
info[cnt].dli_sname ?: "",
array[cnt]);
else
sprintf (buf, "-%#lx",
(unsigned long)(info[cnt].dli_saddr - array[cnt]));

last += 1 + sprintf (last, "%s%s%s%s%s[%p]",
info[cnt].dli_fname ?: "",
info[cnt].dli_sname ? "(" : "",
info[cnt].dli_sname ?: "",
info[cnt].dli_sname ? buf : "",
info[cnt].dli_sname ? ") " : " ",
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%c%#tx) [%p]",
info[cnt].dli_fname ?: "",
info[cnt].dli_sname ?: "",
sign, offset, array[cnt]);
}
}
else
last += 1 + sprintf (last, "[%p]", array[cnt]);
Expand Down
58 changes: 37 additions & 21 deletions sysdeps/generic/elf/backtracesymsfd.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Expand Down Expand Up @@ -46,47 +46,63 @@ __backtrace_symbols_fd (array, size, fd)
{
char buf[WORD_WIDTH];
Dl_info info;
struct link_map *map;
size_t last = 0;

if (_dl_addr (array[cnt], &info, NULL, NULL)
&& info.dli_fname && info.dli_fname[0] != '\0')
if (_dl_addr (array[cnt], &info, &map, NULL)
&& info.dli_fname != NULL && info.dli_fname[0] != '\0')
{
/* Name of the file. */
iov[0].iov_base = (void *) info.dli_fname;
iov[0].iov_len = strlen (info.dli_fname);
last = 1;

/* Symbol name. */
if (info.dli_sname != NULL)
if (info.dli_sname != NULL || map->l_addr != 0)
{
char buf2[WORD_WIDTH];
size_t diff;

iov[1].iov_base = (void *) "(";
iov[1].iov_len = 1;
iov[2].iov_base = (void *) info.dli_sname;
iov[2].iov_len = strlen (info.dli_sname);
iov[last].iov_base = (void *) "(";
iov[last].iov_len = 1;
++last;

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)
{
iov[3].iov_base = (void *) "+0x";
iov[last].iov_base = (void *) "+0x";
diff = array[cnt] - info.dli_saddr;
}
else
{
iov[3].iov_base = (void *) "-0x";
iov[last].iov_base = (void *) "-0x";
diff = info.dli_saddr - array[cnt];
}
iov[3].iov_len = 3;

iov[4].iov_base = _itoa_word ((unsigned long int) diff,
&buf2[WORD_WIDTH], 16, 0);
iov[4].iov_len = &buf2[WORD_WIDTH] - (char *) iov[4].iov_base;

iov[5].iov_base = (void *) ")";
iov[5].iov_len = 1;

last = 6;
iov[last].iov_len = 3;
++last;

iov[last].iov_base = _itoa_word ((unsigned long int) diff,
&buf2[WORD_WIDTH], 16, 0);
iov[last].iov_len = (&buf2[WORD_WIDTH]
- (char *) iov[last].iov_base);
++last;

iov[last].iov_base = (void *) ")";
iov[last].iov_len = 1;
++last;
}
}

Expand Down

0 comments on commit 464dc02

Please sign in to comment.