summaryrefslogtreecommitdiff
path: root/ldso/ldso/xtensa/elfinterp.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2024-06-01 03:39:03 -0700
committerWaldemar Brodkorb <wbx@openadk.org>2024-06-04 16:40:42 +0200
commit138274e92a01be8a98392489b1a2f497ab11c201 (patch)
treef0be841a1e915e86d4215326a13654f8034632a4 /ldso/ldso/xtensa/elfinterp.c
parent8bb33a2e1f2baec2078581d77e181f1ead5f51aa (diff)
xtensa: add FDPIC support
This change implements Xtensa FDPIC ABI as specified in the first version of the following document: https://github.com/jcmvbkbc/xtensa-abi/blob/master/fdpic-xtensa.txt Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'ldso/ldso/xtensa/elfinterp.c')
-rw-r--r--ldso/ldso/xtensa/elfinterp.c114
1 files changed, 89 insertions, 25 deletions
diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c
index e38a02666..d97f23435 100644
--- a/ldso/ldso/xtensa/elfinterp.c
+++ b/ldso/ldso/xtensa/elfinterp.c
@@ -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
+ /* Relocation against an undefined weak symbol:
+ 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; /* Calls _dl_exit(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:
/* Perform a RELATIVE reloc on the GOT entry that transfers
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