OSDN Git Service

Clean up DSBT support
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
index e0d323a..f2ba628 100644 (file)
 #include LDSO_ELFINTERP
 
 /* Global variables used within the shared library loader */
+#ifdef __LDSO_LD_LIBRARY_PATH__
 char *_dl_library_path         = NULL; /* Where we look for libraries */
+#endif
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
 char *_dl_preload              = NULL; /* Things to be loaded before the libs */
 #endif
-char *_dl_ldsopath             = NULL; /* Location of the shared lib loader */
 int _dl_errno                  = 0;    /* We can't use the real errno in ldso */
 size_t _dl_pagesize            = 0;    /* Store the page size for use later */
 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
@@ -76,17 +77,11 @@ char *_dl_debug_bindings  = NULL;
 int   _dl_debug_file      = 2;
 #endif
 
-#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
- */
+#ifdef __DSBT__
+void **_dl_ldso_dsbt = NULL;
+#endif
 
-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"
@@ -119,19 +114,51 @@ extern void _start(void);
 
 #ifdef __UCLIBC_HAS_SSP__
 # include <dl-osinfo.h>
-uintptr_t stack_chk_guard;
+static uintptr_t stack_chk_guard;
 # ifndef THREAD_SET_STACK_GUARD
 /* Only exported for architectures that don't store the stack guard canary
  * in local thread area.  */
 uintptr_t __stack_chk_guard attribute_relro;
-#  ifdef __UCLIBC_HAS_SSP_COMPAT__
-strong_alias(__stack_chk_guard,__guard)
-#  endif
-# elif __UCLIBC_HAS_SSP_COMPAT__
+# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
 uintptr_t __guard attribute_relro;
 # endif
 #endif
 
+#ifdef __LDSO_SEARCH_INTERP_PATH__
+const char *_dl_ldsopath = NULL;       /* Location of the shared lib loader */
+
+static void _dl_ldsopath_init(struct elf_resolve *tpnt)
+{
+       char *ldsopath, *ptmp;
+
+       /*
+        * Store the path where the shared lib loader was found for later use.
+        * Note that this logic isn't bullet proof when it comes to relative
+        * paths: if you use "./lib/ldso.so", and then the app does chdir()
+        * followed by dlopen(), the old ldso path won't get searched.  But
+        * that is a fairly pathological use case, so if you don't like that,
+        * then set a full path to your interp and be done :P.
+        */
+       ldsopath = _dl_strdup(tpnt->libname);
+       ptmp = _dl_strrchr(ldsopath, '/');
+       /*
+        * If there is no "/", then set the path to "", and the code
+        * later on will take this to implicitly mean "search $PWD".
+        */
+       if (!ptmp)
+               ptmp = ldsopath;
+       *ptmp = '\0';
+
+       _dl_ldsopath = ldsopath;
+       _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
+               (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
+               _dl_ldsopath);
+}
+#else
+#define _dl_ldsopath_init(tpnt)
+#endif
+
 char *_dl_getenv(const char *symbol, char **envp)
 {
        char *pnt;
@@ -306,22 +333,26 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)
                                        tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
        }
 
+#if defined USE_TLS && USE_TLS
        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
+#endif
                _dl_dprintf (1, "\n");
 }
 #endif
 
 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
                                                                         DL_LOADADDR_TYPE load_addr,
+                                                                        ElfW(Addr) ldso_mapaddr,
                                                                         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);
+                               DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
+                                                         epnt->e_phoff);
                int j;
                struct stat st;
 
@@ -329,7 +360,7 @@ static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
                                              tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
                                              0);
 
-               tpnt->mapaddr = load_addr;
+               tpnt->mapaddr = ldso_mapaddr;
                if (_dl_stat(tpnt->libname, &st) >= 0) {
                        tpnt->st_dev = st.st_dev;
                        tpnt->st_ino = st.st_ino;
@@ -376,11 +407,11 @@ 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(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
        ElfW(Phdr) *ppnt;
        ElfW(Dyn) *dpnt;
        char *lpntstr;
-       unsigned int i, cnt, k, nscope_elem;
+       unsigned int i, cnt, nscope_elem;
        int unlazy = 0, trace_loaded_objects = 0;
        struct dyn_elf *rpnt;
        struct elf_resolve *tcurr;
@@ -427,6 +458,11 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                _dl_progname = argv[0];
        }
 
+#ifdef __DSBT__
+       _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX];
+       _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt;
+#endif
+
 #ifndef __LDSO_STANDALONE_SUPPORT__
        if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
                _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
@@ -455,7 +491,9 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
                _dl_preload = _dl_getenv("LD_PRELOAD", envp);
 #endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
                _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
+#endif
        } else {
                static const char unsecure_envvars[] =
 #ifdef EXTRA_UNSECURE_ENVVARS
@@ -474,7 +512,9 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
                _dl_preload = NULL;
 #endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
                _dl_library_path = NULL;
+#endif
                /* SUID binaries can be exploited if they do LAZY relocation. */
                unlazy = RTLD_NOW;
        }
