From 464dc022eb0be4950e2f3a90fe4de6a17dc3d7d7 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 20 Aug 2009 15:31:08 -0700 Subject: Improve backtrace_symbols{,_fd} output when missing symbols. --- ChangeLog | 9 +++++ sysdeps/generic/elf/backtracesyms.c | 71 +++++++++++++++++++++++------------ sysdeps/generic/elf/backtracesymsfd.c | 58 +++++++++++++++++----------- 3 files changed, 92 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 39bbb2ab9c..6ace54badd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-08-20 Roland McGrath + + * 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 * scripts/gen-as-const.awk: Fix test for 64-bit platform. diff --git a/sysdeps/generic/elf/backtracesyms.c b/sysdeps/generic/elf/backtracesyms.c index b31be6ac5d..319b207605 100644 --- a/sysdeps/generic/elf/backtracesyms.c +++ b/sysdeps/generic/elf/backtracesyms.c @@ -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 , 1998. @@ -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 - "() [+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 + "(+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; } @@ -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]); diff --git a/sysdeps/generic/elf/backtracesymsfd.c b/sysdeps/generic/elf/backtracesymsfd.c index 6754d145b0..f0ab71587f 100644 --- a/sysdeps/generic/elf/backtracesymsfd.c +++ b/sysdeps/generic/elf/backtracesymsfd.c @@ -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 , 1998. @@ -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; } } -- cgit v1.2.1