mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-03 04:01:43 +08:00
939da41143
Various glibc functions call __stpcpy and __mempcpy for namespace reasons instead of plain stpcpy and mempcpy. But __stpcpy and __mempcpy are macros that call __builtin_stpcpy and __builtin_mempcpy, and unless GCC optimizes the calls, they end up calling the C functions stpcpy and mempcpy. For calls from within shared libc, libc_hidden_builtin_proto ensures that calls to those C functions are in turn mapped to call __GI_stpcpy and __GI_mempcpy. However, for static libc, and for calls from shared libraries other than libc, the ELF symbols stpcpy and mempcpy end up getting called, breaking the ISO C namespace (in the case of stpcpy) or glibc conventions about not relying on the "future library directions" reservations (in the case of mempcpy). This patch fixes this by adding declarations of these functions to include/string.h, under an appropriate condition, with __asm__ used to change the assembler name used for calls (the mempcpy case was previously discussed, and the approach for the fix is as I suggested in <https://sourceware.org/ml/libc-alpha/2013-02/msg00063.html>). Tested for x86_64 with the testsuite; also checked that dcigettext.o (an example previously noted of undesired calls to stpcpy and mempcpy) now calls __stpcpy and __mempcpy instead, as do non-libc shared libraries (__stpcpy and __mempcpy were already exported from shared libc). Disassembly of installed shared libraries isn't easy to compare because of reordered PLT entries resulting from the change in functions called (libnsl, libnss_compat, libnss_dns, libnss_files, libnss_hesiod, libnss_nis, libnss_nisplus, libpthread, librt all have such changes). [BZ #17573] * include/string.h [NOT_IN_libc || !SHARED] (mempcpy): Declare with asm name __mempcpy. [NOT_IN_libc || !SHARED] (stpcpy): Declare with asm name __stpcpy.
160 lines
5.0 KiB
C
160 lines
5.0 KiB
C
#ifndef _STRING_H
|
|
|
|
#ifndef _ISOMAC
|
|
#include <sys/types.h>
|
|
|
|
extern void *__memccpy (void *__dest, const void *__src,
|
|
int __c, size_t __n);
|
|
|
|
extern size_t __strnlen (const char *__string, size_t __maxlen)
|
|
__attribute_pure__;
|
|
|
|
extern char *__strsep (char **__stringp, const char *__delim);
|
|
|
|
extern int __strverscmp (const char *__s1, const char *__s2)
|
|
__attribute_pure__;
|
|
|
|
extern int __strncasecmp (const char *__s1, const char *__s2,
|
|
size_t __n)
|
|
__attribute_pure__;
|
|
|
|
extern int __strcasecmp (const char *__s1, const char *__s2)
|
|
__attribute_pure__;
|
|
|
|
extern char *__strcasestr (const char *__haystack, const char *__needle)
|
|
__attribute_pure__;
|
|
|
|
extern char *__strdup (const char *__string)
|
|
__attribute_malloc__;
|
|
extern char *__strndup (const char *__string, size_t __n)
|
|
__attribute_malloc__;
|
|
|
|
extern void *__rawmemchr (const void *__s, int __c)
|
|
__attribute_pure__;
|
|
|
|
extern char *__strchrnul (const char *__s, int __c)
|
|
__attribute_pure__;
|
|
|
|
extern void *__memrchr (const void *__s, int __c, size_t __n)
|
|
__attribute_pure__;
|
|
|
|
extern void *__memchr (const void *__s, int __c, size_t __n)
|
|
__attribute_pure__;
|
|
|
|
extern int __ffs (int __i) __attribute__ ((const));
|
|
|
|
extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);
|
|
#endif
|
|
|
|
/* Now the real definitions. We do this here since some of the functions
|
|
above are defined as macros in the headers. */
|
|
#include <string/string.h>
|
|
|
|
#ifndef _ISOMAC
|
|
extern __typeof (strcoll_l) __strcoll_l;
|
|
extern __typeof (strxfrm_l) __strxfrm_l;
|
|
extern __typeof (strcasecmp_l) __strcasecmp_l;
|
|
extern __typeof (strncasecmp_l) __strncasecmp_l;
|
|
|
|
/* Alternative version which doesn't pollute glibc's namespace. */
|
|
#ifndef NOT_IN_libc
|
|
# undef strndupa
|
|
# define strndupa(s, n) \
|
|
(__extension__ \
|
|
({ \
|
|
const char *__old = (s); \
|
|
size_t __len = __strnlen (__old, (n)); \
|
|
char *__new = (char *) __builtin_alloca (__len + 1); \
|
|
__new[__len] = '\0'; \
|
|
(char *) memcpy (__new, __old, __len); \
|
|
}))
|
|
#endif
|
|
|
|
libc_hidden_proto (__mempcpy)
|
|
libc_hidden_proto (__stpcpy)
|
|
libc_hidden_proto (__stpncpy)
|
|
libc_hidden_proto (__rawmemchr)
|
|
libc_hidden_proto (__strcasecmp)
|
|
libc_hidden_proto (__strcasecmp_l)
|
|
libc_hidden_proto (__strncasecmp_l)
|
|
libc_hidden_proto (__strdup)
|
|
libc_hidden_proto (__strndup)
|
|
libc_hidden_proto (__strerror_r)
|
|
libc_hidden_proto (__strverscmp)
|
|
libc_hidden_proto (basename)
|
|
libc_hidden_proto (strcoll)
|
|
libc_hidden_proto (__strcoll_l)
|
|
libc_hidden_proto (__strxfrm_l)
|
|
libc_hidden_proto (__strtok_r)
|
|
extern char *__strsep_g (char **__stringp, const char *__delim);
|
|
libc_hidden_proto (__strsep_g)
|
|
libc_hidden_proto (strnlen)
|
|
libc_hidden_proto (memmem)
|
|
libc_hidden_proto (__ffs)
|
|
|
|
libc_hidden_builtin_proto (memchr)
|
|
libc_hidden_builtin_proto (memcpy)
|
|
libc_hidden_builtin_proto (mempcpy)
|
|
libc_hidden_builtin_proto (memcmp)
|
|
libc_hidden_builtin_proto (memmove)
|
|
libc_hidden_builtin_proto (memset)
|
|
libc_hidden_builtin_proto (strcat)
|
|
libc_hidden_builtin_proto (strchr)
|
|
libc_hidden_builtin_proto (strcmp)
|
|
libc_hidden_builtin_proto (strcpy)
|
|
libc_hidden_builtin_proto (strcspn)
|
|
libc_hidden_builtin_proto (strlen)
|
|
libc_hidden_builtin_proto (strncmp)
|
|
libc_hidden_builtin_proto (strncpy)
|
|
libc_hidden_builtin_proto (strpbrk)
|
|
libc_hidden_builtin_proto (stpcpy)
|
|
libc_hidden_builtin_proto (strrchr)
|
|
libc_hidden_builtin_proto (strspn)
|
|
libc_hidden_builtin_proto (strstr)
|
|
libc_hidden_builtin_proto (ffs)
|
|
|
|
#if defined NOT_IN_libc || !defined SHARED
|
|
/* Redirect calls to __builtin_mempcpy and __builtin_stpcpy to call
|
|
__mempcpy and __stpcpy if not inlined. */
|
|
extern __typeof (mempcpy) mempcpy __asm__ ("__mempcpy");
|
|
extern __typeof (stpcpy) stpcpy __asm__ ("__stpcpy");
|
|
#endif
|
|
|
|
# ifndef _ISOMAC
|
|
# ifndef index
|
|
# define index(s, c) (strchr ((s), (c)))
|
|
# endif
|
|
# ifndef rindex
|
|
# define rindex(s, c) (strrchr ((s), (c)))
|
|
# endif
|
|
# endif
|
|
|
|
extern void *__memcpy_chk (void *__restrict __dest,
|
|
const void *__restrict __src, size_t __len,
|
|
size_t __destlen) __THROW;
|
|
extern void *__memmove_chk (void *__dest, const void *__src, size_t __len,
|
|
size_t __destlen) __THROW;
|
|
extern void *__mempcpy_chk (void *__restrict __dest,
|
|
const void *__restrict __src, size_t __len,
|
|
size_t __destlen) __THROW;
|
|
extern void *__memset_chk (void *__dest, int __ch, size_t __len,
|
|
size_t __destlen) __THROW;
|
|
extern char *__strcpy_chk (char *__restrict __dest,
|
|
const char *__restrict __src,
|
|
size_t __destlen) __THROW;
|
|
extern char *__stpcpy_chk (char *__restrict __dest,
|
|
const char *__restrict __src,
|
|
size_t __destlen) __THROW;
|
|
extern char *__strncpy_chk (char *__restrict __dest,
|
|
const char *__restrict __src,
|
|
size_t __len, size_t __destlen) __THROW;
|
|
extern char *__strcat_chk (char *__restrict __dest,
|
|
const char *__restrict __src,
|
|
size_t __destlen) __THROW;
|
|
extern char *__strncat_chk (char *__restrict __dest,
|
|
const char *__restrict __src,
|
|
size_t __len, size_t __destlen) __THROW;
|
|
#endif
|
|
|
|
#endif
|