OSDN Git Service

Merge commit 'origin/master' into prelink
authorCarmelo Amoroso <carmelo.amoroso@st.com>
Sun, 28 Nov 2010 20:09:47 +0000 (21:09 +0100)
committerCarmelo Amoroso <carmelo.amoroso@st.com>
Sun, 28 Nov 2010 20:09:47 +0000 (21:09 +0100)
Conflicts:

ldso/include/dl-hash.h

Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
28 files changed:
Makerules
extra/Configs/Config.in
ldso/include/dl-defs.h
ldso/include/dl-elf.h
ldso/include/dl-hash.h
ldso/include/ldso.h
ldso/ldso/Makefile.in
ldso/ldso/arm/elfinterp.c
ldso/ldso/avr32/elfinterp.c
ldso/ldso/bfin/elfinterp.c
ldso/ldso/cris/elfinterp.c
ldso/ldso/dl-debug.c
ldso/ldso/dl-elf.c
ldso/ldso/dl-hash.c
ldso/ldso/dl-startup.c
ldso/ldso/frv/elfinterp.c
ldso/ldso/i386/elfinterp.c
ldso/ldso/ldso.c
ldso/ldso/m68k/elfinterp.c
ldso/ldso/mips/elfinterp.c
ldso/ldso/powerpc/elfinterp.c
ldso/ldso/sh/elfinterp.c
ldso/ldso/sh64/elfinterp.c
ldso/ldso/sparc/elfinterp.c
ldso/ldso/x86_64/elfinterp.c
ldso/ldso/xtensa/elfinterp.c
ldso/libdl/libdl.c
libc/misc/internals/__uClibc_main.c

index 84eeaea..6ef916c 100644 (file)
--- a/Makerules
+++ b/Makerules
@@ -294,6 +294,15 @@ endef
 cmd_hcompile.u = $(HOSTCC) $(filter-out $(PHONY),$^) $(DEPS-$(notdir $@)) -o $@ $(BUILD_LDFLAGS) $(BUILD_LDFLAGS-$(notdir $(^D))) $(BUILD_LDFLAGS-$(notdir $@)) $(BUILD_CFLAGS) $(BUILD_CFLAGS-$(notdir $(^D))) $(BUILD_CFLAGS-$(notdir $@))
 cmd_hcompile.o = $(HOSTCC) $(filter-out $(PHONY),$<) $(DEPS-$(notdir $@)) -c -o $@ $(BUILD_CFLAGS) $(BUILD_CFLAGS-$(notdir $(^D))) $(BUILD_CFLAGS-$(notdir $@))
 
+define create-lds
+       $(Q)$(RM) $@.lds
+       $(Q)$(CC) -nostdlib -nostartfiles -shared -Wl,-z,combreloc \
+       -Wl,-z,relro -Wl,--hash-style=gnu -Wl,-z,defs \
+       -Wl,--verbose 2>&1 | LC_ALL=C \
+       sed -e '/^=========/,/^=========/!d;/^=========/d' \
+       -e 's/\. = .* + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' > $@.lds
+endef
+
 define link.so
        $(Q)$(RM) $@ $@.$(2) $(dir $@)$(1)
        @$(disp_ld)
index aa459e0..35ce854 100644 (file)
@@ -342,6 +342,34 @@ config LDSO_BASE_FILENAME
          WARNING: Changing the default prefix could cause problems with
                   binutils' ld !
 
+config LDSO_STANDALONE_SUPPORT
+       bool "Dynamic linker stand-alone mode support"
+       depends on HAVE_SHARED
+       default n
+       help
+         The dynamic linker can be run either indirectly through running some
+         dynamically linked program or library (in which case no command line
+         options to the dynamic linker can be passed and, in the ELF case, the
+         dynamic linker which is stored in the .interp section of the program
+         is executed) or directly by running:
+
+         /lib/ld-uClibc.so.*  [OPTIONS] [PROGRAM [ARGUMENTS]]
+
+         Stand-alone execution is a prerequisite for adding prelink
+         capabilities to uClibc dynamic linker, as well useful for testing an
+         updated version of the dynamic linker without breaking the system.
+
+config LDSO_PRELINK_SUPPORT
+       bool "Dynamic linker prelink support"
+       depends on HAVE_SHARED
+       default n
+       select LDSO_STANDALONE_SUPPORT
+       help
+         The dynamic linker can be used in stand-alone mode by the prelink tool
+         for prelinking ELF shared libraries and binaries to speed up startup
+         time. It also is able to load and handle prelinked libraries and
+         binaries at runtime.
+
 config UCLIBC_STATIC_LDCONFIG
        bool "Link ldconfig statically"
        depends on HAVE_SHARED
index 2d6303c..cbbaa3c 100644 (file)
@@ -225,7 +225,7 @@ typedef struct {
 /* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been
    dlopen()ed successfully, when they're dlclose()d.  */
 #ifndef DL_LIB_UNMAP
-# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->loadaddr, (LEN)))
+# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->mapaddr, (LEN)))
 #endif
 
 /* Define this to verify that a library named LIBNAME, whose ELF
index cbb2100..40c88b9 100644 (file)
@@ -15,6 +15,7 @@
 /* Forward declarations for stuff defined in ld_hash.h */
 struct dyn_elf;
 struct elf_resolve;
+struct r_scope_elem;
 
 #include <dl-defs.h>
 #ifdef __LDSO_CACHE_SUPPORT__
@@ -30,16 +31,16 @@ static __inline__ void _dl_unmap_cache(void) { }
 extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
        unsigned long rel_addr, unsigned long rel_size);
 extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size);
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
 extern struct elf_resolve * _dl_load_shared_library(int secure,
        struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
        int trace_loaded_objects);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure,
-       struct dyn_elf **rpnt, char *libname);
+       struct dyn_elf **rpnt, const char *libname);
 extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
        int trace_loaded_objects);
 extern int _dl_linux_resolve(void);
-extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
 extern void _dl_protect_relro (struct elf_resolve *l);
 
 /*
@@ -84,24 +85,47 @@ extern void _dl_protect_relro (struct elf_resolve *l);
 #endif
 
 /* OS and/or GNU dynamic extensions */
+
+#define OS_NUM_BASE 1                  /* for DT_RELOCCOUNT */
+
 #ifdef __LDSO_GNU_HASH_SUPPORT__
-# define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */
+# define OS_NUM_GNU_HASH       1   /* for DT_GNU_HASH entry */
+#else
+# define OS_NUM_GNU_HASH       0
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+# define OS_NUM_PRELINK                6   /* for DT_GNU_PRELINKED entry */
 #else
-# define OS_NUM 1 /* for DT_RELOCCOUNT entry */
+# define OS_NUM_PRELINK        0
 #endif
 
+#define OS_NUM   (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK)
+
 #ifndef ARCH_DYNAMIC_INFO
   /* define in arch specific code, if needed */
 # define ARCH_NUM 0
 #endif
 
-#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
+#define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
 /* Keep ARCH specific entries into dynamic section at the end of the array */
 #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
 /* GNU hash comes just after the relocation count */
 # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
+#else
+# define DT_GNU_HASH_IDX DT_RELCONT_IDX
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+/* GNU prelink comes just after the GNU hash if present */
+#define DT_GNU_PRELINKED_IDX  (DT_GNU_HASH_IDX + 1)
+#define DT_GNU_CONFLICT_IDX   (DT_GNU_HASH_IDX + 2)
+#define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3)
+#define DT_GNU_LIBLIST_IDX    (DT_GNU_HASH_IDX + 4)
+#define DT_GNU_LIBLISTSZ_IDX  (DT_GNU_HASH_IDX + 5)
+#define DT_CHECKSUM_IDX       (DT_GNU_HASH_IDX + 6)
 #endif
 
 extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
@@ -150,6 +174,20 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
                        if (dpnt->d_tag == DT_GNU_HASH)
                                dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
 #endif
