diff options
| -rw-r--r-- | ldso/ldso/arm/dl-sysdep.h | 16 | ||||
| -rw-r--r-- | ldso/ldso/arm/elfinterp.c | 45 | ||||
| -rw-r--r-- | ldso/ldso/arm/resolve.S | 4 |
3 files changed, 52 insertions, 13 deletions
diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h index 65368d296..4f5a517a6 100644 --- a/ldso/ldso/arm/dl-sysdep.h +++ b/ldso/ldso/arm/dl-sysdep.h @@ -5,6 +5,9 @@ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> */ +#ifndef _ARCH_DL_SYSDEP +#define _ARCH_DL_SYSDEP + /* Define this if the system uses RELOCA. */ #undef ELF_USES_RELOCA #include <elf.h> @@ -60,12 +63,16 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); #define ADDR_ALIGN 0xfff #define OFFS_ALIGN 0x7ffff000 -/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so - PLT entries should not be allowed to define the value. +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + 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_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ +#define elf_machine_type_class(type) \ + ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \ + || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32) \ + * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) /* Return the link-time address of _DYNAMIC. Conveniently, this is the @@ -140,3 +147,4 @@ elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, *reloc_addr += load_off; } while (--relative_count); } +#endif /* !_ARCH_DL_SYSDEP */ diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 37531126a..5462a9b88 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -78,7 +78,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) /* Get the address of the GOT entry */ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, - tpnt, ELF_RTYPE_CLASS_PLT); + tpnt, ELF_RTYPE_CLASS_PLT, NULL); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -196,28 +196,41 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, int symtab_index; unsigned long *reloc_addr; unsigned long symbol_addr; + const Elf32_Sym *def = 0; + 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); symbol_addr = 0; if (symtab_index) { + def = _dl_find_hash(strtab + symtab[symtab_index].st_name, + scope, tpnt, + elf_machine_type_class(reloc_type), + &def_mod); - symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, - scope, tpnt, elf_machine_type_class(reloc_type)); - + if (def) + symbol_addr = def->st_value + def_mod->loadaddr; /* * 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 (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - _dl_exit (1); + else if (ELF32_ST_BIND(symtab[symtab_index].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. */ + def = &symtab[symtab_index]; + def_mod = tpnt; } #if defined (__SUPPORT_LD_DEBUG__) @@ -273,6 +286,20 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size); break; +#if USE_TLS + case R_ARM_TLS_DTPMOD32: + *reloc_addr = def_mod->l_tls_modid; + break; + + case R_ARM_TLS_DTPOFF32: + *reloc_addr += def->st_value; + break; + + case R_ARM_TLS_TPOFF32: + CHECK_STATIC_TLS ((struct link_map *) def_mod); + *reloc_addr += (def->st_value + def_mod->l_tls_offset); + break; +#endif default: return -1; /*call _dl_exit(1) */ } diff --git a/ldso/ldso/arm/resolve.S b/ldso/ldso/arm/resolve.S index b422c334d..08889d06e 100644 --- a/ldso/ldso/arm/resolve.S +++ b/ldso/ldso/arm/resolve.S @@ -95,6 +95,10 @@ #include <features.h> +#define sl r10 +#define fp r11 +#define ip r12 + .text .align 4 @ 16 byte boundary and there are 32 bytes below (arm case) #if !defined(__thumb__) || defined(__thumb2__) |
