#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
}
/* 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__
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];
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
_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;
/* 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
free(tpnt);
}
}
+ for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
+ rpnt1_tmp = rpnt1->next;
+ free(rpnt1);
+ }
free(handle->init_fini.init_fini);
free(handle);