@@ -486,14 +526,15 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 
 #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) {
+#ifdef __LDSO_LD_LIBRARY_PATH__
                                _dl_library_path = argv[2];
+#endif
                                _dl_skip_args += 2;
                                argc -= 2;
                                argv += 2;
@@ -565,15 +606,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                        }
                }
 
-               /* 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);
+               _dl_ldsopath_init(tpnt);
        } else {
 #endif
 
@@ -664,6 +697,11 @@ of this helper program; chances are you did not intend to run this program.\n\
                        app_tpnt->mapaddr = app_mapaddr;
                        app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
                        app_tpnt->usage_count++;
+#ifdef __DSBT__
+                       _dl_ldso_dsbt[0] = app_tpnt->dsbt_table;
+                       _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt,
+                                  app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
+#endif
                        lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
 #ifdef ALLOW_ZERO_PLTGOT
                        if (lpnt)
@@ -674,19 +712,8 @@ of this helper program; chances are you did not intend to run this program.\n\
                /* OK, fill this in - we did not have this before */
                if (ppnt->p_type == PT_INTERP) {
                        tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
-#ifdef __LDSO_SEARCH_INTERP_PATH__
-                       {
-                               char *ptmp;
-                               /* 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);
-#endif
+
+                       _dl_ldsopath_init(tpnt);
                }
 
                /* Discover any TLS sections if the target supports them. */
@@ -707,7 +734,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                                _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
 
                        }
-                       _dl_debug_early("Found TLS header for appplication program\n");
+                       _dl_debug_early("Found TLS header for application program\n");
                        break;
 #else
                        _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
@@ -805,6 +832,7 @@ of this helper program; chances are you did not intend to run this program.\n\
        }
 #endif
 
+       ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
        /*
         * OK, fix one more thing - set up debug_addr so it will point
         * to our chain.  Later we may need to fill in more fields, but this
@@ -812,7 +840,8 @@ of this helper program; chances are you did not intend to run this program.\n\
         */
        debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
        debug_addr->r_version = 1;
-       debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
+       debug_addr->r_ldbase = (ElfW(Addr))
+               DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
        debug_addr->r_brk = (unsigned long) &_dl_debug_state;
        _dl_debug_addr = debug_addr;
 
@@ -844,7 +873,9 @@ of this helper program; chances are you did not intend to run this program.\n\
                        if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
                                _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", str, _dl_progname);
 
-                               tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
+                               tpnt1 = _dl_load_shared_library(
+                                       _dl_secure ? DL_RESOLVE_SECURE : 0,
+                                       &rpnt, NULL, str, trace_loaded_objects);
                                if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
                                        if (trace_loaded_objects || _dl_trace_prelink)
@@ -889,6 +920,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                char *preload;
                int fd;
                char c, *cp, *cp2;
+               struct stat st;
 
                if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
                        break;
@@ -988,7 +1020,8 @@ of this helper program; chances are you did not intend to run this program.\n\
                                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 = add_ldso(tpnt, load_addr,
+                                                                                                ldso_mapaddr, auxvt, rpnt);
                                                }
                                                ldso_tpnt->usage_count++;
                                                tpnt1 = ldso_tpnt;
@@ -1088,7 +1121,7 @@ of this helper program; chances are you did not intend to run this program.\n\
         * again once all libs are loaded.
         */
        if (!ldso_tpnt) {
-               tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+               tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
                tpnt->usage_count++;
                nscope_elem++;
        } else
@@ -1128,6 +1161,7 @@ of this helper program; chances are you did not intend to run this program.\n\
        local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
        i = 1;
        for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+               unsigned int k;
                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;
@@ -1164,12 +1198,12 @@ of this helper program; chances are you did not intend to run this program.\n\
        stack_chk_guard = _dl_setup_stack_chk_guard ();
 # ifdef THREAD_SET_STACK_GUARD
        THREAD_SET_STACK_GUARD (stack_chk_guard);
-#  ifdef __UCLIBC_HAS_SSP_COMPAT__
-       __guard = stack_chk_guard;
-#  endif
 # else
        __stack_chk_guard = stack_chk_guard;
 # endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
+       __guard = stack_chk_guard;
+# endif
 #endif
 
 #ifdef __LDSO_PRELINK_SUPPORT__
@@ -1312,7 +1346,7 @@ of this helper program; chances are you did not intend to run this program.\n\
         * ld.so.1, so we have to look up each symbol individually.
         */
 
-       _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, NULL);
+       _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
        if (_dl_envp)
                *_dl_envp = (unsigned long) envp;
 
@@ -1368,21 +1402,21 @@ of this helper program; chances are you did not intend to run this program.\n\
 
        /* Find the real malloc function and make ldso functions use that from now on */
        _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
-                       global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+                       global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #if defined(USE_TLS) && USE_TLS
        /* Find the real functions and make ldso functions use them from now on */
        _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_free_function = (void (*)(void *)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
        _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
-               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+               _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #endif