From 1f5e333a158f4398437287b8b64260371422194f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 15 Oct 2009 16:15:59 -0400 Subject: ldso: clean up breakage in tls merge The TLS merge 534661b91c9849 introduced multiple style problems as well as random breakage: - missing _dl_free - incomplete parametrization of _dl_lookup_hash - restore FDPIC handling in _dl_lookup_hash Signed-off-by: Mike Frysinger --- ldso/ldso/arm/aeabi_read_tp.S | 2 +- ldso/ldso/arm/elfinterp.c | 19 ++++++------ ldso/ldso/dl-elf.c | 8 ++--- ldso/ldso/dl-hash.c | 69 +++++++++++++++++++++++-------------------- ldso/ldso/dl-startup.c | 4 +-- ldso/ldso/dl-tls.c | 16 ++-------- ldso/ldso/ldso.c | 37 +++++++++++------------ ldso/ldso/mips/elfinterp.c | 18 ++++++----- ldso/ldso/sh/dl-sysdep.h | 2 +- ldso/ldso/sh/elfinterp.c | 5 ++-- ldso/ldso/sparc/elfinterp.c | 60 ++++++++++++++++++------------------- 11 files changed, 115 insertions(+), 125 deletions(-) (limited to 'ldso/ldso') diff --git a/ldso/ldso/arm/aeabi_read_tp.S b/ldso/ldso/arm/aeabi_read_tp.S index f81bae676..e906d07ce 100644 --- a/ldso/ldso/arm/aeabi_read_tp.S +++ b/ldso/ldso/arm/aeabi_read_tp.S @@ -53,7 +53,7 @@ #ifndef NOT_IN_libc .global __aeabi_read_tp #else - .hidden __aeabi_read_tp + .hidden __aeabi_read_tp #endif ENTRY (__aeabi_read_tp) mov r0, #0xffff0fff diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 1469df016..bf7426790 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -89,10 +89,10 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) } } if (!_dl_debug_nofixups) { - *got_addr = (char*)new_addr; + *got_addr = (char *)new_addr; } #else - *got_addr = (char*)new_addr; + *got_addr = (char *)new_addr; #endif return new_addr; @@ -192,8 +192,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, struct elf_resolve *def_mod = 0; int goof = 0; - reloc_addr = (unsigned long *) (tpnt->loadaddr - + (unsigned long) rpnt->r_offset); + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); @@ -201,9 +200,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, if (symtab_index) { symbol_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, - scope, tpnt, - elf_machine_type_class(reloc_type), - &def_mod); + scope, tpnt, elf_machine_type_class(reloc_type), &def_mod); /* * We want to allow undefined references to weak symbols - this might @@ -217,9 +214,11 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, } } else { - /* Relocs against STN_UNDEF are usually treated as using a - symbol value of zero, and using the module containing the - reloc itself. */ + /* + * Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. + */ symbol_addr = symtab[symtab_index].st_value; def_mod = tpnt; } diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index e4086d5e9..e7cb138d4 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -436,8 +436,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, maxvma = ppnt->p_vaddr + ppnt->p_memsz; } } - if (ppnt->p_type == PT_TLS) - { + if (ppnt->p_type == PT_TLS) { #if USE_TLS if (ppnt->p_memsz == 0) /* Nothing to do for an empty segment. */ @@ -735,8 +734,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, tpnt->n_phent = epnt->e_phnum; #if USE_TLS - if (tlsppnt) - { + if (tlsppnt) { _dl_debug_early("Found TLS header for %s\n", libname); #if NO_TLS_OFFSET != 0 tpnt->l_tls_offset = NO_TLS_OFFSET; @@ -875,7 +873,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag) } #if 0 -/* _dl_add_to_slotinfo is called by init_tls() for initial DSO +/* _dl_add_to_slotinfo is called by init_tls() for initial DSO or by dlopen() for dynamically loaded DSO. */ #if USE_TLS /* Add object to slot information data if necessasy. */ diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 3103d9f0b..1ac5b948d 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -159,27 +159,27 @@ check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int typ { #if USE_TLS - if((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS)) - || (type_class & (sym->st_shndx == SHN_UNDEF))) - /* No value or undefined symbol itself */ - return NULL; - - if(ELF_ST_TYPE(sym->st_info) > STT_FUNC - && ELF_ST_TYPE(sym->st_info) != STT_COMMON - && ELF_ST_TYPE(sym->st_info) != STT_TLS) - /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC and STT_COMMON - * entries (and STT_TLS if TLS is supported) since these - * are no code/data definitions. - */ - return NULL; -#else - if (type_class & (sym->st_shndx == SHN_UNDEF)) - /* undefined symbol itself */ - return NULL; - - if (sym->st_value == 0) - /* No value */ - return NULL; + if ((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS)) + || (type_class & (sym->st_shndx == SHN_UNDEF))) + /* No value or undefined symbol itself */ + return NULL; + + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC + && ELF_ST_TYPE(sym->st_info) != STT_COMMON + && ELF_ST_TYPE(sym->st_info) != STT_TLS) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC and STT_COMMON + * entries (and STT_TLS if TLS is supported) since these + * are no code/data definitions. + */ + return NULL; +#else + if (type_class & (sym->st_shndx == SHN_UNDEF)) + /* undefined symbol itself */ + return NULL; + + if (sym->st_value == 0) + /* No value */ + return NULL; if (ELF_ST_TYPE(sym->st_info) > STT_FUNC && ELF_ST_TYPE(sym->st_info) != STT_COMMON) @@ -268,11 +268,8 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long * This function resolves externals, and this is either called when we process * relocations or when we call an entry in the PLT table for the first time. */ -char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class -#if USE_TLS -,struct elf_resolve **tls_tpnt -#endif -) +char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, + int type_class _DL_LOOKUP_HASH_EXTRA_TPNT) { struct elf_resolve *tpnt = NULL; ElfW(Sym) *symtab; @@ -338,12 +335,12 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve if (sym) { /* At this point we have found the requested symbol, do binding */ -#if USE_TLS - if(ELF_ST_TYPE(sym->st_info) == STT_TLS) { - _dl_assert((tls_tpnt != NULL)); +#if USE_TLS + if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { + _dl_assert(tls_tpnt != NULL); *tls_tpnt = tpnt; - return (char*)sym->st_value; + return (char *)sym->st_value; } #endif @@ -353,14 +350,22 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve /* Perhaps we should support old style weak symbol handling * per what glibc does when you export LD_DYNAMIC_WEAK */ if (!weak_result) - weak_result = (char *)tpnt->loadaddr + sym->st_value; + weak_result = (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym); break; #endif case STB_GLOBAL: - return (char*)tpnt->loadaddr + sym->st_value; +#ifdef __FDPIC__ + if (tpntp) + *tpntp = tpnt; +#endif + return (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym); default: /* Local symbols not handled here */ break; } } +#ifdef __FDPIC__ + if (tpntp) + *tpntp = tpnt; +#endif return weak_result; } diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 6f07b960a..91b11dc7f 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -220,8 +220,8 @@ DL_START(unsigned long args) /* tpnt->l_tls_modid = 0; */ # if NO_TLS_OFFSET != 0 tpnt->l_tls_offset = NO_TLS_OFFSET; -# endif -#endif +# endif +#endif SEND_EARLY_STDERR_DEBUG("Done scanning DYNAMIC section\n"); diff --git a/ldso/ldso/dl-tls.c b/ldso/ldso/dl-tls.c index e718373cd..52b7aa534 100644 --- a/ldso/ldso/dl-tls.c +++ b/ldso/ldso/dl-tls.c @@ -46,7 +46,7 @@ void * _dl_calloc (size_t __nmemb, size_t __size) { void *result; - size_t size = (__size * __nmemb); + size_t size = (__size * __nmemb); if (_dl_calloc_function) return (*_dl_calloc_function) (__nmemb, __size); @@ -68,18 +68,6 @@ _dl_realloc (void * __ptr, size_t __size) return NULL; } -void -_dl_free (void *__ptr) -{ - if (_dl_free_function) - (*_dl_free_function) (__ptr); - -#if 0 - _dl_debug_early("NOT IMPLEMENTED PROPERLY!!!\n"); -#endif -} - - /* The __tls_get_addr function has two basic forms which differ in the arguments. The IA-64 form takes two parameters, the module ID and offset. The form used, among others, on IA-32 takes a reference to @@ -1009,7 +997,7 @@ init_tls (void) /* This is a module with TLS data. Store the map reference. The generation counter is zero. */ - /* Skeep slot[0]: it will be never used */ + /* Skeep slot[0]: it will be never used */ slotinfo[++i].map = l; } _dl_assert (i == _dl_tls_max_dtv_idx); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 485204298..021f109cd 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -219,8 +219,14 @@ static void *_dl_zalloc(size_t size) return p; } +void _dl_free(void *p) +{ + if (_dl_free_function) + (*_dl_free_function) (p); +} + #if USE_TLS -void * _dl_memalign (size_t __boundary, size_t __size) +void *_dl_memalign(size_t __boundary, size_t __size) { void *result; int i = 0; @@ -291,7 +297,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, #if USE_TLS void *tcbp = NULL; #endif - /* Wahoo!!! We managed to make a function call! Get malloc * setup so we can use _dl_dprintf() to print debug noise @@ -530,15 +535,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, * Adjust the address of the TLS initialization image in * case the executable is actually an ET_DYN object. */ - if (app_tpnt->l_tls_initimage != NULL) - { -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage; -#endif + if (app_tpnt->l_tls_initimage != NULL) { app_tpnt->l_tls_initimage = (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr; - _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size); - + _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", + (unsigned int)app_tpnt->l_tls_initimage, + app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size); } #endif @@ -937,8 +939,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, * used. Trying to do it lazily is too hairy to try when there could be * multiple threads (from a non-TLS-using libpthread). */ bool was_tls_init_tp_called = tls_init_tp_called; - if (tcbp == NULL) - { + if (tcbp == NULL) { _dl_debug_early("Calling init_tls()!\n"); tcbp = init_tls (); } @@ -982,11 +983,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, /* And finally install it for the main thread. If ld.so itself uses TLS we know the thread pointer was initialized earlier. */ - if (! tls_init_tp_called) - { + if (! tls_init_tp_called) { const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD); - if (__builtin_expect (lossage != NULL, 0)) - { + if (__builtin_expect (lossage != NULL, 0)) { _dl_debug_early("cannot set up thread-local storage: %s\n", lossage); _dl_exit(30); } @@ -1062,16 +1061,16 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, /* 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", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); - + _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); - + _dl_free_function = (void (*)(void *)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); - + _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); - + #endif /* Notify the debugger that all objects are now mapped in. */ diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 78cc4c15a..b49f09d36 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -213,14 +213,14 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, _dl_symbol_tables, tpnt_tls, 1, &sym_tls); } - switch (reloc_type) - { + switch (reloc_type) { case R_MIPS_TLS_DTPMOD64: case R_MIPS_TLS_DTPMOD32: if (tpnt_tls) *(ElfW(Word) *)reloc_addr = tpnt_tls->l_tls_modid; -#if defined (__SUPPORT_LD_DEBUG__) -_dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", + (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); #endif break; @@ -228,8 +228,9 @@ _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", (strtab + symtab[symtab_index].st_na case R_MIPS_TLS_DTPREL32: *(ElfW(Word) *)reloc_addr += TLS_DTPREL_VALUE (sym_tls); -#if defined (__SUPPORT_LD_DEBUG__) -_dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n", + (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); #endif break; @@ -238,8 +239,9 @@ _dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_na CHECK_STATIC_TLS((struct link_map *)tpnt_tls); *(ElfW(Word) *)reloc_addr += TLS_TPREL_VALUE (tpnt_tls, sym_tls); -#if defined (__SUPPORT_LD_DEBUG__) -_dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", + (strtab + symtab[symtab_index].st_name), old_val, *((unsigned int *)reloc_addr)); #endif break; } diff --git a/ldso/ldso/sh/dl-sysdep.h b/ldso/ldso/sh/dl-sysdep.h index 7937ceb08..56e1820f3 100644 --- a/ldso/ldso/sh/dl-sysdep.h +++ b/ldso/ldso/sh/dl-sysdep.h @@ -99,7 +99,7 @@ _dl_urem(unsigned int n, unsigned int base) #define elf_machine_type_class(type) \ ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) -#endif +#endif /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index cce563e23..594da53aa 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -160,8 +160,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, unsigned long old_val; #endif -struct elf_resolve *tls_tpnt = NULL; - + struct elf_resolve *tls_tpnt = NULL; reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); @@ -197,7 +196,7 @@ struct elf_resolve *tls_tpnt = NULL; /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous' symbol. This is the case for a static tls variable, so the lookup module is just that one is referencing the tls variable. */ - if(!tls_tpnt) + if (!tls_tpnt) tls_tpnt = tpnt; #endif switch (reloc_type) { diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index a3f9d647f..75e77772c 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -170,7 +170,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; + struct elf_resolve *tls_tpnt = 0; ElfW(Sym) *sym; ElfW(Addr) *reloc_addr; ElfW(Addr) symbol_addr; @@ -194,18 +194,18 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, * symbols here, so all bases should be covered. */ 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; + && (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; - } + /* 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; @@ -235,8 +235,8 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, break; case R_SPARC_JMP_SLOT: - reloc_addr[1] = OPCODE_SETHI_G1 | (( symbol_addr >> 10 ) & 0x3fffff); - reloc_addr[2] = OPCODE_JMP_G1 | ( symbol_addr & 0x3ff ); + reloc_addr[1] = OPCODE_SETHI_G1 | (( symbol_addr >> 10 ) & 0x3fffff); + reloc_addr[2] = OPCODE_JMP_G1 | ( symbol_addr & 0x3ff ); break; case R_SPARC_RELATIVE: @@ -273,24 +273,24 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); break; #if USE_TLS - case R_SPARC_TLS_DTPMOD32: - *reloc_addr = tls_tpnt->l_tls_modid; - break; - - case R_SPARC_TLS_DTPOFF32: - /* 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_SPARC_TLS_TPOFF32: - /* 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_SPARC_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + + case R_SPARC_TLS_DTPOFF32: + /* 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_SPARC_TLS_TPOFF32: + /* 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; #endif default: return -1; /* Calls _dl_exit(1). */ -- cgit v1.2.3