[git commit 0.9.31] libdl: fix local symbol's address handling in dladdr

Filippo Arcidiacono filippo.arcidiacono at st.com
Thu May 12 10:26:41 UTC 2011


commit: http://git.uclibc.org/uClibc/commit/?id=86d70c7d1728fb1ba700b2952e6eded9799f22a5
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/0.9.31

Fix dladdr to correctly handle local function's address so backtrace_symbols
print only the function address for these function, instead of showing the name
of nearest one.
Indeed the dladdr walk through the hash table to find the nearest symbol, that
doesn't contain local symbols.

Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
(cherry picked from commit 974d3140577ac740c8db2f1ad9635c4ba591361e)

Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
---
 ldso/include/dl-defs.h |    8 ++++++++
 ldso/libdl/libdl.c     |   12 ++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index 791d068..4eb14f7 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(SYM_ADDR, SYM, MATCHSYM, ADDR)				\
+  ((ADDR) >= (SYM_ADDR)													\
+   && ((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0)			\
+        && (ADDR) == (SYM_ADDR))										\
+       || (ADDR) < (SYM_ADDR) + (SYM)->st_size)							\
+   && (!(MATCHSYM) || MATCHSYM < (SYM_ADDR)))
+
 /* 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 05a68dd..b3271a1 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -1063,7 +1063,11 @@ 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(symbol_addr, &symtab[si], sa,
+											 (ElfW(Addr)) __address)) {
 						sa = symbol_addr;
 						sn = si;
 						sf = 1;
@@ -1079,7 +1083,11 @@ 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(symbol_addr, &symtab[si], sa,
+										 (ElfW(Addr)) __address)) {
 					sa = symbol_addr;
 					sn = si;
 					sf = 1;
-- 
1.7.3.4



More information about the uClibc-cvs mailing list