From 74d5b684253ce61404c1b72f2726599f00eb0a14 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 28 Nov 2023 23:29:43 +1000 Subject: elf: support ELF binaries in noMMU The Linux kernels ELF-FDPIC binfmt program loader can support loading and running conventional ELF format binaries on noMMU kernels when compiled appropriately. That is when they are constant displacement binaries such as generated using the -pie compile option. Add a configure option to allow selecting ELF binary support in noMMU mode configurations on architectures that support this. The main requirement is to generate the ldso run-time loader to perform relocation at load time. These configurations do not support shared libraries, so there is no need to generate a full shared library, only the static version is required. The use of ELF format binaries does mean a slightly simpler toolchain generation (does not require a -uclinux- for some architectures) and does not require an extra tool like elf2flt. This initial support targets M68K, ARM and RISC-V architectures. No kernel changes are required, the required support for this is already in mainline kernels (certainly as of linux-6.6). Note that for the M68K and ARM architectures that the initialized registers and stack layout at process startup is slightly different for the flat format loader and the ELF/ELF-FDPIC loaders. So we need some changes to the startup code (crt1.S) for them. I have not done extensive testing outside of M68K, ARM and RISC-V. I had to make changes to a couple of the dl-startup.h architecture files to get them to build for this noMMU case. I did not dig down too deep on the reasons, but they still seem ok for the MMU case as well. Signed-off-by: Greg Ungerer --- libc/sysdeps/linux/arm/crt1.S | 2 +- libc/sysdeps/linux/m68k/crt1.S | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'libc/sysdeps') diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S index fade1d25c..799f11080 100644 --- a/libc/sysdeps/linux/arm/crt1.S +++ b/libc/sysdeps/linux/arm/crt1.S @@ -245,7 +245,7 @@ _start: mov fp, #0 mov lr, #0 -#ifdef __ARCH_USE_MMU__ +#if defined(__ARCH_USE_MMU__) || defined(__UCLIBC_FORMAT_ELF__) #ifdef L_rcrt1 /* We don't need to save a1 since no dynamic linker should have run */ ldr a1, .L_GOT /* Get value at .L_GOT + 0 (offset to GOT)*/ diff --git a/libc/sysdeps/linux/m68k/crt1.S b/libc/sysdeps/linux/m68k/crt1.S index 815a6076f..e7292682b 100644 --- a/libc/sysdeps/linux/m68k/crt1.S +++ b/libc/sysdeps/linux/m68k/crt1.S @@ -78,9 +78,13 @@ _start: sub.l %fp, %fp #if !defined __ARCH_USE_MMU__ && defined __PIC__ +#ifdef UCLIBC_FORMAT_ELF + move.l #_GLOBAL_OFFSET_TABLE_, %a5 +#else /* Set up the global pointer. The GOT is at the beginning of the data segment, whose address is in %d5. */ move.l %d5,%a5 +#endif .equ have_current_got, 1 #endif @@ -92,11 +96,11 @@ _start: arguments for `main': argc, argv. envp will be determined later in __libc_start_main. */ move.l (%sp)+, %d0 /* Pop the argument count. */ -#ifndef __ARCH_USE_MMU__ - move.l (%sp)+, %a0 -#else +#if defined(__ARCH_USE_MMU__) || defined(__UCLIBC_FORMAT_ELF__) move.l %sp, %a0 /* The argument vector starts just at the current stack top. */ +#else + move.l (%sp)+, %a0 #endif /* Provide the highest stack address to the user code (for stacks -- cgit v1.2.3