+#ifdef __LDSO_PRELINK_SUPPORT__
+                       if (dpnt->d_tag == DT_GNU_PRELINKED)
+                               dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_GNU_CONFLICT)
+                               dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr;
+                       if (dpnt->d_tag == DT_GNU_CONFLICTSZ)
+                               dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_GNU_LIBLIST)
+                               dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr;
+                       if (dpnt->d_tag == DT_GNU_LIBLISTSZ)
+                               dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_CHECKSUM)
+                               dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val;
+#endif
                }
 #ifdef ARCH_DYNAMIC_INFO
                else {
index 34bed1b..b1927e4 100644 (file)
@@ -25,6 +25,19 @@ 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.  */
+struct r_scope_elem {
+  struct elf_resolve **r_list; /* Array of maps for the scope.  */
+  unsigned int r_nlist;        /* Number of entries in the scope.  */
+  struct r_scope_elem *next;
+};
+
 struct elf_resolve {
   /* These entries must be in this order to be compatible with the interface used
      by gdb to obtain the list of symbols. */
@@ -60,8 +73,13 @@ struct elf_resolve {
 #endif
 
   ElfW(Addr) mapaddr;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+  /* Store the entry point from the ELF header (e_entry) */
+  ElfW(Addr) l_entry;
+#endif
   enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
-  struct dyn_elf * symbol_scope;
+  /* This is the local scope of the shared object */
+  struct r_scope_elem symbol_scope;
   unsigned short usage_count;
   unsigned short int init_flag;
   unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
@@ -128,6 +146,7 @@ struct elf_resolve {
 #define INIT_FUNCS_CALLED   0x000004
 #define FINI_FUNCS_CALLED   0x000008
 #define DL_OPENED          0x000010
+#define DL_RESERVED        0x000020
 
 extern struct dyn_elf     * _dl_symbol_tables;
 extern struct elf_resolve * _dl_loaded_modules;
@@ -139,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, tpntp) _dl_lookup_hash(n, r, m, c)
-# define _dl_find_hash(n, r, m, t, tpntp) _dl_find_hash(n, r, m, t)
+# define _dl_lookup_hash(n, r, m, s, c, tpnt) _dl_lookup_hash(n, r, m, s, c)
+# define _dl_find_hash(n, r, m, s, t, tpntp) _dl_find_hash(n, r, m, s, t)
 #endif
-extern char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt,
-               struct elf_resolve *mytpnt, int type_class,
+extern char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope,
+               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 dyn_elf *rpnt,
-               struct elf_resolve *mytpnt, int type_class,
+static __always_inline char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
+               struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
                struct elf_resolve **tpntp)
 {
-       return _dl_lookup_hash(name, rpnt, mytpnt, type_class, tpntp);
+       return _dl_lookup_hash(name, scope, mytpnt, symbol, type_class, tpntp);
 }
 
 extern int _dl_linux_dynamic_link(void);
index 69b5dd7..9aa610e 100644 (file)
@@ -27,6 +27,7 @@
 /* Pull in compiler and arch stuff */
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stddef.h> /* for ptrdiff_t */
 #define _FCNTL_H
 #include <bits/fcntl.h>
 #include <bits/wordsize.h>
@@ -72,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);
@@ -144,7 +151,7 @@ extern void _dl_dprintf(int, const char *, ...);
 # define DL_GET_READY_TO_RUN_EXTRA_ARGS
 #endif
 
-extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
                DL_GET_READY_TO_RUN_EXTRA_PARMS);
 
index e71ae15..c9dcebd 100644 (file)
@@ -62,8 +62,16 @@ ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS)
 lib-so-y += $(ldso)
 objclean-y += CLEAN_ldso/ldso
 
+ifeq ($(LDSO_PRELINK_SUPPORT),y)
+# Use a specific linker script for ld.so
+LDFLAGS-$(UCLIBC_LDSO_NAME).so += -T $(ldso:.$(ABI_VERSION)=).lds
+endif
+
 $(ldso): $(ldso:.$(ABI_VERSION)=)
 $(ldso:.$(ABI_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a
+ifeq ($(LDSO_PRELINK_SUPPORT),y)
+       $(call create-lds)
+endif
        $(call link.so,$(ldso_FULL_NAME),$(ABI_VERSION))
 
 $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y)
index adc282a..ee2d1e5 100644 (file)
@@ -69,8 +69,8 @@ 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, tpnt->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);
@@ -99,9 +99,9 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        int i;
@@ -181,7 +181,7 @@ fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
 #endif
 
 static int
-_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -192,6 +192,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        struct elf_resolve *def_mod = 0;
        int goof = 0;
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
 
        reloc_type = ELF32_R_TYPE(rpnt->r_info);
@@ -202,7 +204,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                        (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other)
                         != STV_PROTECTED)) {
                symbol_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                       scope, tpnt, elf_machine_type_class(reloc_type), &def_mod);
+                       scope, tpnt, &current_value, elf_machine_type_class(reloc_type), &def_mod);
 
                /*
                 * We want to allow undefined references to weak symbols - this might
@@ -215,6 +217,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                        return 1;
 
                }
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                       &current_value, elf_machine_type_class(reloc_type));
        } else {
                /*
                 * Relocs against STN_UNDEF are usually treated as using a
@@ -311,7 +316,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 }
 
 static int
-_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -350,8 +355,8 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size)
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
 
index 797f851..e741fd6 100644 (file)
@@ -51,8 +51,8 @@ unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)
        symname = strtab + sym->st_name;
 
        new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
-                                                tpnt->symbol_scope, tpnt,
-                                                resolver);
+                                                &_dl_loaded_modules->symbol_scope, tpnt,
+                                                NULL, 0, resolver);
 
        entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
        *entry = new_addr;
@@ -63,9 +63,9 @@ unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_func)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        Elf32_Sym *symtab;
@@ -116,7 +116,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
        return 0;
 }
 
-static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+static int _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                        Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -128,6 +128,8 @@ static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
        reloc_type = ELF32_R_TYPE(rpnt->r_info);
        symtab_index = ELF32_R_SYM(rpnt->r_info);
@@ -137,7 +139,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        if (symtab_index) {
                symbol_addr = (unsigned long)
                        _dl_find_hash(strtab + symtab[symtab_index].st_name,
-                                     tpnt->symbol_scope, tpnt,
+                                     scope, tpnt, &current_value,
                                      elf_machine_type_class(reloc_type), NULL);
 
                /* Allow undefined references to weak symbols */
@@ -147,6 +149,9 @@ static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                                    _dl_progname, symname);
                        return 0;
                }
+               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__)
@@ -185,9 +190,10 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                    struct r_scope_elem *scope,
                                     unsigned long rel_addr,
                                     unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size,
                         _dl_do_reloc);
 }
index e8d88bd..466a3b4 100644 (file)
@@ -65,9 +65,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
        got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
 
        /* Get the address to be used to fill in the GOT entry.  */
-       new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt);
+       new_addr = _dl_lookup_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, NULL, 0, &new_tpnt);
        if (!new_addr) {
-               new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt);
+               new_addr = _dl_lookup_hash(symname, NULL, NULL, NULL, 0, &new_tpnt);
                if (!new_addr) {
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
                                    _dl_progname, symname);
@@ -99,9 +99,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
 {
        unsigned int i;
@@ -150,7 +150,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
              ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -166,6 +166,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr   = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
        __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr));
        reloc_type   = ELF_R_TYPE(rpnt->r_info);
@@ -179,7 +181,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        } else {
 
                symbol_addr = (unsigned long)
-                 _dl_lookup_hash(symname, scope, NULL, 0, &symbol_tpnt);
+                 _dl_lookup_hash(symname, scope, NULL, &current_value, 0, &symbol_tpnt);
 
                /*
                 * We want to allow undefined references to weak symbols - this might
@@ -192,6 +194,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                                     _dl_progname, strtab + symtab[symtab_index].st_name);
                        _dl_exit (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__)
@@ -275,7 +280,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
 static int
 _dl_do_lazy_reloc (struct elf_resolve *tpnt,
-                  struct dyn_elf *scope __attribute__((unused)),
+                  struct r_scope_elem *scope __attribute__((unused)),
                   ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)),
                   char *strtab __attribute__((unused)))
 {
@@ -321,9 +326,9 @@ _dl_parse_lazy_relocation_information
 
 int
 _dl_parse_relocation_information
-(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-  return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+  return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
 
 /* We don't have copy relocs.  */
index 32ea2da..48802aa 100644 (file)
@@ -66,7 +66,7 @@ _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, tpnt->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);
                _dl_exit(1);
@@ -91,9 +91,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                           ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        int symtab_index;
@@ -150,7 +150,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -162,6 +162,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       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);
        symtab_index = ELF32_R_SYM(rpnt->r_info);
@@ -174,15 +176,17 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                        symbol_addr = (unsigned long)tpnt->loadaddr;
                } else {
                  symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
-                                                                  elf_machine_type_class(reloc_type), NULL);
+                       &current_value, elf_machine_type_class(reloc_type), NULL);
                }
 
                if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                        _dl_exit(1);
                }
-
                symbol_addr += rpnt->r_addend;
