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(a)gmail.com>
---
The toolchain components matching the libc are available in
the following repositories with the tag xtensa-fdpic-abi-spec-1.1:
https://github.com/jcmvbkbc/binutils-gdb-xtensa/tree/xtensa-fdpic-abi-spec-…
https://github.com/jcmvbkbc/gcc-xtensa/tree/xtensa-fdpic-abi-spec-1.1
---
Rules.mak | 4 +
extra/Configs/Config.in | 2 +-
extra/Configs/Config.in.arch | 2 +-
include/elf.h | 6 +-
ldso/ldso/xtensa/dl-inlines.h | 1 +
ldso/ldso/xtensa/dl-startup.h | 91 ++++++++++++++-
ldso/ldso/xtensa/dl-sysdep.h | 66 ++++++++++-
ldso/ldso/xtensa/dl-tlsdesc.S | 10 +-
ldso/ldso/xtensa/elfinterp.c | 114 ++++++++++++++-----
libc/sysdeps/linux/xtensa/__start_context.S | 6 +-
libc/sysdeps/linux/xtensa/bits/elf-fdpic.h | 117 ++++++++++++++++++++
libc/sysdeps/linux/xtensa/clone.S | 6 +
libc/sysdeps/linux/xtensa/crt1.S | 81 ++++++++++++++
libc/sysdeps/linux/xtensa/crti.S | 8 ++
libc/sysdeps/linux/xtensa/crtn.S | 6 +
libc/sysdeps/linux/xtensa/crtreloc.c | 105 ++++++++++++++++++
libc/sysdeps/linux/xtensa/getcontext.S | 1 +
libc/sysdeps/linux/xtensa/makecontext.c | 5 +
libc/sysdeps/linux/xtensa/setcontext.S | 1 +
libc/sysdeps/linux/xtensa/setjmp.S | 3 +-
libc/sysdeps/linux/xtensa/swapcontext.S | 1 +
libc/sysdeps/linux/xtensa/sysdep.h | 48 +++++++-
libpthread/nptl/sysdeps/xtensa/dl-tls.h | 33 ++++--
23 files changed, 671 insertions(+), 46 deletions(-)
create mode 100644 ldso/ldso/xtensa/dl-inlines.h
create mode 100644 libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
create mode 100644 libc/sysdeps/linux/xtensa/crtreloc.c
diff --git a/Rules.mak b/Rules.mak
index 5be74b86edd4..70d681238b24 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -520,6 +520,10 @@ ifeq ($(TARGET_ARCH),c6x)
CPU_LDFLAGS-y += $(CPU_CFLAGS)
endif
+ifeq ($(TARGET_ARCH),xtensa)
+ CPU_CFLAGS-$(UCLIBC_FORMAT_FDPIC_ELF) +=-mfdpic
+endif
+
$(eval $(call check-gcc-var,$(PIEFLAG_NAME)))
PIEFLAG := $(CFLAG_$(PIEFLAG_NAME))
ifeq ($(PIEFLAG),)
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index b814449b43a5..be63eae60d3a 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -615,7 +615,7 @@ config UCLIBC_HAS_THREADS_NATIVE
!TARGET_h8300 && \
!TARGET_hppa && \
!TARGET_ia64 && \
- (ARCH_USE_MMU || TARGET_arm)
+ (ARCH_USE_MMU || TARGET_arm || TARGET_xtensa)
help
If you want to compile uClibc with NPTL support, then answer Y.
diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch
index 1ae5134b9df5..c13497893414 100644
--- a/extra/Configs/Config.in.arch
+++ b/extra/Configs/Config.in.arch
@@ -20,7 +20,7 @@ config UCLIBC_FORMAT_ELF
select HAVE_LDSO
config UCLIBC_FORMAT_FDPIC_ELF
bool "FDPIC ELF"
- depends on !ARCH_USE_MMU && (TARGET_bfin || TARGET_frv || TARGET_arm)
+ depends on !ARCH_USE_MMU && (TARGET_bfin || TARGET_frv || TARGET_arm ||
TARGET_xtensa)
select DOPIC
config UCLIBC_FORMAT_DSBT_ELF
bool "DBST ELF"
diff --git a/include/elf.h b/include/elf.h
index c2efa9978677..1e7c89615a44 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -3588,8 +3588,12 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_XTENSA_TLSDESC_FN 50
#define R_XTENSA_TLSDESC_ARG 51
#define R_XTENSA_TLS_TPOFF 53
+#define R_XTENSA_SYM32 63
+#define R_XTENSA_FUNCDESC 68
+#define R_XTENSA_FUNCDESC_VALUE 69
+#define R_XTENSA_TLSDESC 72
/* Keep this the last entry. */
-#define R_XTENSA_NUM 54
+#define R_XTENSA_NUM 77
/* C6X specific relocs */
#define R_C6000_NONE 0
diff --git a/ldso/ldso/xtensa/dl-inlines.h b/ldso/ldso/xtensa/dl-inlines.h
new file mode 100644
index 000000000000..8fdf6eb48679
--- /dev/null
+++ b/ldso/ldso/xtensa/dl-inlines.h
@@ -0,0 +1 @@
+#include "../fdpic/dl-inlines.h"
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
index c9350c0f201e..2a453752acaf 100644
--- a/ldso/ldso/xtensa/dl-startup.h
+++ b/ldso/ldso/xtensa/dl-startup.h
@@ -7,6 +7,68 @@
* Parts taken from glibc/sysdeps/xtensa/dl-machine.h.
*/
+#if defined(__FDPIC__)
+__asm__ (
+ " .text\n"
+ " .align 4\n"
+ " .literal_position\n"
+ " .global _start\n"
+ " .type _start, @function\n"
+ " .hidden _start\n"
+ "_start:\n"
+ " .begin no-transform\n"
+ " _call0 1f\n"
+ "2:\n"
+ " .end no-transform\n"
+ " .align 4\n"
+ "1:\n"
+#if defined(__XTENSA_CALL0_ABI__)
+ " movi a15, 2b\n"
+ " sub a15, a0, a15\n"
+
+ /* Save FDPIC pointers in callee-saved registers */
+ " mov a12, a4\n"
+ " mov a13, a5\n"
+ " mov a14, a6\n"
+
+ /* Call __self_reloc */
+ " mov a2, a5\n"
+ " movi a3, __ROFIXUP_LIST__\n"
+ " add a3, a3, a15\n"
+ " movi a4, __ROFIXUP_END__\n"
+ " add a4, a4, a15\n"
+ " movi a0, __self_reloc\n"
+ " add a0, a0, a15\n"
+ " callx0 a0\n"
+
+ /* call _dl_start */
+ " mov a3, a12\n"
+ " mov a4, a13\n"
+ " mov a5, a14\n"
+ " mov a7, sp\n"
+ " addi sp, sp, -16\n"
+ " mov a6, sp\n"
+ " mov a11, a2\n"
+ /* a13, interpreter map is no longer needed, save interpreter GOT there */
+ " mov a13, a2\n"
+ " movi a0, _dl_start\n"
+ " add a0, a0, a15\n"
+ " callx0 a0\n"
+
+ /* call main */
+ " l32i a0, sp, 0\n"
+ " l32i a11, sp, 4\n"
+ " addi sp, sp, 16\n"
+ " mov a4, a12\n"
+ " movi a5, _dl_fini@GOTOFFFUNCDESC\n"
+ " add a5, a5, a13\n"
+ " mov a6, a14\n"
+ " jx a0\n"
+#else
+#error Unsupported Xtensa ABI
+#endif
+ );
+#else /* __FDPIC__ */
#ifndef L_rcrt1
__asm__ (
" .text\n"
@@ -83,6 +145,7 @@ __asm__ (
" bnez a6, 3b\n"
" j .Lfixup_stack_ret");
#endif
+#endif /* __FDPIC__ */
/* Get a pointer to the argv value. */
#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
@@ -90,7 +153,7 @@ __asm__ (
/* Function calls are not safe until the GOT relocations have been done. */
#define NO_FUNCS_BEFORE_BOOTSTRAP
-#if defined(__ARCH_USE_MMU__)
+#if defined(__ARCH_USE_MMU__) && !defined(__FDPIC__)
#define PERFORM_BOOTSTRAP_GOT(tpnt) \
do { \
xtensa_got_location *got_loc; \
@@ -128,3 +191,29 @@ do { \
} \
} while (0)
#endif
+
+#ifdef __FDPIC__
+#undef DL_START
+#define DL_START(X) \
+static void __attribute__ ((used)) \
+_dl_start (Elf32_Addr dl_boot_got_pointer, \
+ struct elf32_fdpic_loadmap *dl_boot_progmap, \
+ struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ struct funcdesc_value *dl_main_funcdesc, \
+ X)
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. We return the address of the function's entry point to
+ * _dl_boot, see boot1_arch.h.
+ */
+#define START() do { \
+ struct elf_resolve *exec_mod = _dl_loaded_modules; \
+ dl_main_funcdesc->entry_point = _dl_elf_main; \
+ while (exec_mod->libtype != elf_executable) \
+ exec_mod = exec_mod->next; \
+ dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
+ return; \
+} while (0)
+#endif /* __FDPIC__ */
diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h
index 6b908989a8f1..5aa3e177f3a1 100644
--- a/ldso/ldso/xtensa/dl-sysdep.h
+++ b/ldso/ldso/xtensa/dl-sysdep.h
@@ -26,6 +26,7 @@
in l_info array. */
#define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM)
+#ifndef __FDPIC__
typedef struct xtensa_got_location_struct {
Elf32_Off offset;
Elf32_Word length;
@@ -86,6 +87,7 @@ typedef struct xtensa_got_location_struct {
else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ) \
dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val; \
} while (0)
+#endif
/* Here we define the magic numbers that this dynamic loader should accept. */
#define MAGIC1 EM_XTENSA
@@ -115,10 +117,41 @@ elf_machine_dynamic (void)
return (Elf32_Addr) &_DYNAMIC;
}
+#ifdef __FDPIC__
+
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ (piclib) = 2; \
+} \
+while (0)
+
+/* We must force strings used early in the bootstrap into the data
+ segment. */
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { /* FIXME: implement */; } while (0)
+
+#undef INIT_GOT
+#include "../fdpic/dl-sysdep.h"
+#undef INIT_GOT
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ (MODULE)->loadaddr.got_value = (GOT_BASE); \
+ GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \
+ GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \
+ GOT_BASE[2] = (unsigned long) MODULE; \
+}
+
+#endif /* __FDPIC__ */
+
/* Return the run-time load address of the shared object. */
static __always_inline Elf32_Addr
elf_machine_load_address (void)
{
+#ifdef __FDPIC__
+ return 0;
+#else
Elf32_Addr addr, tmp;
/* At this point, the runtime linker is being bootstrapped and the GOT
@@ -135,11 +168,41 @@ elf_machine_load_address (void)
: "=a" (addr), "=a" (tmp));
return addr - 3;
+#endif
}
+#ifdef __FDPIC__
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch (ELF_R_TYPE((RELP)->r_info)){ \
+ case R_XTENSA_SYM32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ case R_XTENSA_RELATIVE: \
+ case R_XTENSA_NONE: \
+ default: \
+ break; \
+ }
+
static __always_inline void
-elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
Elf32_Word relative_count)
+{
+ Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr;
+ while (relative_count--)
+ {
+ Elf32_Addr *const reloc_addr = (Elf32_Addr *) DL_RELOC_ADDR(load_off,
rpnt->r_offset);
+ *reloc_addr = DL_RELOC_ADDR(load_off, *reloc_addr);
+ rpnt++;
+ }
+}
+#else
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
{
Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr;
while (relative_count--)
@@ -149,3 +212,4 @@ elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
rpnt++;
}
}
+#endif
diff --git a/ldso/ldso/xtensa/dl-tlsdesc.S b/ldso/ldso/xtensa/dl-tlsdesc.S
index 426f2180b3c0..1a8eacff20cc 100644
--- a/ldso/ldso/xtensa/dl-tlsdesc.S
+++ b/ldso/ldso/xtensa/dl-tlsdesc.S
@@ -24,6 +24,9 @@
.text
HIDDEN_ENTRY (_dl_tlsdesc_return)
+#ifdef __FDPIC__
+ l32i a2, a2, 4
+#endif
rur.threadptr a3
add a2, a2, a3
abi_ret
@@ -53,7 +56,9 @@ END (_dl_tlsdesc_return)
*/
HIDDEN_ENTRY (_dl_tlsdesc_dynamic)
-
+#ifdef __FDPIC__
+ l32i a2, a2, 4
+#endif
/* dtv_t *dtv = (dtv_t *)THREAD_DTV(); */
rur.threadptr a3
l32i a4, a3, 0
@@ -86,7 +91,8 @@ HIDDEN_ENTRY (_dl_tlsdesc_dynamic)
#elif defined(__XTENSA_CALL0_ABI__)
addi a1, a1, -16
s32i a0, a1, 0
- movi a0, __tls_get_addr
+ movi a0, JUMPTARGET(__tls_get_addr)
+ FDPIC_LOAD_JUMPTARGET(a0, a11, a0)
callx0 a0
l32i a0, a1, 0
addi a1, a1, 16
diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c
index e38a02666477..d97f234353e8 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
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S
b/libc/sysdeps/linux/xtensa/__start_context.S
index a30d7b6188ad..e6ce93347d6d 100644
--- a/libc/sysdeps/linux/xtensa/__start_context.S
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -22,9 +22,10 @@
* There's no entry instruction, makecontext sets up ucontext_t as if
* getcontext was called above and is about to return here.
* Registers on entry to this function:
- * a12: func to call
+ * a12: func to call (function descriptor in case of FDPIC)
* a13: ucp->uc_link, next context to activate if func returns
* a14: func argc
+ * a15: current GOT pointer (in case of FDPIC)
*/
.literal_position
@@ -46,14 +47,17 @@ ENTRY_PREFIX(__start_context)
addi a1, a1, 16
/* func arguments 6..argc - 1 are now at the top of the stack */
1:
+ FDPIC_LOAD_FUNCDESC (a12, a12)
callx0 a12
beqz a13, 1f
mov a2, a13
movi a4, JUMPTARGET (setcontext)
+ FDPIC_LOAD_JUMPTARGET (a4, a15, a4)
callx0 a4
1:
movi a4, JUMPTARGET (_exit)
movi a2, 0
+ FDPIC_LOAD_JUMPTARGET (a4, a15, a4)
callx0 a4
ill
END(__start_context)
diff --git a/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
new file mode 100644
index 000000000000..19bb247b878e
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h
@@ -0,0 +1,117 @@
+/* Copyright 2003, 2004 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+In addition to the permissions in the GNU Lesser General Public
+License, the Free Software Foundation gives you unlimited
+permission to link the compiled version of this file with other
+programs, and to distribute those programs without any restriction
+coming from the use of this file. (The GNU Lesser General Public
+License restrictions do apply in other respects; for example, they
+cover modification of the file, and distribution when not linked
+into another program.)
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_ELF_FDPIC_H
+#define _BITS_ELF_FDPIC_H
+
+/* These data structures are described in the FDPIC ABI extension.
+ The kernel passes a process a memory map, such that for every LOAD
+ segment there is an elf32_fdpic_loadseg entry. A pointer to an
+ elf32_fdpic_loadmap is passed in r7 at start-up, and a pointer to
+ an additional such map is passed in r8 for the interpreter, when
+ there is one. */
+
+#include <elf.h>
+
+/* This data structure represents a PT_LOAD segment. */
+struct elf32_fdpic_loadseg
+{
+ /* Core address to which the segment is mapped. */
+ Elf32_Addr addr;
+ /* VMA recorded in the program header. */
+ Elf32_Addr p_vaddr;
+ /* Size of this segment in memory. */
+ Elf32_Word p_memsz;
+};
+
+struct elf32_fdpic_loadmap {
+ /* Protocol version number, must be zero. */
+ Elf32_Half version;
+ /* Number of segments in this map. */
+ Elf32_Half nsegs;
+ /* The actual memory map. */
+ struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
+struct elf32_fdpic_loadaddr {
+ struct elf32_fdpic_loadmap *map;
+ void *got_value;
+};
+
+/* Map a pointer's VMA to its corresponding address according to the
+ load map. */
+static __always_inline void *
+__reloc_pointer (void *p,
+ const struct elf32_fdpic_loadmap *map)
+{
+ int c;
+
+#if 0
+ if (map->version != 0)
+ /* Crash. */
+ ((void(*)())0)();
+#endif
+
+ /* No special provision is made for NULL. We don't want NULL
+ addresses to go through relocation, so they shouldn't be in
+ .rofixup sections, and, if they're present in dynamic
+ relocations, they shall be mapped to the NULL address without
+ undergoing relocations. */
+
+ for (c = 0;
+ /* Take advantage of the fact that the loadmap is ordered by
+ virtual addresses. In general there will only be 2 entries,
+ so it's not profitable to do a binary search. */
+ c < map->nsegs && p >= (void*)map->segs[c].p_vaddr;
+ c++)
+ {
+ /* This should be computed as part of the pointer comparison
+ above, but we want to use the carry in the comparison, so we
+ can't convert it to an integer type beforehand. */
+ unsigned long offset = (char*)p - (char*)map->segs[c].p_vaddr;
+ /* We only check for one-past-the-end for the last segment,
+ assumed to be the data segment, because other cases are
+ ambiguous in the absence of padding between segments, and
+ rofixup already serves as padding between text and data.
+ Unfortunately, unless we special-case the last segment, we
+ fail to relocate the _end symbol. */
+ if (offset < map->segs[c].p_memsz
+ || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs))
+ return (char*)map->segs[c].addr + offset;
+ }
+
+ /* We might want to crash instead. */
+ return (void*)-1;
+}
+
+# define __RELOC_POINTER(ptr, loadaddr) \
+ (__reloc_pointer ((void*)(ptr), \
+ (loadaddr).map))
+
+void*
+__self_reloc (const struct elf32_fdpic_loadmap *map, void ***p, void ***e);
+
+#endif /* _BITS_ELF_FDPIC_H */
diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S
index ebfdcc1f65be..a11044cd0271 100644
--- a/libc/sysdeps/linux/xtensa/clone.S
+++ b/libc/sysdeps/linux/xtensa/clone.S
@@ -81,11 +81,17 @@ ENTRY (__clone)
callx4 a2
#elif defined(__XTENSA_CALL0_ABI__)
mov a2, a9 /* load up the 'arg' parameter */
+#ifdef __FDPIC__
+ mov a12, a11
+ l32i a11, a7, 4
+ l32i a7, a7, 0
+#endif
callx0 a7 /* call the user's function */
/* Call _exit. Note that any return parameter from the user's
function in a2 is seen as inputs to _exit. */
movi a0, JUMPTARGET(_exit)
+ FDPIC_LOAD_JUMPTARGET(a0, a12, a0)
callx0 a0
#else
#error Unsupported Xtensa ABI
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S
index 3fa14ae583a9..a12f82dd656b 100644
--- a/libc/sysdeps/linux/xtensa/crt1.S
+++ b/libc/sysdeps/linux/xtensa/crt1.S
@@ -35,6 +35,86 @@
#include <features.h>
+#if defined(__FDPIC__)
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment. When the entry point runs, most register values are unspecified,
+ except for:
+
+ a6 Address of .dynamic section
+ a5 Interpreter map
+ a4 Executable map
+
+ a2 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ a1 The stack (i.e., a1+16) contains the arguments and environment:
+ a1+0 argc
+ a1+4 argv[0]
+ ...
+ a1+(4*argc) NULL
+ a1+(4*(argc+1)) envp[0]
+ ...
+ NULL
+ */
+ .text
+ .align 4
+ .literal_position
+ .global _start
+ .type _start, @function
+_start:
+#if defined(__XTENSA_CALL0_ABI__)
+
+ .begin no-transform
+ call0 1f
+2:
+ .end no-transform
+ .align 4
+ .literal_position
+1:
+ movi a15, 2b
+ sub a15, a0, a15
+
+ mov a12, a4
+ mov a13, a5
+ mov a14, a6
+ mov a2, a4
+ movi a3, __ROFIXUP_LIST__
+ add a3, a3, a15
+ movi a4, __ROFIXUP_END__
+ add a4, a4, a15
+ movi a0, __self_reloc
+ add a0, a0, a15
+ callx0 a0
+
+ mov a11, a2
+ movi a2, main@GOTOFFFUNCDESC
+ add a2, a2, a11
+ l32i a3, sp, 0 /* argc */
+ addi a4, sp, 4 /* argv */
+ /* a5 is either 0 when static or set by the RTLD to the rtld_fini */
+ mov a7, a13
+ /* unused stack_end argument is what used to be argc */
+ movi a5, _init@GOTOFFFUNCDESC
+ add a5, a5, a11
+ movi a6, _fini@GOTOFFFUNCDESC
+ add a6, a6, a11
+
+ movi a0, __uClibc_main@GOTOFFFUNCDESC
+ add a0, a0, a11
+ l32i a11, a0, 4
+ l32i a0, a0, 0
+ callx0 a0
+ ill
+
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+#else /* defined(__FDPIC__) */
+
#ifndef __UCLIBC_CTOR_DTOR__
.weak _init
.weak _fini
@@ -173,3 +253,4 @@ __data_start:
.long 0
.weak data_start
data_start = __data_start
+#endif /* defined(__FDPIC__) */
diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S
index 43e66e30820b..2923ff09d0bb 100644
--- a/libc/sysdeps/linux/xtensa/crti.S
+++ b/libc/sysdeps/linux/xtensa/crti.S
@@ -11,6 +11,10 @@ _init:
#elif defined(__XTENSA_CALL0_ABI__)
addi sp, sp, -16
s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
#else
#error Unsupported Xtensa ABI
#endif
@@ -26,6 +30,10 @@ _fini:
#elif defined(__XTENSA_CALL0_ABI__)
addi sp, sp, -16
s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
#else
#error Unsupported Xtensa ABI
#endif
diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S
index a3598da1a537..6f797e8bdd60 100644
--- a/libc/sysdeps/linux/xtensa/crtn.S
+++ b/libc/sysdeps/linux/xtensa/crtn.S
@@ -4,6 +4,9 @@
#if defined(__XTENSA_WINDOWED_ABI__)
retw
#elif defined(__XTENSA_CALL0_ABI__)
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
l32i a0, sp, 0
addi sp, sp, 16
ret
@@ -15,6 +18,9 @@
#if defined(__XTENSA_WINDOWED_ABI__)
retw
#elif defined(__XTENSA_CALL0_ABI__)
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
l32i a0, sp, 0
addi sp, sp, 16
ret
diff --git a/libc/sysdeps/linux/xtensa/crtreloc.c b/libc/sysdeps/linux/xtensa/crtreloc.c
new file mode 100644
index 000000000000..697ef91ab21f
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/crtreloc.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ written by Alexandre Oliva <aoliva(a)redhat.com>
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+In addition to the permissions in the GNU Lesser General Public
+License, the Free Software Foundation gives you unlimited
+permission to link the compiled version of this file with other
+programs, and to distribute those programs without any restriction
+coming from the use of this file. (The GNU Lesser General Public
+License restrictions do apply in other respects; for example, they
+cover modification of the file, and distribution when not linked
+into another program.)
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef __FDPIC__
+
+#include <sys/types.h>
+#include <link.h>
+
+/* This file is to be compiled into crt object files, to enable
+ executables to easily self-relocate. */
+
+/* Compute the runtime address of pointer in the range [p,e), and then
+ map the pointer pointed by it. */
+static __always_inline void ***
+reloc_range_indirect (void ***p, void ***e,
+ const struct elf32_fdpic_loadmap *map)
+{
+ while (p < e)
+ {
+ if (*p != (void **)-1)
+ {
+ void *ptr = __reloc_pointer (*p, map);
+
+ if (ptr != (void *)-1)
+ {
+ unsigned long off = ((unsigned long)ptr & 3) * 8;
+ unsigned long *pa = (unsigned long *)((unsigned long)ptr & -4);
+ unsigned long v2;
+ void *pt;
+
+ if (off)
+ {
+ unsigned long v0, v1;
+#ifdef __XTENSA_EB__
+ v0 = pa[1]; v1 = pa[0];
+ v2 = (v1 >> (32 - off)) | (v0 << off);
+#else /* __XTENSA_EL__ */
+ v0 = pa[0]; v1 = pa[1];
+ v2 = (v0 << (32 - off)) | (v1 >> off);
+#endif
+ pt = (void *)((v1 << (32 - off)) | (v0 >> off));
+ }
+ else
+ pt = *(void**)ptr;
+ pt = __reloc_pointer (pt, map);
+ if (off)
+ {
+ unsigned long v = (unsigned long)pt;
+#ifdef __XTENSA_EB__
+ pa[0] = (v2 << (32 - off)) | (v >> off);
+ pa[1] = (v << (32 - off)) | (v2 >> off);
+#else /* __XTENSA_EL__ */
+ pa[0] = (v2 >> (32 - off)) | (v << off);
+ pa[1] = (v >> (32 - off)) | (v2 << off);
+#endif
+ }
+ else
+ *(void**)ptr = pt;
+ }
+ }
+ p++;
+ }
+ return p;
+}
+
+/* Call __reloc_range_indirect for the given range except for the last
+ entry, whose contents are only relocated. It's expected to hold
+ the GOT value. */
+attribute_hidden void*
+__self_reloc (const struct elf32_fdpic_loadmap *map,
+ void ***p, void ***e)
+{
+ p = reloc_range_indirect (p, e-1, map);
+
+ if (p >= e)
+ return (void*)-1;
+
+ return __reloc_pointer (*p, map);
+}
+
+#endif /* __FDPIC__ */
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S
b/libc/sysdeps/linux/xtensa/getcontext.S
index 7588a91b33b3..4cc644552d42 100644
--- a/libc/sysdeps/linux/xtensa/getcontext.S
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -33,6 +33,7 @@ ENTRY(__getcontext)
addi a4, a2, UCONTEXT_SIGMASK
movi a2, SIG_BLOCK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
jx a5
END(__getcontext)
#elif defined(__XTENSA_WINDOWED_ABI__)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c
b/libc/sysdeps/linux/xtensa/makecontext.c
index da26a0130325..0a8f7116fef2 100644
--- a/libc/sysdeps/linux/xtensa/makecontext.c
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -73,7 +73,12 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
sp -= 4 * (argc + 2);
sp &= -16;
+#ifdef __FDPIC__
+ ucp->uc_mcontext.sc_pc = ((unsigned long *) __start_context)[0];
+ ucp->uc_mcontext.sc_a[15] = ((unsigned long *) __start_context)[1];
+#else
ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+#endif
ucp->uc_mcontext.sc_a[1] = sp;
ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S
b/libc/sysdeps/linux/xtensa/setcontext.S
index 4df7cc049006..72915ef8d74e 100644
--- a/libc/sysdeps/linux/xtensa/setcontext.S
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -28,6 +28,7 @@ ENTRY(__setcontext)
movi a4, 0
movi a2, SIG_SETMASK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
callx0 a5
bnez a2, .Lerror
diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S
index b8152fdd8bac..d629c11a8c41 100644
--- a/libc/sysdeps/linux/xtensa/setjmp.S
+++ b/libc/sysdeps/linux/xtensa/setjmp.S
@@ -155,7 +155,8 @@ ENTRY (__sigsetjmp)
s32i a14, a2, 16
s32i a15, a2, 20
mov a12, a2
- movi a0, __sigjmp_save
+ movi a0, JUMPTARGET(__sigjmp_save)
+ FDPIC_LOAD_JUMPTARGET(a0, a11, a0)
callx0 a0
l32i a0, a12, 0
l32i a12, a12, 8
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S
b/libc/sysdeps/linux/xtensa/swapcontext.S
index a215edc6d54a..40b38e98ca01 100644
--- a/libc/sysdeps/linux/xtensa/swapcontext.S
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -36,6 +36,7 @@ ENTRY(__swapcontext)
addi a4, a2, UCONTEXT_SIGMASK
movi a2, SIG_SETMASK
movi a5, JUMPTARGET (sigprocmask)
+ FDPIC_LOAD_JUMPTARGET (a5, a11, a5)
callx0 a5
bnez a2, .Lerror
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 80b3f30fcc5d..c527d163f66d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -75,13 +75,27 @@
#define LITERAL_POSITION .literal_position
#undef JUMPTARGET
-#ifdef __PIC__
+#if defined(__FDPIC__)
+#define JUMPTARGET(name) name##@GOTOFFFUNCDESC
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc) \
+ l32i a11, funcdesc, 4; \
+ l32i call_target, funcdesc, 0
+
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)\
+ add call_target, got_base, jumptarget; \
+ FDPIC_LOAD_FUNCDESC(call_target, call_target)
+
+#elif defined(__PIC__)
/* The "@PLT" suffix is currently a no-op for non-shared linking, but
it doesn't hurt to use it conditionally for PIC code in case that
changes someday. */
#define JUMPTARGET(name) name##@PLT
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc)
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)
#else
#define JUMPTARGET(name) name
+#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc)
+#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)
#endif
#ifndef FRAMESIZE
@@ -153,6 +167,21 @@
#if defined _LIBC_REENTRANT
# if defined USE___THREAD
+#ifdef __FDPIC__
+# define SYSCALL_ERROR_ERRNO errno
+# define SYSCALL_ERROR_HANDLER \
+0: rur a4, THREADPTR; \
+ movi a3, SYSCALL_ERROR_ERRNO@GOTTPOFF; \
+ .reloc ., R_XTENSA_TLS_TPOFF_PTR, SYSCALL_ERROR_ERRNO; \
+ add a3, a3, a11; \
+ .reloc ., R_XTENSA_TLS_TPOFF_LOAD, SYSCALL_ERROR_ERRNO; \
+ l32i a3, a3, 0; \
+ neg a2, a2; \
+ add a4, a4, a3; \
+ s32i a2, a4, 0; \
+ movi a2, -1; \
+ j .Lpseudo_end;
+#else
# define SYSCALL_ERROR_ERRNO errno
# define SYSCALL_ERROR_HANDLER \
0: rur a4, THREADPTR; \
@@ -162,13 +191,14 @@
s32i a2, a4, 0; \
movi a2, -1; \
j .Lpseudo_end;
+#endif
# else /* !USE___THREAD */
#if defined(__XTENSA_WINDOWED_ABI__)
# define SYSCALL_ERROR_HANDLER \
0: neg a2, a2; \
mov a6, a2; \
- movi a4, __errno_location@PLT; \
+ movi a4, JUMPTARGET(__errno_location); \
callx4 a4; \
s32i a2, a6, 0; \
movi a2, -1; \
@@ -179,7 +209,8 @@
addi a1, a1, -16; \
s32i a0, a1, 0; \
s32i a2, a1, 4; \
- movi a0, __errno_location@PLT; \
+ movi a0, JUMPTARGET(__errno_location); \
+ FDPIC_LOAD_JUMPTARGET(a0, a11, a0) \
callx0 a0; \
l32i a0, a1, 0; \
l32i a3, a1, 4; \
@@ -193,12 +224,23 @@
# endif /* !USE___THREAD */
#else /* !_LIBC_REENTRANT */
+#ifdef __FDPIC__
+#define SYSCALL_ERROR_HANDLER \
+0: movi a4, errno@GOT; \
+ add a4, a4, a11; \
+ l32i a4, a4, 0; \
+ neg a2, a2; \
+ s32i a2, a4, 0; \
+ movi a2, -1; \
+ j .Lpseudo_end;
+#else
#define SYSCALL_ERROR_HANDLER \
0: movi a4, errno; \
neg a2, a2; \
s32i a2, a4, 0; \
movi a2, -1; \
j .Lpseudo_end;
+#endif /* __FDPIC__ */
#endif /* _LIBC_REENTRANT */
#endif /* __ASSEMBLER__ */
diff --git a/libpthread/nptl/sysdeps/xtensa/dl-tls.h
b/libpthread/nptl/sysdeps/xtensa/dl-tls.h
index adc02d74a55c..5fc4ea2d05c8 100644
--- a/libpthread/nptl/sysdeps/xtensa/dl-tls.h
+++ b/libpthread/nptl/sysdeps/xtensa/dl-tls.h
@@ -28,6 +28,29 @@ typedef struct
extern void *__tls_get_addr (tls_index *ti);
+/* Type used as the argument in a TLS descriptor for a symbol that
+ needs dynamic TLS offsets. */
+struct tlsdesc_dynamic_arg
+{
+ tls_index tlsinfo;
+ size_t gen_count;
+};
+
+#ifdef __FDPIC__
+/* Type used to represent a TLS descriptor. */
+struct tlsdesc
+{
+ ptrdiff_t (*entry)(struct tlsdesc *);
+ void *argument;
+};
+
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_return(struct tlsdesc *);
+
+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
+extern ptrdiff_t attribute_hidden
+ _dl_tlsdesc_dynamic(struct tlsdesc *);
+#else
/* Type used to represent a TLS descriptor. */
struct tlsdesc
{
@@ -39,19 +62,11 @@ struct tlsdesc
ptrdiff_t (*entry)(struct tlsdesc *);
};
-/* Type used as the argument in a TLS descriptor for a symbol that
- needs dynamic TLS offsets. */
-struct tlsdesc_dynamic_arg
-{
- tls_index tlsinfo;
- size_t gen_count;
-};
-
extern ptrdiff_t attribute_hidden
_dl_tlsdesc_return(struct tlsdesc_dynamic_arg *);
extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
extern ptrdiff_t attribute_hidden
_dl_tlsdesc_dynamic(struct tlsdesc_dynamic_arg *);
-
+#endif
#endif
--
2.39.2