diff options
Diffstat (limited to 'libc')
27 files changed, 620 insertions, 96 deletions
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 |