From: Filippo Arcidiacono <[email protected]>

Added support for the following tracing capabilities:
- LD_WARN to warn about undefined symbols during the lookup stage.
- LD_TRACE_PRELINKING to trace the needed libraries of the object
  that we are prelinking.

Signed-off-by: Filippo Arcidiacono <[email protected]>
Signed-off-by: Carmelo Amoroso <[email protected]>
---
 ldso/include/dl-hash.h   |   12 ++++--
 ldso/include/ldso.h      |    6 +++
 ldso/ldso/dl-debug.c     |   57 ++++++++++++++++++++++++++
 ldso/ldso/dl-hash.c      |    6 ++-
 ldso/ldso/ldso.c         |   98 ++++++++++++++++++++++++++++++++++++++--------
 ldso/ldso/sh/elfinterp.c |    8 +++-
 ldso/libdl/libdl.c       |    2 +-
 7 files changed, 164 insertions(+), 25 deletions(-)

diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h
index f47384c..e138e1d 100644
--- a/ldso/include/dl-hash.h
+++ b/ldso/include/dl-hash.h
@@ -25,6 +25,10 @@ struct dyn_elf {
   struct dyn_elf * prev;
 };
 
+struct sym_val {
+  const ElfW(Sym) *s;
+  struct elf_resolve *m;
+};
 
 /* Structure to describe a single list of scope elements.  The lookup
    functions get passed an array of pointers to such structures.  */
@@ -154,17 +158,17 @@ extern struct elf_resolve * _dl_add_elf_hash_table(const 
char * libname,
 
 /* Only need extra arg with some configurations */
 #if !((defined(USE_TLS) && USE_TLS) || defined __FDPIC__)
-# define _dl_lookup_hash(n, r, m, c, t) _dl_lookup_hash(n, r, m, c)
+# define _dl_lookup_hash(n, r, m, s, c, t) _dl_lookup_hash(n, r, m, s, c)
 #endif
 extern char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope,
-       struct elf_resolve *mytpnt, int type_class,
+       struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
        struct elf_resolve **tpntp);
 
 static __always_inline char *_dl_find_hash(const char *name, struct 
r_scope_elem *scope,
-                                       struct elf_resolve *mytpnt, int 
type_class,
+                                       struct elf_resolve *mytpnt, struct 
sym_val *symbol, int type_class,
                                        struct elf_resolve **tpntp)
 {
-       return _dl_lookup_hash(name, scope, mytpnt, type_class, tpntp);
+       return _dl_lookup_hash(name, scope, mytpnt, symbol, type_class, tpntp);
 }
 
 extern int _dl_linux_dynamic_link(void);
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index 536f7d2..9aa610e 100644
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -73,6 +73,12 @@ extern char *_dl_preload;              /* Things to be 
loaded before the libs */
 extern char *_dl_ldsopath;             /* Where the shared lib loader was 
found */
 extern const char *_dl_progname;       /* The name of the executable being run 
*/
 extern size_t _dl_pagesize;            /* Store the page size for use later */
+#ifdef __LDSO_PRELINK_SUPPORT__
+extern char *_dl_trace_prelink;        /* Library for prelinking trace */
+extern struct elf_resolve *_dl_trace_prelink_map;      /* Library map for 
prelinking trace */
+#else
+#define _dl_trace_prelink              0
+#endif
 
 #if defined(USE_TLS) && USE_TLS
 extern void _dl_add_to_slotinfo (struct link_map  *l);
