From 534661b91c98492995274c364c8177c45efc63db Mon Sep 17 00:00:00 2001 From: Austin Foxley Date: Sat, 19 Sep 2009 10:04:05 -0700 Subject: ldso/: tls support for dynamic linker Signed-off-by: Austin Foxley --- ldso/ldso/mips/elfinterp.c | 71 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) (limited to 'ldso/ldso/mips') diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 8d9b7c413..97a86a137 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -56,7 +56,7 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index, symname = strtab + sym->st_name; new_addr = (unsigned long) _dl_find_hash(symname, - tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); if (unlikely(!new_addr)) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -111,7 +111,7 @@ __dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry) got_addr = (char **)instr_addr; /* Get the address of the GOT entry. */ - new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); _dl_exit(1); @@ -188,13 +188,66 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, symbol_addr = (unsigned long)_dl_find_hash(symname, tpnt->symbol_scope, tpnt, - elf_machine_type_class(reloc_type)); + elf_machine_type_class(reloc_type), NULL); if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) return 1; } switch (reloc_type) { -#if _MIPS_SIM == _MIPS_SIM_ABI64 +#if USE_TLS +# if _MIPS_SIM == _MIPS_SIM_ABI64 + case R_MIPS_TLS_DTPMOD64: + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_TPREL64: +# else + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: +# endif + { + ElfW(Sym) *sym_tls = &symtab[symtab_index]; + struct elf_resolve *tpnt_tls = tpnt; + + if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) { + _dl_find_hash((strtab + symtab[symtab_index].st_name), + _dl_symbol_tables, tpnt_tls, 1, &sym_tls); + } + + 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)); +#endif + break; + + case R_MIPS_TLS_DTPREL64: + 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)); +#endif + break; + + case R_MIPS_TLS_TPREL32: + case R_MIPS_TLS_TPREL64: + 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)); +#endif + break; + } + + break; + } +#endif /* USE_TLS */ +#if _MIPS_SIM == _MIS_SIM_ABI64 case (R_MIPS_64 << 8) | R_MIPS_REL32: #else /* O32 || N32 */ case R_MIPS_REL32: @@ -241,9 +294,9 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); #if defined (__SUPPORT_LD_DEBUG__) - _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); #else - _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); #endif _dl_exit(1); } @@ -292,12 +345,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy) } else { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); } } else if (sym->st_shndx == SHN_COMMON) { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && *got_entry != sym->st_value && tmp_lazy) { @@ -309,7 +362,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy) } else { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); } got_entry++; -- cgit v1.2.3