+               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__)
@@ -227,7 +231,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -279,8 +283,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                struct r_scope_elem *scope,
                                 unsigned long rel_addr,
                                 unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index 7ce8bfb..47b3231 100644 (file)
@@ -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
index 5562e07..d72dd5a 100644 (file)
@@ -322,7 +322,7 @@ goof:
  */
 
 struct elf_resolve *_dl_load_elf_shared_library(int secure,
-       struct dyn_elf **rpnt, char *libname)
+       struct dyn_elf **rpnt, const char *libname)
 {
        ElfW(Ehdr) *epnt;
        unsigned long dynamic_addr = 0;
@@ -343,7 +343,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        size_t relro_size = 0;
        struct stat st;
        uint32_t *p32;
-       DL_LOADADDR_TYPE lib_loadaddr;
+       DL_LOADADDR_TYPE lib_loadaddr = 0;
        DL_INIT_LOADADDR_EXTRA_DECLS
 
        libaddr = 0;
@@ -397,11 +397,15 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                return NULL;
        }
 
-       if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1
+       if ((epnt->e_type != ET_DYN
+#ifdef __LDSO_STANDALONE_SUPPORT__
+               && epnt->e_type != ET_EXEC
+#endif
+               ) || (epnt->e_machine != MAGIC1
 #ifdef MAGIC2
                                && epnt->e_machine != MAGIC2
 #endif
-                               ))
+                       ))
        {
                _dl_internal_error_number =
                        (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
@@ -426,7 +430,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
                if (ppnt->p_type == PT_LOAD) {
                        /* See if this is a PIC library. */
-                       if (i == 0 && ppnt->p_vaddr > 0x1000000) {
+                       if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
                                piclib = 0;
                                minvma = ppnt->p_vaddr;
                        }
@@ -462,14 +466,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                ppnt++;
        }
 
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       if (epnt->e_type == ET_EXEC)
+               piclib = 0;
+#endif
+
        DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
 
        maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
        minvma = minvma & ~0xffffU;
 
        flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
-       if (!piclib)
-               flags |= MAP_FIXED;
 
        if (piclib == 0 || piclib == 1) {
                status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
@@ -488,7 +495,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        /* Get the memory to store the library */
        ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 
-       DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum);
+       DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
 
        for (i = 0; i < epnt->e_phnum; i++) {
                if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
@@ -510,12 +517,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                        char *tryaddr;
                        ssize_t size;
 
-                       /* See if this is a PIC library. */
-                       if (i == 0 && ppnt->p_vaddr > 0x1000000) {
-                               piclib = 0;
-                               /* flags |= MAP_FIXED; */
-                       }
-
                        if (ppnt->p_flags & PF_W) {
                                unsigned long map_size;
                                char *cpnt;
@@ -559,7 +560,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                                  }
 
                                tryaddr = piclib == 2 ? piclib2map
-                                 : ((char*) (piclib ? libaddr : 0) +
+                                 : ((char*) (piclib ? libaddr : lib_loadaddr) +
                                     (ppnt->p_vaddr & PAGE_ALIGN));
 
                                size = (ppnt->p_vaddr & ADDR_ALIGN)
@@ -644,7 +645,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
                                if (map_size < ppnt->p_vaddr + ppnt->p_memsz
                                    && !piclib2map) {
-                                       tryaddr = map_size + (char*)(piclib ? libaddr : 0);
+                                       tryaddr = map_size + (char*)(piclib ? libaddr : lib_loadaddr);
                                        status = (char *) _dl_mmap(tryaddr,
                                                ppnt->p_vaddr + ppnt->p_memsz - map_size,
                                                LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
@@ -655,7 +656,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                        } else {
                                tryaddr = (piclib == 2 ? 0
                                           : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
-                                          + (piclib ? libaddr : 0));
+                                          + (piclib ? libaddr : lib_loadaddr));
                                size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
                                status = (char *) _dl_mmap
                                           (tryaddr, size, LXFLAGS(ppnt->p_flags),
@@ -679,8 +680,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        }
        _dl_close(infile);
 
-       /* For a non-PIC library, the addresses are all absolute */
-       if (piclib) {
+       /*
+        * The dynamic_addr must be take into acount lib_loadaddr value, to note
+        * it is zero when the SO has been mapped to the elf's physical addr
+        */
+       if (lib_loadaddr) {
                dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
        }
 
@@ -711,7 +715,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
                for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
                        if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
-                               _dl_mprotect((void *) ((piclib ? libaddr : 0) +
+                               _dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) +
                                                        (ppnt->p_vaddr & PAGE_ALIGN)),
                                                (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
                                                PROT_READ | PROT_WRITE | PROT_EXEC);
@@ -727,13 +731,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
        tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
                        dynamic_addr, 0);
+       tpnt->mapaddr = libaddr;
        tpnt->relro_addr = relro_addr;
        tpnt->relro_size = relro_size;
        tpnt->st_dev = st.st_dev;
        tpnt->st_ino = st.st_ino;
-       tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
+       tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
        tpnt->n_phent = epnt->e_phnum;
        tpnt->rtld_flags |= rtld_flags;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       tpnt->l_entry = epnt->e_entry;
+#endif
 
 #if defined(USE_TLS) && USE_TLS
        if (tlsppnt) {
@@ -755,7 +763,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                tpnt->l_tls_modid = _dl_next_tls_modid ();
 
                /* We know the load address, so add it to the offset. */
+#ifdef __LDSO_STANDALONE_SUPPORT__
+               if ((tpnt->l_tls_initimage != NULL) && piclib)
+#else
                if (tpnt->l_tls_initimage != NULL)
+#endif
                {
 # ifdef __SUPPORT_LD_DEBUG_EARLY__
                        unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
@@ -772,7 +784,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        /*
         * Add this object into the symbol chain
         */
-       if (*rpnt) {
+       if (*rpnt
+#ifdef __LDSO_STANDALONE_SUPPORT__
+               /* Do not create a new chain entry for the main executable */
+               && (*rpnt)->dyn
+#endif
+               ) {
                (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
                _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
                (*rpnt)->next->prev = (*rpnt);
@@ -789,9 +806,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        }
 #endif
        (*rpnt)->dyn = tpnt;
-       tpnt->symbol_scope = _dl_symbol_tables;
        tpnt->usage_count++;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
+#else
        tpnt->libtype = elf_lib;
+#endif
 
        /*
         * OK, the next thing we need to do is to insert the dynamic linker into
@@ -817,7 +837,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 }
 
 /* now_flag must be RTLD_NOW or zero */
-int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
+int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
 {
        int goof = 0;
        struct elf_resolve *tpnt;
@@ -825,7 +845,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
        ElfW(Addr) reloc_addr;
 
        if (rpnt->next)
-               goof = _dl_fixup(rpnt->next, now_flag);
+               goof = _dl_fixup(rpnt->next, scope, now_flag);
        if (goof)
                return goof;
        tpnt = rpnt->dyn;
@@ -852,10 +872,15 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
                relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
                if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
                        reloc_size -= relative_count * sizeof(ELF_RELOC);
-                       elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
+                       if (tpnt->loadaddr
+#ifdef __LDSO_PRELINK_SUPPORT__
+                               || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
+#endif
+                               )
+                               elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
                        reloc_addr += relative_count * sizeof(ELF_RELOC);
                }
-               goof += _dl_parse_relocation_information(rpnt,
+               goof += _dl_parse_relocation_information(rpnt, scope,
                                reloc_addr,
                                reloc_size);
                tpnt->init_flag |= RELOCS_DONE;
@@ -871,7 +896,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
                                        tpnt->dynamic_info[DT_JMPREL],
                                        tpnt->dynamic_info [DT_PLTRELSZ]);
                } else {
-                       goof += _dl_parse_relocation_information(rpnt,
+                       goof += _dl_parse_relocation_information(rpnt, scope,
                                        tpnt->dynamic_info[DT_JMPREL],
                                        tpnt->dynamic_info[DT_PLTRELSZ]);
                }
index 0048734..bb4c56b 100644 (file)
@@ -146,7 +146,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
                tpnt->chains = hash_addr;
        }
        tpnt->loadaddr = loadaddr;
-       tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0);
        for (i = 0; i < DYNAMIC_SIZE; i++)
                tpnt->dynamic_info[i] = dynamic_info[i];
        return tpnt;
@@ -268,72 +267,81 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long
  * This function resolves externals, and this is either called when we process
  * relocations or when we call an entry in the PLT table for the first time.
  */
-char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt,
-       int type_class, struct elf_resolve **tpntp)
+char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
+       struct sym_val *symbol, int type_class, struct elf_resolve **tpntp)
 {
        struct elf_resolve *tpnt = NULL;
        ElfW(Sym) *symtab;
+       int i = 0;
 
        unsigned long elf_hash_number = 0xffffffff;
        const ElfW(Sym) *sym = NULL;
 
        char *weak_result = NULL;
+       struct r_scope_elem *loop_scope;
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
        unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
 #endif
 
-       for (; rpnt; rpnt = rpnt->next) {
-               tpnt = rpnt->dyn;
-
-               if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
-                       if (mytpnt == tpnt)
-                               ;
-                       else {
-                               struct init_fini_list *tmp;
-
-                               for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
-                                       if (tmp->tpnt == tpnt)
-                                               break;
+       for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) {
+               for (i = 0; i < loop_scope->r_nlist; i++) {
+                       tpnt = loop_scope->r_list[i];
+
+                       if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
+                               if (mytpnt == tpnt)
+                                       ;
+                               else {
+                                       struct init_fini_list *tmp;
+
+                                       for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
+                                               if (tmp->tpnt == tpnt)
+                                                       break;
+                                       }
+                                       if (!tmp)
+                                               continue;
                                }
-                               if (!tmp)
-                                       continue;
                        }
-               }
-               /* Don't search the executable when resolving a copy reloc. */
-               if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
-                       continue;
+                       /* Don't search the executable when resolving a copy reloc. */
+                       if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+                               continue;
 
-               /* If the hash table is empty there is nothing to do here.  */
-               if (tpnt->nbucket == 0)
-                       continue;
+                       /* If the hash table is empty there is nothing to do here.  */
+                       if (tpnt->nbucket == 0)
+                               continue;
 
-               symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
+                       symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
-               /* Prefer GNU hash style, if any */
-               if (tpnt->l_gnu_bitmask) {
-                       sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
-                       if (sym != NULL)
-                               /* If sym has been found, do not search further */
-                               break;
-               } else {
+                       /* Prefer GNU hash style, if any */
+                       if (tpnt->l_gnu_bitmask) {
+                               sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
+                               if (sym != NULL)
+                                       /* If sym has been found, do not search further */
+                                       break;
+                       } else {
 #endif
-               /* Use the old SysV-style hash table */
+                               /* Use the old SysV-style hash table */
 
-               /* Calculate the old sysv hash number only once */
-               if (elf_hash_number == 0xffffffff)
-                       elf_hash_number = _dl_elf_hash((const unsigned char *)name);
+                               /* Calculate the old sysv hash number only once */
+                               if (elf_hash_number == 0xffffffff)
+                                       elf_hash_number = _dl_elf_hash((const unsigned char *)name);
 
-               sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
-               if (sym != NULL)
-                       break;
+                               sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
+                               if (sym != NULL)
+                                       /* If sym has been found, do not search further */
+                                       break;
 #ifdef __LDSO_GNU_HASH_SUPPORT__
-               }
+                       }
 #endif
-       } /* end of for (; rpnt; rpnt = rpnt->next) { */
+               } /* End of inner for */
+       }
 
        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) {
index a51b583..4799846 100644 (file)
 /* Pull in all the arch specific stuff */
 #include "dl-startup.h"
 
+#ifdef __LDSO_PRELINK_SUPPORT__
+/* These defined magically in the linker script.  */
+extern char _begin[] attribute_hidden;
+#endif
+
 /* Static declarations */
 static int (*_dl_elf_main) (int, char **, char **);
 
@@ -164,11 +169,26 @@ DL_START(unsigned long args)
                aux_dat += 2;
        }
 
-       /* locate the ELF header.   We need this done as soon as possible
-        * (esp since SEND_STDERR() needs this on some platforms... */
+       /*
+        * Locate the dynamic linker ELF header. We need this done as soon as
+        * possible (esp since SEND_STDERR() needs this on some platforms...
+        */
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+       /*
+        * The `_begin' symbol created by the linker script points to ld.so ELF
+        * We use it if the kernel is not passing a valid address through the auxvt.
+        */
+
+       if (!auxvt[AT_BASE].a_un.a_val)
+               auxvt[AT_BASE].a_un.a_val =  (Elf32_Addr) &_begin;
+       /* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */
+       DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address());
+#else
        if (!auxvt[AT_BASE].a_un.a_val)
                auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();
        DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);