diff --git a/ldso/ldso/dl-debug.c b/ldso/ldso/dl-debug.c
index 7ce8bfb..47b3231 100644
--- a/ldso/ldso/dl-debug.c
+++ b/ldso/ldso/dl-debug.c
@@ -104,3 +104,60 @@ static void debug_reloc(ElfW(Sym) *symtab, char *strtab, 
ELF_RELOC *rpnt)
 #define debug_reloc(symtab, strtab, rpnt)
 
 #endif /* __SUPPORT_LD_DEBUG__ */
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+static void
+internal_function
+_dl_debug_lookup (const char *undef_name, struct elf_resolve *undef_map,
+                                       const ElfW(Sym) *ref, struct sym_val 
*value, int type_class)
+{
+#ifdef SHARED
+  unsigned long symbol_addr;
+
+  if (_dl_trace_prelink)
+    {
+      int conflict = 0;
+         struct elf_resolve *tls_tpnt = NULL;
+      struct sym_val val = { NULL, NULL };
+
+      if ((_dl_trace_prelink_map == NULL
+          || _dl_trace_prelink_map == _dl_loaded_modules)
+         && undef_map != _dl_loaded_modules)
+       {
+               symbol_addr = (unsigned long)
+                                         _dl_find_hash(undef_name, 
&undef_map->symbol_scope,
+                                                                       
undef_map, &val, type_class, &tls_tpnt);
+
+         if (val.s != value->s || val.m != value->m)
+           conflict = 1;
+       }
+
+      if (value->s
+         && (__builtin_expect (ELF_ST_TYPE(value->s->st_info)
+                               == STT_TLS, 0)))
+       type_class = 4;
+
+      if (conflict
+         || _dl_trace_prelink_map == undef_map
+         || _dl_trace_prelink_map == NULL
+         || type_class == 4)
+       {
+         _dl_dprintf (1, "%s %x %x -> %x %x ",
+                     conflict ? "conflict" : "lookup",
+                     (size_t) undef_map->mapaddr,
+                     (size_t) (((ElfW(Addr)) ref) - undef_map->mapaddr),
+                     (size_t) (value->m ? value->m->mapaddr : 0),
+                     (size_t) (value->s ? value->s->st_value : 0));
+         if (conflict)
+           _dl_dprintf (1, "x %x %x ",
+                       (size_t) (val.m ? val.m->mapaddr : 0),
+                       (size_t) (val.s ? val.s->st_value : 0));
+         _dl_dprintf (1, "/%x %s\n", type_class, undef_name);
+       }
+}
+#endif
+}
+
+#else
+#define _dl_debug_lookup(undef_name, undef_map, ref, value, type_class)
+#endif
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index 2c4571f..2e2111f 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -269,7 +269,7 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) 
*symtab, unsigned long
  * relocations or when we call an entry in the PLT table for the first time.
  */
 char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope, struct 
elf_resolve *mytpnt,
-       int type_class, struct elf_resolve **tpntp)
+       struct sym_val *symbol, int type_class, struct elf_resolve **tpntp)
 {
        struct elf_resolve *tpnt = NULL;
        ElfW(Sym) *symtab;
@@ -339,6 +339,10 @@ char *_dl_lookup_hash(const char *name, struct 
r_scope_elem *scope, struct elf_r
        }
 
        if (sym) {
+               if (symbol) {
+                       symbol->s = sym;
+                       symbol->m = tpnt;
+               }
                /* At this point we have found the requested symbol, do binding 
*/
 #if defined(USE_TLS) && USE_TLS
                if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index ff3519f..8c6e4d1 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -57,6 +57,11 @@ struct r_debug *_dl_debug_addr = NULL;       /* Used to 
communicate with the gdb debug
 void *(*_dl_malloc_function) (size_t size) = NULL;
 void (*_dl_free_function) (void *p) = NULL;
 
+#ifdef __LDSO_PRELINK_SUPPORT__
+char *_dl_trace_prelink                      = NULL;   /* Library for 
prelinking trace */
+struct elf_resolve *_dl_trace_prelink_map    = NULL;   /* Library module for 
prelinking trace */
+bool _dl_verbose                               = true;                         
        /* On by default */
+#endif
 static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
 
 #ifdef __SUPPORT_LD_DEBUG__
@@ -285,6 +290,31 @@ static void __attribute__ ((destructor)) 
__attribute_used__ _dl_fini(void)
        }
 }
 
+#ifdef __LDSO_PRELINK_SUPPORT__
+
+static void trace_objects(struct elf_resolve *tpnt, char *str_name)
+{
+       if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
+               _dl_trace_prelink_map = tpnt;
+       if (tpnt->libtype == elf_executable) {
+/* Main executeble */
+               _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, 
tpnt->libname,
+                                       tpnt->mapaddr, 
DL_LOADADDR_BASE(tpnt->loadaddr));
+       } else {
+/* Preloaded, Needed or interpreter */
+               _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
+                                       tpnt->mapaddr, 
DL_LOADADDR_BASE(tpnt->loadaddr));
+       }
+
+       if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
+               _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
+                                       (size_t) tpnt->l_tls_offset);
+       else
+               _dl_dprintf (1, "\n");
+}
+
+#endif
+
 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
                                                                                
