OSDN Git Service

ldso: fix fdpic support broken from prelink patch
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
index 14f2f76..85d27a3 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
-#ifdef __LDSO_SEARCH_INTERP_PATH__
-char *_dl_ldsopath             = NULL; /* Location of the shared lib loader */
-#endif
 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 */
@@ -132,6 +131,40 @@ 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;
@@ -318,12 +351,14 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)
 
 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;
 
@@ -331,7 +366,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;
@@ -378,7 +413,7 @@ 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;
@@ -457,7 +492,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
@@ -476,7 +513,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;
        }
@@ -494,7 +533,9 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                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;
@@ -566,20 +607,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                        }
                }
 
-#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);
        } else {
 #endif
 
@@ -680,19 +708,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. */
@@ -713,7 +730,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");
@@ -811,6 +828,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
@@ -818,7 +836,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;
 
@@ -850,7 +869,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)
@@ -995,7 +1016,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;
@@ -1095,7 +1117,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