This series adds FDPIC ABI support as specified in the revision 1 of the https://github.com/jcmvbkbc/xtensa-abi/blob/master/fdpic-xtensa.txt
This implementation conflicts with the changes made for ARM FDPIC and it reverts the conflicting change. Reverting the corresponding change in the gcc is required to keep the ARM FDPIC port functional.
Max Filippov (2): xtensa: add FDPIC support Revert "Allow to generate PIE 'static' binary"
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/misc/internals/__uClibc_main.c | 45 -------- 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 ++++-- 24 files changed, 671 insertions(+), 91 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
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 --- 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-1... 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@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
This change generates function descriptors for .preinit_array, .init_array and .fini_array that are not generated by the gcc after commit 11189793b6ef60645d5d1126d0bd9d0dd83e6583. This doesn't make sense, the change in gcc is reverted, so this change is reverted as well.
This reverts commit 99dfb1e26f784429e23f2e67eef5bbbc6e646b83. --- libc/misc/internals/__uClibc_main.c | 45 ----------------------------- 1 file changed, 45 deletions(-)
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 64a9c82143fa..81949c605108 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -48,39 +48,6 @@ int _pe_secure = 0; libc_hidden_data_def(_pe_secure)
-#if !defined(SHARED) && defined(__FDPIC__) -struct funcdesc_value -{ - void *entry_point; - void *got_value; -} __attribute__((__aligned__(8))); - - -/* Prevent compiler optimization that removes GOT assignment. - - Due to optimization passes (block split and move), in the rare case - where use r9 is the single instruction in a block we can have the - following behaviour: - - this block is marked as a forward block since use is not - considered as an active instruction after reload pass. - - - In this case a jump in this block can be moved to the start of the - next one and so remove use in this flow of instructions which can - lead to a removal of r9 restoration after a call. */ -#define _dl_stabilize_funcdesc(val) \ - ({ __asm__ ("" : "+m" (*(val))); (val); }) - -static void fdpic_init_array_jump(void *addr) -{ - struct funcdesc_value *fm = (struct funcdesc_value *) fdpic_init_array_jump; - struct funcdesc_value fd = {addr, fm->got_value}; - - void (*pf)(void) = (void*) _dl_stabilize_funcdesc(&fd); - - (*pf)(); -} -#endif - #ifndef SHARED void *__libc_stack_end = NULL;
@@ -341,11 +308,7 @@ void __uClibc_fini(void) # elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__) size_t i = __fini_array_end - __fini_array_start; while (i-- > 0) -#if !defined(SHARED) && defined(__FDPIC__) - fdpic_init_array_jump(__fini_array_start[i]); -#else (*__fini_array_start [i]) (); -#endif # endif if (__app_fini != NULL) (__app_fini)(); @@ -474,11 +437,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, const size_t size = __preinit_array_end - __preinit_array_start; size_t i; for (i = 0; i < size; i++) -#if !defined(SHARED) && defined(__FDPIC__) - fdpic_init_array_jump(__preinit_array_start[i]); -#else (*__preinit_array_start [i]) (); -#endif } # endif /* Run all the application's ctors now. */ @@ -494,11 +453,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, const size_t size = __init_array_end - __init_array_start; size_t i; for (i = 0; i < size; i++) -#if !defined(SHARED) && defined(__FDPIC__) - fdpic_init_array_jump(__init_array_start[i]); -#else (*__init_array_start [i]) (); -#endif } # endif #endif
Hi Max,
I am trying your patch series in OpenADK, but it fails with following error: /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibc-gcc -c ldso/ldso/ldso.c -o ldso/ldso/ldso.oS -Wall -Wstrict-prototypes -Wstrict-aliasing -Wno-nonnull-compare -funsigned-char -fno-builtin -fcommon -fno-asm -fmerge-all-constants -std=gnu99 -mfdpic -fno-stack-protector -nostdinc -I./include -I./include -include libc-symbols.h -I./libc/sysdeps/linux/xtensa -I./libc/sysdeps/linux/xtensa -I./libc/sysdeps/linux -I./ldso/ldso/xtensa -I./ldso/include -I. -Os -fstrict-aliasing -fwrapv -fno-ident -mlongcalls -mauto-litpools -mabi=call0 -Os -pipe -fomit-frame-pointer -D__USE_STDIO_FUTEXES__ -D__UCLIBC_HAVE_STATX__ -DHAVE_FORCED_UNWIND -D_LIBC_REENTRANT -I./libpthread/nptl -I./libpthread/nptl -I./libpthread/nptl/sysdeps/unix/sysv/linux/xtensa -I./libpthread/nptl/sysdeps/xtensa -I./libpthread/nptl/sysdeps/xtensa -I./libpthread/nptl/sysdeps/unix/sysv/linux -I./libpthread/nptl/sysdeps/unix/sysv/linux -I./libpthread/nptl/sysdeps/pthread -I./libpthread/nptl/sysdeps/pthread/bits -I./libpthread/nptl/sysdeps/generic -I./libc/sysdeps/linux/common -isystem /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/include-fixed -isystem /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/include -I/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/usr/include/ -DNDEBUG -DNOT_IN_libc -DIS_IN_rtld -fno-stack-protector -fno-omit-frame-pointer -I./ldso/ldso/xtensa -I./ldso/include -I./ldso/ldso -DUCLIBC_RUNTIME_PREFIX="/" -DUCLIBC_LDSO="ld-uClibc.so.1" -DIN_LIB=rtld -mfdpic -DSHARED -DLDSO_ELFINTERP="xtensa/elfinterp.c" -DLDSO_MULTILIB_DIR="lib/" -MT ldso/ldso/ldso.oS -MD -MP -MF ldso/ldso/.ldso.oS.dep In file included from ./include/bits/waitstatus.h:72, from ./include/stdlib.h:44, from ./ldso/include/ldso.h:33, from ldso/ldso/ldso.c:32: ./ldso/include/dl-syscall.h: In function '_dl_pread': ./ldso/include/dl-syscall.h:237:76: warning: right shift count >= width of type [-Wshift-count-overflow] 237 | return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR((offset >> 32), (offset & 0xffffffff))); | ^~ ./include/endian.h:52:39: note: in definition of macro '__LONG_LONG_PAIR' 52 | # define __LONG_LONG_PAIR(HI, LO) LO, HI | ^~ In file included from ldso/ldso/ldso.c:87: ldso/ldso/dl-startup.c: In function '_dl_start': ldso/ldso/dl-startup.c:128:20: warning: variable 'got' set but not used [-Wunused-but-set-variable] 128 | ElfW(Addr) got; | ^~~ ldso/ldso/dl-tls.c: Assembler messages: ldso/ldso/dl-tls.c:197: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:203: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:694: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:811: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:160: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:1045: Error: invalid register 'threadptr' for 'wur' instruction ldso/ldso/dl-tls.c:852: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:859: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/ldso.c:1360: Error: invalid register 'threadptr' for 'wur' instruction gmake[6]: *** [Makerules:374: ldso/ldso/ldso.oS] Error 1 gmake[5]: *** [Makefile:353: /home/wbx/openadk/toolchain_build_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/w-uClibc-ng-git-1/uClibc-ng-git/.compiled] Error 2 gmake[4]: *** [Makefile:106: uclibc-ng-compile] Error 2 gmake[3]: *** [mk/build.mk:227: toolchain/final] Error 2 gmake[2]: *** [/home/wbx/openadk/mk/build.mk:176: world] Error 2
I am using an very old overlay for de212, which defaults to windowed ABI, but I added -mabi=call0 to CFLAGS. Are you testing with another CPU? I always use de212 for noMMU configurations.
What I am doing wrong?
best regards Waldemar
Hi Waldemar,
On Thu, May 2, 2024 at 7:13 AM Waldemar Brodkorb wbx@openadk.org wrote:
I am trying your patch series in OpenADK, but it fails with following error:
[...]
ldso/ldso/dl-tls.c: Assembler messages: ldso/ldso/dl-tls.c:197: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:203: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:694: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:811: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:160: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:1045: Error: invalid register 'threadptr' for 'wur' instruction ldso/ldso/dl-tls.c:852: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:859: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/ldso.c:1360: Error: invalid register 'threadptr' for 'wur' instruction gmake[6]: *** [Makerules:374: ldso/ldso/ldso.oS] Error 1 gmake[5]: *** [Makefile:353: /home/wbx/openadk/toolchain_build_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/w-uClibc-ng-git-1/uClibc-ng-git/.compiled] Error 2 gmake[4]: *** [Makefile:106: uclibc-ng-compile] Error 2 gmake[3]: *** [mk/build.mk:227: toolchain/final] Error 2 gmake[2]: *** [/home/wbx/openadk/mk/build.mk:176: world] Error 2
I am using an very old overlay for de212, which defaults to windowed ABI, but I added -mabi=call0 to CFLAGS. Are you testing with another CPU? I always use de212 for noMMU configurations.
de212 doesn't have the THREADPTR option so ATM there's no native TLS implementation that would work for it. For testing I'm using dc233c with call0 ABI and MMU option disabled in the uClibc config. The overlay source for it is available here:
https://github.com/jcmvbkbc/xtensa-toolchain-build/blob/master/overlays/orig...
Also I build the dynconfig library
https://github.com/jcmvbkbc/xtensa-dynconfig/tree/original
for configuring the toolchain instead of applying the overlay.
Hi Max, Max Filippov wrote,
Hi Waldemar,
On Thu, May 2, 2024 at 7:13 AM Waldemar Brodkorb wbx@openadk.org wrote:
I am trying your patch series in OpenADK, but it fails with following error:
[...]
ldso/ldso/dl-tls.c: Assembler messages: ldso/ldso/dl-tls.c:197: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:203: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:694: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:811: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:160: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:1045: Error: invalid register 'threadptr' for 'wur' instruction ldso/ldso/dl-tls.c:852: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/dl-tls.c:859: Error: invalid register 'threadptr' for 'rur' instruction ldso/ldso/ldso.c:1360: Error: invalid register 'threadptr' for 'wur' instruction gmake[6]: *** [Makerules:374: ldso/ldso/ldso.oS] Error 1 gmake[5]: *** [Makefile:353: /home/wbx/openadk/toolchain_build_qemu-xtensa_uclibc-ng_de212_fdpic_nommu/w-uClibc-ng-git-1/uClibc-ng-git/.compiled] Error 2 gmake[4]: *** [Makefile:106: uclibc-ng-compile] Error 2 gmake[3]: *** [mk/build.mk:227: toolchain/final] Error 2 gmake[2]: *** [/home/wbx/openadk/mk/build.mk:176: world] Error 2
I am using an very old overlay for de212, which defaults to windowed ABI, but I added -mabi=call0 to CFLAGS. Are you testing with another CPU? I always use de212 for noMMU configurations.
de212 doesn't have the THREADPTR option so ATM there's no native TLS implementation that would work for it. For testing I'm using dc233c with call0 ABI and MMU option disabled in the uClibc config. The overlay source for it is available here:
https://github.com/jcmvbkbc/xtensa-toolchain-build/blob/master/overlays/orig...
Okay, I switched to dc233c with call0 ABI. Now I get a linker issue: rm -f lib/ld-uClibc.so lib/ld-uClibc.so.1 lib/ld-uClibc-1.0.48.so /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibc-gcc -Wl,-EL -shared -Wl,--warn-common -Wl,--warn-once -Wl,-z,combreloc -Wl,-z,relro -Wl,-O2 -Wl,-z,defs -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/lib -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-O1 -Wl,-rpath -Wl,/usr/lib -Wl,-rpath-link -Wl,/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic -Wl,--sort-common -Wl,--no-undefined -Wl,--discard-locals -Wl,--dis card-all -Wl,-soname=ld-uClibc.so.1 -nostdlib -nostartfiles -o lib/ld-uClibc-1.0.48.so -Wl,--whole-archive ldso/ldso/ld-uClibc_so.a -Wl,--no-whole-archive -shared /home/wbx/openadk/toolchain_qemu-xtensa_uclibc -ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/libgcc.a /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation
What does unexpected FDPIC-specific relocation means?
I am still using the overlay method for binutils/gcc and Linux.
best regards Waldemar
On Thu, May 2, 2024 at 9:53 AM Waldemar Brodkorb wbx@openadk.org wrote:
On Thu, May 2, 2024 at 7:13 AM Waldemar Brodkorb wbx@openadk.org wrote:
Okay, I switched to dc233c with call0 ABI. Now I get a linker issue: rm -f lib/ld-uClibc.so lib/ld-uClibc.so.1 lib/ld-uClibc-1.0.48.so /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibc-gcc -Wl,-EL -shared -Wl,--warn-common -Wl,--warn-once -Wl,-z,combreloc -Wl,-z,relro -Wl,-O2 -Wl,-z,defs -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/lib -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-O1 -Wl,-rpath -Wl,/usr/lib -Wl,-rpath-link -Wl,/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic -Wl,--sort-common -Wl,--no-undefined -Wl,--discard-locals -Wl,--dis card-all -Wl,-soname=ld-uClibc.so.1 -nostdlib -nostartfiles -o lib/ld-uClibc-1.0.48.so -Wl,--whole-archive ldso/ldso/ld-uClibc_so.a -Wl,--no-whole-archive -shared /home/wbx/openadk/toolchain_qemu-xtensa_uclibc -ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/libgcc.a /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation
What does unexpected FDPIC-specific relocation means?
It means an attempt to link code with FDPIC relocations into a non-FDPIC output. It seems that you configured the toolchain for the xtensa-linux-uclibc, for that triplet -mfdpic option is required both at compilation and at linking steps. If you configure for xtensa-linux-uclibcfdpic the linker will be producing FDPIC output by default.
FWIW I have ct-ng branch that I used to build reference toolchain here: https://github.com/jcmvbkbc/crosstool-NG/commits/xtensa-fdpic/
I am still using the overlay method for binutils/gcc and Linux.
It should still work and the result should be the same.
Hi Max, Max Filippov wrote,
On Thu, May 2, 2024 at 9:53 AM Waldemar Brodkorb wbx@openadk.org wrote:
On Thu, May 2, 2024 at 7:13 AM Waldemar Brodkorb wbx@openadk.org wrote:
Okay, I switched to dc233c with call0 ABI. Now I get a linker issue: rm -f lib/ld-uClibc.so lib/ld-uClibc.so.1 lib/ld-uClibc-1.0.48.so /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibc-gcc -Wl,-EL -shared -Wl,--warn-common -Wl,--warn-once -Wl,-z,combreloc -Wl,-z,relro -Wl,-O2 -Wl,-z,defs -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/lib -L/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-O1 -Wl,-rpath -Wl,/usr/lib -Wl,-rpath-link -Wl,/home/wbx/openadk/target_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic -Wl,--sort-common -Wl,--no-undefined -Wl,--discard-locals -Wl,--dis card-all -Wl,-soname=ld-uClibc.so.1 -nostdlib -nostartfiles -o lib/ld-uClibc-1.0.48.so -Wl,--whole-archive ldso/ldso/ld-uClibc_so.a -Wl,--no-whole-archive -shared /home/wbx/openadk/toolchain_qemu-xtensa_uclibc -ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/libgcc.a /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation /home/wbx/openadk/toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/lib/gcc/xtensa-openadk-linux-uclibc/14.0.1/../../../../xtensa-openadk-linux-uclibc/bin/ld: ldso/ldso/ld-uClibc_so.a(ldso.oS): unexpected FDPIC-specific relocation
What does unexpected FDPIC-specific relocation means?
It means an attempt to link code with FDPIC relocations into a non-FDPIC output. It seems that you configured the toolchain for the xtensa-linux-uclibc, for that triplet -mfdpic option is required both at compilation and at linking steps. If you configure for xtensa-linux-uclibcfdpic the linker will be producing FDPIC output by default.
FWIW I have ct-ng branch that I used to build reference toolchain here: https://github.com/jcmvbkbc/crosstool-NG/commits/xtensa-fdpic/
I am still using the overlay method for binutils/gcc and Linux.
It should still work and the result should be the same.
That have worked. Now I am booting up the system in Qemu with following command: qemu-system-xtensa -nographic -M lx60 -cpu dc233c -kernel qemu-xtensa-initramfspiggyback-kernel
Now every command f.e. ls or ps works but gives a Illegal Instruction in dmesg after exit(0).
[ 12.727280] Illegal Instruction in 'hush' (pid = 26, pc = 0x01d52e30) [ 57.203598] Illegal Instruction in 'hush' (pid = 29, pc = 0x01d52e30)
Download of the image is here: https://debug.openadk.org/qemu-xtensa-initramfspiggyback-kernel
Any idea? best regards Waldemar
On Fri, May 3, 2024 at 5:55 AM Waldemar Brodkorb wbx@openadk.org wrote:
Now I am booting up the system in Qemu with following command: qemu-system-xtensa -nographic -M lx60 -cpu dc233c -kernel qemu-xtensa-initramfspiggyback-kernel
Now every command f.e. ls or ps works but gives a Illegal Instruction in dmesg after exit(0).
[ 12.727280] Illegal Instruction in 'hush' (pid = 26, pc = 0x01d52e30) [ 57.203598] Illegal Instruction in 'hush' (pid = 29, pc = 0x01d52e30)
Looks like that kernel is built without call0 userspace ABI support. CONFIG_USER_ABI_CALL0_ONLY or CONFIG_USER_ABI_CALL0_PROBE need to be set in the kernel config for correct signal delivery to call0 processes.
Hi Max, Max Filippov wrote,
On Fri, May 3, 2024 at 5:55 AM Waldemar Brodkorb wbx@openadk.org wrote:
Now I am booting up the system in Qemu with following command: qemu-system-xtensa -nographic -M lx60 -cpu dc233c -kernel qemu-xtensa-initramfspiggyback-kernel
Now every command f.e. ls or ps works but gives a Illegal Instruction in dmesg after exit(0).
[ 12.727280] Illegal Instruction in 'hush' (pid = 26, pc = 0x01d52e30) [ 57.203598] Illegal Instruction in 'hush' (pid = 29, pc = 0x01d52e30)
Looks like that kernel is built without call0 userspace ABI support. CONFIG_USER_ABI_CALL0_ONLY or CONFIG_USER_ABI_CALL0_PROBE need to be set in the kernel config for correct signal delivery to call0 processes.
You are right again. Now I could successfully run the test suite: Total skipped: 7 Total failed: 10 Total passed: 241
A lot of NPTL tests are using fork(), should we disable them for noMMU to get at least some coverage for the NPTL/TLS code in noMMU FDPIC case? At the moment all NPTL cases are disabled in OpenADK in the noMMU case.
How did you test NPTL/TLS?
Thanks Waldemar
On Fri, May 3, 2024 at 8:15 PM Waldemar Brodkorb wbx@openadk.org wrote:
Hi Max, Max Filippov wrote,
On Fri, May 3, 2024 at 5:55 AM Waldemar Brodkorb wbx@openadk.org wrote:
Now I am booting up the system in Qemu with following command: qemu-system-xtensa -nographic -M lx60 -cpu dc233c -kernel qemu-xtensa-initramfspiggyback-kernel
Now every command f.e. ls or ps works but gives a Illegal Instruction in dmesg after exit(0).
[ 12.727280] Illegal Instruction in 'hush' (pid = 26, pc = 0x01d52e30) [ 57.203598] Illegal Instruction in 'hush' (pid = 29, pc = 0x01d52e30)
Looks like that kernel is built without call0 userspace ABI support. CONFIG_USER_ABI_CALL0_ONLY or CONFIG_USER_ABI_CALL0_PROBE need to be set in the kernel config for correct signal delivery to call0 processes.
You are right again. Now I could successfully run the test suite: Total skipped: 7 Total failed: 10 Total passed: 241
A lot of NPTL tests are using fork(), should we disable them for noMMU to get at least some coverage for the NPTL/TLS code in noMMU FDPIC case? At the moment all NPTL cases are disabled in OpenADK in the noMMU case.
How did you test NPTL/TLS?
I grepped for the tests explicitly using fork and added them to the TESTS_DISABLED in the test/nptl/Makefile.in, and also added there the tests that internally time out, got the following list:
+TESTS_DISABLED := tst-atfork1 \ + tst-atfork2 \ + tst-atfork2mod \ + tst-barrier2 \ + tst-basic4 \ + tst-cancel16 \ + tst-cancel21 \ + tst-cancel4 \ + tst-cancel5 \ + tst-cancelx16 \ + tst-cancelx21 \ + tst-cancelx4 \ + tst-cond12 \ + tst-cond13 \ + tst-cond4 \ + tst-cond6 \ + tst-cpuclock1 \ + tst-cputimer3 \ + tst-exec2 \ + tst-exec3 \ + tst-exec4 \ + tst-flock2 \ + tst-fork1 \ + tst-fork2 \ + tst-fork3 \ + tst-fork4 \ + tst-getpid3 \ + tst-mqueue1 \ + tst-mqueue3 \ + tst-mqueue5 \ + tst-mutex4 \ + tst-mutex9 \ + tst-rwlock12 \ + tst-rwlock4 \ + tst-sem3 \ + tst-sem4 \ + tst-signal1 \ + tst-signal2 \ + tst-spin2 \ + tst-tsd6
On top of that a few tests expect termination with a signal, they show as failed, but in fact do pass. I also wrote a couple local tests for the cases where I had bugs earlier.
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Fri, May 3, 2024 at 8:15 PM Waldemar Brodkorb wbx@openadk.org wrote:
How did you test NPTL/TLS?
...and for TLS I've posted a patch for the testsuite that adds FDPIC-specific implementations of the test TLS macros. The whole tls subdirectory is passing for me with that change.
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Fri, May 3, 2024 at 8:15 PM Waldemar Brodkorb wbx@openadk.org wrote:
How did you test NPTL/TLS?
I grepped for the tests explicitly using fork and added them to the TESTS_DISABLED in the test/nptl/Makefile.in, and also added there the tests that internally time out, got the following list:
+TESTS_DISABLED := tst-atfork1 \
tst-atfork2 \
tst-atfork2mod \
tst-barrier2 \
tst-basic4 \
tst-cancel16 \
tst-cancel21 \
tst-cancel4 \
tst-cancel5 \
tst-cancelx16 \
tst-cancelx21 \
tst-cancelx4 \
tst-cond12 \
tst-cond13 \
tst-cond4 \
tst-cond6 \
tst-cpuclock1 \
tst-cputimer3 \
tst-exec2 \
tst-exec3 \
tst-exec4 \
tst-flock2 \
tst-fork1 \
tst-fork2 \
tst-fork3 \
tst-fork4 \
tst-getpid3 \
tst-mqueue1 \
tst-mqueue3 \
tst-mqueue5 \
tst-mutex4 \
tst-mutex9 \
tst-rwlock12 \
tst-rwlock4 \
tst-sem3 \
tst-sem4 \
tst-signal1 \
tst-signal2 \
tst-spin2 \
tst-tsd6
also the following tests either hang or cause problems, so I disabled them as well:
mmap/mmap2 \ nptl/tst-basic7 \ nptl/tst-cond3 \ nptl/tst-eintr1 \ nptl/tst-eintr2 \ nptl/tst-eintr3 \ nptl/tst-eintr4 \ nptl/tst-eintr5 \ nptl/tst-exit2 \ nptl/tst-exit3 \ nptl/tst-mqueue6 \ nptl/tst-stdio1
Hi Max, Max Filippov wrote,
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Fri, May 3, 2024 at 8:15 PM Waldemar Brodkorb wbx@openadk.org wrote:
How did you test NPTL/TLS?
I grepped for the tests explicitly using fork and added them to the TESTS_DISABLED in the test/nptl/Makefile.in, and also added there the tests that internally time out, got the following list:
+TESTS_DISABLED := tst-atfork1 \
tst-atfork2 \
tst-atfork2mod \
tst-barrier2 \
tst-basic4 \
tst-cancel16 \
tst-cancel21 \
tst-cancel4 \
tst-cancel5 \
tst-cancelx16 \
tst-cancelx21 \
tst-cancelx4 \
tst-cond12 \
tst-cond13 \
tst-cond4 \
tst-cond6 \
tst-cpuclock1 \
tst-cputimer3 \
tst-exec2 \
tst-exec3 \
tst-exec4 \
tst-flock2 \
tst-fork1 \
tst-fork2 \
tst-fork3 \
tst-fork4 \
tst-getpid3 \
tst-mqueue1 \
tst-mqueue3 \
tst-mqueue5 \
tst-mutex4 \
tst-mutex9 \
tst-rwlock12 \
tst-rwlock4 \
tst-sem3 \
tst-sem4 \
tst-signal1 \
tst-signal2 \
tst-spin2 \
tst-tsd6
I added a check for MMU for these tests.
also the following tests either hang or cause problems, so I disabled them as well:
mmap/mmap2 \ nptl/tst-basic7 \ nptl/tst-cond3 \ nptl/tst-eintr1 \ nptl/tst-eintr2 \ nptl/tst-eintr3 \ nptl/tst-eintr4 \ nptl/tst-eintr5 \ nptl/tst-exit2 \ nptl/tst-exit3 \ nptl/tst-mqueue6 \ nptl/tst-stdio1
I would like to disable these tests only for Xtensa FDPIC, but wbx@helium:~/openadk$ ./toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibcfdpic-gcc -dM -E -</dev/null|grep -i fdpic wbx@helium:~/openadk$
wbx@helium:~/openadk$ ./toolchain_qemu-arm-versatilepb_uclibc-ng_arm926ej_s_hard_eabihf_fdpic_arm_nommu/usr/bin/arm-openadk-uclinuxfdpiceabi-gcc -dM -E - </dev/null|grep -i fdpic #define __FDPIC__ 1 wbx@helium:~/openadk$
Any reason there is no __FDPIC__ set?
I will check these tests soon on real ARM noMMU hardware.
Thanks Waldemar
Hi Waldemar,
On Sun, May 5, 2024 at 2:51 AM Waldemar Brodkorb wbx@openadk.org wrote:
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Fri, May 3, 2024 at 8:15 PM Waldemar Brodkorb wbx@openadk.org wrote:
How did you test NPTL/TLS?
I grepped for the tests explicitly using fork and added them to the TESTS_DISABLED in the test/nptl/Makefile.in, and also added there the tests that internally time out, got the following list:
+TESTS_DISABLED := tst-atfork1 \
tst-atfork2 \
tst-atfork2mod \
tst-barrier2 \
tst-basic4 \
tst-cancel16 \
tst-cancel21 \
tst-cancel4 \
tst-cancel5 \
tst-cancelx16 \
tst-cancelx21 \
tst-cancelx4 \
tst-cond12 \
tst-cond13 \
tst-cond4 \
tst-cond6 \
tst-cpuclock1 \
tst-cputimer3 \
tst-exec2 \
tst-exec3 \
tst-exec4 \
tst-flock2 \
tst-fork1 \
tst-fork2 \
tst-fork3 \
tst-fork4 \
tst-getpid3 \
tst-mqueue1 \
tst-mqueue3 \
tst-mqueue5 \
tst-mutex4 \
tst-mutex9 \
tst-rwlock12 \
tst-rwlock4 \
tst-sem3 \
tst-sem4 \
tst-signal1 \
tst-signal2 \
tst-spin2 \
tst-tsd6
I added a check for MMU for these tests.
also the following tests either hang or cause problems, so I disabled them as well:
mmap/mmap2 \ nptl/tst-basic7 \ nptl/tst-cond3 \ nptl/tst-eintr1 \ nptl/tst-eintr2 \ nptl/tst-eintr3 \ nptl/tst-eintr4 \ nptl/tst-eintr5 \ nptl/tst-exit2 \ nptl/tst-exit3 \ nptl/tst-mqueue6 \ nptl/tst-stdio1
I would like to disable these tests only for Xtensa FDPIC
I doubt that they're FDPIC-specific. The mmap2 is clearly related to noMMU, I haven't looked closely at the rest yet, I'll do it this week.
but wbx@helium:~/openadk$ ./toolchain_qemu-xtensa_uclibc-ng_dc233c_call0_fdpic_nommu/usr/bin/xtensa-openadk-linux-uclibcfdpic-gcc -dM -E -</dev/null|grep -i fdpic wbx@helium:~/openadk$
wbx@helium:~/openadk$ ./toolchain_qemu-arm-versatilepb_uclibc-ng_arm926ej_s_hard_eabihf_fdpic_arm_nommu/usr/bin/arm-openadk-uclinuxfdpiceabi-gcc -dM -E - </dev/null|grep -i fdpic #define __FDPIC__ 1 wbx@helium:~/openadk$
Any reason there is no __FDPIC__ set?
It haven't been implemented in that gcc version, it should be there in the gcc tagged xtensa-fdpic-abi-spec-1.2 Also binutils/gcc tagged xtensa-fdpic-abi-spec-1.2 should be able to build xtensa FDPIC toolchain with both uclibc-ng and musl.
I will check these tests soon on real ARM noMMU hardware.
Hi Waldemar,
On Mon, May 6, 2024 at 11:17 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Sun, May 5, 2024 at 2:51 AM Waldemar Brodkorb wbx@openadk.org wrote:
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote: also the following tests either hang or cause problems, so I disabled them as well:
mmap/mmap2 \ nptl/tst-basic7 \ nptl/tst-cond3 \ nptl/tst-eintr1 \ nptl/tst-eintr2 \ nptl/tst-eintr3 \ nptl/tst-eintr4 \ nptl/tst-eintr5 \ nptl/tst-exit2 \ nptl/tst-exit3 \ nptl/tst-mqueue6 \ nptl/tst-stdio1
I would like to disable these tests only for Xtensa FDPIC
I doubt that they're FDPIC-specific. The mmap2 is clearly related to noMMU, I haven't looked closely at the rest yet, I'll do it this week.
Most of the issues with the tests in the above list are caused by using direct ( -d ) mode to run them when targeting noMMU, but it seems to me that it doesn't have to be like that: even on noMMU the test skeleton can do vfork and exec itself in direct mode. I'll post a patch that implements this change, with that patch most of the above tests run to successful completion.
There's still a few failures I observe with the xtensa FDPIC port even with that change:
nptl/tst-attr3 -- fails because thread stack guard size in the test is the same as the default thread stack size. Building uclibc with bigger default stack size fixes that failure.
nptl/tst-basic7 -- fails because it sets prlimit(RLIMIT_AS) to 10MB and tries to exhaust it, but mmap doesn't fail on noMMU until it runs out of memory. It looks like a kernel bug to me (there's no call to may_expand_vm() from the nommu do_mmap version). If it's supposed to be like that on the kernel side it means that this test is not applicable on a noMMU target.
nptl/tst-cancel7, nptl/tst-cancelx7 -- fail because it expects that a shell started by system() execs the program without forking, so that killing it releases the file lock it might have taken. It seems to me that it relies on implementation details (not even the libc implementation details) and the test should be fixed.
nptl/tst-mqueue6 -- fails because mq_notify() called with notification->sigev_notify set to SIGEV_THREAD fails with ENOSYS, because init_mq_netlink() calls pthread_atfork(), which is not implemented on noMMU. It seems to me that either pthread_atfork may be avoided on a noMMU target, or it can be implemented on a noMMU target. Or the test is not applicable on a noMMU target.
unistd/errno -- fails because of the stupid mistake in the xtensa FDPICI port I introduced at a recent code rebase (missing ';' after FDPIC_LOAD_JUMPTARGET in the SYSCALL_ERROR_HANDLER variant for linuxthreads, that swallowed the following call to __errno_location()) and that surprisingly wasn't caught by the assembler. I fixed it by adding the ';' and also defining USE___THREAD in ASFLAGS in the xtensa NPTL port, so that the appropriate version of SYSCALL_ERROR_HANDLER is used for linuxthreads and for NPTL.
Hi Max, Max Filippov wrote,
Hi Waldemar,
On Mon, May 6, 2024 at 11:17 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Sun, May 5, 2024 at 2:51 AM Waldemar Brodkorb wbx@openadk.org wrote:
On Sat, May 4, 2024 at 12:14 AM Max Filippov jcmvbkbc@gmail.com wrote: also the following tests either hang or cause problems, so I disabled them as well:
mmap/mmap2 \ nptl/tst-basic7 \ nptl/tst-cond3 \ nptl/tst-eintr1 \ nptl/tst-eintr2 \ nptl/tst-eintr3 \ nptl/tst-eintr4 \ nptl/tst-eintr5 \ nptl/tst-exit2 \ nptl/tst-exit3 \ nptl/tst-mqueue6 \ nptl/tst-stdio1
I would like to disable these tests only for Xtensa FDPIC
I doubt that they're FDPIC-specific. The mmap2 is clearly related to noMMU, I haven't looked closely at the rest yet, I'll do it this week.
Most of the issues with the tests in the above list are caused by using direct ( -d ) mode to run them when targeting noMMU, but it seems to me that it doesn't have to be like that: even on noMMU the test skeleton can do vfork and exec itself in direct mode. I'll post a patch that implements this change, with that patch most of the above tests run to successful completion.
There's still a few failures I observe with the xtensa FDPIC port even with that change:
nptl/tst-attr3 -- fails because thread stack guard size in the test is the same as the default thread stack size. Building uclibc with bigger default stack size fixes that failure.
nptl/tst-basic7 -- fails because it sets prlimit(RLIMIT_AS) to 10MB and tries to exhaust it, but mmap doesn't fail on noMMU until it runs out of memory. It looks like a kernel bug to me (there's no call to may_expand_vm() from the nommu do_mmap version). If it's supposed to be like that on the kernel side it means that this test is not applicable on a noMMU target.
nptl/tst-cancel7, nptl/tst-cancelx7 -- fail because it expects that a shell started by system() execs the program without forking, so that killing it releases the file lock it might have taken. It seems to me that it relies on implementation details (not even the libc implementation details) and the test should be fixed.
nptl/tst-mqueue6 -- fails because mq_notify() called with notification->sigev_notify set to SIGEV_THREAD fails with ENOSYS, because init_mq_netlink() calls pthread_atfork(), which is not implemented on noMMU. It seems to me that either pthread_atfork may be avoided on a noMMU target, or it can be implemented on a noMMU target. Or the test is not applicable on a noMMU target.
unistd/errno -- fails because of the stupid mistake in the xtensa FDPICI port I introduced at a recent code rebase (missing ';' after FDPIC_LOAD_JUMPTARGET in the SYSCALL_ERROR_HANDLER variant for linuxthreads, that swallowed the following call to __errno_location()) and that surprisingly wasn't caught by the assembler. I fixed it by adding the ';' and also defining USE___THREAD in ASFLAGS in the xtensa NPTL port, so that the appropriate version of SYSCALL_ERROR_HANDLER is used for linuxthreads and for NPTL.
Thanks for the explanations.
Is the uClibc-ng port ready to commit or do you have any changes open?
best regards Waldemar
Hi Waldemar,
On Mon, May 20, 2024 at 9:12 PM Waldemar Brodkorb wbx@openadk.org wrote:
Is the uClibc-ng port ready to commit or do you have any changes open?
There's one fix for the xtensa port, I will resend the fixed version in a couple days, along with the new tags for the binutils and gcc. And then there's a conflict with the change made by the ARM port (reverted in the second patch of the series) that involves gcc and for which I don't have the exact plan ATM. Let me take a good look at it.
On Tue, May 21, 2024 at 12:01 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Mon, May 20, 2024 at 9:12 PM Waldemar Brodkorb wbx@openadk.org wrote:
Is the uClibc-ng port ready to commit or do you have any changes open?
There's one fix for the xtensa port, I will resend the fixed version in a couple days, along with the new tags for the binutils and gcc.
And then there's a conflict with the change made by the ARM port (reverted in the second patch of the series) that involves gcc and for which I don't have the exact plan ATM. Let me take a good look at it.
So I tried to understand how to make a proper fix for this issue and I think that it must be done in the binutils. xtensa needs a binutils fix as well to be able to build working FDPIC static PIEs, but since nothing in the patch that adds xtensa FDPIC support to uclibc-ng depends on it, let's fix it separately. For now I've dropped the second patch from the xtensa FDPIC series for the uclibc-ng and the matching patch from the gcc with FDPIC support for xtensa.
My current plan is to provide the fix for binutils that would handle init_array/fini_array pointers correctly in FDPIC static PIEs, then revert the workaround in the gcc (or restrict it only for ARM), then restrict the workaround in uclibc-ng to gcc versions that would still have the workaround.
-- Thanks. -- Max