+#endif
        header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
 
        /* Check the ELF header to make sure everything looks ok.  */
@@ -183,7 +203,7 @@ DL_START(unsigned long args)
                _dl_exit(0);
        }
        SEND_EARLY_STDERR_DEBUG("ELF header=");
-       SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1);
+       SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1);
 
        /* Locate the global offset table.  Since this code must be PIC
         * we can take advantage of the magic offset register, if we
@@ -192,7 +212,7 @@ DL_START(unsigned long args)
        DL_BOOT_COMPUTE_GOT(got);
 
        /* Now, finally, fix up the location of the dynamic stuff */
-       DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr);
+       DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)header);
 
        SEND_EARLY_STDERR_DEBUG("First Dynamic section entry=");
        SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
@@ -258,7 +278,12 @@ DL_START(unsigned long args)
 
                        if (!indx && relative_count) {
                                rel_size -= relative_count * sizeof(ELF_RELOC);
-                               elf_machine_relative(load_addr, rel_addr, relative_count);
+                               if (load_addr
+#ifdef __LDSO_PRELINK_SUPPORT__
+                                       || !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]
+#endif
+                                       )
+                                       elf_machine_relative(load_addr, rel_addr, relative_count);
                                rel_addr += relative_count * sizeof(ELF_RELOC);
                        }
 
@@ -321,12 +346,12 @@ DL_START(unsigned long args)
 
        __rtld_stack_end = (void *)(argv - 1);
 
-       _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv
-                            DL_GET_READY_TO_RUN_EXTRA_ARGS);
+       _dl_elf_main = (int (*)(int, char **, char **))
+                       _dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, auxvt, envp, argv
+                                            DL_GET_READY_TO_RUN_EXTRA_ARGS);
 
        /* Transfer control to the application.  */
        SEND_STDERR_DEBUG("transfering control to application @ ");
-       _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val;
        SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);
 
 #if !defined(START)
index 4b94033..726b58b 100644 (file)
@@ -54,7 +54,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
          DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr);
 
        /* Get the address to be used to fill in the GOT entry.  */
-       new_addr = _dl_find_hash_mod(symname, tpnt->symbol_scope, NULL, 0,
+       new_addr = _dl_find_hash_mod(symname, &_dl_loaded_modules->symbol_scope, NULL, 0,
                                     &new_tpnt);
        if (!new_addr) {
                new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0,
@@ -91,9 +91,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        unsigned int i;
@@ -146,7 +146,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -276,7 +276,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
 static int
 _dl_do_lazy_reloc (struct elf_resolve *tpnt,
-                  struct dyn_elf *scope __attribute_used__,
+                  struct r_scope_elem *scope __attribute_used__,
                   ELF_RELOC *rpnt, Elf32_Sym *symtab __attribute_used__,
                   char *strtab __attribute_used__)
 {
@@ -325,9 +325,9 @@ _dl_parse_lazy_relocation_information
 
 int
 _dl_parse_relocation_information
-(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-  return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+  return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
 
 /* We don't have copy relocs.  */
index 1e3a2b2..0c821ce 100644 (file)
@@ -71,7 +71,7 @@ _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, tpnt->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' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@ -98,9 +98,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                           ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        unsigned int i;
@@ -156,7 +156,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -169,6 +169,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       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);
        symtab_index = ELF32_R_SYM(rpnt->r_info);
@@ -179,7 +181,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
            (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other)
             != STV_PROTECTED)) {
                symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
-                                                          elf_machine_type_class(reloc_type), &tls_tpnt);
+                               &current_value, elf_machine_type_class(reloc_type), &tls_tpnt);
 
                /*
                 * We want to allow undefined references to weak symbols - this
@@ -189,6 +191,10 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
                                        && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
                        return 1;
+
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                       &current_value, elf_machine_type_class(reloc_type));
        } else {
                if (symtab_index)
                        symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
@@ -198,7 +204,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                tls_tpnt = tpnt;
        }
        
-
 #if defined (__SUPPORT_LD_DEBUG__)
        old_val = *reloc_addr;
 #endif
@@ -268,7 +273,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -317,8 +322,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                struct r_scope_elem *scope,
                                 unsigned long rel_addr,
                                 unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index ea4ad0f..e0d323a 100644 (file)
@@ -57,6 +57,12 @@ 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 */
+bool prelinked                                 = false;
+#endif
 static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
 
 #ifdef __SUPPORT_LD_DEBUG__
