unsigned long
_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
{
- int reloc_type;
ELF_RELOC *this_reloc;
char *strtab;
ElfW(Sym) *symtab;
rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
- reloc_type = ELF_R_TYPE(this_reloc->r_info);
symtab_index = ELF_R_SYM(this_reloc->r_info);
symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
symname = strtab + symtab[symtab_index].st_name;
- if (unlikely(reloc_type != R_X86_64_JUMP_SLOT)) {
- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
- _dl_progname);
- _dl_exit(1);
- }
-
/* Address of the jump instruction to fix up. */
instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
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, &_dl_loaded_modules->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);
_dl_exit(1);
}
static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
unsigned long rel_addr, unsigned long rel_size,
- int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
{
unsigned int i;
}
static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
{
int reloc_type;
int symtab_index;
char *symname;
+ struct elf_resolve *tls_tpnt = NULL;
+ struct symbol_ref sym_ref;
ElfW(Addr) *reloc_addr;
ElfW(Addr) symbol_addr;
#if defined (__SUPPORT_LD_DEBUG__)
reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
symbol_addr = 0;
- symname = strtab + symtab[symtab_index].st_name;
+ symname = strtab + sym_ref.sym->st_name;
if (symtab_index) {
symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
- elf_machine_type_class(reloc_type));
+ elf_machine_type_class(reloc_type), &sym_ref);
/*
* 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(symtab[symtab_index].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_ref.sym->st_info) != STT_TLS)
+ && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+ }
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ tls_tpnt = sym_ref.tpnt;
+ } 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_ref.sym->st_value;
+ tls_tpnt = tpnt;
}
#if defined (__SUPPORT_LD_DEBUG__)
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
- *reloc_addr = symbol_addr;
+ *reloc_addr = symbol_addr + rpnt->r_addend;
break;
/* handled by elf_machine_relative()
*reloc_addr = map->l_addr + rpnt->r_addend;
break;
*/
-#if 0
+#if defined USE_TLS && USE_TLS
case R_X86_64_DTPMOD64:
+ *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 = symbol_addr + rpnt->r_addend;
break;
case R_X86_64_TPOFF64:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ /* 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 = symbol_addr - tls_tpnt->l_tls_offset + rpnt->r_addend;
break;
+#endif
case R_X86_64_32:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
+ /* XXX: should check for overflow eh ? */
break;
-#endif
case R_X86_64_COPY:
if (symbol_addr) {
#if defined (__SUPPORT_LD_DEBUG__)
if (_dl_debug_move)
_dl_dprintf(_dl_debug_file,
"\t%s move %d bytes from %x to %x\n",
- symname, symtab[symtab_index].st_size,
+ symname, sym_ref.sym->st_size,
symbol_addr, reloc_addr);
#endif
_dl_memcpy((char *)reloc_addr,
(char *)symbol_addr,
- symtab[symtab_index].st_size);
+ sym_ref.sym->st_size);
} else
_dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
break;
return 0;
}
-#if 0
static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
{
int reloc_type;
case R_X86_64_NONE:
break;
case R_X86_64_JUMP_SLOT:
- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value;
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
break;
default:
_dl_exit(1);
return 0;
}
-#endif
void
_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
unsigned long rel_addr,
unsigned long rel_size)
{
- _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
-/* jump slot isnt working
(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
-*/
}
int
_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
unsigned long rel_addr,
unsigned long rel_size)
{
- return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
}