struct elf_resolve *map)
 {
@@ -715,6 +745,16 @@ of this helper program; chances are you did not intend to 
run this program.\n\
        }
 #endif
 
+#ifdef __LDSO_PRELINK_SUPPORT__
+{
+       char *ld_warn = _dl_getenv ("LD_WARN", envp);
+
+       if (ld_warn && *ld_warn == '\0')
+               _dl_verbose = false;
+}
+       _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
+#endif
+
        if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
                trace_loaded_objects++;
        }
@@ -768,7 +808,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                                tpnt1 = _dl_load_shared_library(_dl_secure, 
&rpnt, NULL, str, trace_loaded_objects);
                                if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
-                                       if (trace_loaded_objects)
+                                       if (trace_loaded_objects || 
_dl_trace_prelink)
                                                _dl_dprintf(1, "\t%s => not 
found\n", str);
                                        else
 #endif
@@ -782,7 +822,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                                        _dl_debug_early("Loading: (%x) %s\n", 
DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
-                                       if (trace_loaded_objects &&
+                                       if (trace_loaded_objects && 
!_dl_trace_prelink &&
                                            tpnt1->usage_count == 1) {
                                                /* This is a real hack to make
                                                 * ldd not print the library
@@ -859,7 +899,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                        tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, 
trace_loaded_objects);
                        if (!tpnt1) {
 # ifdef __LDSO_LDD_SUPPORT__
-                               if (trace_loaded_objects)
+                               if (trace_loaded_objects || _dl_trace_prelink)
                                        _dl_dprintf(1, "\t%s => not found\n", 
cp2);
                                else
 # endif
@@ -873,7 +913,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                                _dl_debug_early("Loading: (%x) %s\n", 
DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
 
 # ifdef __LDSO_LDD_SUPPORT__
-                               if (trace_loaded_objects &&
+                               if (trace_loaded_objects && !_dl_trace_prelink 
&&
                                    tpnt1->usage_count == 1) {
                                        _dl_dprintf(1, "\t%s => %s (%x)\n",
                                                    cp2, tpnt1->libname,
@@ -911,7 +951,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
 
                                if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, 
tcurr, lpntstr, trace_loaded_objects))) {
 #ifdef __LDSO_LDD_SUPPORT__
-                                       if (trace_loaded_objects) {
+                                       if (trace_loaded_objects || 
_dl_trace_prelink) {
                                                _dl_dprintf(1, "\t%s => not 
found\n", lpntstr);
                                                continue;
                                        } else
@@ -932,7 +972,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                                _dl_debug_early("Loading: (%x) %s\n", 
DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
-                               if (trace_loaded_objects &&
+                               if (trace_loaded_objects && !_dl_trace_prelink 
&&
                                    tpnt1->usage_count == 1) {
                                        _dl_dprintf(1, "\t%s => %s (%x)\n",
                                                    lpntstr, tpnt1->libname,
@@ -947,12 +987,15 @@ of this helper program; chances are you did not intend to 
run this program.\n\
        /* Keep track of the number of elements in the global scope */
        nscope_elem = nlist;
 
-       --nlist; /* Exclude the application. */
+       if (_dl_loaded_modules->libtype == elf_executable) {
+               --nlist; /* Exclude the application. */
+               tcurr = _dl_loaded_modules->next;
+       } else
+               tcurr = _dl_loaded_modules;
        init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
        i = 0;
-       for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+       for (; tcurr; tcurr = tcurr->next)
                init_fini_list[i++] = tcurr;
-       }
 
        /* Sort the INIT/FINI list in dependency order. */
        for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
@@ -1065,7 +1108,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
         */
        global_scope = &_dl_loaded_modules->symbol_scope;
 
-       /* Build the local scope for the each loaded modules. */
+       /* Build the local scope for each loaded modules. */
        local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
        i = 1;
        for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
@@ -1082,7 +1125,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
 
 #ifdef __LDSO_LDD_SUPPORT__
        /* End of the line for ldd.... */
-       if (trace_loaded_objects) {
+       if (trace_loaded_objects && !_dl_trace_prelink) {
                _dl_dprintf(1, "\t%s => %s (%x)\n",
                            rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
                            rpnt->dyn->libname, 
DL_LOADADDR_BASE(rpnt->dyn->loadaddr));
@@ -1118,6 +1161,27 @@ of this helper program; chances are you did not intend 
to run this program.\n\
 #endif
 
 
+       /* FIXME: The glibc code doesn't trace the ldso when LD_TRACE_OBJECT is 
set,
+        *        here has been trace to mantain the original one.
+        *        Another difference Vs Glibc is the check to verify if an 
object is
+        *        "statically linked" (only if LD_TRACE_OBJECT is on).
+        */
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+       if (_dl_trace_prelink) {
+               for (i = 0; i < nscope_elem; i++)
+                       trace_objects(scope_elem_list[i],
+                               
_dl_get_last_path_component(scope_elem_list[i]->libname));
+
+               if (_dl_verbose)
+                       /* Warn about undefined symbols. */
+                       if (_dl_symbol_tables)
+                               if (_dl_fixup(_dl_symbol_tables, global_scope, 
unlazy))
+                                       _dl_exit(-1);
+               _dl_exit(0);
+       }
+#endif
+
        _dl_debug_early("Beginning relocation fixups\n");
 
 #ifdef __mips__
@@ -1172,7 +1236,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
         * ld.so.1, so we have to look up each symbol individually.
         */
 
-       _dl_envp = (unsigned long *) (intptr_t) 
_dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
+       _dl_envp = (unsigned long *) (intptr_t) 
_dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, 
NULL);
        if (_dl_envp)
                *_dl_envp = (unsigned long) envp;
 
@@ -1228,21 +1292,21 @@ of this helper program; chances are you did not intend 
to run this program.\n\
 
        /* Find the real malloc function and make ldso functions use that from 
now on */
        _dl_malloc_function = (void* (*)(size_t)) (intptr_t) 
_dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
-                       global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+                       global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #if defined(USE_TLS) && USE_TLS
        /* Find the real functions and make ldso functions use them from now on 
*/
        _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, 
ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, 
NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, 
NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, 
NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_free_function = (void (*)(void *)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, 
ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, 
NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, 
NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, 
NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #endif
 
diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c
index d3465bc..e94c44d 100644
--- a/ldso/ldso/sh/elfinterp.c
+++ b/ldso/ldso/sh/elfinterp.c
@@ -69,7 +69,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, 
int reloc_entry)
        got_addr = (char **) instr_addr;
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, 
tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, 
tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        if (unlikely(!new_addr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, 
symname);
@@ -161,6 +161,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem 
*scope,
 #endif
 
        struct elf_resolve *tls_tpnt = NULL;
+       struct sym_val current_value = { NULL, NULL };
 
        reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned 
long) rpnt->r_offset);
        reloc_type = ELF32_R_TYPE(rpnt->r_info);
@@ -169,7 +170,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem 
*scope,
        symname = strtab + symtab[symtab_index].st_name;
 
        if (symtab_index) {
-               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, 
tpnt,
+               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, 
tpnt, &current_value,
                                                            
elf_machine_type_class(reloc_type), &tls_tpnt);
                /*
                 * We want to allow undefined references to weak symbols - this 
might
@@ -186,6 +187,9 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem 
*scope,
                        /* Let the caller to handle the error: it may be non 
fatal if called from dlopen */
                        return 1;
                }
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                                       &current_value, 
elf_machine_type_class(reloc_type));
        }
 
 #if defined (__SUPPORT_LD_DEBUG__)
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index b641fe3..3b49216 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -706,7 +706,7 @@ void *dlsym(void *vhandle, const char *name)
        tpnt = NULL;
        if (handle == _dl_symbol_tables)
                tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global 
object */
-       ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, NULL, 0, 
&tls_tpnt);
+       ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, NULL, NULL, 0, 
&tls_tpnt);
 
 #if defined(USE_TLS) && USE_TLS && defined SHARED
        if (tls_tpnt) {
-- 
1.5.5.6

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

Reply via email to