@@ -70,8 +76,18 @@ char *_dl_debug_bindings  = NULL;
 int   _dl_debug_file      = 2;
 #endif
 
-/* Needed for standalone execution. */
+#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
+/* Not hidden, needed for standalone execution. */
+/*
+ * FIXME: align dl_start for SH to other archs so that we can keep this symbol
+ *        hidden and we don't need to handle in __uClibc_main
+ */
+
+unsigned long _dl_skip_args = 0;
+#else
 unsigned long attribute_hidden _dl_skip_args = 0;
+#endif
+
 const char *_dl_progname = UCLIBC_LDSO;      /* The name of the executable being run */
 #include "dl-startup.c"
 #include "dl-symbols.c"
@@ -97,6 +113,7 @@ static unsigned char *_dl_malloc_addr = NULL;        /* Lets _dl_malloc use the already
 static unsigned char *_dl_mmap_zero   = NULL;  /* Also used by _dl_malloc */
 
 static struct elf_resolve **init_fini_list;
+static struct elf_resolve **scope_elem_list;
 static unsigned int nlist; /* # items in init_fini_list */
 extern void _start(void);
 
@@ -274,20 +291,101 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
        }
 }
 
-void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
-                         ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
-                         char **argv
+#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 struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
+                                                                        DL_LOADADDR_TYPE load_addr,
+                                                                        ElfW(auxv_t) auxvt[AT_EGID + 1],
+                                                                        struct dyn_elf *rpnt)
+{
+               ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+               ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
+                                                               DL_RELOC_ADDR(load_addr, epnt->e_phoff);
+               int j;
+               struct stat st;
+
+               tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
+                                             tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
+                                             0);
+
+               tpnt->mapaddr = load_addr;
+               if (_dl_stat(tpnt->libname, &st) >= 0) {
+                       tpnt->st_dev = st.st_dev;
+                       tpnt->st_ino = st.st_ino;
+               }
+               tpnt->n_phent = epnt->e_phnum;
+               tpnt->ppnt = myppnt;
+               for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
+                       if (myppnt->p_type ==  PT_GNU_RELRO) {
+                               tpnt->relro_addr = myppnt->p_vaddr;
+                               tpnt->relro_size = myppnt->p_memsz;
+                               break;
+                       }
+               }
+               tpnt->libtype = program_interpreter;
+               if (rpnt) {
+                       rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
+                       rpnt->next->prev = rpnt;
+                       rpnt = rpnt->next;
+               } else {
+                       rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+               }
+               rpnt->dyn = tpnt;
+               tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
+
+       return tpnt;
+}
+
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+                                                                               struct elf_resolve *map)
+{
+       struct elf_resolve **p = list;
+       struct init_fini_list *q;
+
+       *p++ = map;
+       map->init_flag |= DL_RESERVED;
+       if (map->init_fini)
+               for (q = map->init_fini; q; q = q->next)
+                       if (! (q->tpnt->init_flag & DL_RESERVED))
+                               p += _dl_build_local_scope (p, q->tpnt);
+       return p - list;
+}
+
+void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+                         ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
                          DL_GET_READY_TO_RUN_EXTRA_PARMS)
 {
        ElfW(Addr) app_mapaddr = 0;
        ElfW(Phdr) *ppnt;
        ElfW(Dyn) *dpnt;
        char *lpntstr;
-       unsigned int i;
+       unsigned int i, cnt, k, nscope_elem;
        int unlazy = 0, trace_loaded_objects = 0;
        struct dyn_elf *rpnt;
        struct elf_resolve *tcurr;
        struct elf_resolve *tpnt1;
+       struct elf_resolve *ldso_tpnt = NULL;
        struct elf_resolve app_tpnt_tmp;
        struct elf_resolve *app_tpnt = &app_tpnt_tmp;
        struct r_debug *debug_addr;
@@ -295,7 +393,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
        unsigned long *_dl_envp;                /* The environment address */
        ElfW(Addr) relro_addr = 0;
        size_t relro_size = 0;
-       struct stat st;
+       struct r_scope_elem *global_scope;
+       struct elf_resolve **local_scope;
+
 #if defined(USE_TLS) && USE_TLS
        void *tcbp = NULL;
 #endif
@@ -327,10 +427,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                _dl_progname = argv[0];
        }
 
+#ifndef __LDSO_STANDALONE_SUPPORT__
        if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
-               _dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n");
+               _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
                _dl_exit(1);
        }
+#endif
 
        /* Start to build the tables of the modules that are required for
         * this beast to run.  We start with the basic executable, and then
@@ -382,6 +484,99 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
        _dl_init_static_tls = &_dl_nothread_init_static_tls;
 #endif
 
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+               char *ptmp;
+               unsigned int *aux_dat = (unsigned int *) argv;
+               int argc = aux_dat[-1];
+
+               tpnt->libname = argv[0];
+               while (argc > 1)
+                       if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
+                               _dl_library_path = argv[2];
+                               _dl_skip_args += 2;
+                               argc -= 2;
+                               argv += 2;
+                       } else
+                               break;
+
+       /*
+        * If we have no further argument the program was called incorrectly.
+        * Grant the user some education.
+        */
+
+               if (argc < 2) {
+                       _dl_dprintf(1, "\
+Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
+You have invoked `ld.so', the helper program for shared library executables.\n\
+This program usually lives in the file `/lib/ld.so', and special directives\n\
+in executable files using ELF shared libraries tell the system's program\n\
+loader to load the helper program from this file.  This helper program loads\n\
+the shared libraries needed by the program executable, prepares the program\n\
+to run, and runs it.  You may invoke this helper program directly from the\n\
+command line to load and run an ELF executable file; this is like executing\n\
+that file itself, but always uses this helper program from the file you\n\
+specified, instead of the helper program file specified in the executable\n\
+file you run.  This is mostly of use for maintainers to test new versions\n\
+of this helper program; chances are you did not intend to run this program.\n\
+\n\
+  --library-path PATH   use given PATH instead of content of the environment\n\
+                        variable LD_LIBRARY_PATH\n");
+                       _dl_exit(1);
+               }
+
+               ++_dl_skip_args;
+               ++argv;
+               _dl_progname = argv[0];
+
+               _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+               /*
+                * It needs to load the _dl_progname and to map it
+                * Usually it is the main application launched by means of the ld.so
+                * but it could be also a shared object (when ld.so used for tracing)
+                * We keep the misleading app_tpnt name to avoid variable pollution
+                */
+               app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
+               if (!app_tpnt) {
+                       _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
+                       _dl_exit(16);
+               }
+               /*
+                * FIXME: it needs to properly handle a PIE executable
+                * Usually for a main application, loadaddr is computed as difference
+                * between auxvt entry points and phdr, so if it is not 0, that it is a
+                * PIE executable. In this case instead we need to set the loadaddr to 0
+                * because we are actually mapping the ELF for the main application by
+                * ourselves. So the PIE case must be checked.
+                */
+
+               app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
+
+               /*
+                * This is used by gdb to locate the chain of shared libraries that are
+                * currently loaded.
+                */
+               debug_addr = _dl_zalloc(sizeof(struct r_debug));
+               ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
+               for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
+                       if (ppnt->p_type == PT_DYNAMIC) {
+                               dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
+                               _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
+                       }
+               }
+
+               /* Store the path where the shared lib loader was found
+                * for later use
+                */
+               _dl_ldsopath = _dl_strdup(tpnt->libname);
+               ptmp = _dl_strrchr(_dl_ldsopath, '/');
+               if (ptmp != _dl_ldsopath)
+                       *ptmp = '\0';
+
+               _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
+       } else {
+#endif
+
        /* At this point we are now free to examine the user application,
         * and figure out which libraries are supposed to be called.  Until
         * we have this list, we will not be completely ready for dynamic
@@ -469,7 +664,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                        app_tpnt->mapaddr = app_mapaddr;
                        app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
                        app_tpnt->usage_count++;
-                       app_tpnt->symbol_scope = _dl_symbol_tables;
                        lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
 #ifdef ALLOW_ZERO_PLTGOT
                        if (lpnt)
@@ -530,14 +724,18 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
         * case the executable is actually an ET_DYN object.
         */
        if (app_tpnt->l_tls_initimage != NULL) {
+               unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
                app_tpnt->l_tls_initimage =
                        (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
                _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
-                       (unsigned int)app_tpnt->l_tls_initimage,
-                       app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
+                       tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
        }
 #endif
 
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       } /* ! ldso standalone mode */
+#endif
+
 #ifdef __SUPPORT_LD_DEBUG__
        _dl_debug = _dl_getenv("LD_DEBUG", envp);
        if (_dl_debug) {
@@ -586,6 +784,16 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
        }
 #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++;
        }
