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 |