Hello,
this series does a couple cleanups in the ldso, static PIE code and xtensa code and enables static PIE support for the xtensa architecture.
Changes v1->v2: - clean up PERFORM_BOOTSTRAP_GOT condition in the ldso - drop patch that adds PERFORM_BOOTSTRAP_GOT to reloc_static_pie
Max Filippov (5): static pie: fix building static PDE ldso: clean up PERFORM_BOOTSTRAP_GOT ifdeferry xtensa: ldso: make GOT protection adjustment conditional xtensa: drop ARCH_NEEDS_BOOTSTRAP_RELOCS xtensa: add static pie support
extra/Configs/Config.in | 4 +++- ldso/ldso/dl-startup.c | 3 --- ldso/ldso/xtensa/dl-startup.h | 15 ++++-------- ldso/ldso/xtensa/dl-sysdep.h | 3 --- libc/misc/internals/reloc_static_pie.c | 6 ++--- libc/sysdeps/linux/xtensa/crt1.S | 27 ++++++++++++++++++++++ libpthread/nptl/sysdeps/generic/libc-tls.c | 7 ++++-- 7 files changed, 42 insertions(+), 23 deletions(-)
When uclibc is built with static PIE support the _dl_load_base variable shared between the libc-tls.c and reloc_static_pie.c creates the dependency that requires linking reloc_static_pie.o into static position-dependent executables resulting in the following build errors: gcc -static test.c -o test ...ld: ...usr/lib/libc.a(reloc_static_pie.os):(.text+0x0): undefined reference to `_DYNAMIC'
Move _dl_load_base definition to libc-tls.c to resolve this dependency and fix static PDE build.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- libc/misc/internals/reloc_static_pie.c | 4 ++-- libpthread/nptl/sysdeps/generic/libc-tls.c | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index c0027de6fe06..ce42cb9b30df 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -25,7 +25,7 @@ #include <dl-startup.h> #endif
-ElfW(Addr) _dl_load_base = NULL; +extern ElfW(Addr) _dl_load_base;
void reloc_static_pie (ElfW(Addr) load_addr); @@ -107,4 +107,4 @@ reloc_static_pie(ElfW(Addr) load_addr) #endif } _dl_load_base = load_addr; -} \ No newline at end of file +} diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c index 54f3cb0c72b5..7cfe9ac1a85c 100644 --- a/libpthread/nptl/sysdeps/generic/libc-tls.c +++ b/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -117,6 +117,10 @@ init_static_tls (size_t memsz, size_t align) GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); }
+#if !defined(__FDPIC__) && !defined(SHARED) && defined(STATIC_PIE) +ElfW(Addr) _dl_load_base; +#endif + void __libc_setup_tls (size_t tcbsize, size_t tcbalign); void __libc_setup_tls (size_t tcbsize, size_t tcbalign) @@ -143,8 +147,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) #else initimage = (void *) phdr->p_vaddr; #if !defined(SHARED) && defined(STATIC_PIE) - extern ElfW(Addr) _dl_load_base; - initimage += _dl_load_base; + initimage += _dl_load_base; #endif #endif align = phdr->p_align;
3 architectures currently define PERFORM_BOOTSTRAP_GOT: avr32, mips and xtensa. A block of code that applies relative relocations in the DL_START is disabled when PERFORM_BOOTSTRAP_GOT is defined, unless it's avr32 or mips, effectively disabling it only for xtensa. This may be simplified by removing the call to elf_machine_relative from the xtensa PERFORM_BOOTSTRAP_GOT and always using common code.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- Changes v1->v2: - new patch
ldso/ldso/dl-startup.c | 3 --- ldso/ldso/xtensa/dl-startup.h | 11 ----------- 2 files changed, 14 deletions(-)
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 24b046c62b0b..a1b3d49fdd39 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -255,8 +255,6 @@ DL_START(unsigned long args) PERFORM_BOOTSTRAP_GOT(tpnt); #endif
-#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) || defined(__mips__) - /* OK, now do the relocations. We do not do a lazy binding here, so that once we are done, we have considerably more flexibility. */ SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n"); @@ -337,7 +335,6 @@ DL_START(unsigned long args) #endif } } -#endif
SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n");
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index db223feadc90..92877aa016fb 100644 --- a/ldso/ldso/xtensa/dl-startup.h +++ b/ldso/ldso/xtensa/dl-startup.h @@ -92,8 +92,6 @@ __asm__ ( do { \ xtensa_got_location *got_loc; \ unsigned long l_addr = tpnt->loadaddr; \ - Elf32_Word relative_count; \ - unsigned long rel_addr; \ Elf32_Addr prev_got_start = 0, prev_got_end = 0; \ int x; \ \ @@ -125,13 +123,4 @@ do { \ prev_got_end - prev_got_start, \ PROT_READ | PROT_WRITE | PROT_EXEC); \ } \ -\ - /* The following is a stripped down version of the code following \ - the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c. That \ - code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \ - to be done here instead. */ \ - relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \ - rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \ - if (rel_addr) \ - elf_machine_relative(load_addr, rel_addr, relative_count); \ } while (0)
Xtensa PERFORM_BOOTSTRAP_GOT macro uses mprotect to make bits of GOT writable, but noMMU linux kernel returns ENOSYS to mprotect syscalls, and syscall wrapper tries to update errno with the error code. This happens well before the relocations are done and results in writes to unrelated locations, memory corruption or protection violations.
Only define PERFORM_BOOTSTRAP_GOT when building xtensa configuration with MMU support.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- Changes v1->v2: - now that PERFORM_BOOTSTRAP_GOT only does mprotect calls make its whole definition conditional instead of extracting that part.
ldso/ldso/xtensa/dl-startup.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index 92877aa016fb..439bdbd7a5e2 100644 --- a/ldso/ldso/xtensa/dl-startup.h +++ b/ldso/ldso/xtensa/dl-startup.h @@ -88,6 +88,7 @@ __asm__ ( /* Function calls are not safe until the GOT relocations have been done. */ #define NO_FUNCS_BEFORE_BOOTSTRAP
+#if defined(__ARCH_USE_MMU__) #define PERFORM_BOOTSTRAP_GOT(tpnt) \ do { \ xtensa_got_location *got_loc; \ @@ -124,3 +125,4 @@ do { \ PROT_READ | PROT_WRITE | PROT_EXEC); \ } \ } while (0) +#endif
Xtensa does not define PERFORM_BOOTSTRAP_RELOC so it doesn't need ARCH_NEEDS_BOOTSTRAP_RELOCS definition. Remove it.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- ldso/ldso/xtensa/dl-sysdep.h | 3 --- 1 file changed, 3 deletions(-)
diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h index d308237d39ed..6b908989a8f1 100644 --- a/ldso/ldso/xtensa/dl-sysdep.h +++ b/ldso/ldso/xtensa/dl-sysdep.h @@ -94,9 +94,6 @@ typedef struct xtensa_got_location_struct { /* Used for error messages. */ #define ELF_TARGET "Xtensa"
-/* Need bootstrap relocations */ -#define ARCH_NEEDS_BOOTSTRAP_RELOCS - struct elf_resolve; extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- extra/Configs/Config.in | 4 +++- ldso/ldso/xtensa/dl-startup.h | 2 ++ libc/misc/internals/reloc_static_pie.c | 2 +- libc/sysdeps/linux/xtensa/crt1.S | 27 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 43c04fd0a271..dd1beaadcee3 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -324,7 +324,9 @@ config DOPIC config STATIC_PIE bool "Add support for Static Position Independent Executables (PIE)" default n - depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips) + depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && \ + (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || \ + TARGET_mips || TARGET_xtensa)
config ARCH_HAS_NO_SHARED bool diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index 439bdbd7a5e2..c9350c0f201e 100644 --- a/ldso/ldso/xtensa/dl-startup.h +++ b/ldso/ldso/xtensa/dl-startup.h @@ -7,6 +7,7 @@ * Parts taken from glibc/sysdeps/xtensa/dl-machine.h. */
+#ifndef L_rcrt1 __asm__ ( " .text\n" " .align 4\n" @@ -81,6 +82,7 @@ __asm__ ( " addi a5, a5, 8\n" " bnez a6, 3b\n" " j .Lfixup_stack_ret"); +#endif
/* Get a pointer to the argv value. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index ce42cb9b30df..ab1923024c2b 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -21,7 +21,7 @@ #include <dl-elf.h>
#include <ldso.h> -#ifdef __mips__ +#if defined(__mips__) || defined(__xtensa__) #include <dl-startup.h> #endif
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S index efbe264c03f0..3fa14ae583a9 100644 --- a/libc/sysdeps/linux/xtensa/crt1.S +++ b/libc/sysdeps/linux/xtensa/crt1.S @@ -76,9 +76,26 @@ .global _start .type _start, @function _start: +#ifdef L_rcrt1 + .begin no-transform + call0 1f +.Lret_addr: + .end no-transform + .align 4 +1: +#endif #if defined(__XTENSA_WINDOWED_ABI__) +#ifdef L_rcrt1 + movi a6, .Lret_addr + sub a6, a0, a6 + movi a0, 0 + movi a4, reloc_static_pie + add a4, a4, a6 + callx4 a4 +#else /* Clear a0 to obviously mark the outermost frame. */ movi a0, 0 +#endif
/* Load up the user's main function. */ movi a6, main @@ -106,8 +123,18 @@ _start: movi a4, __uClibc_main callx4 a4 #elif defined(__XTENSA_CALL0_ABI__) +#ifdef L_rcrt1 + mov a12, a2 + movi a2, .Lret_addr + sub a2, a0, a2 + movi a0, reloc_static_pie + add a0, a0, a2 + callx0 a0 + mov a7, a12 +#else /* Setup the shared library termination function. */ mov a7, a2 +#endif
/* Load up the user's main function. */ movi a2, main
Tested this along with the patches for binutils and gcc. Everything is working for me when tested with buildroot's qemu_xtensa_lx60_defconfig and qemu.
On Thu, Sep 15, 2022 at 3:31 PM Max Filippov jcmvbkbc@gmail.com wrote:
Signed-off-by: Max Filippov jcmvbkbc@gmail.com
extra/Configs/Config.in | 4 +++- ldso/ldso/xtensa/dl-startup.h | 2 ++ libc/misc/internals/reloc_static_pie.c | 2 +- libc/sysdeps/linux/xtensa/crt1.S | 27 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 43c04fd0a271..dd1beaadcee3 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -324,7 +324,9 @@ config DOPIC config STATIC_PIE bool "Add support for Static Position Independent Executables (PIE)" default n
depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm ||
TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips)
depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && \
(TARGET_arm || TARGET_i386 || TARGET_x86_64 ||
TARGET_aarch64 || \
TARGET_mips || TARGET_xtensa)
config ARCH_HAS_NO_SHARED bool diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index 439bdbd7a5e2..c9350c0f201e 100644 --- a/ldso/ldso/xtensa/dl-startup.h +++ b/ldso/ldso/xtensa/dl-startup.h @@ -7,6 +7,7 @@
- Parts taken from glibc/sysdeps/xtensa/dl-machine.h.
*/
+#ifndef L_rcrt1 __asm__ ( " .text\n" " .align 4\n" @@ -81,6 +82,7 @@ __asm__ ( " addi a5, a5, 8\n" " bnez a6, 3b\n" " j .Lfixup_stack_ret"); +#endif
/* Get a pointer to the argv value. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index ce42cb9b30df..ab1923024c2b 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -21,7 +21,7 @@ #include <dl-elf.h>
#include <ldso.h> -#ifdef __mips__ +#if defined(__mips__) || defined(__xtensa__) #include <dl-startup.h> #endif
diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S index efbe264c03f0..3fa14ae583a9 100644 --- a/libc/sysdeps/linux/xtensa/crt1.S +++ b/libc/sysdeps/linux/xtensa/crt1.S @@ -76,9 +76,26 @@ .global _start .type _start, @function _start: +#ifdef L_rcrt1
.begin no-transform
call0 1f
+.Lret_addr:
.end no-transform
.align 4
+1: +#endif #if defined(__XTENSA_WINDOWED_ABI__) +#ifdef L_rcrt1
movi a6, .Lret_addr
sub a6, a0, a6
movi a0, 0
movi a4, reloc_static_pie
add a4, a4, a6
callx4 a4
+#else /* Clear a0 to obviously mark the outermost frame. */ movi a0, 0 +#endif
/* Load up the user's main function. */ movi a6, main
@@ -106,8 +123,18 @@ _start: movi a4, __uClibc_main callx4 a4 #elif defined(__XTENSA_CALL0_ABI__) +#ifdef L_rcrt1
mov a12, a2
movi a2, .Lret_addr
sub a2, a0, a2
movi a0, reloc_static_pie
add a0, a0, a2
callx0 a0
mov a7, a12
+#else /* Setup the shared library termination function. */ mov a7, a2 +#endif
/* Load up the user's main function. */ movi a2, main
-- 2.30.2
Hi Max,
thanks for the patches, all applied and pushed.
best regards Waldemar
Max Filippov wrote,
Hello,
this series does a couple cleanups in the ldso, static PIE code and xtensa code and enables static PIE support for the xtensa architecture.
Changes v1->v2:
- clean up PERFORM_BOOTSTRAP_GOT condition in the ldso
- drop patch that adds PERFORM_BOOTSTRAP_GOT to reloc_static_pie
Max Filippov (5): static pie: fix building static PDE ldso: clean up PERFORM_BOOTSTRAP_GOT ifdeferry xtensa: ldso: make GOT protection adjustment conditional xtensa: drop ARCH_NEEDS_BOOTSTRAP_RELOCS xtensa: add static pie support
extra/Configs/Config.in | 4 +++- ldso/ldso/dl-startup.c | 3 --- ldso/ldso/xtensa/dl-startup.h | 15 ++++-------- ldso/ldso/xtensa/dl-sysdep.h | 3 --- libc/misc/internals/reloc_static_pie.c | 6 ++--- libc/sysdeps/linux/xtensa/crt1.S | 27 ++++++++++++++++++++++ libpthread/nptl/sysdeps/generic/libc-tls.c | 7 ++++-- 7 files changed, 42 insertions(+), 23 deletions(-)
-- 2.30.2
devel mailing list -- devel@uclibc-ng.org To unsubscribe send an email to devel-leave@uclibc-ng.org