@@ -639,7 +847,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                                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
@@ -653,7 +861,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                                        _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
@@ -730,7 +938,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                        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
@@ -744,7 +952,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                                _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,
@@ -775,14 +983,21 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 
                                lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
                                name = _dl_get_last_path_component(lpntstr);
-                               if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
-                                       continue;
-
                                _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname);
 
-                               if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) {
+                               if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
+                                               if (!ldso_tpnt) {
+                                                       /* Insert the ld.so only once */
+                                                       ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+                                               }
+                                               ldso_tpnt->usage_count++;
+                                               tpnt1 = ldso_tpnt;
+                               } else
+                                       tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 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", lpntstr);
                                                continue;
                                        } else
@@ -803,7 +1018,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                                _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,
@@ -815,12 +1030,18 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
        }
        _dl_unmap_cache();
 
-       --nlist; /* Exclude the application. */
+       /* Keep track of the number of elements in the global scope */
+       nscope_elem = nlist;
+
+       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) {
@@ -866,41 +1087,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
         * functions in the dynamic linker and to relocate the interpreter
         * again once all libs are loaded.
         */
-       if (tpnt) {
-               ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
-               ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff);
-               int j;
-
-               tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr,
-                                             tpnt->dynamic_info,
-                                             (unsigned long)tpnt->dynamic_addr,
-                                             0);
-
-               if (_dl_stat(tpnt->libname, &st) >= 0) {
-                       tpnt->st_dev = st.st_dev;
-                       tpnt->st_ino = st.st_ino;
-               }
-               tpnt->n_phent = epnt->e_phnum;
-               tpnt->ppnt = myppnt;
-               for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
-                       if (myppnt->p_type ==  PT_GNU_RELRO) {
-                               tpnt->relro_addr = myppnt->p_vaddr;
-                               tpnt->relro_size = myppnt->p_memsz;
-                               break;
-                       }
-               }
-               tpnt->libtype = program_interpreter;
+       if (!ldso_tpnt) {
+               tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
                tpnt->usage_count++;
-               tpnt->symbol_scope = _dl_symbol_tables;
-               if (rpnt) {
-                       rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
-                       rpnt->next->prev = rpnt;
-                       rpnt = rpnt->next;
-               } else {
-                       rpnt = _dl_zalloc(sizeof(struct dyn_elf));
-               }
-               rpnt->dyn = tpnt;
-               tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
+               nscope_elem++;
+       } else
+               tpnt = ldso_tpnt;
+
 #ifdef RERELOCATE_LDSO
                /* Only rerelocate functions for now. */
                tpnt->init_flag = RELOCS_DONE;
@@ -913,16 +1106,43 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
 #endif
                tpnt = NULL;
+
+       /*
+        * Allocate the global scope array.
+        */
+       scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+
+       for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
+               scope_elem_list[i++] = tcurr;
+
+       _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
+       _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
+       /*
+        * The symbol scope of the application, that is the first entry of the
+        * _dl_loaded_modules list, is just the global scope to be used for the
+        * symbol lookup.
+        */
+       global_scope = &_dl_loaded_modules->symbol_scope;
+
+       /* 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) {
+               cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
+               tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+               tcurr->symbol_scope.r_nlist = cnt;
+               _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
+               /* Restoring the init_flag.*/
+               for (k = 1; k < nscope_elem; k++)
+                       scope_elem_list[k]->init_flag &= ~DL_RESERVED;
        }
 
+       _dl_free(local_scope);
+
 #ifdef __LDSO_LDD_SUPPORT__
-       /* End of the line for ldd.... */
-       if (trace_loaded_objects) {
-               _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));
+       /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
+       if (trace_loaded_objects && !_dl_trace_prelink)
                _dl_exit(0);
-       }
 #endif
 
 #if defined(USE_TLS) && USE_TLS
@@ -952,6 +1172,90 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 # endif
 #endif
 
+#ifdef __LDSO_PRELINK_SUPPORT__
+       if (_dl_trace_prelink) {
+
+               unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1);
+
+               for (i = 0; i < nscope_trace; 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);
+       }
+
+       if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
+               ElfW(Lib) *liblist, *liblistend;
+               struct elf_resolve **r_list, **r_listend, *l;
+               const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
+
+               _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
+               liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
+               liblistend = (ElfW(Lib) *)
+               ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
+               r_list = _dl_loaded_modules->symbol_scope.r_list;
+               r_listend = r_list + nscope_elem;
+
+               for (; r_list < r_listend && liblist < liblistend; r_list++) {
+                       l = *r_list;
+
+                       if (l == _dl_loaded_modules)
+                               continue;
+
+                       /* If the library is not mapped where it should, fail.  */
+                       if (l->loadaddr)
+                               break;
+
+                       /* Next, check if checksum matches.  */
+                       if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
+                               l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
+                               break;
+
+                       if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
+                               (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
+                               break;
+
+                       if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
+                               break;
+
+                       ++liblist;
+               }
+
+
+               if (r_list == r_listend && liblist == liblistend)
+                       prelinked = true;
+
+       }
+
+       _dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
+
+       if (prelinked) {
+               if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
+                       ELF_RELOC *conflict;
+                       unsigned long conflict_size;
+
+                       _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
+                       conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
+                       conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
+                       _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
+                               (unsigned long) conflict, conflict_size);
+               }
+
+               /* Mark all the objects so we know they have been already relocated.  */
+               for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+                       tpnt->init_flag |= RELOCS_DONE;
+                       if (tpnt->relro_size)
+                               _dl_protect_relro (tpnt);
+               }
+       } else
+#endif
+
+       {
 
        _dl_debug_early("Beginning relocation fixups\n");
 
@@ -970,13 +1274,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
         * order so that COPY directives work correctly.
         */
        if (_dl_symbol_tables)
-               if (_dl_fixup(_dl_symbol_tables, unlazy))
+               if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
                        _dl_exit(-1);
 
        for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
                if (tpnt->relro_size)
                        _dl_protect_relro (tpnt);
        }
+       } /* not prelinked */
 
 #if defined(USE_TLS) && USE_TLS
        if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
@@ -1007,7 +1312,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
         * 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", _dl_symbol_tables, 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;
 
@@ -1063,27 +1368,34 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 
        /* 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",
-                       _dl_symbol_tables, 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", _dl_symbol_tables, 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", _dl_symbol_tables, 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", _dl_symbol_tables, 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", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #endif
 
        /* Notify the debugger that all objects are now mapped in.  */
        _dl_debug_addr->r_state = RT_CONSISTENT;
        _dl_debug_state();
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+       if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
+               return (void *) app_tpnt->l_entry;
+       else
+#endif
+               return (void *) auxvt[AT_ENTRY].a_un.a_val;
 }
 
 #include "dl-hash.c"
index 04c301e..195dba5 100644 (file)
@@ -70,7 +70,7 @@ _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, tpnt->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);
                _dl_exit(1);
@@ -94,9 +94,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                           ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
 {
        unsigned int i;
@@ -151,7 +151,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
             ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -164,6 +164,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        ElfW(Addr) old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
        reloc_type = ELF_R_TYPE(rpnt->r_info);
        symtab_index = ELF_R_SYM(rpnt->r_info);
@@ -173,7 +175,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 
        if (symtab_index) {
                symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
-                                                           elf_machine_type_class(reloc_type), NULL);
+                                               &current_value, elf_machine_type_class(reloc_type), NULL);
                /*
                 * We want to allow undefined references to weak symbols - this
                 * might have been intentional.  We should not be linking local
@@ -183,6 +185,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
                        _dl_exit(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__)
@@ -256,7 +261,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 #undef LAZY_RELOC_WORKS
 #ifdef LAZY_RELOC_WORKS
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -305,14 +310,15 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 #ifdef LAZY_RELOC_WORKS
        (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
 #else
-       _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
+       _dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope, rel_addr, rel_size);
 #endif
 }
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                struct r_scope_elem *scope,
                                 unsigned long rel_addr,
                                 unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index a56ee81..2a433e2 100644 (file)
@@ -56,7 +56,7 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index,
        symname = strtab + sym->st_name;
 
        new_addr = (unsigned long) _dl_find_hash(symname,
-                       tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+                       &_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);
@@ -111,7 +111,7 @@ __dl_runtime_pltresolve(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, tpnt->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' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@ -145,7 +145,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *xpnt,
-       unsigned long rel_addr, unsigned long rel_size)
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
        ElfW(Sym) *symtab;
        ELF_RELOC *rpnt;
@@ -161,6 +161,8 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
        unsigned long old_val=0;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        /* Now parse the relocation information */
        rel_size = rel_size / sizeof(ElfW(Rel));
        rpnt = (ELF_RELOC *) rel_addr;
