|
@@ -36,6 +36,13 @@
|
|
|
#include "tlsdeschtab.h"
|
|
|
#endif
|
|
|
|
|
|
+#ifdef __FDPIC__
|
|
|
+unsigned long
|
|
|
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#else
|
|
|
unsigned long
|
|
|
_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
|
|
|
{
|
|
@@ -83,7 +90,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
|
|
|
|
|
|
return (unsigned long) new_addr;
|
|
|
}
|
|
|
-
|
|
|
+#endif
|
|
|
|
|
|
static int
|
|
|
_dl_parse (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
@@ -145,8 +152,8 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
int reloc_type;
|
|
|
int symtab_index;
|
|
|
char *symname;
|
|
|
-#if defined USE_TLS && USE_TLS
|
|
|
- struct elf_resolve *tls_tpnt = NULL;
|
|
|
+#if defined USE_TLS && USE_TLS || defined (__FDPIC__)
|
|
|
+ struct elf_resolve *def_mod = NULL;
|
|
|
#endif
|
|
|
struct symbol_ref sym_ref;
|
|
|
ElfW(Addr) *reloc_addr;
|
|
@@ -155,7 +162,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
ElfW(Addr) old_val;
|
|
|
#endif
|
|
|
|
|
|
- reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset);
|
|
|
+ reloc_addr = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, 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];
|
|
@@ -164,9 +171,17 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
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), &sym_ref);
|
|
|
+ if (ELF_ST_BIND (sym_ref.sym->st_info) == STB_LOCAL) {
|
|
|
+ symbol_addr = (ElfW(Addr))
|
|
|
+ DL_RELOC_ADDR(tpnt->loadaddr,
|
|
|
+ symtab[symtab_index].st_value);
|
|
|
+ sym_ref.tpnt = tpnt;
|
|
|
+ } else {
|
|
|
+ symbol_addr = (ElfW(Addr))
|
|
|
+ _dl_find_hash (symname, scope, tpnt,
|
|
|
+ elf_machine_type_class (reloc_type),
|
|
|
+ &sym_ref);
|
|
|
+ }
|
|
|
|
|
|
|
|
|
* We want to allow undefined references to weak symbols - this might
|
|
@@ -182,13 +197,13 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
_dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
|
|
|
&sym_ref, elf_machine_type_class(reloc_type));
|
|
|
}
|
|
|
-#if defined USE_TLS && USE_TLS
|
|
|
- tls_tpnt = sym_ref.tpnt;
|
|
|
+#if defined USE_TLS && USE_TLS || defined (__FDPIC__)
|
|
|
+ def_mod = sym_ref.tpnt;
|
|
|
#endif
|
|
|
} else {
|
|
|
symbol_addr =symtab[symtab_index].st_value;
|
|
|
-#if defined USE_TLS && USE_TLS
|
|
|
- tls_tpnt = tpnt;
|
|
|
+#if defined USE_TLS && USE_TLS || defined (__FDPIC__)
|
|
|
+ def_mod = tpnt;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -202,6 +217,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
|
|
|
case R_XTENSA_GLOB_DAT:
|
|
|
case R_XTENSA_JMP_SLOT:
|
|
|
+ case R_XTENSA_SYM32:
|
|
|
*reloc_addr = symbol_addr + rpnt->r_addend;
|
|
|
break;
|
|
|
|
|
@@ -219,19 +235,63 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
break;
|
|
|
|
|
|
case R_XTENSA_RELATIVE:
|
|
|
- *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
|
|
|
+ *reloc_addr += DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_addend);
|
|
|
break;
|
|
|
|
|
|
+#ifdef __FDPIC__
|
|
|
+ case R_XTENSA_FUNCDESC_VALUE:
|
|
|
+ {
|
|
|
+ struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr;
|
|
|
+
|
|
|
+ dst->entry_point = (void *) (symbol_addr + rpnt->r_addend);
|
|
|
+ dst->got_value = def_mod->loadaddr.got_value;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case R_XTENSA_FUNCDESC:
|
|
|
+ if (symbol_addr)
|
|
|
+ *reloc_addr = (unsigned long)
|
|
|
+ _dl_funcdesc_for((void *) (symbol_addr + rpnt->r_addend),
|
|
|
+ sym_ref.tpnt->loadaddr.got_value);
|
|
|
+ else
|
|
|
+
|
|
|
+ set funcdesc to zero. */
|
|
|
+ *reloc_addr = 0;
|
|
|
+ break;
|
|
|
+ case R_XTENSA_TLS_TPOFF:
|
|
|
+ CHECK_STATIC_TLS((struct link_map *) def_mod);
|
|
|
+ *reloc_addr = symbol_addr + rpnt->r_addend + def_mod->l_tls_offset;
|
|
|
+ break;
|
|
|
+ case R_XTENSA_TLSDESC:
|
|
|
+ {
|
|
|
+ struct tlsdesc *td = (struct tlsdesc *) reloc_addr;
|
|
|
+#ifndef SHARED
|
|
|
+ CHECK_STATIC_TLS((struct link_map *) def_mod);
|
|
|
+#else
|
|
|
+ if (!TRY_STATIC_TLS ((struct link_map *) def_mod))
|
|
|
+ {
|
|
|
+ td->entry = _dl_tlsdesc_dynamic;
|
|
|
+ td->argument = _dl_make_tlsdesc_dynamic((struct link_map *) def_mod,
|
|
|
+ symbol_addr + rpnt->r_addend);
|
|
|
+ }
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ td->entry = _dl_tlsdesc_return;
|
|
|
+ td->argument = (void *) (symbol_addr + rpnt->r_addend + def_mod->l_tls_offset);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+#else
|
|
|
#if defined USE_TLS && USE_TLS
|
|
|
case R_XTENSA_TLS_TPOFF:
|
|
|
- CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
- *reloc_addr = symbol_addr + tls_tpnt->l_tls_offset + rpnt->r_addend;
|
|
|
+ CHECK_STATIC_TLS((struct link_map *) def_mod);
|
|
|
+ *reloc_addr = symbol_addr + rpnt->r_addend + def_mod->l_tls_offset;
|
|
|
break;
|
|
|
case R_XTENSA_TLSDESC_FN:
|
|
|
#ifndef SHARED
|
|
|
- CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
+ CHECK_STATIC_TLS((struct link_map *) def_mod);
|
|
|
#else
|
|
|
- if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
|
|
|
+ if (!TRY_STATIC_TLS ((struct link_map *) def_mod))
|
|
|
*reloc_addr = (ElfW(Addr)) _dl_tlsdesc_dynamic;
|
|
|
else
|
|
|
#endif
|
|
@@ -239,25 +299,25 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
break;
|
|
|
case R_XTENSA_TLSDESC_ARG:
|
|
|
#ifndef SHARED
|
|
|
- CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
+ CHECK_STATIC_TLS((struct link_map *) def_mod);
|
|
|
#else
|
|
|
- if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
|
|
|
+ if (!TRY_STATIC_TLS ((struct link_map *) def_mod))
|
|
|
*reloc_addr = (ElfW(Addr))
|
|
|
- _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt,
|
|
|
+ _dl_make_tlsdesc_dynamic((struct link_map *) def_mod,
|
|
|
symbol_addr + rpnt->r_addend);
|
|
|
else
|
|
|
#endif
|
|
|
*reloc_addr = symbol_addr + rpnt->r_addend +
|
|
|
- tls_tpnt->l_tls_offset;
|
|
|
+ def_mod->l_tls_offset;
|
|
|
break;
|
|
|
#endif
|
|
|
-
|
|
|
+#endif
|
|
|
default:
|
|
|
return -1;
|
|
|
}
|
|
|
#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
if (_dl_debug_reloc && _dl_debug_detail)
|
|
|
- _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
|
|
|
+ _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %p\n",
|
|
|
old_val, *reloc_addr, reloc_addr);
|
|
|
#endif
|
|
|
|
|
@@ -275,7 +335,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
ElfW(Addr) old_val;
|
|
|
#endif
|
|
|
|
|
|
- reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset);
|
|
|
+ reloc_addr = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
|
|
|
reloc_type = ELF_R_TYPE (rpnt->r_info);
|
|
|
|
|
|
#if defined (__SUPPORT_LD_DEBUG__)
|
|
@@ -286,7 +346,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
case R_XTENSA_JMP_SLOT:
|
|
|
|
|
|
to the stub function. */
|
|
|
- *reloc_addr += tpnt->loadaddr;
|
|
|
+ *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, *reloc_addr);
|
|
|
break;
|
|
|
case R_XTENSA_NONE:
|
|
|
break;
|
|
@@ -296,7 +356,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
|
|
|
|
|
|
#if defined (__SUPPORT_LD_DEBUG__)
|
|
|
if (_dl_debug_reloc && _dl_debug_detail)
|
|
|
- _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
|
|
|
+ _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %p\n",
|
|
|
old_val, *reloc_addr, reloc_addr);
|
|
|
#endif
|
|
|
return 0;
|
|
@@ -320,3 +380,7 @@ _dl_parse_relocation_information (struct dyn_elf *rpnt,
|
|
|
return _dl_parse (rpnt->dyn, scope, rel_addr, rel_size,
|
|
|
_dl_do_reloc);
|
|
|
}
|
|
|
+
|
|
|
+#ifndef IS_IN_libdl
|
|
|
+# include "../../libc/sysdeps/linux/xtensa/crtreloc.c"
|
|
|
+#endif
|