diff options
45 files changed, 827 insertions, 187 deletions
| @@ -1,7 +1,7 @@  # Rules.mak for uClibc-ng  #  # Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> -# Copyright (C) 2015-2022 Waldemar Brodkorb <wbx@uclibc-ng.org> +# Copyright (C) 2015-2023 Waldemar Brodkorb <wbx@uclibc-ng.org>  #  # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.  # @@ -128,7 +128,7 @@ export RUNTIME_PREFIX DEVEL_PREFIX KERNEL_HEADERS MULTILIB_DIR  # Now config hard core  MAJOR_VERSION := 1  MINOR_VERSION := 0 -SUBLEVEL      := 42 +SUBLEVEL      := 43  EXTRAVERSION  :=  VERSION       := $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL)  ABI_VERSION   := $(MAJOR_VERSION) @@ -296,6 +296,7 @@ ifneq ($(TARGET_ARCH),c6x)  ifneq ($(TARGET_ARCH),h8300)  ifneq ($(TARGET_ARCH),arc)  ifneq ($(TARGET_ARCH),aarch64) +ifneq ($(TARGET_ARCH),riscv32)  CPU_CFLAGS-y += -msoft-float  endif  endif @@ -307,6 +308,7 @@ endif  endif  endif  endif +endif  ifeq ($(TARGET_ARCH),aarch64)  CPU_CFLAGS-y += -ftls-model=initial-exec diff --git a/docs/porting.txt b/docs/porting.txt index 380645801..31c188ae1 100644 --- a/docs/porting.txt +++ b/docs/porting.txt @@ -12,6 +12,8 @@ you are hacking on.     the shared library loader work requires you first have basic architecture     support working.  Thus you should add ARCH_HAS_NO_SHARED and     ARCH_HAS_NO_LDSO to Config.ARCH's TARGET_ARCH +- When static pie support is added this TARGET_arch can be appended to the  +   list in extra/Configs/Config.in  ====================  === libc sysdeps === @@ -56,6 +58,15 @@ you are hacking on.    usually these are written in assembler, but you may be able to cheat and    write them in C ... see other ports for more information +- Once static and pie executables are stable, static-pie support can be  +  added by modifying crt1.S to calculate the address that the kernel loaded  +  the main elf. Once the elf load address is found, call reloc_static_pie to +  perform all the dynamic relocations normally handled by ldso. This new +  code should be placed at the begining of _start and surrounded by defines +  so that it is only compiled into rcrt1.o and not the static or shared  +  versions. This is usually done by using the special L_rcrt1 preprocessor  +  define. i386 and x86_64 have good reference implementations. +  ====================  === ldso sysdeps ===  ==================== diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index e0905e956..6bbb6f572 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -39,6 +39,7 @@ choice  	default TARGET_or1k if DESIRED_TARGET_ARCH = "or1k"  	default TARGET_powerpc if DESIRED_TARGET_ARCH = "powerpc"  	default TARGET_riscv64 if DESIRED_TARGET_ARCH = "riscv64" +	default TARGET_riscv32 if DESIRED_TARGET_ARCH = "riscv32"  	default TARGET_sh if DESIRED_TARGET_ARCH = "sh"  	default TARGET_sparc if DESIRED_TARGET_ARCH = "sparc"  	default TARGET_sparc64 if DESIRED_TARGET_ARCH = "sparc64" @@ -125,6 +126,9 @@ config TARGET_powerpc  config TARGET_riscv64  	bool "riscv64" +config TARGET_riscv32 +	bool "riscv32" +  config TARGET_sh  	bool "superh" @@ -260,6 +264,10 @@ if TARGET_riscv64  source "extra/Configs/Config.riscv64"  endif +if TARGET_riscv32 +source "extra/Configs/Config.riscv32" +endif +  if TARGET_sh  source "extra/Configs/Config.sh"  endif @@ -324,7 +332,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) +	depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && \ +		(TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || \ +		 TARGET_mips || TARGET_xtensa || TARGET_powerpc)  config ARCH_HAS_NO_SHARED  	bool @@ -563,6 +573,7 @@ config UCLIBC_HAS_LINUXTHREADS  	select UCLIBC_HAS_REALTIME  	depends on !TARGET_aarch64 && \  		   !TARGET_riscv64 && \ +		   !TARGET_riscv32 && \  		   !TARGET_metag  	help  	  If you want to compile uClibc with Linuxthreads support, then answer Y. diff --git a/extra/Configs/Config.riscv32 b/extra/Configs/Config.riscv32 new file mode 100644 index 000000000..304d30f70 --- /dev/null +++ b/extra/Configs/Config.riscv32 @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH +	string +	default "riscv32" + +config FORCE_OPTIONS_FOR_ARCH +	bool +	default y +	select ARCH_LITTLE_ENDIAN +	select ARCH_HAS_MMU diff --git a/include/elf.h b/include/elf.h index 7d66d70a4..b7edbade2 100644 --- a/include/elf.h +++ b/include/elf.h @@ -270,9 +270,10 @@ typedef struct  #define EM_METAG	174		/* Imagination Technologies Meta */  #define EM_AARCH64	183		/* ARM AARCH64 */  #define EM_MICROBLAZE	189		/* Xilinx Microblaze */ -#define EM_ARCV2	195		/* ARCv2 Cores */ +#define EM_ARCV2	195		/* Synopsys ARCv2 Cores */  #define EM_RISCV        243     	/* RISC-V */  #define EM_CSKY		252		/* C-SKY Cores */ +#define EM_ARCV3_32	255		/* Synopsys ARCv3 32-bit Cores */  #define EM_KVX		256		/* Kalray VLIW core of the MPPA processor family */  /* NEXT FREE NUMBER: Increment this after adding your official arch number */ diff --git a/include/sys/auxv.h b/include/sys/auxv.h new file mode 100644 index 000000000..f35196423 --- /dev/null +++ b/include/sys/auxv.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2022 uClibc-ng +   This file is part of the uClibc-ng 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. + +   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 +   Lesser 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; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#ifndef _SYS_AUXV_H +#define _SYS_AUXV_H 1 + +#include <features.h> +#include <elf.h> + +__BEGIN_DECLS + +/* Return the value associated with an Elf*_auxv_t type from the auxv list +   passed to the program on startup.  If TYPE was not present in the auxv +   list, returns zero and sets errno to ENOENT.  */ +extern unsigned long int getauxval (unsigned long int __type) __THROW; + +__END_DECLS + +#endif /* sys/auxv.h */ diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index f19957d1d..c035b3b52 100644..100755 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -148,6 +148,7 @@ extern int   _dl_debug_file;  #define NULL ((void *) 0)  #endif +  extern void *_dl_malloc(size_t size);  extern void *_dl_calloc(size_t __nmemb, size_t __size);  extern void *_dl_realloc(void *__ptr, size_t __size); @@ -176,7 +177,7 @@ extern void _dl_dprintf(int, const char *, ...);  #endif  extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, -		ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv +		char **envp, char **argv  		DL_GET_READY_TO_RUN_EXTRA_PARMS);  #ifdef HAVE_DL_INLINES_H @@ -185,6 +186,11 @@ extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE loa  #else /* __ARCH_HAS_NO_SHARED__ */  #include <dl-defs.h> +#include <dl-elf.h> +  #endif +#define AUX_MAX_AT_ID 40 +extern ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID]; +  #endif /* _LDSO_H */ diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in index 4f2a18454..2d3886d73 100644 --- a/ldso/ldso/Makefile.in +++ b/ldso/ldso/Makefile.in @@ -38,7 +38,8 @@ CFLAGS-ldso.c	+= -DLDSO_MULTILIB_DIR=\"$(MULTILIB_DIR)\"  endif  ifeq ($(TARGET_ARCH),arc) -CFLAGS-ldso.c += -mno-long-calls +$(eval $(call check-gcc-var,-mno-long-calls)) +CFLAGS-ldso.c += $(CFLAGS_-mno-long-calls)  endif  LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-$(UCLIBC_LDSO_NAME).so := -Wl,--dsbt-index=1 diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h index ed8b37205..c8915511a 100644 --- a/ldso/ldso/arc/dl-sysdep.h +++ b/ldso/ldso/arc/dl-sysdep.h @@ -75,6 +75,9 @@ do {									\  #elif defined(__HS__)  #define MAGIC1 EM_ARCV2  #define ELF_TARGET "ARCv2"	/* For error messages */ +#elif defined(__ARC64_ARCH32__) +#define MAGIC1 EM_ARCV3_32 +#define ELF_TARGET "ARCv3_32"	/* For error messages */  #endif  #undef  MAGIC2 diff --git a/ldso/ldso/arc/resolve.S b/ldso/ldso/arc/resolve.S index 891f66b97..2b66c69cb 100644 --- a/ldso/ldso/arc/resolve.S +++ b/ldso/ldso/arc/resolve.S @@ -4,6 +4,7 @@   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.   */ +#include <asm.h>  #include <sysdep.h>  #include <sys/syscall.h> @@ -12,30 +13,30 @@  ; 	r10-r12 are already clobbered by PLTn, PLT0 thus neednot be saved  .macro	SAVE_CALLER_SAVED -	push_s	r0 -	push_s	r1 -	push_s	r2 -	push_s	r3 -	st.a	r4, [sp, -4] -	st.a	r5, [sp, -4] -	st.a	r6, [sp, -4] -	st.a	r7, [sp, -4] -	st.a	r8, [sp, -4] -	st.a	r9, [sp, -4] -	push_s	blink +	PUSHR_S	r0 +	PUSHR_S	r1 +	PUSHR_S	r2 +	PUSHR_S	r3 +	PUSHR	r4 +	PUSHR	r5 +	PUSHR	r6 +	PUSHR	r7 +	PUSHR	r8 +	PUSHR	r9 +	PUSHR_S	blink  .endm  .macro RESTORE_CALLER_SAVED_BUT_R0 -	ld.ab	blink,[sp, 4] -	ld.ab	r9, [sp, 4] -	ld.ab	r8, [sp, 4] -	ld.ab	r7, [sp, 4] -	ld.ab	r6, [sp, 4] -	ld.ab	r5, [sp, 4] -	ld.ab	r4, [sp, 4] -	pop_s   r3 -	pop_s   r2 -	pop_s   r1 +	POPR	blink +	POPR	r9 +	POPR	r8 +	POPR	r7 +	POPR	r6 +	POPR	r5 +	POPR	r4 +	POPR_S	r3 +	POPR_S	r2 +	POPR_S	r1  .endm  ; Upon entry, PLTn, which led us here, sets up the following regs @@ -53,5 +54,5 @@ ENTRY(_dl_linux_resolve)  	RESTORE_CALLER_SAVED_BUT_R0  	j_s.d   [r0]    ; r0 has resolved function addr -	pop_s   r0      ; restore first arg to resolved call +	POPR_S	r0      ; restore first arg to resolved call  END(_dl_linux_resolve) diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 24b046c62..e36d688b4 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -98,6 +98,9 @@  extern ElfW(Addr) _begin[] attribute_hidden;  #endif + +ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID]; +  #ifdef LDSO_NEED_DPNT  ElfW(Dyn) *_dl_saved_dpnt = 0;  #endif @@ -127,7 +130,7 @@ DL_START(unsigned long args)  	ElfW(Ehdr) *header;  	struct elf_resolve tpnt_tmp;  	struct elf_resolve *tpnt = &tpnt_tmp; -	ElfW(auxv_t) auxvt[AT_EGID + 1]; +	ElfW(auxv_t) _dl_auxvt_tmp[AUX_MAX_AT_ID];  	ElfW(Dyn) *dpnt;  	uint32_t  *p32; @@ -158,7 +161,7 @@ DL_START(unsigned long args)  	/* Place -1 here as a checkpoint.  We later check if it was changed  	 * when we read in the auxvt */ -	auxvt[AT_UID].a_type = -1; +	_dl_auxvt_tmp[AT_UID].a_type = -1;  	/* The junk on the stack immediately following the environment is  	 * the Auxiliary Vector Table.  Read out the elements of the auxvt, @@ -166,9 +169,11 @@ DL_START(unsigned long args)  	while (*aux_dat) {  		ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; -		if (auxv_entry->a_type <= AT_EGID) { -			_dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); +		if (auxv_entry->a_type < AUX_MAX_AT_ID) { +			_dl_memcpy(&(_dl_auxvt_tmp[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));  		} +		 +		  		aux_dat += 2;  	} @@ -183,16 +188,16 @@ DL_START(unsigned long args)  	 * We use it if the kernel is not passing a valid address through the auxvt.  	 */ -	if (!auxvt[AT_BASE].a_un.a_val) -		auxvt[AT_BASE].a_un.a_val =  (ElfW(Addr)) &_begin; +	if (!_dl_auxvt_tmp[AT_BASE].a_un.a_val) +		_dl_auxvt_tmp[AT_BASE].a_un.a_val =  (ElfW(Addr)) &_begin;  	/* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */  	DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address());  #else -	if (!auxvt[AT_BASE].a_un.a_val) -		auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); -	DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val); +	if (!_dl_auxvt_tmp[AT_BASE].a_un.a_val) +		_dl_auxvt_tmp[AT_BASE].a_un.a_val = elf_machine_load_address(); +	DL_INIT_LOADADDR_BOOT(load_addr, _dl_auxvt_tmp[AT_BASE].a_un.a_val);  #endif -	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; +	header = (ElfW(Ehdr) *) _dl_auxvt_tmp[AT_BASE].a_un.a_val;  	/* Check the ELF header to make sure everything looks ok.  */  	if (!header || header->e_ident[EI_CLASS] != ELF_CLASS || @@ -255,8 +260,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 +340,6 @@ DL_START(unsigned long args)  #endif  		}  	} -#endif  	SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n"); @@ -356,8 +358,13 @@ DL_START(unsigned long args)  #endif  	__rtld_stack_end = (void *)(argv - 1); +	/* +	*  now the globals work. so copy the aux vector +	*/ +	_dl_memcpy( _dl_auxvt, _dl_auxvt_tmp, sizeof( ElfW(auxv_t) ) * AUX_MAX_AT_ID ); +  	_dl_elf_main = (int (*)(int, char **, char **)) -			_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv +			_dl_get_ready_to_run(tpnt, load_addr, envp, argv  					     DL_GET_READY_TO_RUN_EXTRA_ARGS);  	/* Transfer control to the application.  */ diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index b33547670..8e4914df5 100644..100755 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -350,10 +350,9 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)  static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,  									 DL_LOADADDR_TYPE load_addr,  									 ElfW(Addr) ldso_mapaddr, -									 ElfW(auxv_t) auxvt[AT_EGID + 1],  									 struct dyn_elf *rpnt)  { -		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; +		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) _dl_auxvt[AT_BASE].a_un.a_val;  		ElfW(Phdr) *myppnt = (ElfW(Phdr) *)  				DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),  							  epnt->e_phoff); @@ -422,7 +421,7 @@ static void _dl_setup_progname(const char *argv0)  }  void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, -			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv +			  char **envp, char **argv  			  DL_GET_READY_TO_RUN_EXTRA_PARMS)  {  	ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0; @@ -461,7 +460,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	_dl_memset(app_tpnt, 0, sizeof(*app_tpnt));  	/* Store the page size for later use */ -	_dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; +	_dl_pagesize = (_dl_auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) _dl_auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;  	/* Make it so _dl_malloc can use the page of memory we have already  	 * allocated.  We shouldn't need to grab any more memory.  This must  	 * be first since things like _dl_dprintf() use _dl_malloc()... @@ -485,7 +484,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  #endif  #ifndef __LDSO_STANDALONE_SUPPORT__ -	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { +	if (_start == (void *) _dl_auxvt[AT_ENTRY].a_un.a_val) {  		_dl_dprintf(2, "Standalone execution is not enabled\n");  		_dl_exit(1);  	} @@ -504,10 +503,10 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	 * Note that for SUID programs we ignore the settings in  	 * LD_LIBRARY_PATH.  	 */ -	if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || -	    (auxvt[AT_UID].a_un.a_val != (size_t)-1 && -	     auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val && -	     auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) { +	if ((_dl_auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || +	    (_dl_auxvt[AT_UID].a_un.a_val != (size_t)-1 && +	     _dl_auxvt[AT_UID].a_un.a_val == _dl_auxvt[AT_EUID].a_un.a_val && +	     _dl_auxvt[AT_GID].a_un.a_val == _dl_auxvt[AT_EGID].a_un.a_val)) {  		_dl_secure = 0;  #ifdef __LDSO_PRELOAD_ENV_SUPPORT__  		_dl_preload = _dl_getenv("LD_PRELOAD", envp); @@ -546,7 +545,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  #endif  #ifdef __LDSO_STANDALONE_SUPPORT__ -	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { +	if (_start == (void *) _dl_auxvt[AT_ENTRY].a_un.a_val) {  		ElfW(Addr) *aux_dat = (ElfW(Addr) *) argv;  		int argc = (int) aux_dat[-1]; @@ -643,11 +642,11 @@ of this helper program; chances are you did not intend to run this program.\n\  	 */  	{  		unsigned int idx; -		ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; +		ElfW(Phdr) *phdr = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val; -		for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++) +		for (idx = 0; idx < _dl_auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)  			if (phdr->p_type == PT_PHDR) { -				DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); +				DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, _dl_auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);  				break;  			} @@ -662,8 +661,8 @@ of this helper program; chances are you did not intend to run this program.\n\  	 */  	debug_addr = _dl_zalloc(sizeof(struct r_debug)); -	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; -	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { +	ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val; +	for (i = 0; i < _dl_auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {  		if (ppnt->p_type == PT_GNU_RELRO) {  			relro_addr = ppnt->p_vaddr;  			relro_size = ppnt->p_memsz; @@ -685,8 +684,8 @@ of this helper program; chances are you did not intend to run this program.\n\  				int j;  				ElfW(Phdr) *ppnt_outer = ppnt;  				_dl_debug_early("calling mprotect on the application program\n"); -				ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; -				for (j = 0; j < auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) { +				ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val; +				for (j = 0; j < _dl_auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) {  					if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))  						_dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),  							     (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) + @@ -713,8 +712,8 @@ of this helper program; chances are you did not intend to run this program.\n\  					(unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),  					ppnt->p_filesz);  			_dl_loaded_modules->libtype = elf_executable; -			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; -			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; +			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val; +			_dl_loaded_modules->n_phent = _dl_auxvt[AT_PHNUM].a_un.a_val;  			_dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));  			rpnt->dyn = _dl_loaded_modules;  			app_tpnt->mapaddr = app_mapaddr; @@ -856,7 +855,7 @@ of this helper program; chances are you did not intend to run this program.\n\  	}  #endif -	ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val; +	ldso_mapaddr = (ElfW(Addr)) _dl_auxvt[AT_BASE].a_un.a_val;  	/*  	 * OK, fix one more thing - set up debug_addr so it will point  	 * to our chain.  Later we may need to fill in more fields, but this @@ -1046,7 +1045,7 @@ of this helper program; chances are you did not intend to run this program.\n\  						if (!ldso_tpnt) {  							/* Insert the ld.so only once */  							ldso_tpnt = add_ldso(tpnt, load_addr, -												 ldso_mapaddr, auxvt, rpnt); +												 ldso_mapaddr, rpnt);  						} else {  							ldso_tpnt->init_flag |= DL_OPENED2;  						} @@ -1148,7 +1147,7 @@ of this helper program; chances are you did not intend to run this program.\n\  	 * again once all libs are loaded.  	 */  	if (!ldso_tpnt) { -		tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt); +		tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, rpnt);  		tpnt->usage_count++;  		nscope_elem++;  	} else @@ -1450,11 +1449,11 @@ of this helper program; chances are you did not intend to run this program.\n\  	_dl_debug_state();  #ifdef __LDSO_STANDALONE_SUPPORT__ -	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) +	if (_start == (void *) _dl_auxvt[AT_ENTRY].a_un.a_val)  		return (void *) app_tpnt->l_entry;  	else  #endif -		return (void *) auxvt[AT_ENTRY].a_un.a_val; +		return (void *) _dl_auxvt[AT_ENTRY].a_un.a_val;  }  #include "dl-hash.c" diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h index 8026f1702..c2168d774 100644 --- a/ldso/ldso/mips/dl-startup.h +++ b/ldso/ldso/mips/dl-startup.h @@ -7,6 +7,7 @@  #include <sgidefs.h> +#ifndef L_rcrt1  __asm__(""      "	.text\n"      "	.globl	_start\n" @@ -114,6 +115,7 @@ __asm__(""      "\n\n"      ".previous\n"  ); +#endif  /*   * Get a pointer to the argv array.  On many platforms this can be just @@ -191,6 +193,5 @@ do {										\  	case R_MIPS_NONE:							\  		break;								\  	default:								\ -		SEND_STDERR("Aiieeee!");					\  		_dl_exit(1);							\  	} diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index db223fead..c9350c0f2 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) @@ -88,12 +90,11 @@ __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; \  	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 +126,5 @@ 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) +#endif diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h index d308237d3..6b908989a 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); diff --git a/libc/misc/Makefile.in b/libc/misc/Makefile.in index 53bb6d6c8..caf7f1391 100644 --- a/libc/misc/Makefile.in +++ b/libc/misc/Makefile.in @@ -5,7 +5,9 @@  # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.  # +  include $(top_srcdir)libc/misc/assert/Makefile.in +include $(top_srcdir)libc/misc/auxvt/Makefile.in  include $(top_srcdir)libc/misc/ctype/Makefile.in  include $(top_srcdir)libc/misc/dirent/Makefile.in  include $(top_srcdir)libc/misc/error/Makefile.in diff --git a/libc/misc/auxvt/Makefile.in b/libc/misc/auxvt/Makefile.in new file mode 100644 index 000000000..142ade10c --- /dev/null +++ b/libc/misc/auxvt/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/auxvt + +CSRC-y := getauxval.c + +MISC_AUXVT_DIR := $(top_srcdir)libc/misc/auxvt +MISC_AUXVT_OUT := $(top_builddir)libc/misc/auxvt + +MISC_AUXVT_SRC := $(patsubst %.c,$(MISC_AUXVT_DIR)/%.c,$(CSRC-y)) +MISC_AUXVT_OBJ := $(patsubst %.c,$(MISC_AUXVT_OUT)/%.o,$(CSRC-y)) + +libc-y += $(MISC_AUXVT_OBJ) + +objclean-y += CLEAN_libc/misc/auxvt + +CLEAN_libc/misc/auxvt: +	$(do_rm) $(addprefix $(MISC_AUXVT_OUT)/*., o os) diff --git a/libc/misc/auxvt/getauxval.c b/libc/misc/auxvt/getauxval.c new file mode 100755 index 000000000..b4e621301 --- /dev/null +++ b/libc/misc/auxvt/getauxval.c @@ -0,0 +1,40 @@ +/*  Copyright (C) 2022     Ramin Seyed Moussavi + *  An getauxval() function compatible with the glibc auxv.h + *  that is used by uClibc-ng. + * + *  This library is free software; you can redistribute it and/or + *  modify it under the terms of the GNU Library General Public + *  License as published by the Free Software Foundation; either + *  version 2 of the License, or (at your option) any later version. + * + *  This 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 Library General Public + *  License along with this library; if not, see + *  <http://www.gnu.org/licenses/>. + */ + +#include "errno.h" +#include "ldso.h" +#include "sys/auxv.h" + + +unsigned long int getauxval (unsigned long int __type) +{ +	if ( __type >= AUX_MAX_AT_ID ){ +		__set_errno (ENOENT); +		return 0; +	} +	 +	if ( _dl_auxvt[__type].a_type == __type){ +		return _dl_auxvt[__type].a_un.a_val; +	} + +	__set_errno (ENOENT); +	return 0; +} + + diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in index 69af8b76e..908b18321 100644 --- a/libc/misc/internals/Makefile.in +++ b/libc/misc/internals/Makefile.in @@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y))  MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y))  CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS) -CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1  libc-y += $(MISC_INTERNALS_OBJ)  ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y) diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index 578202d23..ab1923024 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -15,33 +15,96 @@     You should have received a copy of the GNU Lesser General Public     License along with the GNU C Library; if not, see     <https://www.gnu.org/licenses/>.  */ - +#define IS_IN_rtld      // force inline function calls  #include <link.h>  #include <elf.h>  #include <dl-elf.h> -ElfW(Addr) _dl_load_base = NULL; +#include <ldso.h> +#if defined(__mips__) || defined(__xtensa__) +#include <dl-startup.h> +#endif + +extern ElfW(Addr) _dl_load_base;  void  reloc_static_pie (ElfW(Addr) load_addr);  void -reloc_static_pie (ElfW(Addr) load_addr) +reloc_static_pie(ElfW(Addr) load_addr)  { -    ElfW(Word) relative_count = 0; -    ElfW(Addr) rel_addr = 0; -    ElfW(Dyn) * dyn_addr = NULL; -    unsigned long dynamic_info[DYNAMIC_SIZE] = {0}; +    int indx; +    ElfW(Addr) got; +    ElfW(Dyn) *dpnt; +    struct elf_resolve tpnt_tmp; +	struct elf_resolve *tpnt = &tpnt_tmp; + +    DL_BOOT_COMPUTE_GOT(got); +    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr); + +    _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); +    tpnt->loadaddr = load_addr; +    tpnt->dynamic_addr = dpnt; + +    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); + +#if defined(PERFORM_BOOTSTRAP_GOT) +	/* some arches (like MIPS) we have to tweak the GOT before relocations */ +	PERFORM_BOOTSTRAP_GOT(tpnt); +#endif + + +#if defined(ELF_MACHINE_PLTREL_OVERLAP) +# define INDX_MAX 1 +#else +# define INDX_MAX 2 +#endif + +    for (indx = 0; indx < INDX_MAX; indx++) { +        unsigned long rel_addr, rel_size; +        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + +        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : +                           tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); +        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : +			               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); + +        if (!rel_addr) +            continue; -    /* Read our own dynamic section and fill in the info array.  */ -    dyn_addr = ((void *) load_addr + elf_machine_dynamic ()); +        if((0 == indx) && relative_count) { +			rel_size -= relative_count * sizeof(ELF_RELOC); +            elf_machine_relative(load_addr, rel_addr, relative_count); +			rel_addr += relative_count * sizeof(ELF_RELOC); +        } -    /* Use the underlying function to avoid TLS access before initialization */ -    __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr); +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS +			{ +				ELF_RELOC *rpnt; +				unsigned int i; +				ElfW(Sym) *sym; +				unsigned long symbol_addr; +				int symtab_index; +				unsigned long *reloc_addr; -    /* Perform relocations */ -    relative_count = dynamic_info[DT_RELCONT_IDX]; -    rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR]; -    elf_machine_relative(load_addr, rel_addr, relative_count); +				/* Now parse the relocation information */ +				rpnt = (ELF_RELOC *) rel_addr; +				for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { +					reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset); +					symtab_index = ELF_R_SYM(rpnt->r_info); +					symbol_addr = 0; +					sym = NULL; +					if (symtab_index) { +						ElfW(Sym) *symtab; +						symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; +						sym = &symtab[symtab_index]; +						symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value); +					} +					/* Use this machine-specific macro to perform the actual relocation.  */ +					PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); +				} +			} +#endif +    }      _dl_load_base = load_addr;  } diff --git a/libc/string/arc/memcmp.S b/libc/string/arc/memcmp.S index a60757e7a..20122a296 100644 --- a/libc/string/arc/memcmp.S +++ b/libc/string/arc/memcmp.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -17,6 +17,8 @@  #endif  ENTRY(memcmp) + +#if defined(__ARC700__) || defined(__ARCHS__)  	or	r12,r0,r1  	asl_s	r12,r12,30  	sub	r3,r2,1 @@ -149,6 +151,96 @@ ENTRY(memcmp)  .Lnil:  	j_s.d	[blink]  	mov	r0,0 + +#elif (__ARC64_ARCH32__) +	;; Based on Synopsys code from newlib's arc64/memcmp.S +	cmp		r2, 32 +	bls.d	@.L_compare_1_bytes +	mov		r3, r0	; "r0" will be used as return value + +	lsr		r12, r2, 4	; counter for 16-byte chunks +	xor		r13, r13, r13	; the mask showing inequal registers + +.L_compare_16_bytes: +	ld.ab	r4, [r3, +4] +	ld.ab	r5, [r1, +4] +	ld.ab	r6, [r3, +4] +	ld.ab	r7, [r1, +4] +	ld.ab	r8, [r3, +4] +	ld.ab	r9, [r1, +4] +	ld.ab	r10, [r3, +4] +	ld.ab	r11, [r1, +4] +	xor.f	0, r4, r5 +	xor.ne	r13, r13, 0b0001 +	xor.f	0, r6, r7 +	xor.ne	r13, r13, 0b0010 +	xor.f	0, r8, r9 +	xor.ne	r13, r13, 0b0100 +	xor.f	0, r10, r11 +	xor.ne	r13, r13, 0b1000 +	brne	r13, 0, @.L_unequal_find +	dbnz	r12, @.L_compare_16_bytes + +	;; Adjusting the pointers because of the extra loads in the end +	sub		r1, r1, 4 +	sub		r3, r3, 4 +	bmsk_s	  r2, r2, 3	; any remaining bytes to compare + +.L_compare_1_bytes: +	cmp		r2, 0 +	jeq.d	[blink] +	xor_s	r0, r0, r0 + +2: +	ldb.ab	r4, [r3, +1] +	ldb.ab	r5, [r1, +1] +	sub.f	r0, r4, r5 +	jne		[blink] +	dbnz	r2, @2b +	j_s		[blink] + +	;; At this point, we want to find the _first_ comparison that marked the +	;; inequality of "lhs" and "rhs" +.L_unequal_find: +	ffs		r13, r13 +	asl		r13, r13, 2 +	bi		[r13] +.L_unequal_r4r5: +	mov		r1, r4 +	b.d		@.L_diff_byte_in_regs +	mov		r2, r5 +	nop +.L_unequal_r6r7: +	mov		r1, r6 +	b.d		@.L_diff_byte_in_regs +	mov		r2, r7 +	nop +.L_unequal_r8r9: +	mov		r1, r8 +	b.d		@.L_diff_byte_in_regs +	mov		r2, r9 +	nop +.L_unequal_r10r11: +	mov		r1, r10 +	mov		r2, r11 + +	;; fall-through +	;; If we're here, that means the two operands are not equal. +.L_diff_byte_in_regs: +	xor		r0, r1, r2 +	ffs		r0, r0 +	and		r0, r0, 0x18 +	lsr		r1, r1, r0 +	lsr		r2, r2, r0 +	bmsk_s	r1, r1, 7 +	bmsk_s	r2, r2, 7 +	j_s.d	[blink] +	sub		r0, r1, r2 + +#else +#error "Unsupported ARC CPU type" +#endif +  END(memcmp)  libc_hidden_def(memcmp) diff --git a/libc/string/arc/memcpy.S b/libc/string/arc/memcpy.S index 69d7220b8..153083765 100644 --- a/libc/string/arc/memcpy.S +++ b/libc/string/arc/memcpy.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013, 2014-2015, 2017 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2014-2015, 2017, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -7,13 +7,9 @@  #include <sysdep.h> -#if !defined(__ARC700__) && !defined(__ARCHS__) -#error "Neither ARC700 nor ARCHS is defined!" -#endif -  ENTRY(memcpy) -#ifdef __ARC700__ +#if defined(__ARC700__)  /* This memcpy implementation does not support objects of 1GB or larger -     the check for alignment does not work then.  */  /* We assume that most sources and destinations are aligned, and @@ -73,9 +69,9 @@ ENTRY(memcpy)  .Lendbloop:  	j_s.d	[blink]  	stb	r12,[r5,0] -#endif /* __ARC700__ */ -#ifdef __ARCHS__ +#elif defined(__ARCHS__) +  #ifdef __LITTLE_ENDIAN__  # define SHIFT_1(RX,RY,IMM)	asl	RX, RY, IMM	; <<  # define SHIFT_2(RX,RY,IMM)	lsr	RX, RY, IMM	; >> @@ -299,7 +295,58 @@ ENTRY(memcpy)  	stb.ab	r6, [r3,1]  .Lcopybytewise_3:  	j	[blink] -#endif /* __ARCHS__ */ + +#elif defined(__ARC64_ARCH32__) +	;; Based on Synopsys code from newlib's arc64/memcpy.S +	lsr.f	r11, r2, 4		; counter for 16-byte chunks +	beq.d	@.L_write_15_bytes +	mov	r3, r0			; work on a copy of "r0" + +.L_write_16_bytes: +#if defined(__ARC64_LL64__) +	ldd.ab	r4, [r1, 8] +	ldd.ab	r6, [r1, 8] +	std.ab	r4, [r3, 8] +	std.ab	r6, [r3, 8] +	dbnz	r11, @.L_write_16_bytes +#else +	ld.ab	r4, [r1, 4] +	ld.ab	r5, [r1, 4] +	ld.ab	r6, [r1, 4] +	ld.ab	r7, [r1, 4] +	st.ab	r4, [r3, 4] +	st.ab	r5, [r3, 4] +	st.ab	r6, [r3, 4] +	dbnz.d	r11, @.L_write_16_bytes +	st.ab	r7, [r3, 4] +#endif +	bmsk_s	r2, r2, 3 + +.L_write_15_bytes: +	bbit0.d	r2, 1, @1f +	lsr	r11, r2, 2 +	ldh.ab	r4, [r1, 2] +	sth.ab	r4, [r3, 2] +1: +	bbit0.d	r2, 0, @1f +	xor	r11, r11, 3 +	ldb.ab	r4, [r1, 1] +	stb.ab	r4, [r3, 1] +1: +	asl	r11, r11, 1 +	bi	[r11] +	ld.ab	r4,[r1, 4] +	st.ab	r4,[r3, 4] +	ld.ab	r4,[r1, 4] +	st.ab	r4,[r3, 4] +	ld	r4,[r1] +	st	r4,[r3] + +	j_s	[blink] + +#else +#error "Unsupported ARC CPU type" +#endif  END(memcpy)  libc_hidden_def(memcpy) diff --git a/libc/string/arc/memset.S b/libc/string/arc/memset.S index 0b74ddc7f..5aa5d6c65 100644 --- a/libc/string/arc/memset.S +++ b/libc/string/arc/memset.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013, 2014-2015, 2017 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2014-2015, 2017, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -7,13 +7,9 @@  #include <sysdep.h> -#if !defined(__ARC700__) && !defined(__ARCHS__) -#error "Neither ARC700 nor ARCHS is defined!" -#endif -  ENTRY(memset) -#ifdef __ARC700__ +#if defined(__ARC700__)  #define SMALL	7 /* Must be at least 6 to deal with alignment/loop issues.  */  	mov_s	r4,r0 @@ -52,9 +48,8 @@ ENTRY(memset)  	stb.ab	r1,[r4,1]  .Ltiny_end:  	j_s	[blink] -#endif /* __ARC700__ */ -#ifdef __ARCHS__ +#elif defined(__ARCHS__)  #ifdef DONT_USE_PREALLOC  #define PREWRITE(A,B)	prefetchw [(A),(B)]  #else @@ -156,7 +151,55 @@ ENTRY(memset)  .Lcopy3bytes:  	j	[blink] -#endif /* __ARCHS__ */ + +#elif defined(__ARC64_ARCH32__) +	;; Based on Synopsys code from newlib's arc64/memset.S + +	;; Assemble the bytes to 32bit words +	bmsk_s	r1, r1, 7		; treat it like unsigned char +	lsl8	r3, r1 +	or_s	r1, r1, r3 +	lsl16	r3, r1 +	or	r6, r1, r3 +	mov r7,r6 + +	lsr.f	r5, r2, 4		; counter for 16-byte chunks +	beq.d	@.L_write_15_bytes +	mov	r4, r0			; work on a copy of "r0" + +.L_write_16_bytes: +#if defined(__ARC64_LL64__) +	std.ab	r6, [r4, 8] +	std.ab	r6, [r4, 8] +	dbnz	r5, @.L_write_16_bytes +#else +	st.ab	r6, [r4, 4] +	st.ab	r6, [r4, 4] +	st.ab	r6, [r4, 4] +	dbnz.d	r5, @.L_write_16_bytes +	st.ab	r6, [r4, 4] +#endif +	bmsk_s	r2, r2, 3 + +.L_write_15_bytes: +	bbit0.d	r2, 1, @1f +	lsr	r3, r2, 2 +	sth.ab	r6, [r4, 2] +1: +	bbit0.d	r2, 0, @1f +	xor	r3, r3, 3 +	stb.ab	r6, [r4, 1] +1: +	bi	[r3] +	st.ab	r6,[r4, 4] +	st.ab	r6,[r4, 4] +	st.ab	r6,[r4, 4] + +	j_s	[blink] + +#else +#error "Unsupported ARC CPU type" +#endif  END(memset)  libc_hidden_def(memset) diff --git a/libc/string/arc/strchr.S b/libc/string/arc/strchr.S index 443993589..df25eb3be 100644 --- a/libc/string/arc/strchr.S +++ b/libc/string/arc/strchr.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -7,6 +7,7 @@  #include <sysdep.h>  #include <features.h> +#include <asm.h>  /* ARC700 has a relatively long pipeline and branch prediction, so we want     to avoid branches that are hard to predict.  On the other hand, the @@ -21,7 +22,7 @@ ENTRY(strchr)  	mov_s	r3,0x01010101  	breq.d	r2,r0,.Laligned  	asl	r4,r5,16 -	sub_s	r0,r0,r2 +	SUBR_S	r0,r0,r2  	asl	r7,r2,3  	ld_s	r2,[r0]  #ifdef __LITTLE_ENDIAN__ @@ -77,10 +78,10 @@ ENTRY(strchr)  	sub	r3,r7,1  	bic	r3,r3,r7  	norm	r2,r3 -	sub_s	r0,r0,1 -	asr_s	r2,r2,3 +	SUBR_S	r0,r0,1 +	ASRR_S	r2,r2,3  	j.d	[blink] -	sub_s	r0,r0,r2 +	SUBR_S	r0,r0,r2  	.balign	4  .Lfound0_ua: @@ -90,13 +91,13 @@ ENTRY(strchr)  	bic	r3,r3,r6  	and	r2,r3,r4  	or_s	r12,r12,r2 -	sub_s	r3,r12,1 +	SUBR_S	r3,r12,1  	bic_s	r3,r3,r12  	norm	r3,r3 -	add_s	r0,r0,3 -	asr_s	r12,r3,3 +	ADDR_S	r0,r0,3 +	ASRR_S	r12,r3,3  	asl.f	0,r2,r3 -	sub_s	r0,r0,r12 +	SUBR_S	r0,r0,r12  	j_s.d	[blink]  	mov.pl	r0,0  #else /* BIG ENDIAN */ @@ -106,10 +107,10 @@ ENTRY(strchr)  	bic	r2,r7,r6  .Lfound_char_b:  	norm	r2,r2 -	sub_s	r0,r0,4 +	SUBR_S	r0,r0,4  	asr_s	r2,r2,3  	j.d	[blink] -	add_s	r0,r0,r2 +	ADDR_S	r0,r0,r2  .Lfound0_ua:  	mov_s	r3,r7 @@ -126,7 +127,7 @@ ENTRY(strchr)  	add.pl	r3,r3,1  	asr_s	r12,r3,3  	asl.f	0,r2,r3 -	add_s	r0,r0,r12 +	ADDR_S	r0,r0,r12  	j_s.d	[blink]  	mov.mi	r0,0  #endif /* ENDIAN */ diff --git a/libc/string/arc/strcmp.S b/libc/string/arc/strcmp.S index ad38d9e00..3f64ac421 100644 --- a/libc/string/arc/strcmp.S +++ b/libc/string/arc/strcmp.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013, 2014-2015, 2017 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2014-2015, 2017, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -7,14 +7,11 @@  #include <features.h>  #include <sysdep.h> - -#if !defined(__ARC700__) && !defined(__ARCHS__) -#error "Neither ARC700 nor ARCHS is defined!" -#endif +#include <asm.h>  ENTRY(strcmp) -#ifdef __ARC700__ +#if defined(__ARC700__) || defined(__ARC64_ARCH32__)  /* This is optimized primarily for the ARC700.     It would be possible to speed up the loops by one cycle / word     respective one cycle / byte by forcing double source 1 alignment, unrolling @@ -38,7 +35,7 @@ ENTRY(strcmp)  	breq	r2,r3,.Lwordloop  #ifdef	__LITTLE_ENDIAN__  	xor	r0,r2,r3	; mask for difference -	sub_s	r1,r0,1 +	SUBR_S	r1,r0,1  	bic_s	r0,r0,r1	; mask for least significant difference bit  	sub	r1,r5,r0  	xor	r0,r5,r1	; mask for least significant difference byte @@ -55,7 +52,7 @@ ENTRY(strcmp)  .Lfound0:  	xor	r0,r2,r3	; mask for difference  	or	r0,r0,r4	; or in zero indicator -	sub_s	r1,r0,1 +	SUBR_S	r1,r0,1  	bic_s	r0,r0,r1	; mask for least significant difference bit  	sub	r1,r5,r0  	xor	r0,r5,r1	; mask for least significant difference byte @@ -99,9 +96,8 @@ ENTRY(strcmp)  .Lcmpend:  	j_s.d	[blink]  	sub	r0,r2,r3 -#endif /* __ARC700__ */ -#ifdef __ARCHS__ +#elif defined(__ARCHS__)  	or	r2, r0, r1  	bmsk_s	r2, r2, 1  	brne	r2, 0, @.Lcharloop @@ -168,7 +164,10 @@ ENTRY(strcmp)  .Lcmpend:  	j_s.d	[blink]  	sub	r0, r2, r3 -#endif /* __ARCHS__ */ + +#else +#error "Unsupported ARC CPU type" +#endif  END(strcmp)  libc_hidden_def(strcmp) diff --git a/libc/string/arc/strlen.S b/libc/string/arc/strlen.S index 0b9b93815..0d1d3aa4e 100644 --- a/libc/string/arc/strlen.S +++ b/libc/string/arc/strlen.S @@ -1,5 +1,5 @@  /* - * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * Copyright (C) 2013, 2022 Synopsys, Inc. (www.synopsys.com)   * Copyright (C) 2007 ARC International (UK) LTD   *   * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. @@ -7,6 +7,7 @@  #include <sysdep.h> +#include <asm.h>  ENTRY(strlen)  	or	r3,r0,7 @@ -15,7 +16,7 @@ ENTRY(strlen)  	mov	r4,0x01010101  	; uses long immediate  #ifdef __LITTLE_ENDIAN__ -	asl_s	r1,r0,3 +	ASLR_S	r1,r0,3  	btst_s	r0,2  	asl	r7,r4,r1  	ror	r5,r4 @@ -59,7 +60,7 @@ ENTRY(strlen)  	sub.ne	r3,r3,4  	mov.eq	r1,r12  #ifdef __LITTLE_ENDIAN__ -	sub_s	r2,r1,1 +	SUBR_S	r2,r1,1  	bic_s	r2,r2,r1  	norm	r1,r2  	sub_s	r0,r0,3 diff --git a/libc/string/generic/strchr.c b/libc/string/generic/strchr.c index 321d2b8c3..b34884d67 100644 --- a/libc/string/generic/strchr.c +++ b/libc/string/generic/strchr.c @@ -60,22 +60,19 @@ char *strchr (const char *s, int c_in)       The 1-bits make sure that carries propagate to the next 0-bit.       The 0-bits provide holes for carries to fall into.  */ -  switch (sizeof (longword)) -    { -    case 4: magic_bits = 0x7efefeffL; break; -    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; -    default: -      abort (); -    } -    /* Set up a longword, each of whose bytes is C.  */ +#if __WORDSIZE == 32 +  magic_bits = 0x7efefeffL;    charmask = c | (c << 8);    charmask |= charmask << 16; -  if (sizeof (longword) > 4) -    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */ -    charmask |= (charmask << 16) << 16; -  if (sizeof (longword) > 8) -    abort (); +#elif __WORDSIZE == 64 +  magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; +  charmask = c | (c << 8); +  charmask |= charmask << 16; +  charmask |= (charmask << 16) << 16; +#else +  #error unexpected integer size strchr() +#endif    /* Instead of the traditional loop which tests each character,       we will test a longword at a time.  The tricky part is testing diff --git a/libc/string/generic/strchrnul.c b/libc/string/generic/strchrnul.c index d11d9e00d..d9fadc776 100644 --- a/libc/string/generic/strchrnul.c +++ b/libc/string/generic/strchrnul.c @@ -59,22 +59,19 @@ char *strchrnul (const char *s, int c_in)       The 1-bits make sure that carries propagate to the next 0-bit.       The 0-bits provide holes for carries to fall into.  */ -  switch (sizeof (longword)) -    { -    case 4: magic_bits = 0x7efefeffL; break; -    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; -    default: -      abort (); -    } -  /* Set up a longword, each of whose bytes is C.  */ +#if __WORDSIZE == 32 +  magic_bits = 0x7efefeffL;    charmask = c | (c << 8);    charmask |= charmask << 16; -  if (sizeof (longword) > 4) -    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */ -    charmask |= (charmask << 16) << 16; -  if (sizeof (longword) > 8) -    abort (); +#elif __WORDSIZE == 64 +  magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; +  charmask = c | (c << 8); +  charmask |= charmask << 16; +  charmask |= (charmask << 16) << 16; +#else +  #error unexpected integer size strchr() +#endif    /* Instead of the traditional loop which tests each character,       we will test a longword at a time.  The tricky part is testing diff --git a/libc/sysdeps/linux/arc/asm.h b/libc/sysdeps/linux/arc/asm.h new file mode 100644 index 000000000..f83075ea1 --- /dev/null +++ b/libc/sysdeps/linux/arc/asm.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022, Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#ifndef _ARC_ASM_H +#define _ARC_ASM_H + +/* + * Some 16-bit instructions were excluded from the ARCv3 ISA + * the following macros are introduced to handle these changes in one place. + * This will allow not to change existing ARCv2 code and use 16-bit versions + * of instructions for ARCv2 and replace them with 32-bit vesrions for ARCv3 + */ + +#if defined (__ARC64_ARCH32__) + +.macro PUSHR reg +	push	\reg +.endm + +.macro PUSHR_S reg +	push	\reg +.endm + +.macro POPR reg +	pop	\reg +.endm + +.macro POPR_S reg +	pop	\reg +.endm + +.macro SUBR_S dst,src1,src2 +	sub	\dst, \src1, \src2 +.endm + +.macro ADDR_S dst,src1,src2 +	add	\dst, \src1, \src2 +.endm + +.macro ASRR_S dst,src1,src2 +	asr	\dst, \src1, \src2 +.endm + +.macro ASLR_S dst,src1,src2 +	asl	\dst, \src1, \src2 +.endm + +#elif defined (__ARC64_ARCH64__) + +# error ARCv3 64-bit is not supported by uClibc-ng + +#else /* ARCHS || ARC700 */ + +.macro PUSHR reg +	push	\reg +.endm + +.macro PUSHR_S reg +	push_s	\reg +.endm + +.macro POPR reg +	pop	\reg +.endm + +.macro POPR_S reg +	pop_s	\reg +.endm + +.macro SUBR_S dst,src1,src2 +	sub_s	\dst, \src1, \src2 +.endm + +.macro ADDR_S dst,src1,src2 +	add_s	\dst, \src1, \src2 +.endm + +.macro ASRR_S dst,src1,src2 +	asr_s	\dst, \src1, \src2 +.endm + +.macro ASLR_S dst,src1,src2 +	asl_s	\dst, \src1, \src2 +.endm + +#endif + +#endif /* _ARC_ASM_H  */ diff --git a/libc/sysdeps/linux/arc/bits/syscalls.h b/libc/sysdeps/linux/arc/bits/syscalls.h index c858d788b..000b6b631 100644 --- a/libc/sysdeps/linux/arc/bits/syscalls.h +++ b/libc/sysdeps/linux/arc/bits/syscalls.h @@ -100,7 +100,7 @@ extern long __syscall_error (int);  #ifdef __A7__  #define ARC_TRAP_INSN	"trap0		\n\t" -#elif defined(__HS__) +#else  #define ARC_TRAP_INSN	"trap_s 0	\n\t"  #endif @@ -182,7 +182,7 @@ extern long __syscall_error (int);  #ifdef __A7__  #define ARC_TRAP_INSN	trap0 -#elif defined(__HS__) +#else  #define ARC_TRAP_INSN	trap_s 0  #endif diff --git a/libc/sysdeps/linux/arc/crt1.S b/libc/sysdeps/linux/arc/crt1.S index 70a06e058..ff36d252e 100644 --- a/libc/sysdeps/linux/arc/crt1.S +++ b/libc/sysdeps/linux/arc/crt1.S @@ -40,7 +40,9 @@ __start:  	ld_s	r1, [sp]	; argc  	mov_s	r5, r0		; rltd_fini -	add_s	r2, sp, 4	; argv +	/* Use the universal 32-bit add instruction as 16-bit add_s was excluded from +	   ARCv3 ISA */ +	add	r2, sp, 4	; argv  #ifdef L_Scrt1  	ld	r0, [pcl, @main@gotpc]  	ld	r3, [pcl, @_init@gotpc] diff --git a/libc/sysdeps/linux/common/bits/mman-linux.h b/libc/sysdeps/linux/common/bits/mman-linux.h index 6ca08415a..4947ddd89 100644 --- a/libc/sysdeps/linux/common/bits/mman-linux.h +++ b/libc/sysdeps/linux/common/bits/mman-linux.h @@ -46,6 +46,7 @@  /* Other flags.  */  #define MAP_FIXED	0x10		/* Interpret addr exactly.  */ +# define MAP_FIXED_NOREPLACE 0x100000 /* Used to solve problem with MAP_FIXED */  #ifdef __USE_MISC  # define MAP_FILE	0  # ifdef __MAP_ANONYMOUS diff --git a/libc/sysdeps/linux/common/bits/syscalls-common.h b/libc/sysdeps/linux/common/bits/syscalls-common.h index 3665345a6..adae45aac 100644..100755 --- a/libc/sysdeps/linux/common/bits/syscalls-common.h +++ b/libc/sysdeps/linux/common/bits/syscalls-common.h @@ -104,11 +104,16 @@ type name(C_DECL_ARGS_##nargs(args)) {					\  	return (type)INLINE_SYSCALL_NOERR(name, nargs, C_ARGS_##nargs(args));	\  } +#define SYSCALL_FUNC_BODY(nargs, type, name, args...)			\ +	return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); + +  #define _syscall0(args...)		SYSCALL_FUNC(0, args)  #define _syscall_noerr0(args...)	SYSCALL_NOERR_FUNC(0, args)  #define _syscall1(args...)		SYSCALL_FUNC(1, args)  #define _syscall_noerr1(args...)	SYSCALL_NOERR_FUNC(1, args)  #define _syscall2(args...)		SYSCALL_FUNC(2, args) +#define _syscall2_body(args...)		SYSCALL_FUNC_BODY(2, args)  #define _syscall3(args...)		SYSCALL_FUNC(3, args)  #define _syscall4(args...)		SYSCALL_FUNC(4, args)  #define _syscall5(args...)		SYSCALL_FUNC(5, args) diff --git a/libc/sysdeps/linux/common/futimesat.c b/libc/sysdeps/linux/common/futimesat.c index bd73eae7e..fd19fea7c 100644 --- a/libc/sysdeps/linux/common/futimesat.c +++ b/libc/sysdeps/linux/common/futimesat.c @@ -11,6 +11,28 @@  #ifdef __NR_futimesat  _syscall3(int, futimesat, int, fd, const char *, file, const struct timeval *, tvp) -#else -/* should add emulation with futimes() and /proc/self/fd/ ... */ +#elif defined __NR_utimensat +#include <errno.h> +#define __need_NULL +#include <stddef.h> + +int futimesat(int dirfd, const char *file, const struct timeval tvp[2]) +{ +	struct timespec ts[2]; + +	if (tvp != NULL) +	{ +		if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 +		    || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) +		{ +			__set_errno(EINVAL); +			return -1; +		} + +		TIMEVAL_TO_TIMESPEC(&tvp[0], &ts[0]); +		TIMEVAL_TO_TIMESPEC(&tvp[1], &ts[1]); +	} + +	return utimensat(dirfd, file, tvp ? ts : NULL, 0); +}  #endif diff --git a/libc/sysdeps/linux/common/gettimeofday.c b/libc/sysdeps/linux/common/gettimeofday.c index 1c62b3937..e5141088e 100644..100755 --- a/libc/sysdeps/linux/common/gettimeofday.c +++ b/libc/sysdeps/linux/common/gettimeofday.c @@ -9,5 +9,28 @@  #include <sys/syscall.h>  #include <sys/time.h> -_syscall2(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) +#include "ldso.h" + + + +#ifdef __VDSO_SUPPORT__ +typedef int (*gettimeofday_func)(struct timeval * tv, __timezone_ptr_t tz); +#endif + +int gettimeofday(struct timeval * tv, __timezone_ptr_t tz) { + +    #ifdef __VDSO_SUPPORT__ +        if ( _dl__vdso_gettimeofday != 0 ){ +            gettimeofday_func func= _dl__vdso_gettimeofday; +            return func( tv, tz ); + +        }else{ +            _syscall2_body(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) +        } +    #else +        _syscall2_body(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) +    #endif +} + +  libc_hidden_def(gettimeofday) diff --git a/libc/sysdeps/linux/mips/crt1.S b/libc/sysdeps/linux/mips/crt1.S index 083615515..7c4db447c 100644 --- a/libc/sysdeps/linux/mips/crt1.S +++ b/libc/sysdeps/linux/mips/crt1.S @@ -78,6 +78,10 @@  	.weak	_init  	.weak	_fini  #endif +#ifdef L_rcrt1 +	.type	reloc_static_pie,@function +	.hidden	.L0 +#endif  	.type	    main,@function  	.type	    __uClibc_main,@function  	.ent	__start @@ -90,6 +94,25 @@ __start:  	PTR_LA $28, _gp             /* Setup GP correctly if we're non-PIC.  */  	move $31, $0  #endif +#ifdef L_rcrt1 +	PTR_LA $4, _DYNAMIC           /* Place _DYNAMIC into the GOT */ +	REG_S $4, -0x7ff0($28)        /* offset to GOT stolen from dl-startup */ +	jal .L0                       /* Get the current $pc address */ +.L0: +	PTR_SUBU $4, $31, $25         /* Calculate load addr */ +	move $31, $0                  /* Clear ra */ +	and $29, -2 * SZREG           /* Ensure stack is aligned */ +	PTR_ADDIU $29, (-2 * SZREG)   /* Allocate 2 register spaces on stack */ +	REG_S $2, SZREG($29)          /* Store atexit in case it exists */ +	PTR_LA $5, reloc_static_pie   /* function calls before relocation +	                                 don't work unless we set $t9 manually */ +	PTR_ADDU $25, $4, $5          /* store reloc_static_pie in $t9 */ +	jalr $25                      /* call reloc_static_pie */ +	nop							  /* delay slot, just in case */ +	REG_L $2, SZREG($29)          /* cleanup stack */ +	PTR_ADDIU $29, $29, (2 * SZREG) + +#endif  	PTR_LA $4, main		/* main */  	PTR_L $5, 0($29)		/* argc */ diff --git a/libc/sysdeps/linux/powerpc/crt1.S b/libc/sysdeps/linux/powerpc/crt1.S index 3f5d056c0..3ac32636c 100644 --- a/libc/sysdeps/linux/powerpc/crt1.S +++ b/libc/sysdeps/linux/powerpc/crt1.S @@ -41,6 +41,9 @@  	.weak _init  	.weak _fini  #endif +#ifdef L_rcrt1 +	.type reloc_static_pie,%function +#endif  	.type	main,%function  	.type	__uClibc_main,%function @@ -61,6 +64,22 @@ _start:  # ifdef PPC_HAS_SECUREPLT  	mr	30,31  # endif +#ifdef L_rcrt1 +	stwu r3, -4(r1)					/* Save r3 */ +	stwu r9, -16(r1)				/* Save r9 */ +	bcl 20,31,2f					/* Jump to label 2 */ +2:	mflr r3							/* Load lr into r3 */ +	addis r3, r3, _DYNAMIC-2b@ha	/* Add high half of _DYNAMIC to r3 */ +	addi r3,r3,_DYNAMIC-2b@l		/* Add low half of _DYNAMIC */ +	lwz r4, 0(r31)					/* load _DYNAMIC from the GOT */ +	subf r3, r4, r3					/* sub _DYNAMIC@got and it's actual address */ +	bl reloc_static_pie				/* Call reloc_static_pie */ +	lwzu r9, 0(r1)					/* restore r9 */ +	addi r1, r1, 16					/* update stack pointer */ +	lwzu r3, 0(r1)					/* restore r3 */ +	addi r1, r1, 4					/* update stack pointer */ +	li r5, 0						/* zero r5 */ +#endif  #endif  	/* Set up the small data pointer in r13.  */  #ifdef __PIC__ diff --git a/libc/sysdeps/linux/riscv32 b/libc/sysdeps/linux/riscv32 new file mode 120000 index 000000000..11677ef05 --- /dev/null +++ b/libc/sysdeps/linux/riscv32 @@ -0,0 +1 @@ +riscv64
\ No newline at end of file diff --git a/libc/sysdeps/linux/riscv64/bits/wordsize.h b/libc/sysdeps/linux/riscv64/bits/wordsize.h index 67a16ba62..1fc649aad 100644 --- a/libc/sysdeps/linux/riscv64/bits/wordsize.h +++ b/libc/sysdeps/linux/riscv64/bits/wordsize.h @@ -25,5 +25,6 @@  #if __riscv_xlen == 64  # define __WORDSIZE_TIME64_COMPAT32 1  #else -# error "rv32i-based targets are not supported" +# define __WORDSIZE_TIME64_COMPAT32 1 +// # warning "rv32i-based targets are experimental"  #endif diff --git a/libc/sysdeps/linux/riscv64/setjmp.S b/libc/sysdeps/linux/riscv64/setjmp.S index 4cdb8e9c3..100a0bd78 100644 --- a/libc/sysdeps/linux/riscv64/setjmp.S +++ b/libc/sysdeps/linux/riscv64/setjmp.S @@ -20,7 +20,7 @@  ENTRY (_setjmp)    li	a1, 0 -  j	__sigsetjmp +  j	HIDDEN_JUMPTARGET (__sigsetjmp)  END (_setjmp)  ENTRY (setjmp)    li	a1, 1 diff --git a/libc/sysdeps/linux/riscv64/sys/asm.h b/libc/sysdeps/linux/riscv64/sys/asm.h index ddb84b683..3c94c9a70 100644 --- a/libc/sysdeps/linux/riscv64/sys/asm.h +++ b/libc/sysdeps/linux/riscv64/sys/asm.h @@ -26,7 +26,11 @@  # define REG_S sd  # define REG_L ld  #elif __riscv_xlen == 32 -# error "rv32i-based targets are not supported" +# define PTRLOG 2 +# define SZREG    4 +# define REG_S sw +# define REG_L lw +// # warning "rv32i-based targets are experimental"  #else  # error __riscv_xlen must equal 32 or 64  #endif diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S index efbe264c0..3fa14ae58 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 diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c index 2a1ee62af..122997b10 100644 --- a/libpthread/linuxthreads/manager.c +++ b/libpthread/linuxthreads/manager.c @@ -47,6 +47,15 @@  # define USE_SELECT  #endif +/* MAP_FIXED_NOREPLACE is not supported in kernel <= 4.17 + * If it's not already defined, define it to 0. + * We check the results of mmap to ensure the correct + * results, and error out otherwise. + */ +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0 +#endif +  /* Array of active threads. Entry 0 is reserved for the initial thread. */  struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =  { { __LOCK_INITIALIZER, &__pthread_initial_thread, 0}, @@ -371,12 +380,19 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,        /* Allocate space for stack and thread descriptor at default address */        new_thread = default_new_thread;        new_thread_bottom = (char *) (new_thread + 1) - stacksize; -      if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE), +      void * new_stack_addr = NULL; +      new_stack_addr = mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE),                 INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -               MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -               -1, 0) == MAP_FAILED) +               MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE | MAP_GROWSDOWN, +               -1, 0); +      if (new_stack_addr == MAP_FAILED){          /* Bad luck, this segment is already mapped. */          return -1; +      } else if ( new_stack_addr != (caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE)) { +        /* Worse luck, we almost overwrote an existing page */ +        munmap(new_stack_addr, INITIAL_STACK_SIZE); +        return -2; +      }        /* We manage to get a stack.  Now see whether we need a guard           and allocate it if necessary.  Notice that the default           attributes (stack_size = STACK_SIZE - pagesize) do not need @@ -496,9 +512,10 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,  	return EAGAIN;        if (__pthread_handles[sseg].h_descr != NULL)  	continue; -      if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize, +      int res = pthread_allocate_stack(attr, thread_segment(sseg), pagesize,                                   &new_thread, &new_thread_bottom, -                                 &guardaddr, &guardsize) == 0) +                                 &guardaddr, &guardsize); +      if ( res == 0)          break;  #ifndef __ARCH_USE_MMU__        else @@ -507,6 +524,14 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,           * use the next one. However, when there is no MMU, malloc () is used.           * It's waste of CPU cycles to continue to try if it fails.  */          return EAGAIN; +#else +      else if (res == -2) +        /*  When there is an MMU, if pthread_allocate_stack failed with -2, +         *  it indicates that we are attempting to mmap in address space which +         *  is already allocated. Any additional attempts will result in failure +         *  since we have exhausted our stack area. +         */ +        return EAGAIN;  #endif      }    __pthread_handles_num++; diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c index 0c8c558d0..7cfe9ac1a 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; @@ -166,10 +169,13 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)       for FDPIC MMU-less platforms:       fs/binfmt_elf_fdpic.c: fix brk area overlap with stack on NOMMU       https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/fs/binfmt_elf_fdpic.c?id=4ac313111018cb44ecc250445de5ccb93026a980 +     Loading static PIE ELFs on noMMU is possible since the linux kernel commit +     1bde925d2354 ("fs/binfmt_elf_fdpic.c: provide NOMMU loader for regular ELF binaries") +     and it is subject to the same brk restriction.     */  # if defined(TLS_TCB_AT_TP)    tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); -#  if defined(__FDPIC__) +#  if defined(__FDPIC__) || (!defined(__ARCH_USE_MMU__) && defined(STATIC_PIE))    tlsblock = mmap (NULL, tcb_offset + tcbsize + max_align,                     PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  #  else @@ -177,7 +183,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)  #  endif  # elif defined(TLS_DTV_AT_TP)    tcb_offset = roundup (tcbsize, align ?: 1); -#  if defined(__FDPIC__) +#  if defined(__FDPIC__) || (!defined(__ARCH_USE_MMU__) && defined(STATIC_PIE))    tlsblock = mmap (NULL, tcb_offset + memsz + max_align + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size),                     PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  #  else diff --git a/utils/ldd.c b/utils/ldd.c index dfc4ee9a5..46cd97170 100644 --- a/utils/ldd.c +++ b/utils/ldd.c @@ -30,7 +30,12 @@  #endif  #if defined(__arc__) -#define MATCH_MACHINE(x) (x == EM_ARCOMPACT) +#define MATCH_MACHINE(x) (x == EM_ARCOMPACT || x == EM_ARCV2) +#define ELFCLASSM      ELFCLASS32 +#endif + +#if defined(__ARC64_ARCH32__) +#define MATCH_MACHINE(x) (x == EM_ARCV3_32)  #define ELFCLASSM      ELFCLASS32  #endif | 