@@ -186,11 +188,14 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
 
                if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
                        symbol_addr = (unsigned long)_dl_find_hash(symname,
-                                                                  tpnt->symbol_scope,
-                                                                  tpnt,
+                                                                  scope,
+                                                                  tpnt, &current_value,
                                                                   elf_machine_type_class(reloc_type), NULL);
                        if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
                                return 1;
+                       if (_dl_trace_prelink)
+                               _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                                       &current_value, elf_machine_type_class(reloc_type));
                }
                if (!symtab_index) {
                        /* Relocs against STN_UNDEF are usually treated as using a
@@ -215,8 +220,8 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                                struct elf_resolve *tpnt_tls = NULL;
 
                                if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
-                                       symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope,
-                                               tpnt, elf_machine_type_class(reloc_type), &tpnt_tls);
+                                       symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
+                                               tpnt, &current_value, elf_machine_type_class(reloc_type), &tpnt_tls);
                                }
                            /* In case of a TLS reloc, tpnt_tls NULL means we have an 'anonymous'
                               symbol.  This is the case for a static tls variable, so the lookup
@@ -314,7 +319,6 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
                                _dl_exit(1);
                        }
                }
-
        }
 #if defined (__SUPPORT_LD_DEBUG__)
        if (_dl_debug_reloc && _dl_debug_detail && reloc_addr)
@@ -358,12 +362,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
                                }
                                else {
                                        *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                               sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+                                               sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
                                }
                        }
                        else if (sym->st_shndx == SHN_COMMON) {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+                                       sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
                        }
                        else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
                                *got_entry != sym->st_value && tmp_lazy) {
@@ -375,7 +379,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
                        }
                        else {
                                *got_entry = (unsigned long) _dl_find_hash(strtab +
-                                       sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+                                       sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
                        }
 
                        got_entry++;
index 855c040..043534e 100644 (file)
@@ -139,7 +139,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
        /* Get the address of the GOT entry */
        finaladdr = (Elf32_Addr) _dl_find_hash(symname,
-                       tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+                       &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely(!finaladdr)) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
                _dl_exit(1);
@@ -182,7 +182,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static __inline__ int
-_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -197,6 +197,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        symbol_addr  = tpnt->loadaddr; /* For R_PPC_RELATIVE */
        reloc_addr   = (Elf32_Addr *)(intptr_t) (symbol_addr + (unsigned long) rpnt->r_offset);
        reloc_type   = ELF32_R_TYPE(rpnt->r_info);
@@ -205,7 +207,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        symname      = strtab + sym->st_name;
        if (symtab_index) {
                symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
-                                                           elf_machine_type_class(reloc_type), &tls_tpnt);
+                                               &current_value, elf_machine_type_class(reloc_type), &tls_tpnt);
                /* We want to allow undefined references to weak symbols - this might
                 * have been intentional.  We should not be linking local symbols
                 * here, so all bases should be covered.
@@ -214,10 +216,14 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                        && (ELF32_ST_TYPE(sym->st_info) != STT_TLS
                                && ELF32_ST_BIND(sym->st_info) != STB_WEAK)))
                        return 1;
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                               &current_value, elf_machine_type_class(reloc_type));
        } else {
                symbol_addr = sym->st_value;
                tls_tpnt = tpnt;
        }
+
 #if defined (__SUPPORT_LD_DEBUG__)
        old_val = *reloc_addr;
 #endif
@@ -385,9 +391,9 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 static __inline__ int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        unsigned int i;
@@ -440,7 +446,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size)
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index 756f6c4..928a84b 100644 (file)
@@ -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, tpnt->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);
@@ -95,9 +95,9 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        unsigned int i;
@@ -148,7 +148,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 
 
 static int
-_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -161,6 +161,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *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);
@@ -170,9 +171,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        if (symtab_index) {
                symname = strtab + symtab[symtab_index].st_name;
                if (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other)
-                        != STV_PROTECTED) {
-                       symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
-                                                               elf_machine_type_class(reloc_type), &tls_tpnt);
+                       != STV_PROTECTED) {
+                       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
                         * have been intentional.  We should not be linking local symbols
@@ -183,7 +184,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                                && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
                                && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
                                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-                                           _dl_progname, strtab + symtab[symtab_index].st_name);
+                                               _dl_progname, strtab + symtab[symtab_index].st_name);
 
                                /* Let the caller to handle the error: it may be non fatal if called from dlopen */
                                return 1;
@@ -192,6 +193,10 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                        /* Resolve protected symbols locally */
                        symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
                                                                                        &symtab[symtab_index]);
+
+               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__)
@@ -257,7 +262,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
 
 static int
-_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -299,7 +304,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size)
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index 74fda04..8f6b320 100644 (file)
@@ -73,7 +73,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 
        /* Get the address of the GOT entry */
-       new_addr = _dl_find_hash(symname, tpnt->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);
@@ -102,10 +102,10 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        return (unsigned long)new_addr;
 }
 
-static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                     unsigned long rel_addr, unsigned long rel_size,
                     int (*reloc_fnc)(struct elf_resolve *tpnt,
-                                     struct dyn_elf *scope,
+                                     struct r_scope_elem *scope,
                                      ELF_RELOC *rpnt, Elf32_Sym *symtab,
                                      char *strtab))
 {
@@ -162,7 +162,7 @@ static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
        return 0;
 }
 
-static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
+static int _dl_do_reloc(struct elf_resolve *tpnt,struct r_scope_elem *scope,
                        ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
         int reloc_type;
@@ -174,6 +174,8 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
        unsigned long old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_type   = ELF32_R_TYPE(rpnt->r_info);
        symtab_index = ELF32_R_SYM(rpnt->r_info);
        symbol_addr  = 0;
@@ -186,7 +188,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
                int stb;
 
                symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
-                                                          elf_machine_type_class(reloc_type), NULL);
+                       &current_value, elf_machine_type_class(reloc_type), NULL);
 
                /*
                 * We want to allow undefined references to weak symbols - this
@@ -200,6 +202,9 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
                                     _dl_progname, strtab + symtab[symtab_index].st_name);
                        _dl_exit (1);
                }
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                               &current_value, elf_machine_type_class(reloc_type));
        }
 
 #ifdef __SUPPORT_LD_DEBUG__
@@ -287,7 +292,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,
        return 0;
 }
 
-static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type, symtab_index, lsb;
@@ -332,7 +337,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 }
 
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size)
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index 56335cb..b33ad91 100644 (file)
@@ -80,7 +80,7 @@ _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, tpnt->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);
                _dl_exit(1);
@@ -107,9 +107,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                unsigned long rel_addr, unsigned long rel_size,
-               int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+               int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                           ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
 {
        unsigned int i;
@@ -164,7 +164,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                         ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -178,6 +178,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        ElfW(Addr) old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
        reloc_type = ELF_R_TYPE(rpnt->r_info);
        symtab_index = ELF_R_SYM(rpnt->r_info);
@@ -186,7 +188,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        symname = strtab + sym->st_name;
 
        if (symtab_index) {
-               symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+               symbol_addr = (ElfW(Addr))_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
@@ -199,6 +201,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                        return 1;
 
                }
+               if (_dl_trace_prelink)
+                       _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+                                               &current_value, elf_machine_type_class(reloc_type));
        } else {
                /* Relocs against STN_UNDEF are usually treated as using a
                 * symbol value of zero, and using the module containing the
@@ -308,7 +313,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 #undef __SPARC_LAZY_RELOC_WORKS
 #ifdef __SPARC_LAZY_RELOC_WORKS
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -356,14 +361,16 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 #ifdef __SPARC_LAZY_RELOC_WORKS
        (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
 #else
-       _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
+       _dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope,
+                                                                       rel_addr, rel_size);
 #endif
 }
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                struct r_scope_elem *scope,
                                 unsigned long rel_addr,
                                 unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index fce2ec7..de5a8c0 100644 (file)
@@ -70,7 +70,7 @@ _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, tpnt->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);
                _dl_exit(1);
@@ -94,9 +94,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
          unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                           ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
 {
        unsigned int i;
@@ -151,7 +151,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
             ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -165,6 +165,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        ElfW(Addr) old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
        reloc_type = ELF_R_TYPE(rpnt->r_info);
        symtab_index = ELF_R_SYM(rpnt->r_info);
@@ -173,7 +175,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
        symname = strtab + sym->st_name;
 
        if (symtab_index) {
-               symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+               symbol_addr = (ElfW(Addr))_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
@@ -185,6 +187,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                        /* This 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));
        } else {
                /* Relocs against STN_UNDEF are usually treated as using a
                 * symbol value of zero, and using the module containing the
@@ -193,7 +198,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
                tls_tpnt = tpnt;
        }
 
-
 #if defined (__SUPPORT_LD_DEBUG__)
        old_val = *reloc_addr;
 #endif
@@ -274,7 +278,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
 }
 
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
                  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
 {
        int reloc_type;
@@ -324,8 +328,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+                                struct r_scope_elem *scope,
                                 unsigned long rel_addr,
                                 unsigned long rel_size)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
index 4828191..59f6415 100644 (file)
@@ -56,7 +56,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
        got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr);
 
        /* Get the address of the GOT entry.  */
