summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rules.mak6
-rw-r--r--docs/porting.txt11
-rw-r--r--extra/Configs/Config.in13
-rw-r--r--extra/Configs/Config.riscv3214
-rw-r--r--include/elf.h3
-rw-r--r--include/sys/auxv.h33
-rwxr-xr-x[-rw-r--r--]ldso/include/ldso.h8
-rw-r--r--ldso/ldso/Makefile.in3
-rw-r--r--ldso/ldso/arc/dl-sysdep.h3
-rw-r--r--ldso/ldso/arc/resolve.S45
-rw-r--r--ldso/ldso/dl-startup.c35
-rwxr-xr-x[-rw-r--r--]ldso/ldso/ldso.c47
-rw-r--r--ldso/ldso/mips/dl-startup.h3
-rw-r--r--ldso/ldso/xtensa/dl-startup.h15
-rw-r--r--ldso/ldso/xtensa/dl-sysdep.h3
-rw-r--r--libc/misc/Makefile.in2
-rw-r--r--libc/misc/auxvt/Makefile.in23
-rwxr-xr-xlibc/misc/auxvt/getauxval.c40
-rw-r--r--libc/misc/internals/Makefile.in2
-rw-r--r--libc/misc/internals/reloc_static_pie.c93
-rw-r--r--libc/string/arc/memcmp.S94
-rw-r--r--libc/string/arc/memcpy.S65
-rw-r--r--libc/string/arc/memset.S61
-rw-r--r--libc/string/arc/strchr.S25
-rw-r--r--libc/string/arc/strcmp.S21
-rw-r--r--libc/string/arc/strlen.S7
-rw-r--r--libc/string/generic/strchr.c23
-rw-r--r--libc/string/generic/strchrnul.c23
-rw-r--r--libc/sysdeps/linux/arc/asm.h91
-rw-r--r--libc/sysdeps/linux/arc/bits/syscalls.h4
-rw-r--r--libc/sysdeps/linux/arc/crt1.S4
-rw-r--r--libc/sysdeps/linux/common/bits/mman-linux.h1
-rwxr-xr-x[-rw-r--r--]libc/sysdeps/linux/common/bits/syscalls-common.h5
-rw-r--r--libc/sysdeps/linux/common/futimesat.c26
-rwxr-xr-x[-rw-r--r--]libc/sysdeps/linux/common/gettimeofday.c25
-rw-r--r--libc/sysdeps/linux/mips/crt1.S23
-rw-r--r--libc/sysdeps/linux/powerpc/crt1.S19
l---------libc/sysdeps/linux/riscv321
-rw-r--r--libc/sysdeps/linux/riscv64/bits/wordsize.h3
-rw-r--r--libc/sysdeps/linux/riscv64/setjmp.S2
-rw-r--r--libc/sysdeps/linux/riscv64/sys/asm.h6
-rw-r--r--libc/sysdeps/linux/xtensa/crt1.S27
-rw-r--r--libpthread/linuxthreads/manager.c35
-rw-r--r--libpthread/nptl/sysdeps/generic/libc-tls.c14
-rw-r--r--utils/ldd.c7
45 files changed, 827 insertions, 187 deletions
diff --git a/Rules.mak b/Rules.mak
index 8b54e2854..8984edb38 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -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