]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/libdl.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / ldso / libdl / libdl.c
index 667798a7078751ac0156a53de0222e9cc2d5191b..e3b0e8445d0a3ab5c1f9ae11f99bc2584689567a 100644 (file)
@@ -42,7 +42,6 @@
 
 #if defined(USE_TLS) && USE_TLS
 #include <ldsodefs.h>
-extern void (*_dl_init_static_tls) (struct link_map *);
 extern void _dl_add_to_slotinfo(struct link_map  *l);
 #endif
 
@@ -305,7 +304,18 @@ void *dlopen(const char *libname, int flag)
        }
        /* Cover the trivial case first */
        if (!libname)
-               return _dl_symbol_tables;
+      {
+// L4: Fix the case that a static program does not have a symbol table for
+// the main program but needs to set the error code. LD_NO_SYMBOL has been
+// taken because it sounds useful for that case. glibc does seem to have a
+// rather strange handling in the static case.
+#ifdef SHARED
+        return _dl_symbol_tables;
+#else
+        _dl_error_number = LD_NO_SYMBOL;
+        return NULL;
+#endif
+      }
 
 #ifndef SHARED
 # ifdef __SUPPORT_LD_DEBUG__
@@ -616,7 +626,7 @@ void *dlsym(void *vhandle, const char *name)
        ElfW(Addr) from;
        struct dyn_elf *rpnt;
        void *ret;
-       struct elf_resolve *tls_tpnt = NULL;
+       struct symbol_ref sym_ref = { NULL, NULL };
        /* Nastiness to support underscore prefixes.  */
 #ifdef __UCLIBC_UNDERSCORES__
        char tmp_buf[80];
@@ -671,13 +681,13 @@ 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, tpnt, 0, &sym_ref);
 
 #if defined(USE_TLS) && USE_TLS && defined SHARED
-       if (tls_tpnt) {
+       if (sym_ref.tpnt) {
                /* The found symbol is a thread-local storage variable.
                Return the address for to the current thread.  */
-               ret = _dl_tls_symaddr ((struct link_map *)tls_tpnt, (Elf32_Addr)ret);
+               ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
        }
 #endif
 
@@ -739,7 +749,7 @@ static int do_dlclose(void *vhandle, int need_fini)
                _dl_handles = rpnt->next_handle;
        _dl_if_debug_print("%s: usage count: %d\n",
                        handle->dyn->libname, handle->dyn->usage_count);
-       if (handle->dyn->usage_count != 1) {
+       if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
                handle->dyn->usage_count--;
                free(handle);
                return 0;
@@ -747,7 +757,8 @@ static int do_dlclose(void *vhandle, int need_fini)
        /* OK, this is a valid handle - now close out the file */
        for (j = 0; j < handle->init_fini.nlist; ++j) {
                tpnt = handle->init_fini.init_fini[j];
-               if (--tpnt->usage_count == 0) {
+               tpnt->usage_count--;
+               if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
                        if ((tpnt->dynamic_info[DT_FINI]
                             || tpnt->dynamic_info[DT_FINI_ARRAY])
                         && need_fini
@@ -924,6 +935,10 @@ static int do_dlclose(void *vhandle, int need_fini)
                        free(tpnt);
                }
        }
+       for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
+               rpnt1_tmp = rpnt1->next;
+               free(rpnt1);
+       }
        free(handle->init_fini.init_fini);
        free(handle);