-       new_addr = _dl_find_hash (symname, tpnt->symbol_scope, tpnt,
+       new_addr = _dl_find_hash (symname, &_dl_loaded_modules->symbol_scope, tpnt,
                                                          ELF_RTYPE_CLASS_PLT, NULL);
        if (unlikely (!new_addr)) {
                _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
@@ -82,9 +82,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
 
 
 static int
-_dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                   unsigned long rel_addr, unsigned long rel_size,
-                  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+                  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                                                         ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
        unsigned int i;
@@ -140,7 +140,7 @@ _dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope,
 
 
 static int
-_dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                          ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -153,6 +153,8 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
        Elf32_Addr old_val;
 #endif
 
+       struct sym_val current_value = { NULL, NULL };
+
        reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset);
        reloc_type = ELF32_R_TYPE (rpnt->r_info);
        symtab_index = ELF32_R_SYM (rpnt->r_info);
@@ -162,7 +164,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
 
        if (symtab_index) {
                symbol_addr = (Elf32_Addr)
-                       _dl_find_hash (symname, scope, tpnt,
+                       _dl_find_hash (symname, scope, tpnt, &current_value,
                                                   elf_machine_type_class (reloc_type), NULL);
 
                /*
@@ -176,6 +178,9 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
                                                 _dl_progname, symname);
                        _dl_exit (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__)
@@ -222,7 +227,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
 
 
 static int
-_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                                   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
        int reloc_type;
@@ -269,9 +274,10 @@ _dl_parse_lazy_relocation_information (struct dyn_elf *rpnt,
 
 int
 _dl_parse_relocation_information (struct dyn_elf *rpnt,
+                                                                 struct r_scope_elem *scope,
                                                                  unsigned long rel_addr,
                                                                  unsigned long rel_size)
 {
-       return _dl_parse (rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
+       return _dl_parse (rpnt->dyn, scope, rel_addr, rel_size,
                                          _dl_do_reloc);
 }
index 3957e84..3b49216 100644 (file)
@@ -55,7 +55,7 @@ extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);
 
 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
        struct elf_resolve *, char *, int);
-extern int _dl_fixup(struct dyn_elf *rpnt, int lazy);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
 extern void _dl_protect_relro(struct elf_resolve * tpnt);
 extern int _dl_errno;
 extern struct dyn_elf *_dl_symbol_tables;
@@ -271,6 +271,21 @@ void dl_cleanup(void)
        }
 }
 
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+       struct elf_resolve *map)
+{
+       struct elf_resolve **p = list;
+       struct init_fini_list *q;
+
+       *p++ = map;
+       map->init_flag |= DL_RESERVED;
+       if (map->init_fini)
+               for (q = map->init_fini; q; q = q->next)
+                       if (! (q->tpnt->init_flag & DL_RESERVED))
+                               p += _dl_build_local_scope (p, q->tpnt);
+       return p - list;
+}
+
 void *dlopen(const char *libname, int flag)
 {
        struct elf_resolve *tpnt, *tfrom;
@@ -283,6 +298,8 @@ void *dlopen(const char *libname, int flag)
        unsigned int nlist, i;
        struct elf_resolve **init_fini_list;
        static bool _dl_init;
+       struct elf_resolve **local_scope;
+       struct r_scope_elem *ls;
 #if defined(USE_TLS) && USE_TLS
        bool any_tls = false;
 #endif
@@ -458,6 +475,23 @@ void *dlopen(const char *libname, int flag)
                }
 
        }
+       /* Build the local scope for the dynamically loaded modules. */
+       local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
+       for (i = 0; i < nlist; i++)
+               if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
+                       int k, cnt;
+                       cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
+                       init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+                       init_fini_list[i]->symbol_scope.r_nlist = cnt;
+                       _dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
+                                       cnt * sizeof (struct elf_resolve *));
+                       /* Restoring the init_flag.*/
+                       for (k = 0; k < nlist; k++)
+                               init_fini_list[k]->init_flag &= ~DL_RESERVED;
+               }
+
+       _dl_free(local_scope);
+
        /* Sort the INIT/FINI list in dependency order. */
        for (runp2 = dep_list; runp2; runp2 = runp2->next) {
                unsigned int j, k;
@@ -505,8 +539,13 @@ void *dlopen(const char *libname, int flag)
         */
        _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
 #endif
+       /* Get the tail of the list */
+       for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
 
-       if (_dl_fixup(dyn_chain, now_flag))
+       /* Extend the global scope by adding the local scope of the dlopened DSO. */
+       ls->next = &dyn_chain->dyn->symbol_scope;
+
+       if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
                goto oops;
 
        if (relro_ptr) {
@@ -667,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, 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) {
@@ -708,6 +747,7 @@ static int do_dlclose(void *vhandle, int need_fini)
        struct dyn_elf *handle;
        unsigned int end;
        unsigned int i, j;
+       struct r_scope_elem *ls;
 #if defined(USE_TLS) && USE_TLS
        bool any_tls = false;
        size_t tls_free_start = NO_TLS_OFFSET;
@@ -873,7 +913,7 @@ static int do_dlclose(void *vhandle, int need_fini)
                        }
 #endif
 
-                       DL_LIB_UNMAP (tpnt, end);
+                       DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);
                        /* Free elements in RTLD_LOCAL scope list */
                        for (runp = tpnt->rtld_local; runp; runp = tmp) {
                                tmp = runp->next;
@@ -897,6 +937,16 @@ static int do_dlclose(void *vhandle, int need_fini)
                                }
                        }
 
+                       if (handle->dyn == tpnt) {
+                               /* Unlink the local scope from global one */
+                               for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next)
+                                       if (ls->next->r_list[0] == tpnt) {
+                                               _dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname);
+                                               break;
+                                       }
+                               ls->next = ls->next->next;
+                       }
+
                        /* Next, remove tpnt from the global symbol table list */
                        if (_dl_symbol_tables) {
                                if (_dl_symbol_tables->dyn == tpnt) {
@@ -918,6 +968,7 @@ static int do_dlclose(void *vhandle, int need_fini)
                                }
                        }
                        free(tpnt->libname);
+                       free(tpnt->symbol_scope.r_list);
                        free(tpnt);
                }
        }
index 58f6643..36c0c6c 100644 (file)
@@ -153,6 +153,10 @@ extern void (*__fini_array_end []) (void) attribute_hidden;
 # endif
 #endif
 
+#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (SHARED) && defined __sh__
+extern unsigned long _dl_skip_args;
+#endif
+
 attribute_hidden const char *__uclibc_progname = "";
 #ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
 const char *program_invocation_short_name = "";
@@ -341,11 +345,23 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
 
     __rtld_fini = rtld_fini;
 
+#if defined __LDSO_STANDALONE_SUPPORT__ && defined SHARED && defined __sh__
+       /*
+        * Skip ld.so and its arguments
+        * Other archs except for SH do this in _dl_start before passing
+        * control to the application.
+        * FIXME: align SH _dl_start to other archs and remove this from here,
+        *        so that we can keep the visibility hidden.
+        */
+       argc -= _dl_skip_args;
+       argv += _dl_skip_args;
+#endif
+
     /* The environment begins right after argv.  */
     __environ = &argv[argc + 1];
 
     /* If the first thing after argv is the arguments
-     * the the environment is empty. */
+     * then the environment is empty. */
     if ((char *) __environ == *argv) {
        /* Make __environ point to the NULL at argv[argc] */
        __environ = &argv[argc];