diff options
Diffstat (limited to 'libc/string')
| -rw-r--r-- | libc/string/generic/bp-checks.h | 129 | ||||
| -rw-r--r-- | libc/string/generic/memcmp.c | 17 | ||||
| -rw-r--r-- | libc/string/generic/strcpy.c | 28 | ||||
| -rw-r--r-- | libc/string/i386/memchr.c | 50 | ||||
| -rw-r--r-- | libc/string/i386/memcpy.c | 6 | ||||
| -rw-r--r-- | libc/string/i386/memmove.c | 52 | ||||
| -rw-r--r-- | libc/string/i386/memset.c | 1 | ||||
| -rw-r--r-- | libc/string/i386/strchr.c | 32 | ||||
| -rw-r--r-- | libc/string/i386/strcpy.c | 2 | ||||
| -rw-r--r-- | libc/string/i386/strlen.c | 20 | ||||
| -rw-r--r-- | libc/string/i386/strncat.c | 73 | ||||
| -rw-r--r-- | libc/string/i386/strncmp.c | 41 | ||||
| -rw-r--r-- | libc/string/i386/strncpy.c | 55 | ||||
| -rw-r--r-- | libc/string/i386/strnlen.c | 51 | ||||
| -rw-r--r-- | libc/string/i386/strrchr.c | 29 | ||||
| -rw-r--r-- | libc/string/ia64/memchr.S | 8 | ||||
| -rw-r--r-- | libc/string/memchr.c | 1 | ||||
| -rw-r--r-- | libc/string/memcpy.c | 1 | ||||
| -rw-r--r-- | libc/string/mempcpy.c | 1 | ||||
| -rw-r--r-- | libc/string/memset.c | 2 | ||||
| -rw-r--r-- | libc/string/sparc/sparc32/memchr.S | 2 |
21 files changed, 278 insertions, 323 deletions
diff --git a/libc/string/generic/bp-checks.h b/libc/string/generic/bp-checks.h deleted file mode 100644 index 08c70aa5d..000000000 --- a/libc/string/generic/bp-checks.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Bounded-pointer checking macros for C. - Copyright (C) 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Greg McGary <greg@mcgary.org> - - 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _bp_checks_h_ -#define _bp_checks_h_ 1 - -#if __BOUNDED_POINTERS__ - -# define BOUNDS_VIOLATED (__builtin_trap (), 0) - -/* Verify that pointer's value >= low. Return pointer value. */ -# define CHECK_BOUNDS_LOW(ARG) \ - (((__ptrvalue (ARG) < __ptrlow (ARG)) && BOUNDS_VIOLATED), \ - __ptrvalue (ARG)) - -/* Verify that pointer's value < high. Return pointer value. */ -# define CHECK_BOUNDS_HIGH(ARG) \ - (((__ptrvalue (ARG) > __ptrhigh (ARG)) && BOUNDS_VIOLATED), \ - __ptrvalue (ARG)) - -# define _CHECK_N(ARG, N, COND) \ - (((COND) \ - && (__ptrvalue (ARG) < __ptrlow (ARG) \ - || __ptrvalue (ARG) + (N) > __ptrhigh (ARG)) \ - && BOUNDS_VIOLATED), \ - __ptrvalue (ARG)) - -extern void *__unbounded __ubp_memchr (const void *__unbounded, int, unsigned); - -# define _CHECK_STRING(ARG, COND) \ - (((COND) \ - && (__ptrvalue (ARG) < __ptrlow (ARG) \ - || !__ubp_memchr (__ptrvalue (ARG), '\0', \ - (__ptrhigh (ARG) - __ptrvalue (ARG)))) \ - && BOUNDS_VIOLATED), \ - __ptrvalue (ARG)) - -/* Check bounds of a pointer seated to an array of N objects. */ -# define CHECK_N(ARG, N) _CHECK_N ((ARG), (N), 1) -/* Same as CHECK_N, but tolerate ARG == NULL. */ -# define CHECK_N_NULL_OK(ARG, N) _CHECK_N ((ARG), (N), __ptrvalue (ARG)) - -/* Check bounds of a pointer seated to a single object. */ -# define CHECK_1(ARG) CHECK_N ((ARG), 1) -/* Same as CHECK_1, but tolerate ARG == NULL. */ -# define CHECK_1_NULL_OK(ARG) CHECK_N_NULL_OK ((ARG), 1) - -/* Check for NUL-terminator within string's bounds. */ -# define CHECK_STRING(ARG) _CHECK_STRING ((ARG), 1) -/* Same as CHECK_STRING, but tolerate ARG == NULL. */ -# define CHECK_STRING_NULL_OK(ARG) _CHECK_STRING ((ARG), __ptrvalue (ARG)) - -/* Check bounds of signal syscall args with type sigset_t. */ -# define CHECK_SIGSET(SET) CHECK_N ((SET), _NSIG / (8 * sizeof *(SET))) -/* Same as CHECK_SIGSET, but tolerate SET == NULL. */ -# define CHECK_SIGSET_NULL_OK(SET) CHECK_N_NULL_OK ((SET), _NSIG / (8 * sizeof *(SET))) - -# if defined (_IOC_SIZESHIFT) && defined (_IOC_SIZEBITS) -/* Extract the size of the ioctl data and check its bounds. */ -# define CHECK_IOCTL(ARG, CMD) \ - CHECK_N ((const char *) (ARG), \ - (((CMD) >> _IOC_SIZESHIFT) & ((1 << _IOC_SIZEBITS) - 1))) -# else -/* We don't know the size of the ioctl data, so the best we can do - is check that the first byte is within bounds. */ -# define CHECK_IOCTL(ARG, CMD) CHECK_1 ((const char *) ARG) -# endif - -/* Check bounds of `struct flock *' for the locking fcntl commands. */ -# define CHECK_FCNTL(ARG, CMD) \ - (((CMD) == F_GETLK || (CMD) == F_SETLK || (CMD) == F_SETLKW) \ - ? CHECK_1 ((struct flock *) ARG) : (unsigned long) (ARG)) - -/* Check bounds of an array of mincore residency-status flags that - cover a region of NBYTES. Such a vector occupies one byte per page - of memory. */ -# define CHECK_N_PAGES(ARG, NBYTES) \ - ({ int _page_size_ = __sysconf (_SC_PAGE_SIZE); \ - CHECK_N ((const char *) (ARG), \ - ((NBYTES) + _page_size_ - 1) / _page_size_); }) - -/* Return a bounded pointer with value PTR that satisfies CHECK_N (PTR, N). */ -# define BOUNDED_N(PTR, N) \ - ({ __typeof (PTR) __bounded _p_; \ - __ptrvalue _p_ = __ptrlow _p_ = __ptrvalue (PTR); \ - __ptrhigh _p_ = __ptrvalue _p_ + (N); \ - _p_; }) - -#else /* !__BOUNDED_POINTERS__ */ - -/* Do nothing if not compiling with -fbounded-pointers. */ - -# define BOUNDS_VIOLATED -# define CHECK_BOUNDS_LOW(ARG) (ARG) -# define CHECK_BOUNDS_HIGH(ARG) (ARG) -# define CHECK_1(ARG) (ARG) -# define CHECK_1_NULL_OK(ARG) (ARG) -# define CHECK_N(ARG, N) (ARG) -# define CHECK_N_NULL_OK(ARG, N) (ARG) -# define CHECK_STRING(ARG) (ARG) -# define CHECK_SIGSET(SET) (SET) -# define CHECK_SIGSET_NULL_OK(SET) (SET) -# define CHECK_IOCTL(ARG, CMD) (ARG) -# define CHECK_FCNTL(ARG, CMD) (ARG) -# define CHECK_N_PAGES(ARG, NBYTES) (ARG) -# define BOUNDED_N(PTR, N) (PTR) - -#endif /* !__BOUNDED_POINTERS__ */ - -#define BOUNDED_1(PTR) BOUNDED_N (PTR, 1) - -#endif /* _bp_checks_h_ */ diff --git a/libc/string/generic/memcmp.c b/libc/string/generic/memcmp.c index fc63a2eae..27db6b3d3 100644 --- a/libc/string/generic/memcmp.c +++ b/libc/string/generic/memcmp.c @@ -26,10 +26,6 @@ #include <endian.h> #if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN -#endif - -#ifdef WORDS_BIGENDIAN # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) #else # define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) @@ -48,17 +44,12 @@ 3. Compare the few remaining bytes. */ -#ifndef WORDS_BIGENDIAN +#if __BYTE_ORDER != __BIG_ENDIAN /* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. A and B are known to be different. This is needed only on little-endian machines. */ -static int memcmp_bytes __P((op_t, op_t)); - -# ifdef __GNUC__ -__inline -# endif -static int +static __inline__ int memcmp_bytes (op_t a, op_t b) { long int srcp1 = (long int) &a; @@ -77,8 +68,6 @@ memcmp_bytes (op_t a, op_t b) } #endif -static int memcmp_common_alignment __P((long, long, size_t)); - /* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for memory operations on `op_t's. */ @@ -161,8 +150,6 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len) return 0; } -static int memcmp_not_common_alignment __P((long, long, size_t)); - /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory operations on `op_t', but SRCP1 *should be unaligned*. */ diff --git a/libc/string/generic/strcpy.c b/libc/string/generic/strcpy.c index 99e077139..b9a0a286a 100644 --- a/libc/string/generic/strcpy.c +++ b/libc/string/generic/strcpy.c @@ -20,28 +20,18 @@ #include <stddef.h> #include "memcopy.h" -#include "bp-checks.h" /* Experimentally off - libc_hidden_proto(strcpy) */ /* Copy SRC to DEST. */ -char *strcpy (char *dest, const char *src) +char *strcpy(char *dest, const char *src) { - reg_char c; - char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src); - const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1; - size_t n; - - do - { - c = *s++; - s[off] = c; - } - while (c != '\0'); - - n = s - src; - (void) CHECK_BOUNDS_HIGH (src + n); - (void) CHECK_BOUNDS_HIGH (dest + n); - - return dest; + char *dst = dest; + + while ((*dst = *src) != '\0') { + src++; + dst++; + } + + return dest; } libc_hidden_def(strcpy) diff --git a/libc/string/i386/memchr.c b/libc/string/i386/memchr.c index 5c64445e0..c2fc44b4a 100644 --- a/libc/string/i386/memchr.c +++ b/libc/string/i386/memchr.c @@ -33,19 +33,43 @@ #include <string.h> #undef memchr -void *memchr(const void *cs, int c, size_t count) +//#define memchr TESTING +void *memchr(const void *s, int c, size_t count) { - int d0; - register void * __res; - if (!count) - return NULL; - __asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "je 1f\n\t" - "movl $1,%0\n" - "1:\tdecl %0" - :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count)); - return __res; + void *edi; + int ecx; + __asm__ __volatile__( + " jecxz 1f\n" + " repne; scasb\n" + " leal -1(%%edi), %%edi\n" + " je 2f\n" + "1:\n" + " xorl %%edi, %%edi\n" /* NULL */ + "2:\n" + : "=&D" (edi), "=&c" (ecx) + : "a" (c), "0" (s), "1" (count) + /* : no clobbers */ + ); + return edi; } +#ifndef memchr libc_hidden_def(memchr) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memchr.c -o memchr + * and run ./memchr + */ +int main() +{ + static const char str[] = "abc.def"; + printf((char*)memchr(str, '.',-2) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.',-1) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 1) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 2) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 3) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 4) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/memcpy.c b/libc/string/i386/memcpy.c index af86cf255..697d0bdc2 100644 --- a/libc/string/i386/memcpy.c +++ b/libc/string/i386/memcpy.c @@ -38,11 +38,11 @@ void *memcpy(void * to, const void * from, size_t n) int d0, d1, d2; __asm__ __volatile__( " rep; movsl\n" - " movl %4,%%ecx\n" - " andl $3,%%ecx\n" + " movl %4, %%ecx\n" + " andl $3, %%ecx\n" /* jz is optional. avoids "rep; movsb" with ecx == 0, * but adds a branch, which is currently (2008) faster */ - " jz 1f\n" + " jz 1f\n" " rep; movsb\n" "1:\n" : "=&c" (d0), "=&D" (d1), "=&S" (d2) diff --git a/libc/string/i386/memmove.c b/libc/string/i386/memmove.c index a924efcbc..72d8002a5 100644 --- a/libc/string/i386/memmove.c +++ b/libc/string/i386/memmove.c @@ -32,28 +32,40 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(memmove) */ +#undef memmove +//#define memmove TESTING void *memmove(void *dest, const void *src, size_t n) { - int d0, d1, d2; - if (dest<src) + int eax, ecx, esi, edi; __asm__ __volatile__( - "rep\n\t" - "movsb" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n),"1" (src),"2" (dest) - : "memory"); - else - __asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n), - "1" (n-1+(const char *)src), - "2" (n-1+(char *)dest) - :"memory"); - return dest; + " movl %%eax, %%edi\n" + " cmpl %%esi, %%eax\n" + " je 2f\n" /* (optional) src == dest -> NOP */ + " jb 1f\n" /* src > dest -> simple copy */ + " leal -1(%%esi,%%ecx), %%esi\n" + " leal -1(%%eax,%%ecx), %%edi\n" + " std\n" + "1: rep; movsb\n" + " cld\n" + "2:\n" + : "=&c" (ecx), "=&S" (esi), "=&a" (eax), "=&D" (edi) + : "0" (n), "1" (src), "2" (dest) + : "memory" + ); + return (void*)eax; } +#ifndef memmove libc_hidden_def(memmove) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memmove.c -o memmove + * and run ./memmove + */ +int main() +{ + static char str[] = "abcdef.123"; + memmove(str + 1, str, 5); + printf(strcmp(str, "aabcde.123") == 0 ? "ok\n" : "BAD!\n"); + memmove(str, str + 1, 5); + printf(strcmp(str, "abcdee.123") == 0 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/memset.c b/libc/string/i386/memset.c index 779725f2f..cfc16983c 100644 --- a/libc/string/i386/memset.c +++ b/libc/string/i386/memset.c @@ -32,6 +32,7 @@ #include <string.h> +/* Experimentally off - libc_hidden_proto(memset) */ #undef memset void *memset(void *s, int c, size_t count) { diff --git a/libc/string/i386/strchr.c b/libc/string/i386/strchr.c index 46b1dfb6e..93cc9583e 100644 --- a/libc/string/i386/strchr.c +++ b/libc/string/i386/strchr.c @@ -32,23 +32,25 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strchr) */ +#undef strchr char *strchr(const char *s, int c) { - int d0; - register char * __res; - __asm__ __volatile__( - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "je 2f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "movl $1,%1\n" - "2:\tmovl %1,%0\n\t" - "decl %0" - :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); - return __res; + int esi; + register char * eax; + __asm__ __volatile__( + " movb %%al, %%ah\n" + "1: lodsb\n" + " cmpb %%ah, %%al\n" + " je 2f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + " movl $1, %%esi\n" /* can use shorter xor + inc */ + "2: leal -1(%%esi), %%eax\n" + : "=a" (eax), "=&S" (esi) + : "0" (c), "1" (s) + /* no clobbers */ + ); + return eax; } libc_hidden_def(strchr) #ifdef __UCLIBC_SUSV3_LEGACY__ diff --git a/libc/string/i386/strcpy.c b/libc/string/i386/strcpy.c index 09065a9b7..fff1bd006 100644 --- a/libc/string/i386/strcpy.c +++ b/libc/string/i386/strcpy.c @@ -32,7 +32,7 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strcpy) */ +#undef strcpy char *strcpy(char * dest, const char * src) { int d0, d1, d2; diff --git a/libc/string/i386/strlen.c b/libc/string/i386/strlen.c index 61a178393..ff2baeb38 100644 --- a/libc/string/i386/strlen.c +++ b/libc/string/i386/strlen.c @@ -32,17 +32,17 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strlen) */ +#undef strlen size_t strlen(const char *s) { - int d0; - register int __res; - __asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "notl %0\n\t" - "decl %0" - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); - return __res; + int eax, ecx, edi; + __asm__ __volatile__( + " repne; scasb\n" + " notl %%ecx\n" + " leal -1(%%ecx), %%eax\n" + : "=&c" (ecx), "=&D" (edi), "=&a" (eax) + : "0" (0xffffffff), "1" (s), "2" (0) + ); + return eax; } libc_hidden_def(strlen) diff --git a/libc/string/i386/strncat.c b/libc/string/i386/strncat.c index 3872679d5..640b0d213 100644 --- a/libc/string/i386/strncat.c +++ b/libc/string/i386/strncat.c @@ -32,30 +32,55 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strncat) */ -char *strncat(char * dest, - const char * src, size_t count) +#undef strncat +//#define strncat TESTING +char *strncat(char * dest, const char * src, size_t count) { - int d0, d1, d2, d3; - __asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "decl %1\n\t" - "movl %8,%3\n" - "incl %3\n" - "1:\tdecl %3\n\t" - "jz 2f\n" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "jmp 3f\n" - "2:\txorl %2,%2\n\t" - "stosb\n" - "3:" - : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) - : "memory"); - return dest; + int esi, edi, eax, ecx, edx; + __asm__ __volatile__( + " xorl %%eax, %%eax\n" + " incl %%edx\n" + " pushl %%edi\n" /* save dest */ + " repne; scasb\n" + " decl %%edi\n" /* edi => NUL in dest */ + /* count-- */ + "1: decl %%edx\n" + /* if count reached 0, store NUL and bail out */ + " movl %%edx, %%eax\n" + " jz 2f\n" + /* else copy a char */ + " lodsb\n" + "2: stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + /* end of loop */ + " popl %%eax\n" /* restore dest into eax */ + : "=&S" (esi), "=&D" (edi), "=&a" (eax), "=&c" (ecx), "=&d" (edx) + : "0" (src), "1" (dest), "3" (0xffffffff), "4" (count) + : "memory" + ); + return (char *)eax; } +#ifndef strncat libc_hidden_def(strncat) +#else +/* Uncomment TESTING, gcc -m32 -Os strncat.c -o strncat + * and run ./strncat + */ +int main() +{ + char buf[99]; + + strcpy(buf, "abc"); buf[4] = '*'; strncat(buf, "def", 0); + printf(strcmp(buf, "abc") == 0 && buf[4] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", 50); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", -1); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def123", 3); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/strncmp.c b/libc/string/i386/strncmp.c index a14bb503b..bfb20c307 100644 --- a/libc/string/i386/strncmp.c +++ b/libc/string/i386/strncmp.c @@ -32,27 +32,28 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strncmp) */ +#undef strncmp int strncmp(const char *cs, const char *ct, size_t count) { - register int __res; - int d0, d1, d2; - __asm__ __volatile__( - "incl %3\n" - "1:\tdecl %3\n\t" - "jz 2f\n" - "lodsb\n\t" - "scasb\n\t" - "jne 3f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %%eax,%%eax\n\t" - "jmp 4f\n" - "3:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "4:" - :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs),"2" (ct),"3" (count)); - return __res; + int eax; + int esi, edi, ecx; + __asm__ __volatile__( + " incl %%ecx\n" + "1: decl %%ecx\n" + " jz 2f\n" + " lodsb\n" + " scasb\n" + " jne 3f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + "2: xorl %%eax, %%eax\n" + " jmp 4f\n" + "3: sbbl %%eax, %%eax\n" + " orb $1, %%al\n" + "4:\n" + : "=a" (eax), "=&S" (esi), "=&D" (edi), "=&c" (ecx) + : "1" (cs), "2" (ct), "3" (count) + ); + return eax; } libc_hidden_weak(strncmp) diff --git a/libc/string/i386/strncpy.c b/libc/string/i386/strncpy.c index 76aa6ae1b..e1c7f1dcf 100644 --- a/libc/string/i386/strncpy.c +++ b/libc/string/i386/strncpy.c @@ -32,25 +32,44 @@ #include <string.h> -/* Experimentally off - libc_hidden_proto(strncpy) */ +#undef strncpy +//#define strncpy TESTING char *strncpy(char * dest, const char * src, size_t count) { - int d0, d1, d2, d3; - __asm__ __volatile__( - "incl %2\n" - "1:\n" - "decl %2\n" - "jz 2f\n" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "decl %2\n" - "rep\n\t" - "stosb\n" - "2:" - : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) - :"0" (src),"1" (dest),"2" (count) : "memory"); - return dest; + int esi, edi, ecx, eax; + __asm__ __volatile__( + "1: subl $1, %%ecx\n" /* not dec! it doesnt set CF */ + " jc 2f\n" + " lodsb\n" + " stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + " rep; stosb\n" + "2:\n" + : "=&S" (esi), "=&D" (edi), "=&c" (ecx), "=&a" (eax) + : "0" (src), "1" (dest), "2" (count) + : "memory" + ); + return dest; } +#ifndef strncpy libc_hidden_def(strncpy) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strncpy.c -o strncpy + * and run ./strncpy + */ +int main() +{ + static char str[99]; + + str[3] = '*'; str[4] = 0; strncpy(str, "abc", 3); + printf(strcmp(str, "abc*") == 0 ? "ok\n" : "BAD!\n"); + + str[4] = '*'; str[5] = '+'; strncpy(str, "abc", 5); + printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ? + "ok\n" : "BAD!\n"); + strncpy(str, "def", 0); /* should do nothing */ + printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ? + "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/strnlen.c b/libc/string/i386/strnlen.c index 02c72f530..3abde48e2 100644 --- a/libc/string/i386/strnlen.c +++ b/libc/string/i386/strnlen.c @@ -33,24 +33,43 @@ #include <string.h> #ifdef __USE_GNU -/* Experimentally off - libc_hidden_proto(strnlen) */ + +#undef strnlen +//#define strnlen TESTING size_t strnlen(const char *s, size_t count) { - int d0; - register int __res; - __asm__ __volatile__( - "movl %2,%0\n\t" - "incl %1\n" - "jmp 2f\n" - "1:\tcmpb $0,(%0)\n\t" - "je 3f\n\t" - "incl %0\n" - "2:\tdecl %1\n\t" - "jne 1b\n" - "3:\tsubl %2,%0" - :"=a" (__res), "=&d" (d0) - :"c" (s),"1" (count)); - return __res; + int edx; + int eax; + __asm__ __volatile__( + " leal -1(%%ecx), %%eax\n" + "1: incl %%eax\n" + " decl %%edx\n" + " jz 3f\n" + " cmpb $0, (%%eax)\n" + " jnz 1b\n" + "3: subl %%ecx, %%eax" + : "=a" (eax), "=&d" (edx) + : "c" (s), "1" (count + 1) + ); + return eax; } +#ifndef strnlen libc_hidden_def(strnlen) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strnlen.c -o strnlen + * and run ./strnlen + */ +int main() +{ + printf(strnlen("abc\0def", -2) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", -1) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 0) == 0 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 1) == 1 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 2) == 2 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 3) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 4) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 5) == 3 ? "ok\n" : "BAD!\n"); +} +#endif + #endif diff --git a/libc/string/i386/strrchr.c b/libc/string/i386/strrchr.c index ef378685b..9f2c74923 100644 --- a/libc/string/i386/strrchr.c +++ b/libc/string/i386/strrchr.c @@ -35,18 +35,23 @@ /* Experimentally off - libc_hidden_proto(strrchr) */ char *strrchr(const char *s, int c) { - int d0, d1; - register char * __res; - __asm__ __volatile__( - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "jne 2f\n\t" - "leal -1(%%esi),%0\n" - "2:\ttestb %%al,%%al\n\t" - "jne 1b" - :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); - return __res; + char *eax; + + __asm__ __volatile__( + " movb %%cl, %%ch\n" + "1: movb (%1), %%cl\n" /* load char */ + " cmpb %%cl, %%ch\n" /* char == c? */ + " jne 2f\n" + " movl %1, %%eax\n" + "2: incl %1\n" + " testb %%cl, %%cl\n" /* char == NUL? */ + " jnz 1b\n" + /* "=c": use ecx, not ebx (-fpic uses it). */ + : "=a" (eax), "=r" (s), "=c" (c) + : "0" (0), "1" (s), "2" (c) + /* : no clobbers */ + ); + return eax; } libc_hidden_def(strrchr) #ifdef __UCLIBC_SUSV3_LEGACY__ diff --git a/libc/string/ia64/memchr.S b/libc/string/ia64/memchr.S index 0246b5997..f25e80302 100644 --- a/libc/string/ia64/memchr.S +++ b/libc/string/ia64/memchr.S @@ -126,8 +126,6 @@ ENTRY(__memchr) END(__memchr) -weak_alias (__memchr, memchr) -#if !__BOUNDED_POINTERS__ -weak_alias (__memchr, __ubp_memchr) -#endif -libc_hidden_def (memchr) +weak_alias(__memchr, memchr) +weak_alias(__memchr, __ubp_memchr) +libc_hidden_def(memchr) diff --git a/libc/string/memchr.c b/libc/string/memchr.c index 5e60f6554..438f4fa4a 100644 --- a/libc/string/memchr.c +++ b/libc/string/memchr.c @@ -10,6 +10,7 @@ #ifdef WANT_WIDE # define Wmemchr wmemchr #else +# undef memchr # define Wmemchr memchr #endif diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c index aa8d4ee38..cbb6e633a 100644 --- a/libc/string/memcpy.c +++ b/libc/string/memcpy.c @@ -10,6 +10,7 @@ #ifdef WANT_WIDE # define Wmemcpy wmemcpy #else +# undef memcpy # define Wmemcpy memcpy #endif diff --git a/libc/string/mempcpy.c b/libc/string/mempcpy.c index e7605146a..d79bd1937 100644 --- a/libc/string/mempcpy.c +++ b/libc/string/mempcpy.c @@ -12,6 +12,7 @@ #ifdef WANT_WIDE # define Wmempcpy wmempcpy #else +# undef mempcpy # define Wmempcpy mempcpy #endif diff --git a/libc/string/memset.c b/libc/string/memset.c index 6dd20d668..9daf59f69 100644 --- a/libc/string/memset.c +++ b/libc/string/memset.c @@ -10,7 +10,7 @@ #ifdef WANT_WIDE # define Wmemset wmemset #else -/* Experimentally off - libc_hidden_proto(memset) */ +# undef memset # define Wmemset memset #endif diff --git a/libc/string/sparc/sparc32/memchr.S b/libc/string/sparc/sparc32/memchr.S index 4d57a553b..d926e9787 100644 --- a/libc/string/sparc/sparc32/memchr.S +++ b/libc/string/sparc/sparc32/memchr.S @@ -139,6 +139,4 @@ ENTRY(memchr) END(memchr) libc_hidden_def(memchr) -#if !__BOUNDED_POINTERS__ weak_alias(memchr,__ubp_memchr) -#endif |
