I Thomas,
I tested backtrace example on my sh4 arch and fix the problem of address 
resolution of static function.
Follow the output I got executing the test:

# ./prog 3
backtrace() returned 7 addresses
./prog(myfunc3+0x1e) [0x40082a]
./prog [0x40090c]
./prog(myfunc+0x30) [0x400948]
./prog(myfunc+0x26) [0x40093e]
./prog(myfunc+0x26) [0x40093e]
./prog(main+0x5a) [0x4009b2]
/lib/libc.so.0(__uClibc_main+0x21e) [0x295ce466]

The following patch (against the uclibc master branch) fix it in the dladdr 
function.
Could you try on your arch?

Regards,
Filippo Arcidiacono

>From a386894ad712d4b4a712d0ec3df950495ad5b53f Mon Sep 17 00:00:00 2001
From: Filippo Arcidiacono <[email protected]>
Date: Fri, 6 May 2011 16:49:28 +0200
Subject: [PATCH] libdl: fix symbol resolution of static functions in dladdr

Fix dladdr to correctly resolve static function so backtrace_symbols
print only the function address.

Signed-off-by: Filippo Arcidiacono <[email protected]>
---
 ldso/include/dl-defs.h |    8 ++++++++
 ldso/libdl/libdl.c     |    5 ++++-
 2 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index be0a81d..9b2f028 100644
--- a/ldso/include/dl-defs.h
+++ b/ldso/include/dl-defs.h
@@ -179,6 +179,14 @@ typedef struct {
 #define DL_LOOKUP_ADDRESS(ADDRESS) (ADDRESS)
 #endif
 
+/* On some architectures dladdr can't use st_size of all symbols this way.  */
+#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR)                              
                \
+  ((ADDR) >= (L)->loadaddr + (SYM)->st_value                                   
                \
+   && ((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0)                  
\
+        && (ADDR) == (L)->loadaddr + (SYM)->st_value)                          
        \
+       || (ADDR) < (L)->loadaddr + (SYM)->st_value + (SYM)->st_size)   \
+   && ((MATCHSYM) == NULL || MATCHSYM < (L)->loadaddr + (SYM)->st_value))
+
 /* Use this macro to convert a pointer to a function's entry point to
  * a pointer to function.  The pointer is assumed to have already been
  * relocated.  LOADADDR is passed because it may contain additional
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 68cd579..2454cc7 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -1067,7 +1067,10 @@ int dladdr(const void *__address, Dl_info * __info)
                                        ElfW(Addr) symbol_addr;
 
                                        symbol_addr = (ElfW(Addr)) 
DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
-                                       if (symbol_addr <= 
(ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
+                                       if ((symtab[si].st_shndx != SHN_UNDEF ||
+                                                symtab[si].st_value != 0) &&
+                                       ELF_ST_TYPE(symtab[si].st_info) != 
STT_TLS &&
+                                       DL_ADDR_SYM_MATCH(pelf, &symtab[si], 
sa, __address)) {
                                                sa = symbol_addr;
                                                sn = si;
                                                sf = 1;
-- 
1.5.5.6


_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to