summaryrefslogtreecommitdiff
path: root/ldso/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/ldso')
-rw-r--r--ldso/ldso/Makefile.in6
-rw-r--r--ldso/ldso/arm/aeabi_read_tp.S1
-rw-r--r--ldso/ldso/dl-elf.c18
-rw-r--r--ldso/ldso/dl-tls.c5
-rw-r--r--ldso/ldso/i386/elfinterp.c10
-rw-r--r--ldso/ldso/ldso.c26
-rw-r--r--ldso/ldso/x86_64/dl-sysdep.h8
-rw-r--r--ldso/ldso/x86_64/elfinterp.c28
8 files changed, 68 insertions, 34 deletions
diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in
index 724563155..e71ae1563 100644
--- a/ldso/ldso/Makefile.in
+++ b/ldso/ldso/Makefile.in
@@ -62,9 +62,9 @@ ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS)
lib-so-y += $(ldso)
objclean-y += CLEAN_ldso/ldso
-$(ldso): $(ldso:.$(MAJOR_VERSION)=)
-$(ldso:.$(MAJOR_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a
- $(call link.so,$(ldso_FULL_NAME),$(MAJOR_VERSION))
+$(ldso): $(ldso:.$(ABI_VERSION)=)
+$(ldso:.$(ABI_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a
+ $(call link.so,$(ldso_FULL_NAME),$(ABI_VERSION))
$($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y)
$(Q)$(RM) $@
diff --git a/ldso/ldso/arm/aeabi_read_tp.S b/ldso/ldso/arm/aeabi_read_tp.S
index e906d07ce..564f59331 100644
--- a/ldso/ldso/arm/aeabi_read_tp.S
+++ b/ldso/ldso/arm/aeabi_read_tp.S
@@ -38,7 +38,6 @@
#ifdef __UCLIBC_HAS_THREADS_NATIVE__
#include <sysdep.h>
-#include <tls.h>
/* GCC will emit calls to this routine under -mtp=soft. Linux has an
equivalent helper function (which clobbers fewer registers than
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 6b64f3e04..5562e0784 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -337,6 +337,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
unsigned long *lpnt;
unsigned long libaddr;
unsigned long minvma = 0xffffffff, maxvma = 0;
+ unsigned int rtld_flags;
int i, flags, piclib, infile;
ElfW(Addr) relro_addr = 0;
size_t relro_size = 0;
@@ -700,7 +701,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
dpnt = (ElfW(Dyn) *) dynamic_addr;
_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
- _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
+ rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
/* If the TEXTREL is set, this means that we need to make the pages
writable before we perform relocations. Do this now. They get set
back again later. */
@@ -732,13 +733,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
tpnt->st_ino = st.st_ino;
tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
tpnt->n_phent = epnt->e_phnum;
+ tpnt->rtld_flags |= rtld_flags;
#if defined(USE_TLS) && USE_TLS
if (tlsppnt) {
_dl_debug_early("Found TLS header for %s\n", libname);
-#if NO_TLS_OFFSET != 0
+# if NO_TLS_OFFSET != 0
tpnt->l_tls_offset = NO_TLS_OFFSET;
-#endif
+# endif
tpnt->l_tls_blocksize = tlsppnt->p_memsz;
tpnt->l_tls_align = tlsppnt->p_align;
if (tlsppnt->p_align == 0)
@@ -755,10 +757,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
/* We know the load address, so add it to the offset. */
if (tpnt->l_tls_initimage != NULL)
{
+# ifdef __SUPPORT_LD_DEBUG_EARLY__
unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
_dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
tmp = 0;
+# else
+ tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
+# endif
}
}
#endif
@@ -987,8 +993,8 @@ char *_dl_strdup(const char *string)
return retval;
}
-void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
- void *debug_addr, DL_LOADADDR_TYPE load_off)
+unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+ void *debug_addr, DL_LOADADDR_TYPE load_off)
{
- __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
+ return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
}
diff --git a/ldso/ldso/dl-tls.c b/ldso/ldso/dl-tls.c
index 52b7aa534..d2808f968 100644
--- a/ldso/ldso/dl-tls.c
+++ b/ldso/ldso/dl-tls.c
@@ -842,7 +842,10 @@ __tls_get_addr (GET_ADDR_ARGS)
void *p;
if (__builtin_expect (dtv[0].counter != _dl_tls_generation, 0))
- the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+ {
+ the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+ dtv = THREAD_DTV ();
+ }
p = dtv[GET_ADDR_MODULE].pointer.val;
diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c
index a01c1d020..1e3a2b248 100644
--- a/ldso/ldso/i386/elfinterp.c
+++ b/ldso/ldso/i386/elfinterp.c
@@ -175,7 +175,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
symbol_addr = 0;
symname = strtab + symtab[symtab_index].st_name;
- if (symtab_index) {
+ if (symtab_index &&
+ (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);
@@ -188,7 +190,11 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
&& ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
return 1;
} else {
- symbol_addr = symtab[symtab_index].st_value;
+ if (symtab_index)
+ symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
+ &symtab[symtab_index]);
+ else
+ symbol_addr = symtab[symtab_index].st_value;
tls_tpnt = tpnt;
}
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index a8224e2c7..ea4ad0f1c 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -382,19 +382,6 @@ 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 __UCLIBC_HAS_SSP__
- /* Set up the stack checker's canary. */
- 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
-#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
@@ -952,6 +939,19 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
tcbp = init_tls ();
}
#endif
+#ifdef __UCLIBC_HAS_SSP__
+ /* Set up the stack checker's canary. */
+ 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
+#endif
+
_dl_debug_early("Beginning relocation fixups\n");
diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h
index 0eed657e8..ae3542aed 100644
--- a/ldso/ldso/x86_64/dl-sysdep.h
+++ b/ldso/ldso/x86_64/dl-sysdep.h
@@ -46,8 +46,12 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
define the value.
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
of the main executable's symbols, as for a COPY reloc. */
-#define elf_machine_type_class(type) \
- ((((type) == R_X86_64_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+#define elf_machine_type_class(type) \
+ ((((type) == R_X86_64_JUMP_SLOT \
+ || (type) == R_X86_64_DTPMOD64 \
+ || (type) == R_X86_64_DTPOFF64 \
+ || (type) == R_X86_64_TPOFF64) \
+ * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY))
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c
index 92ac5acbc..54528d382 100644
--- a/ldso/ldso/x86_64/elfinterp.c
+++ b/ldso/ldso/x86_64/elfinterp.c
@@ -157,6 +157,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
int reloc_type;
int symtab_index;
char *symname;
+ struct elf_resolve *tls_tpnt = 0;
ElfW(Sym) *sym;
ElfW(Addr) *reloc_addr;
ElfW(Addr) symbol_addr;
@@ -173,18 +174,26 @@ _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);
+ 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.
*/
- if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
- _dl_exit(1);
+ if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym->st_info) != STT_TLS)
+ && (ELF_ST_BIND(sym->st_info) != STB_WEAK))) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
}
+ } else {
+ /* Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself. */
+ symbol_addr = sym->st_value;
+ tls_tpnt = tpnt;
}
+
#if defined (__SUPPORT_LD_DEBUG__)
old_val = *reloc_addr;
#endif
@@ -212,13 +221,20 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
break;
*/
case R_X86_64_DTPMOD64:
- *reloc_addr = 1;
+ *reloc_addr = tls_tpnt->l_tls_modid;
break;
case R_X86_64_DTPOFF64:
+ /* During relocation all TLS symbols are defined and used.
+ * Therefore the offset is already correct. */
*reloc_addr = sym->st_value + rpnt->r_addend;
break;
case R_X86_64_TPOFF64:
- *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
+ /* The offset is negative, forward from the thread pointer.
+ * We know the offset of the object the symbol is contained in.
+ * It is a negative value which will be added to the
+ * thread pointer. */
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend;
break;
case R_X86_64_32:
*(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;