+2009-03-16 Ulrich Drepper <drepper@redhat.com>
+
+ * include/dirent.h: Yet more changes to match sort function type
+ change.
+ * sysdeps/unix/sysv/linux/i386/alphasort64.c: Likewise.
+ * sysdeps/unix/sysv/linux/i386/olddirent.h: Likewise.
+ * sysdeps/unix/sysv/linux/i386/versionsort64.c: Likewise.
+
+2009-03-16 Thomas Schwinge <tschwinge@gnu.org>
+
+ * dirent/scandir64.c (scandir64): Adjust declaration to type change.
+
+2009-03-16 Ulrich Drepper <drepper@redhat.com>
+
+ * nscd/connections.c (restart): Try to preserve the process name
+ by reading the /proc/self/exe symlink and using the return name.
+ Patch by Jeff Bastian <jbastian@redhat.com>.
+
+2009-03-15 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #9733]
+ * elf/dl-load.c (_dl_map_object_from_fd): Only call audit hooks
+ if we are not loading a new audit library.
+ * elf/dl-reloc (_dl_relocate_object): Third parameter is now a bitmask.
+ Only use profiling trampoline for auditing if we are not relocating
+ an audit library.
+ * elf/dl-open.c (dl_open_worker): Adjust _dl_relocate_object call.
+ * elf/rtld.c: Likewise.
+ * sysdeps/generic/ldsodefs.h: Adjust _dl_relocate_object prototype.
+
+ * elf/rtld.c (dl_main): Extend help message for --audit option.
+
+ [BZ #9759]
+ * dirent/dirent.h: Adjust prototypes of scandir, scandir64, alphasort,
+ alphasort64, versionsort, and versionsort64 to POSIX 2008.
+ * dirent/alphasort.c: Adjust implementation to type change.
+ * dirent/alphasort64.c: Likewise.
+ * dirent/scandir.c: Likewise.
+ * dirent/versionsort.c: Likewise.
+ * dirent/versionsort64.c: Likewise.
+ * sysdeps/wordsize-64/alphasort.c: Add hack to hide alphasort64
+ declaration.
+ * sysdeps/wordsize-64/versionsort.c: Add hack to hide versionsort64
+ declaration.
+
+ [BZ #9880]
+ * inet/inet6_rth.c (inet6_rth_reverse): Compute number of segments
+ correctly. Set segleft member in output as required.
+ Patch partly by Yang Hongyang <yanghy@cn.fujitsu.com>.
+ * inet/tst-inet6_rth.c (do_test): Add tests for inet6_rth_reverse.
+
+ [BZ #9881]
+ * inet/inet6_rth.c (inet6_rth_add): Add some error checking.
+ Patch mostly by Yang Hongyang <yanghy@cn.fujitsu.com>.
+ * inet/Makefile (tests): Add tst-inet6_rth.
+ * inet/tst-inet6_rth.c: New file.
+
+ [BZ #5807]
+ * string/strlen.c (strlen): Fix omission in the expression to test
+ for NUL bytes.
+
+2009-03-14 Ulrich Drepper <drepper@redhat.com>
+
+ * crypt/sha256test.c (main): Perform 100,000 'a' test in a second way.
+
+ * elf/dl-runtime.c (reloc_offset): Define.
+ (reloc_index): Define.
+ (_dl_fixup): Rename reloc_offset parameter to reloc_arg.
+ (_dl_fixup_profile): Likewise. Use reloc_index instead of
+ computing index from reloc_offset.
+ (_dl_call_pltexit): Likewise.
+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve): Just pass
+ the relocation index to _dl_fixup.
+ (_dl_runtime_profile): Likewise for _dl_fixup_profile and
+ _dl_call_pltexit.
+ * sysdeps/x86_64/dl-runtime.c: New file.
+
+ [BZ #9893]
+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): Fix
+ alignment of La_x86_64_regs. Store xmm parameters.
+ Patch mostly by Jiri Olsa <olsajiri@gmail.com>.
+
+ [BZ #9913]
+ * string/strverscmp.c (__strverscmp): Fix case of different digits
+ in fractional part of string.
+ Patch by Jingyu Liu <jyliu@fortinet.com>.
+ * string/Makefile (tests): Add tst-svc2.
+ * string/tst-svc2.c: New file.
+
+ * string/strverscmp.c (__strverscmp): Optimize size of tables.
+
+ * locale/iso-639.def: Add Min Nan.
+
+2009-03-11 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
+
+ [BZ #9948]
+ * elf/dl-sysdep.c (_dl_show_auxv): Add support for AT_BASE_PLATFORM.
+
+2009-03-14 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-sysdep.c (auxvars): Compress data structure.
+
+ * sysdeps/i386/dl-machine.h (elf_machine_rel): Implement
+ STT_GNU_IFUNC handling.
+ (elf_machine_rela): Likewise.
+
+2009-03-13 Ulrich Drepper <drepper@redhat.com>
+
+ * config.h.in (USE_MULTIARCH): Define.
+ * configure.in: Handle --enable-multi-arch.
+ * elf/dl-runtime.c (_dl_fixup): Handle STT_GNU_IFUNC.
+ (_dl_fixup_profile): Likewise.
+ * elf/do-lookup.c (dl_lookup_x): Likewise.
+ * sysdeps/x86_64/dl-machine.h: Handle STT_GNU_IFUNC.
+ * elf/elf.h (STT_GNU_IFUNC): Define.
+ * include/libc-symbols.h (libc_ifunc): Define.
+ * sysdeps/x86_64/cacheinfo.c: If USE_MULTIARCH is defined, use the
+ framework in init-arch.h to get CPUID values.
+ * sysdeps/x86_64/multiarch/Makefile: New file.
+ * sysdeps/x86_64/multiarch/init-arch.c: New file.
+ * sysdeps/x86_64/multiarch/init-arch.h: New file.
+ * sysdeps/x86_64/multiarch/sched_cpucount.c: New file.
+
+ * config.make.in (experimental-malloc): Define.
+ * configure.in: Handle --enable-experimental-malloc.
+ * malloc/Makefile: Handle experimental-malloc flag.
+ * malloc/malloc.c: Implement PER_THREAD and ATOMIC_FASTBINS features.
+ * malloc/arena.c: Likewise.
+ * malloc/hooks.c: Likewise.
+ * malloc/malloc.h: Define M_ARENA_TEST and M_ARENA_MAX.
+
+2009-03-11 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Add branch
+ prediction. A few size optimizations.
+
2009-03-10 Ulrich Drepper <drepper@redhat.com>
* time/tzset.c: Optimize a bit for size.
-GNU C Library NEWS -- history of user-visible changes. 2009-3-8
+GNU C Library NEWS -- history of user-visible changes. 2009-3-14
Copyright (C) 1992-2008, 2009 Free Software Foundation, Inc.
See the end for copying conditions.
\f
Version 2.10
-* New Linux interface: accept4
+* New Linux interfaces: accept4, fallocate, fallocate64.
* Correct declarations of string function when used in C++ code. This
could lead to compile error for invalid C++ code.
* New ISO C++1x interfaces: quick_exit, at_quick_exit
Implemented by Ulrich Drepper.
+* Support for selecting between multiple function definitions at runtime
+ using STT_GNU_IFUNC symbols. Implemented by Ulrich Drepper.
+
+* New locale: nan_TW@latin
+
\f
Version 2.9
/* Define if __stack_chk_guard canary should be randomized at program startup. */
#undef ENABLE_STACKGUARD_RANDOMIZE
+/* Define if multi-arch DSOs should be generated. */
+#undef USE_MULTIARCH
+
/*
\f */
oldest-abi = @oldest_abi@
no-whole-archive = @no_whole_archive@
exceptions = @exceptions@
+multi-arch = @multi_arch@
mach-interface-list = @mach_interface_list@
sizeof-long-double = @sizeof_long_double@
+experimental-malloc = @experimental_malloc@
+
# Configuration options.
build-static = @static@
build-shared = @shared@
bindnow
force_install
all_warnings
+multi_arch
+experimental_malloc
build
build_cpu
build_vendor
--enable-kernel=VERSION compile for compatibility with kernel not older than
VERSION
--enable-all-warnings enable all useful warnings gcc can issue
+ --enable-multi-arch enable single DSO with optimizations for multiple
+ architectures
+ --enable-experimental-malloc
+ enable experimental malloc features
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+# Check whether --enable-multi-arch was given.
+if test "${enable_multi_arch+set}" = set; then
+ enableval=$enable_multi_arch; multi_arch=$enableval
+else
+ multi_arch=no
+fi
+
+if test x"$multi_arch" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define USE_MULTIARCH 1
+_ACEOF
+
+ multi_arch_d=/multiarch
+fi
+
+
+# Check whether --enable-experimental-malloc was given.
+if test "${enable_experimental_malloc+set}" = set; then
+ enableval=$enable_experimental_malloc; experimental_malloc=$enableval
+fi
+
+
+
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
{ { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
test "$v" = / && continue
for o in /$ostry ''; do
test "$o" = / && continue
- for m in $mach ''; do
+ for m in $multi_arch_d $mach ''; do
for d in $add_ons_pfx ''; do
for a in $add_ons_sfx ''; do
if test -n "$m0$m0sub$b$v$o$m$msub"; then
fi
+# For the multi-arch option we need support in the assembler.
+if test "$multi_arch" = yes; then
+ if test "x$libc_cv_asm_type_prefix" != xno; then
+{ echo "$as_me:$LINENO: checking for assembler gnu_indirect_function symbol type support" >&5
+echo $ECHO_N "checking for assembler gnu_indirect_function symbol type support... $ECHO_C" >&6; }
+if test "${libc_cv_asm_gnu_indirect_function+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat > conftest.s <<EOF
+.type foo,%gnu_indirect_function
+EOF
+if ${CC-cc} -c $ASFLAGS conftest.s 1>&5 2>&5;
+then
+ libc_cv_asm_gnu_indirect_function=yes
+else
+ libc_cv_asm_gnu_indirect_function=no
+fi
+rm -f conftest*
+fi
+{ echo "$as_me:$LINENO: result: $libc_cv_asm_gnu_indirect_function" >&5
+echo "${ECHO_T}$libc_cv_asm_gnu_indirect_function" >&6; }
+ else
+ libc_cv_asm_gnu_indirect_function=no
+ fi
+ if test x"$libc_cv_asm_gnu_indirect_function" != xyes; then
+ { { echo "$as_me:$LINENO: error: --enable-multi-arch support requires assembler and linker support" >&5
+echo "$as_me: error: --enable-multi-arch support requires assembler and linker support" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
{ echo "$as_me:$LINENO: checking for .symver assembler directive" >&5
echo $ECHO_N "checking for .symver assembler directive... $ECHO_C" >&6; }
if test "${libc_cv_asm_symver_directive+set}" = set; then
bindnow!$bindnow$ac_delim
force_install!$force_install$ac_delim
all_warnings!$all_warnings$ac_delim
+multi_arch!$multi_arch$ac_delim
+experimental_malloc!$experimental_malloc$ac_delim
build!$build$ac_delim
build_cpu!$build_cpu$ac_delim
build_vendor!$build_vendor$ac_delim
KSH!$KSH$ac_delim
libc_cv_have_ksh!$libc_cv_have_ksh$ac_delim
AWK!$AWK$ac_delim
-PERL!$PERL$ac_delim
-INSTALL_INFO!$INSTALL_INFO$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
+PERL!$PERL$ac_delim
+INSTALL_INFO!$INSTALL_INFO$ac_delim
BISON!$BISON$ac_delim
VERSIONING!$VERSIONING$ac_delim
libc_cv_cc_with_libunwind!$libc_cv_cc_with_libunwind$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 54; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 56; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
[])
AC_SUBST(all_warnings)
+AC_ARG_ENABLE([multi-arch],
+ AC_HELP_STRING([--enable-multi-arch],
+ [enable single DSO with optimizations for multiple architectures]),
+ [multi_arch=$enableval],
+ [multi_arch=no])
+if test x"$multi_arch" = xyes; then
+ AC_DEFINE(USE_MULTIARCH)
+ multi_arch_d=/multiarch
+fi
+AC_SUBST(multi_arch)
+
+AC_ARG_ENABLE([experimental-malloc],
+ AC_HELP_STRING([--enable-experimental-malloc],
+ [enable experimental malloc features]),
+ [experimental_malloc=$enableval],
+ [])
+AC_SUBST(experimental_malloc)
+
AC_CANONICAL_HOST
# The way shlib-versions is used to generate soversions.mk uses a
test "$v" = / && continue
for o in /$ostry ''; do
test "$o" = / && continue
- for m in $mach ''; do
+ for m in $multi_arch_d $mach ''; do
for d in $add_ons_pfx ''; do
for a in $add_ons_sfx ''; do
if test -n "$m0$m0sub$b$v$o$m$msub"; then
AC_DEFINE_UNQUOTED(ASM_TYPE_DIRECTIVE_PREFIX, ${libc_cv_asm_type_prefix})
fi
+# For the multi-arch option we need support in the assembler.
+if test "$multi_arch" = yes; then
+ if test "x$libc_cv_asm_type_prefix" != xno; then
+AC_CACHE_CHECK([for assembler gnu_indirect_function symbol type support],
+ libc_cv_asm_gnu_indirect_function, [dnl
+cat > conftest.s <<EOF
+.type foo,%gnu_indirect_function
+EOF
+if ${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD;
+then
+ libc_cv_asm_gnu_indirect_function=yes
+else
+ libc_cv_asm_gnu_indirect_function=no
+fi
+rm -f conftest*])
+ else
+ libc_cv_asm_gnu_indirect_function=no
+ fi
+ if test x"$libc_cv_asm_gnu_indirect_function" != xyes; then
+ AC_MSG_ERROR([--enable-multi-arch support requires assembler and linker support])
+ fi
+fi
+
AC_CACHE_CHECK(for .symver assembler directive, libc_cv_asm_symver_directive,
[cat > conftest.s <<EOF
${libc_cv_dot_text}
"\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0";
if (memcmp (expected, sum, 32) != 0)
{
- printf ("test %d failed\n", cnt);
+ printf ("test %d failed\n", cnt++);
+ result = 1;
+ }
+
+ __sha256_init_ctx (&ctx);
+ for (int i = 0; i < 100000; ++i)
+ __sha256_process_bytes (buf, 10, &ctx);
+ __sha256_finish_ctx (&ctx, sum);
+ if (memcmp (expected, sum, 32) != 0)
+ {
+ printf ("test %d failed\n", cnt++);
result = 1;
}
-/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1997, 1998, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-alphasort (const void *a, const void *b)
+alphasort (const struct dirent **a, const struct dirent **b)
{
- return strcoll ((*(const struct dirent **) a)->d_name,
- (*(const struct dirent **) b)->d_name);
+ return strcoll ((*a)->d_name, (*b)->d_name);
}
-/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1997, 1998, 2000, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-alphasort64 (const void *a, const void *b)
+alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
{
- return strcoll ((*(const struct dirent64 **) a)->d_name,
- (*(const struct dirent64 **) b)->d_name);
+ return strcoll ((*a)->d_name, (*b)->d_name);
}
extern int scandir (__const char *__restrict __dir,
struct dirent ***__restrict __namelist,
int (*__selector) (__const struct dirent *),
- int (*__cmp) (__const void *, __const void *))
+ int (*__cmp) (__const struct dirent **,
+ __const struct dirent **))
__nonnull ((1, 2));
# else
# ifdef __REDIRECT
(__const char *__restrict __dir,
struct dirent ***__restrict __namelist,
int (*__selector) (__const struct dirent *),
- int (*__cmp) (__const void *, __const void *)),
+ int (*__cmp) (__const struct dirent **,
+ __const struct dirent **)),
scandir64) __nonnull ((1, 2));
# else
# define scandir scandir64
extern int scandir64 (__const char *__restrict __dir,
struct dirent64 ***__restrict __namelist,
int (*__selector) (__const struct dirent64 *),
- int (*__cmp) (__const void *, __const void *))
+ int (*__cmp) (__const struct dirent64 **,
+ __const struct dirent64 **))
__nonnull ((1, 2));
# endif
/* Function to compare two `struct dirent's alphabetically. */
# ifndef __USE_FILE_OFFSET64
-extern int alphasort (__const void *__e1, __const void *__e2)
+extern int alphasort (__const struct dirent **__e1,
+ __const struct dirent **__e2)
__THROW __attribute_pure__ __nonnull ((1, 2));
# else
# ifdef __REDIRECT
extern int __REDIRECT_NTH (alphasort,
- (__const void *__e1, __const void *__e2),
+ (__const struct dirent **__e1,
+ __const struct dirent **__e2),
alphasort64) __attribute_pure__ __nonnull ((1, 2));
# else
# define alphasort alphasort64
# endif
# if defined __USE_GNU && defined __USE_LARGEFILE64
-extern int alphasort64 (__const void *__e1, __const void *__e2)
+extern int alphasort64 (__const struct dirent64 **__e1,
+ __const struct dirent64 **__e2)
__THROW __attribute_pure__ __nonnull ((1, 2));
# endif
+#endif /* Use BSD or misc or XPG7. */
-# if defined __USE_BSD || defined __USE_MISC
+#if defined __USE_BSD || defined __USE_MISC
/* Read directory entries from FD into BUF, reading at most NBYTES.
Reading starts at offset *BASEP, and *BASEP is updated with the new
position after reading. Returns the number of bytes read; zero when at
end of directory; or -1 for errors. */
-# ifndef __USE_FILE_OFFSET64
+# ifndef __USE_FILE_OFFSET64
extern __ssize_t getdirentries (int __fd, char *__restrict __buf,
size_t __nbytes,
__off_t *__restrict __basep)
__THROW __nonnull ((2, 4));
-# else
-# ifdef __REDIRECT
+# else
+# ifdef __REDIRECT
extern __ssize_t __REDIRECT_NTH (getdirentries,
(int __fd, char *__restrict __buf,
size_t __nbytes,
__off64_t *__restrict __basep),
getdirentries64) __nonnull ((2, 4));
-# else
-# define getdirentries getdirentries64
-# endif
+# else
+# define getdirentries getdirentries64
# endif
+# endif
-# ifdef __USE_LARGEFILE64
+# ifdef __USE_LARGEFILE64
extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf,
size_t __nbytes,
__off64_t *__restrict __basep)
__THROW __nonnull ((2, 4));
-# endif
-# endif /* Use BSD or misc. */
-#endif /* Use BSD or misc or XPG7. */
+# endif
+#endif /* Use BSD or misc. */
#ifdef __USE_GNU
/* Function to compare two `struct dirent's by name & version. */
# ifndef __USE_FILE_OFFSET64
-extern int versionsort (__const void *__e1, __const void *__e2)
+extern int versionsort (__const struct dirent **__e1,
+ __const struct dirent **__e2)
__THROW __attribute_pure__ __nonnull ((1, 2));
# else
# ifdef __REDIRECT
extern int __REDIRECT_NTH (versionsort,
- (__const void *__e1, __const void *__e2),
+ (__const struct dirent **__e1,
+ __const struct dirent **__e2),
versionsort64)
__attribute_pure__ __nonnull ((1, 2));
# else
# endif
# ifdef __USE_LARGEFILE64
-extern int versionsort64 (__const void *__e1, __const void *__e2)
+extern int versionsort64 (__const struct dirent64 **__e1,
+ __const struct dirent64 **__e2)
__THROW __attribute_pure__ __nonnull ((1, 2));
# endif
#endif /* Use GNU. */
-/* Copyright (C) 1992-1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1992-1998,2000,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
const char *dir;
DIRENT_TYPE ***namelist;
int (*select) (const DIRENT_TYPE *);
- int (*cmp) (const void *, const void *);
+ int (*cmp) (const DIRENT_TYPE **, const DIRENT_TYPE **);
{
DIR *dp = __opendir (dir);
DIRENT_TYPE **v = NULL;
{
/* Sort the list if we have a comparison function to sort with. */
if (cmp != NULL)
- qsort (v, c.cnt, sizeof (*v), cmp);
+ qsort (v, c.cnt, sizeof (*v),
+ (int (*) (const void *, const void *)) cmp);
*namelist = v;
}
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
int scandir64 (__const char *__restrict __dir,
struct dirent64 ***__restrict __namelist,
int (*__selector) (__const struct dirent64 *),
- int (*__cmp) (__const void *, __const void *));
+ int (*__cmp) (__const struct dirent64 **,
+ __const struct dirent64 **));
#include <dirent/scandir.c>
-/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1997, 1998, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-versionsort (const void *a, const void *b)
+versionsort (const struct dirent **a, const struct dirent **b)
{
- return __strverscmp ((*(const struct dirent **) a)->d_name,
- (*(const struct dirent **) b)->d_name);
+ return __strverscmp ((*a)->d_name, (*b)->d_name);
}
-/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1997, 1998, 2000, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-versionsort64 (const void *a, const void *b)
+versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
{
- return __strverscmp ((*(const struct dirent64 **) a)->d_name,
- (*(const struct dirent64 **) b)->d_name);
+ return __strverscmp ((*a)->d_name, (*b)->d_name);
}
{
#ifdef SHARED
/* Auditing checkpoint: we are going to add new objects. */
- if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ if ((mode & __RTLD_AUDIT) == 0
+ && __builtin_expect (GLRO(dl_naudit) > 0, 0))
{
struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
/* Do not call the functions for any auditing object. */
/* Load a shared object at runtime, relocate it, and run its initializer.
- Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
const char *file = args->file;
int mode = args->mode;
struct link_map *new;
- int lazy;
unsigned int i;
bool any_tls = false;
struct link_map *call_map = NULL;
_dl_debug_state ();
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
- lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy);
+ int reloc_mode = mode & __RTLD_AUDIT;
+ if (GLRO(dl_lazy))
+ reloc_mode |= mode & RTLD_LAZY;
/* Relocate the objects loaded. We do this in reverse order so that copy
relocs of earlier objects overwrite the data written by later objects. */
start the profiling. */
struct link_map *old_profile_map = GL(dl_profile_map);
- _dl_relocate_object (l, l->l_scope, 1, 1);
+ _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
{
}
else
#endif
- _dl_relocate_object (l, l->l_scope, lazy, 0);
+ _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
}
if (l == new)
/* Relocate a shared object and resolve its references to other loaded objects.
- Copyright (C) 1995-2004, 2005, 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1995-2006, 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
- int lazy, int consider_profiling)
+ int reloc_mode, int consider_profiling)
{
struct textrels
{
} *textrels = NULL;
/* Initialize it to make the compiler happy. */
const char *errstring = NULL;
+ int lazy = reloc_mode & RTLD_LAZY;
#ifdef SHARED
/* If we are auditing, install the same handlers we need for profiling. */
- consider_profiling |= GLRO(dl_audit) != NULL;
+ if ((reloc_mode & __RTLD_AUDIT) == 0)
+ consider_profiling |= GLRO(dl_audit) != NULL;
#elif defined PROF
/* Never use dynamic linker profiling for gprof profiling code. */
# define consider_profiling 0
/* On-demand PLT fixup for shared objects.
- Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
# define ARCH_FIXUP_ATTRIBUTE
#endif
+#ifndef reloc_offset
+# define reloc_offset reloc_arg
+# define reloc_index reloc_arg / sizeof (PLTREL)
+#endif
+
+
/* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation
# endif
/* GKM FIXME: Fix trampoline to pass bounds so we can do
without the `__unbounded' qualifier. */
- struct link_map *__unbounded l, ElfW(Word) reloc_offset)
+ struct link_map *__unbounded l, ElfW(Word) reloc_arg)
{
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
+ if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
+ value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) ();
+
/* Finally, fix up the plt itself. */
if (__builtin_expect (GLRO(dl_bind_not), 0))
return value;
#endif
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
-
DL_FIXUP_VALUE_TYPE
__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
_dl_profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
#endif
- struct link_map *l, ElfW(Word) reloc_offset,
+ struct link_map *l, ElfW(Word) reloc_arg,
ElfW(Addr) retaddr, void *regs, long int *framesizep)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
/* This is the address in the array where we store the result of previous
relocations. */
- struct reloc_result *reloc_result
- = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+ struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
DL_FIXUP_VALUE_TYPE value = *resultp;
defsym != NULL
? LOOKUP_VALUE_ADDRESS (result)
+ defsym->st_value : 0);
+
+ if (__builtin_expect (ELFW(ST_TYPE) (defsym->st_info)
+ == STT_GNU_IFUNC, 0))
+ value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) ();
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value);
+
+ if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info)
+ == STT_GNU_IFUNC, 0))
+ value = ((DL_FIXUP_VALUE_TYPE (*) (void)) value) ();
+
result = l;
}
/* And now perhaps the relocation addend. */
#include <stdio.h>
void
ARCH_FIXUP_ATTRIBUTE
-_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset,
+_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
const void *inregs, void *outregs)
{
#ifdef SHARED
relocations. */
// XXX Maybe the bound information must be stored on the stack since
// XXX with bind_not a new value could have been stored in the meantime.
- struct reloc_result *reloc_result
- = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+ struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB])
+ reloc_result->boundndx);
{
static const struct
{
- const char label[20];
- enum { unknown = 0, dec, hex, str, ignore } form;
+ const char label[17];
+ enum { unknown = 0, dec, hex, str, ignore } form : 8;
} auxvars[] =
{
- [AT_EXECFD - 2] = { "AT_EXECFD: ", dec },
- [AT_EXECFN - 2] = { "AT_EXECFN: ", str },
- [AT_PHDR - 2] = { "AT_PHDR: 0x", hex },
- [AT_PHENT - 2] = { "AT_PHENT: ", dec },
- [AT_PHNUM - 2] = { "AT_PHNUM: ", dec },
- [AT_PAGESZ - 2] = { "AT_PAGESZ: ", dec },
- [AT_BASE - 2] = { "AT_BASE: 0x", hex },
- [AT_FLAGS - 2] = { "AT_FLAGS: 0x", hex },
- [AT_ENTRY - 2] = { "AT_ENTRY: 0x", hex },
- [AT_NOTELF - 2] = { "AT_NOTELF: ", hex },
- [AT_UID - 2] = { "AT_UID: ", dec },
- [AT_EUID - 2] = { "AT_EUID: ", dec },
- [AT_GID - 2] = { "AT_GID: ", dec },
- [AT_EGID - 2] = { "AT_EGID: ", dec },
- [AT_PLATFORM - 2] = { "AT_PLATFORM: ", str },
- [AT_HWCAP - 2] = { "AT_HWCAP: ", hex },
- [AT_CLKTCK - 2] = { "AT_CLKTCK: ", dec },
- [AT_FPUCW - 2] = { "AT_FPUCW: ", hex },
- [AT_DCACHEBSIZE - 2] = { "AT_DCACHEBSIZE: 0x", hex },
- [AT_ICACHEBSIZE - 2] = { "AT_ICACHEBSIZE: 0x", hex },
- [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex },
- [AT_IGNOREPPC - 2] = { "AT_IGNOREPPC", ignore },
- [AT_SECURE - 2] = { "AT_SECURE: ", dec },
- [AT_SYSINFO - 2] = { "AT_SYSINFO: 0x", hex },
- [AT_SYSINFO_EHDR - 2] = { "AT_SYSINFO_EHDR: 0x", hex },
- [AT_RANDOM - 2] = { "AT_RANDOM: 0x", hex },
+ [AT_EXECFD - 2] = { "EXECFD: ", dec },
+ [AT_EXECFN - 2] = { "EXECFN: ", str },
+ [AT_PHDR - 2] = { "PHDR: 0x", hex },
+ [AT_PHENT - 2] = { "PHENT: ", dec },
+ [AT_PHNUM - 2] = { "PHNUM: ", dec },
+ [AT_PAGESZ - 2] = { "PAGESZ: ", dec },
+ [AT_BASE - 2] = { "BASE: 0x", hex },
+ [AT_FLAGS - 2] = { "FLAGS: 0x", hex },
+ [AT_ENTRY - 2] = { "ENTRY: 0x", hex },
+ [AT_NOTELF - 2] = { "NOTELF: ", hex },
+ [AT_UID - 2] = { "UID: ", dec },
+ [AT_EUID - 2] = { "EUID: ", dec },
+ [AT_GID - 2] = { "GID: ", dec },
+ [AT_EGID - 2] = { "EGID: ", dec },
+ [AT_PLATFORM - 2] = { "PLATFORM: ", str },
+ [AT_HWCAP - 2] = { "HWCAP: ", hex },
+ [AT_CLKTCK - 2] = { "CLKTCK: ", dec },
+ [AT_FPUCW - 2] = { "FPUCW: ", hex },
+ [AT_DCACHEBSIZE - 2] = { "DCACHEBSIZE: 0x", hex },
+ [AT_ICACHEBSIZE - 2] = { "ICACHEBSIZE: 0x", hex },
+ [AT_UCACHEBSIZE - 2] = { "UCACHEBSIZE: 0x", hex },
+ [AT_IGNOREPPC - 2] = { "IGNOREPPC", ignore },
+ [AT_SECURE - 2] = { "SECURE: ", dec },
+ [AT_BASE_PLATFORM - 2] = { "BASE_PLATFORM:", str },
+ [AT_SYSINFO - 2] = { "SYSINFO: 0x", hex },
+ [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex },
+ [AT_RANDOM - 2] = { "RANDOM: 0x", hex },
};
unsigned int idx = (unsigned int) (av->a_type - 2);
val = _itoa ((unsigned long int) av->a_un.a_val,
buf + sizeof buf - 1, 16, 0);
- _dl_printf ("%s%s\n", auxvars[idx].label, val);
+ _dl_printf ("AT_%s%s\n", auxvars[idx].label, val);
continue;
}
/* Look up a symbol in the loaded objects.
- Copyright (C) 1995-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-2007, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC
&& ELFW(ST_TYPE) (sym->st_info) != STT_COMMON
- && ELFW(ST_TYPE) (sym->st_info) != STT_TLS, 0))
- /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_COMMON
- entries (and STT_TLS if TLS is supported) since these
- are no code/data definitions. */
+ && ELFW(ST_TYPE) (sym->st_info) != STT_TLS
+ && ELFW(ST_TYPE) (sym->st_info) != STT_GNU_IFUNC,
+ 0))
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, STT_COMMON,
+ STT_TLS, and STT_GNU_IFUNC since these are no code/data
+ definitions. */
return NULL;
if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
#define STT_TLS 6 /* Symbol is thread-local data object*/
#define STT_NUM 7 /* Number of defined types. */
#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */
#define STT_HIOS 12 /* End of OS-specific */
#define STT_LOPROC 13 /* Start of processor-specific */
#define STT_HIPROC 15 /* End of processor-specific */
struct relocate_args
{
struct link_map *l;
- int lazy;
+ int reloc_mode;
};
struct map_args
{
struct relocate_args *args = (struct relocate_args *) a;
- _dl_relocate_object (args->l, args->l->l_scope, args->lazy, 0);
+ _dl_relocate_object (args->l, args->l->l_scope, args->reloc_mode, 0);
}
static void
--library-path PATH use given PATH instead of content of the environment\n\
variable LD_LIBRARY_PATH\n\
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
- in LIST\n");
+ in LIST\n\
+ --audit LIST use objects named in LIST as auditors\n");
++_dl_skip_args;
--_dl_argc;
struct link_map *l = main_map;
/* Relocate the main executable. */
- struct relocate_args args = { .l = l, .lazy = GLRO(dl_lazy) };
+ struct relocate_args args = { .l = l,
+ .reloc_mode = (GLRO(dl_lazy)
+ ? RTLD_LAZY : 0) };
_dl_receive_error (print_unresolved, relocate_doit, &args);
/* This loop depends on the dependencies of the executable to
struct relocate_args args;
struct link_map *l;
- args.lazy = GLRO(dl_lazy);
+ args.reloc_mode = GLRO(dl_lazy) ? RTLD_LAZY : 0;
l = main_map;
while (l->l_next != NULL)
}
if (l != &GL(dl_rtld_map))
- _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy),
+ _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
consider_profiling);
/* Add object to slot information data if necessasy. */
glibc-base := HEAD
DIST_BRANCH := devel
COLLECTION := dist-f8
-fedora-sync-date := 2009-03-10 19:25 UTC
-fedora-sync-tag := fedora-glibc-20090310T1925
+fedora-sync-date := 2009-03-20 19:44 UTC
+fedora-sync-tag := fedora-glibc-20090320T1944
Summary: The GNU libc libraries
Name: glibc
Version: @glibcversion@
-Release: 10
+Release: 11
# GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
# Things that are linked directly into dynamically linked programs
# and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
%endif
%changelog
+* Fri Mar 20 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-11
+- update from trunk
+ - POSIX 2008 prototype adjustments for scandir{,64}, alphasort{,64} and
+ versionsort{,64}
+ - fix libthread_db (#491197)
+
* Tue Mar 10 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-10
- update from trunk
- fix atexit/__cxa_atexit
extern int __scandir64 (__const char * __dir,
struct dirent64 *** __namelist,
int (*__selector) (__const struct dirent64 *),
- int (*__cmp) (__const void *, __const void *));
+ int (*__cmp) (__const struct dirent64 **,
+ __const struct dirent64 **));
extern __ssize_t __getdents (int __fd, char *__buf, size_t __nbytes)
internal_function;
extern __ssize_t __getdents64 (int __fd, char *__buf, size_t __nbytes)
internal_function;
-extern int __alphasort64 (const void *a, const void *b)
+extern int __alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
__attribute_pure__;
-extern int __versionsort64 (const void *a, const void *b)
+extern int __versionsort64 (const struct dirent64 **a,
+ const struct dirent64 **b)
__attribute_pure__;
extern DIR *__alloc_dir (int fd, bool close_fd, const struct stat64 *statp)
internal_function;
/* Support macros for making weak and strong aliases for symbols,
and for using symbol sets and linker warnings with GNU ld.
- Copyright (C) 1995-1998,2000-2003,2004,2005,2006
- Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2006, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
# define compat_data_section .section ".data.compat", "aw";
#endif
+/* Marker used for indirection function symbols. */
+#define libc_ifunc(name, expr) \
+ extern void *name##_ifunc (void) __asm__ (#name); \
+ void *name##_ifunc (void) \
+ { \
+ INIT_ARCH (); \
+ __typeof (name) *res = expr; \
+ return res; \
+ } \
+ __asm__ (".type " #name ", %gnu_indirect_function");
+
#endif /* libc-symbols.h */
-# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc.
+# Copyright (C) 1991-2006, 2007, 2009 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
- tst-getni1 tst-getni2
+ tst-getni1 tst-getni2 tst-inet6_rth
include ../Rules
-/* Copyright (C) 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2006.
struct ip6_rthdr0 *rthdr0;
case IPV6_RTHDR_TYPE_0:
rthdr0 = (struct ip6_rthdr0 *) rthdr;
+ if (rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr)
+ - rthdr0->ip6r0_segleft < 1)
+ return -1;
memcpy (&rthdr0->ip6r0_addr[rthdr0->ip6r0_segleft++],
addr, sizeof (struct in6_addr));
/* Copy header, not the addresses. The memory regions can overlap. */
memmove (out_rthdr0, in_rthdr0, sizeof (struct ip6_rthdr0));
- int total = in_rthdr0->ip6r0_segleft * 8 / sizeof (struct in6_addr);
+ int total = in_rthdr0->ip6r0_len * 8 / sizeof (struct in6_addr);
for (int i = 0; i < total / 2; ++i)
{
/* Remember, IN_RTHDR0 and OUT_RTHDR0 might overlap. */
if (total % 2 != 0 && in != out)
out_rthdr0->ip6r0_addr[total / 2] = in_rthdr0->ip6r0_addr[total / 2];
+ out_rthdr0->ip6r0_segleft = total;
+
return 0;
}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netinet/ip6.h>
+
+static int
+do_test (void)
+{
+ int res = 0;
+ char buf[1000];
+ void *p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 0);
+ if (p == NULL)
+ {
+ puts ("first inet6_rth_init failed");
+ res = 1;
+ }
+ else if (inet6_rth_add (p, &in6addr_any) == 0)
+ {
+ puts ("first inet6_rth_add succeeded");
+ res = 1;
+ }
+
+ p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 1);
+ if (p == NULL)
+ {
+ puts ("second inet6_rth_init failed");
+ res = 1;
+ }
+ else if (inet6_rth_add (p, &in6addr_any) != 0)
+ {
+ puts ("second inet6_rth_add failed");
+ res = 1;
+ }
+
+ for (int nseg = 4; nseg < 6; ++nseg)
+ {
+ printf ("nseg = %d\n", nseg);
+
+ p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg);
+ if (p == NULL)
+ {
+ puts ("third inet6_rth_init failed");
+ res = 1;
+ }
+ else
+ {
+ struct in6_addr tmp;
+ memset (&tmp, '\0', sizeof (tmp));
+
+ for (int i = 0; i < nseg; ++i)
+ {
+ tmp.s6_addr[0] = i;
+ if (inet6_rth_add (p, &tmp) != 0)
+ {
+ printf ("call %d of third inet6_rth_add failed\n", i + 1);
+ res = 1;
+ goto out;
+ }
+ }
+ ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0;
+ if (inet6_rth_segments (p) != nseg)
+ {
+ puts ("\
+inet6_rth_segments returned wrong value after loop with third inet6_rth_add");
+ res = 1;
+ goto out;
+ }
+
+ char buf2[1000];
+ if (inet6_rth_reverse (p, buf2) != 0)
+ {
+ puts ("first inet6_rth_reverse call failed");
+ res = 1;
+ goto out;
+ }
+ if (((struct ip6_rthdr0 *) buf2)->ip6r0_segleft != nseg)
+ {
+ puts ("segleft after first inet6_rth_reverse wrong");
+ res = 1;
+ }
+
+ if (inet6_rth_segments (p) != inet6_rth_segments (buf2))
+ {
+ puts ("number of seconds after first inet6_rth_reverse differs");
+ res = 1;
+ goto out;
+ }
+
+ for (int i = 0; i < nseg; ++i)
+ {
+ struct in6_addr *addr = inet6_rth_getaddr (buf2, i);
+ if (addr == NULL)
+ {
+ printf ("call %d of first inet6_rth_getaddr failed\n",
+ i + 1);
+ res = 1;
+ }
+ else if (addr->s6_addr[0] != nseg - 1 - i
+ || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1],
+ sizeof (in6addr_any)
+ - sizeof (in6addr_any.s6_addr[0])) != 0)
+ {
+ char addrbuf[100];
+ inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf));
+ printf ("\
+address %d after first inet6_rth_reverse wrong (%s)\n",
+ i + 1, addrbuf);
+ res = 1;
+ }
+ }
+ out:
+ ;
+ }
+
+ p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg);
+ if (p == NULL)
+ {
+ puts ("fourth inet6_rth_init failed");
+ res = 1;
+ }
+ else
+ {
+ struct in6_addr tmp;
+ memset (&tmp, '\0', sizeof (tmp));
+
+ for (int i = 0; i < nseg; ++i)
+ {
+ tmp.s6_addr[0] = i;
+ if (inet6_rth_add (p, &tmp) != 0)
+ {
+ printf ("call %d of fourth inet6_rth_add failed\n", i + 1);
+ res = 1;
+ goto out2;
+ }
+ }
+ ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0;
+ if (inet6_rth_segments (p) != nseg)
+ {
+ puts ("\
+inet6_rth_segments returned wrong value after loop with fourth inet6_rth_add");
+ res = 1;
+ goto out2;
+ }
+
+ if (inet6_rth_reverse (p, p) != 0)
+ {
+ puts ("second inet6_rth_reverse call failed");
+ res = 1;
+ goto out2;
+ }
+ if (((struct ip6_rthdr0 *) p)->ip6r0_segleft != nseg)
+ {
+ puts ("segleft after second inet6_rth_reverse wrong");
+ res = 1;
+ }
+
+ for (int i = 0; i < nseg; ++i)
+ {
+ struct in6_addr *addr = inet6_rth_getaddr (p, i);
+ if (addr == NULL)
+ {
+ printf ("call %d of second inet6_rth_getaddr failed\n",
+ i + 1);
+ res = 1;
+ }
+ else if (addr->s6_addr[0] != nseg - 1 - i
+ || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1],
+ sizeof (in6addr_any)
+ - sizeof (in6addr_any.s6_addr[0])) != 0)
+ {
+ char addrbuf[100];
+ inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf));
+ printf ("\
+address %d after second inet6_rth_reverse wrong (%s)\n",
+ i + 1, addrbuf);
+ res = 1;
+ }
+ }
+ out2:
+ ;
+ }
+ }
+
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
DEFINE_LANGUAGE_CODE3 ("Mende", men, men)
DEFINE_LANGUAGE_CODE3 ("Mi'kmaq; Micmac", mic, mic)
DEFINE_LANGUAGE_CODE3 ("Minangkabau", min, min)
+DEFINE_LANGUAGE_CODE3 ("Min Nan", nan, nan)
DEFINE_LANGUAGE_CODE3 ("Mirandese", mwl, mwl)
DEFINE_LANGUAGE_CODE3 ("Miscellaneous languages", mis, mis)
DEFINE_LANGUAGE_CODE3 ("Mohawk", moh, moh)
+2009-03-15 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #9844]
+ * locales/iso14651_t1_common: Move U0138 entry.
+
+ [BZ #9833]
+ * locales/ko_KR: Fix noexpr. Add nostr.
+
+ [BZ #9891]
+ * locales/mt_MT: Fix spelling of August (Awwissu).
+ Patch by Martin Pitt.
+
+2009-03-14 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #9916]
+ * SUPPORTED (SUPPORTED-LOCALES): Add nan_TW@latin.
+ * locales/nan_TW@latin: New file.
+ Contributed by Arne Goetje.
+
2009-02-11 Ulrich Drepper <drepper@redhat.com>
* locales/iso14651_t1_common: Add rules for sorting Malayalam.
ms_MY/ISO-8859-1 \
mt_MT.UTF-8/UTF-8 \
mt_MT/ISO-8859-3 \
+nan_TW@latin/UTF-8 \
nb_NO.UTF-8/UTF-8 \
nb_NO/ISO-8859-1 \
nds_DE/UTF-8 \
# mlvw- denotes Malayalam vowel
# ml-visarga - dentos Malayalam Visarga
# consonant + virama is considered half of consonant or consonant without vowel part
-# so it consonant + virama should be considered as cluster and should be
+# so it consonant + virama should be considered as cluster and should be
# sorted before the consonant. All consonants are considered to have an implicit a vowel
# part associated with it.
collating-element <ml-chillu-n> from "<U0D28><U0D4D>"
<U1E33> <k>;<BPT>;<MIN>;IGNORE # 337 ḳ
<U1E35> <k>;<BMA>;<MIN>;IGNORE # 338 ḵ
<U0199> <k>;<CRL>;<MIN>;IGNORE # 339 ƙ
-<U0138> <k>;<PCL>;<MIN>;IGNORE # 340 <kk>
<U006C> <l>;<BAS>;<MIN>;IGNORE # 341 l
<U013A> <l>;<ACA>;<MIN>;IGNORE # 342 <l'>
<U013E> <l>;<CAR>;<MIN>;IGNORE # 343 <l<>
<U1E55> <p>;<ACA>;<MIN>;IGNORE # 411 <p'>
<U1E57> <p>;<PCT>;<MIN>;IGNORE # 412 <p.>
<U0071> <q>;<BAS>;<MIN>;IGNORE # 413 q
+<U0138> <q>;<PCL>;<MIN>;IGNORE # 340 <kk>
<U0072> <r>;<BAS>;<MIN>;IGNORE # 414 r
<U0155> <r>;<ACA>;<MIN>;IGNORE # 415 <r'>
<U0159> <r>;<CAR>;<MIN>;IGNORE # 416 <r<>
<ml-dh> "<ml-dha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D22> "<ml-dha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-nn> "<ml-nna><ml-virama>";<BAS>;<MIN>;IGNORE # ണ് = ണ + ് + zwj
-<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ണ = ണ + ് + അ
+<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ണ = ണ + ് + അ
<ml-th> "<ml-tha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D24> "<ml-tha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-thh> "<ml-thha><ml-virama>";<BAS>;<MIN>;IGNORE
<ml-bh> "<ml-bha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D2D> "<ml-bha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<U0D02> "<ml-ma><ml-virama>";<BAS>;<MIN>;IGNORE # ം = മ + ്
-<ml-m> "<ml-ma><ml-virama>";"<BAS><ml-virama>";<MIN>;IGNORE # ം = മ + ്
-<U0D2E> "<ml-ma><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # മ = മ + ് + അ
+<ml-m> "<ml-ma><ml-virama>";"<BAS><ml-virama>";<MIN>;IGNORE # ം = മ + ്
+<U0D2E> "<ml-ma><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # മ = മ + ് + അ
<ml-y> "<ml-ya><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D2F> "<ml-ya><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-r> "<ml-ra><ml-virama>";<BAS>;<MIN>;IGNORE # ര = ര + ് + zwj
-<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ര = ര + ് + അ
+<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ര = ര + ് + അ
<ml-chillu-l> <ml-la>;<BAS>;<MIN>;IGNORE # ല് = ല + ് + zwj
-<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ല = ല + ് + അ
+<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ല = ല + ് + അ
<ml-v> "<ml-va><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D35> "<ml-va><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-ss> "<ml-ssa><ml-virama>";<BAS>;<MIN>;IGNORE
<ml-h> "<ml-ha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D39> "<ml-ha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-ll> "<ml-lla><ml-virama>";<BAS>;<MIN>;IGNORE # ള് = ള + ് + zwj
-<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ള = ള + ് + അ
+<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ള = ള + ് + അ
<ml-zh> "<ml-zha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D34> "<ml-zha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-rr> "<ml-rra><ml-virama>";<BAS>;<MIN>;IGNORE
yesexpr "<U005E><U005B><U0079><U0059><UC608><U005D>"
-noexpr "<U005E><U005B><U006E><U004E><UC544><UB2C8><UC624><U005D>"
+noexpr "<U005E><U005B><U006E><U004E><UC544><U005D>"
+
+nostr "<UC544><UB2C8><UC624>"
END LC_MESSAGES
abmon "<U004A><U0061><U006E>";"<U0046><U0072><U0061>";/
"<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
"<U004D><U0065><U006A>";"<U0120><U0075><U006E>";/
- "<U004C><U0075><U006C>";"<U0041><U0077><U0069>";/
+ "<U004C><U0075><U006C>";"<U0041><U0077><U0077>";/
"<U0053><U0065><U0074>";"<U004F><U0074><U0074>";/
"<U004E><U006F><U0076>";"<U0044><U0069><U010B>"
%
"<U004D><U0065><U006A><U006A><U0075>";/
"<U0120><U0075><U006E><U006A><U0075>";/
"<U004C><U0075><U006C><U006A><U0075>";/
- "<U0041><U0077><U0069><U0073><U0073><U0075>";/
+ "<U0041><U0077><U0077><U0069><U0073><U0073><U0075>";/
"<U0053><U0065><U0074><U0074><U0065><U006D><U0062><U0072><U0075>";/
"<U004F><U0074><U0074><U0075><U0062><U0072><U0075>";/
"<U004E><U006F><U0076><U0065><U006D><U0062><U0072><U0075>";/
--- /dev/null
+comment_char %
+escape_char /
+%
+% Minnan Language Locale for Taiwan
+% Source:
+% Contact: Arne Goetje
+% Email: arne@ubuntu.com
+% Language: nan
+% Territory: TW
+% Revision: 0.1
+% Date: 2008-06-16
+% Users: general
+% Charset: UTF-8
+% Distribution and use is free, also
+% for commercial purposes.
+
+LC_IDENTIFICATION
+title "Minnan language locale for Taiwan"
+source ""
+address ""
+contact "Arne Goetje"
+email "arne@canonical.com"
+tel ""
+fax ""
+language "Minnan"
+territory "Taiwan"
+revision "0.1"
+date "2008-06-16"
+
+category "nan_TW@latin:2000";LC_IDENTIFICATION
+category "nan_TW@latin:2000";LC_CTYPE
+category "nan_TW@latin:2000";LC_COLLATE
+category "nan_TW@latin:2000";LC_TIME
+category "nan_TW@latin:2000";LC_NUMERIC
+category "nan_TW@latin:2000";LC_PAPER
+category "nan_TW@latin:2000";LC_TELEPHONE
+category "nan_TW@latin:2000";LC_MEASUREMENT
+category "nan_TW@latin:2000";LC_ADDRESS
+category "nan_TW@latin:2000";LC_MESSAGES
+category "nan_TW@latin:2000";LC_MONETARY
+
+END LC_IDENTIFICATION
+
+LC_CTYPE
+copy "i18n"
+
+translit_start
+
+% accents are simply omitted if they cannot be represented.
+include "translit_combining";""
+
+translit_end
+
+END LC_CTYPE
+
+LC_COLLATE
+copy "iso14651_t1"
+
+%% a b c d e f g h i j k l m n o o͘ p q r s t u v w x y z ⁿ
+
+collating-element <oo> from "<U006F><U0358>"
+collating-element <OO> from "<U004F><U0358>"
+collating-element <nn> from "<U207F>"
+
+collating-symbol <CAP-MIN>
+collating-symbol <MIN-CAP>
+
+reorder-after <MIN>
+<MIN-CAP>
+reorder-after <CAP>
+<CAP-MIN>
+
+reorder-after <U006E>
+<oo>
+reorder-after <U004E>
+<OO>
+reorder-after <U007A>
+<nn>
+reorder-after <U005A>
+<nn>
+
+reorder-end
+
+END LC_COLLATE
+
+LC_MONETARY
+copy "zh_TW"
+END LC_MONETARY
+
+LC_NUMERIC
+copy "zh_TW"
+END LC_NUMERIC
+
+LC_TIME
+abday "<U006C><U0070>";/
+ "<U0070><U0031>";/
+ "<U0070><U0032>";/
+ "<U0070><U0033>";/
+ "<U0070><U0034>";/
+ "<U0070><U0035>";/
+ "<U0070><U0036>"
+day "<U006C><U00E9><U002D><U0070><U00E0><U0069><U002D><U006A><U0069><U030D><U0074>";/
+ "<U0070><U00E0><U0069><U002D><U0069><U0074>";/
+ "<U0070><U00E0><U0069><U002D><U006A><U012B>";/
+ "<U0070><U00E0><U0069><U002D><U0073><U0061><U207F>";/
+ "<U0070><U00E0><U0069><U002D><U0073><U00EC>";/
+ "<U0070><U00E0><U0069><U002D><U0067><U014D><U0358>";/
+ "<U0070><U00E0><U0069><U002D><U006C><U0061><U030D><U006B>"
+abmon "<U0031><U0067>";/
+ "<U0032><U0067>";/
+ "<U0033><U0067>";/
+ "<U0034><U0067>";/
+ "<U0035><U0067>";/
+ "<U0036><U0067>";/
+ "<U0037><U0067>";/
+ "<U0038><U0067>";/
+ "<U0039><U0067>";/
+ "<U0031><U0030><U0067>";/
+ "<U0031><U0031><U0067>";/
+ "<U0031><U0032><U0067>"
+mon "<U0031><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0032><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0033><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0034><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0035><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0036><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0037><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0038><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0039><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0031><U0030><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0031><U0031><U0067><U006F><U0065><U030D><U0068>";/
+ "<U0031><U0032><U0067><U006F><U0065><U030D><U0068>"
+%
+d_t_fmt "<U0025><U0059><U0020><U0025><U0062><U0020><U0025><U0064><U0020><U0028><U0025><U0061><U0029><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
+d_fmt "<U0025><U0046>"
+t_fmt "<U0025><U0072>"
+am_pm "<U0074><U00E9><U006E><U0067><U002D><U0070><U006F><U0358>";"<U0113><U002D><U0070><U006F><U0358>"
+t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>"
+timezone "<U0054><U0053><U0054><U002D><U0038>"
+date_fmt "<U0025><U0059><U0020><U0025><U0062><U0020><U0025><U0064><U0020><U0028><U0025><U0061><U0029><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
+END LC_TIME
+
+LC_MESSAGES
+
+% "^[sS].*" for "Yes"
+yesexpr "<U005E><U005B><U0073><U0053><U005D><U002E><U002A>"
+
+% "^[mM].*" for "No"
+noexpr "<U005E><U005B><U006D><U004D><U005D><U002E><U002A>"
+
+% "Sī" for "Yes"
+yesstr "<U0053><U012B>"
+
+% "M̄-sī" for "No"
+nostr "<U004D><U0304><U002D><U0053><U012B>"
+
+END LC_MESSAGES
+
+LC_PAPER
+height 297
+width 210
+END LC_PAPER
+
+LC_MEASUREMENT
+measurement 1
+END LC_MEASUREMENT
+
+LC_NAME
+%FIXME
+name_fmt "<U0025><U0064><U0025><U0074><U0025><U0067><U0025><U0074>/
+<U0025><U006D><U0025><U0074><U0025><U0066>"
+name_miss "<U006B><U006F><U0358><U002D><U006E><U0069><U00FB>"
+name_mr "<U0073><U0069><U0061><U006E><U002D><U0073><U0069><U207F>"
+name_mrs "<U006C><U00FA><U002D><U0073><U016B>"
+name_ms "<U0073><U0069><U00F3><U002D><U0063><U0068><U0069><U00E1>"
+END LC_NAME
+
+LC_ADDRESS
+% postal_fmt: "%f%N%a%N%d%N%b%N%r %e %h %s%N%z %T%N%c%N"
+postal_fmt "<U0025><U0066><U0025><U004E><U0025><U0061><U0025><U004E>/
+<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0072>/
+<U0020><U0025><U0065><U0020><U0025><U0068><U0020><U0025><U0073><U0025>/
+<U004E><U0025><U007A><U0020><U0025><U0054><U0025>/
+<U004E><U0025><U0063><U0025><U004E>"
+% Reference: http://www.un.org/Depts/unsd/methods/m49alpha.htm
+% http://www.isbn.spk-berlin.de/html/prefix.htm
+% country_ab2: TW
+% country_ab3: TWN
+% country_isbn: 957
+country_name "<U0054><U00E2><U0069><U002D><U006F><U00E2><U006E>"
+%country_post "FIXME"
+country_ab2 "<U0054><U0057>"
+country_ab3 "<U0054><U0057><U004E>"
+country_num 158
+%country_car "FIXME"
+country_isbn "<U0039><U0035><U0037>"
+%lang_name "Bân-lâm-gú, Hō-ló-oē"
+lang_name "<U0042><U00E2><U006E><U002D><U006C><U00E2><U006D><U002D><U0067><U00FA><U002C><U0020><U0048><U014D><U002D><U006C><U00F3><U002D><U006F><U0113>"
+lang_term "<U006E><U0061><U006E>"
+lang_lib "<U006E><U0061><U006E>"
+END LC_ADDRESS
+
+LC_TELEPHONE
+copy "zh_TW"
+END LC_TELEPHONE
-# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007
+# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2009
# Free Software Foundation, Inc.
# This file is part of the GNU C Library.
tst-mcheck-ENV = MALLOC_CHECK_=3
+ifeq ($(experimental-malloc),yes)
+CPPFLAGS-malloc.c += -DPER_THREAD -DATOMIC_FASTBINS
+endif
# Uncomment this for test releases. For public releases it is too expensive.
#CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1
/* Malloc implementation for multiple threads without lock contention.
- Copyright (C) 2001,2002,2003,2004,2005,2006,2007
+ Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2009
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
static tsd_key_t arena_key;
static mutex_t list_lock;
+#ifdef PER_THREAD
+static size_t narenas;
+static mstate free_list;
+#endif
#if THREAD_STATS
static int stat_n_heaps;
in the new arena. */
#define arena_get(ptr, size) do { \
+ arena_lookup(ptr); \
+ arena_lock(ptr, size); \
+} while(0)
+
+#define arena_lookup(ptr) do { \
Void_t *vptr = NULL; \
ptr = (mstate)tsd_getspecific(arena_key, vptr); \
+} while(0)
+
+#ifdef PER_THREAD
+#define arena_lock(ptr, size) do { \
+ if(ptr) \
+ (void)mutex_lock(&ptr->mutex); \
+ else \
+ ptr = arena_get2(ptr, (size)); \
+} while(0)
+#else
+#define arena_lock(ptr, size) do { \
if(ptr && !mutex_trylock(&ptr->mutex)) { \
THREAD_STAT(++(ptr->stat_lock_direct)); \
} else \
ptr = arena_get2(ptr, (size)); \
} while(0)
+#endif
/* find the heap and corresponding arena for a given ptr */
}
#endif
+#ifdef ATOMIC_FASTBINS
+ ar_ptr = arena_for_chunk(p);
+ tsd_getspecific(arena_key, vptr);
+ _int_free(ar_ptr, p, vptr == ATFORK_ARENA_PTR);
+#else
ar_ptr = arena_for_chunk(p);
tsd_getspecific(arena_key, vptr);
if(vptr != ATFORK_ARENA_PTR)
_int_free(ar_ptr, p);
if(vptr != ATFORK_ARENA_PTR)
(void)mutex_unlock(&ar_ptr->mutex);
+#endif
}
tsd_setspecific(arena_key, save_arena);
__malloc_hook = save_malloc_hook;
__free_hook = save_free_hook;
+#endif
+#ifdef PER_THREAD
+ free_list = NULL;
#endif
for(ar_ptr = &main_arena;;) {
mutex_init(&ar_ptr->mutex);
+#ifdef PER_THREAD
+ if (ar_ptr != save_arena) {
+ ar_ptr->next_free = free_list;
+ free_list = ar_ptr;
+ }
+#endif
ar_ptr = ar_ptr->next;
if(ar_ptr == &main_arena) break;
}
mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD;
mp_.pagesize = malloc_getpagesize;
+#ifdef PER_THREAD
+# define NARENAS_FROM_NCORES(n) ((n) * (sizeof(long) == 4 ? 2 : 8))
+ mp_.arena_test = NARENAS_FROM_NCORES (1);
+ narenas = 1;
+#endif
}
}
break;
case 9:
- if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0)
- mALLOPt(M_MMAP_MAX, atoi(&envline[10]));
+ if (! secure)
+ {
+ if (memcmp (envline, "MMAP_MAX_", 9) == 0)
+ mALLOPt(M_MMAP_MAX, atoi(&envline[10]));
+#ifdef PER_THREAD
+ else if (memcmp (envline, "ARENA_MAX", 9) == 0)
+ mALLOPt(M_ARENA_MAX, atoi(&envline[10]));
+#endif
+ }
break;
+#ifdef PER_THREAD
+ case 10:
+ if (! secure)
+ {
+ if (memcmp (envline, "ARENA_TEST", 10) == 0)
+ mALLOPt(M_ARENA_TEST, atoi(&envline[11]));
+ }
+ break;
+#endif
case 15:
if (! secure)
{
top(a) = (mchunkptr)ptr;
set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE);
+ tsd_setspecific(arena_key, (Void_t *)a);
+ mutex_init(&a->mutex);
+ (void)mutex_lock(&a->mutex);
+
+#ifdef PER_THREAD
+ (void)mutex_lock(&list_lock);
+#endif
+
+ /* Add the new arena to the global list. */
+ a->next = main_arena.next;
+ atomic_write_barrier ();
+ main_arena.next = a;
+
+#ifdef PER_THREAD
+ ++narenas;
+
+ (void)mutex_unlock(&list_lock);
+#endif
+
+ THREAD_STAT(++(a->stat_lock_loop));
+
return a;
}
+
+#ifdef PER_THREAD
+static mstate
+get_free_list (void)
+{
+ mstate result = free_list;
+ if (result != NULL)
+ {
+ (void)mutex_lock(&list_lock);
+ result = free_list;
+ if (result != NULL)
+ free_list = result->next_free;
+ (void)mutex_unlock(&list_lock);
+
+ if (result != NULL)
+ {
+ (void)mutex_lock(&result->mutex);
+ tsd_setspecific(arena_key, (Void_t *)result);
+ THREAD_STAT(++(result->stat_lock_loop));
+ }
+ }
+
+ return result;
+}
+
+
+static mstate
+reused_arena (void)
+{
+ if (narenas <= mp_.arena_test)
+ return NULL;
+
+ static int narenas_limit;
+ if (narenas_limit == 0)
+ {
+ if (mp_.arena_max != 0)
+ narenas_limit = mp_.arena_max;
+ else
+ {
+ int n = __get_nprocs ();
+
+ if (n >= 1)
+ narenas_limit = NARENAS_FROM_NCORES (n);
+ else
+ /* We have no information about the system. Assume two
+ cores. */
+ narenas_limit = NARENAS_FROM_NCORES (2);
+ }
+ }
+
+ if (narenas < narenas_limit)
+ return NULL;
+
+ mstate result;
+ static mstate next_to_use;
+ if (next_to_use == NULL)
+ next_to_use = &main_arena;
+
+ result = next_to_use;
+ do
+ {
+ if (!mutex_trylock(&result->mutex))
+ goto out;
+
+ result = result->next;
+ }
+ while (result != next_to_use);
+
+ /* No arena available. Wait for the next in line. */
+ (void)mutex_lock(&result->mutex);
+
+ out:
+ tsd_setspecific(arena_key, (Void_t *)result);
+ THREAD_STAT(++(result->stat_lock_loop));
+ next_to_use = result->next;
+
+ return result;
+}
+#endif
+
static mstate
internal_function
#if __STD_C
{
mstate a;
+#ifdef PER_THREAD
+ if ((a = get_free_list ()) == NULL
+ && (a = reused_arena ()) == NULL)
+ /* Nothing immediately available, so generate a new arena. */
+ a = _int_new_arena(size);
+#else
if(!a_tsd)
a = a_tsd = &main_arena;
else {
/* Nothing immediately available, so generate a new arena. */
a = _int_new_arena(size);
- if(a)
- {
- tsd_setspecific(arena_key, (Void_t *)a);
- mutex_init(&a->mutex);
- mutex_lock(&a->mutex); /* remember result */
-
- /* Add the new arena to the global list. */
- a->next = main_arena.next;
- atomic_write_barrier ();
- main_arena.next = a;
-
- THREAD_STAT(++(a->stat_lock_loop));
- }
(void)mutex_unlock(&list_lock);
+#endif
return a;
}
+#ifdef PER_THREAD
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
+arena_thread_freeres (void)
+{
+ Void_t *vptr = NULL;
+ mstate a = tsd_getspecific(arena_key, vptr);
+ tsd_setspecific(arena_key, NULL);
+
+ if (a != NULL)
+ {
+ (void)mutex_lock(&list_lock);
+ a->next_free = free_list;
+ free_list = a;
+ (void)mutex_unlock(&list_lock);
+ }
+}
+text_set_element (__libc_thread_subfreeres, arena_thread_freeres);
+#endif
+
#endif /* USE_ARENAS */
/*
mchunkptr p;
if(!mem) return;
- (void)mutex_lock(&main_arena.mutex);
p = mem2chunk_check(mem, NULL);
if(!p) {
- (void)mutex_unlock(&main_arena.mutex);
-
malloc_printerr(check_action, "free(): invalid pointer", mem);
return;
}
#if HAVE_MMAP
if (chunk_is_mmapped(p)) {
- (void)mutex_unlock(&main_arena.mutex);
munmap_chunk(p);
return;
}
#if 0 /* Erase freed memory. */
memset(mem, 0, chunksize(p) - (SIZE_SZ+1));
#endif
+#ifdef ATOMIC_FASTBINS
+ _int_free(&main_arena, p, 0);
+#else
+ (void)mutex_lock(&main_arena.mutex);
_int_free(&main_arena, p);
(void)mutex_unlock(&main_arena.mutex);
+#endif
}
static Void_t*
return;
}
#endif
+#ifdef ATOMIC_FASTBINS
+ _int_free(&main_arena, p, 1);
+#else
_int_free(&main_arena, p);
+#endif
}
# endif /* !defiend NO_STARTER */
clear_fastchunks(&main_arena);
set_max_fast(DEFAULT_MXFAST);
for (i=0; i<NFASTBINS; ++i)
- main_arena.fastbins[i] = 0;
+ fastbin (&main_arena, i) = 0;
for (i=0; i<BINMAPSIZE; ++i)
main_arena.binmap[i] = 0;
top(&main_arena) = ms->av[2];
Tuning options that are also dynamically changeable via mallopt:
- DEFAULT_MXFAST 64
+ DEFAULT_MXFAST 64 (for 32bit), 128 (for 64bit)
DEFAULT_TRIM_THRESHOLD 128 * 1024
DEFAULT_TOP_PAD 0
DEFAULT_MMAP_THRESHOLD 128 * 1024
#include <malloc-machine.h>
#ifdef _LIBC
+#ifdef ATOMIC_FASTBINS
+#include <atomic.h>
+#endif
#include <stdio-common/_itoa.h>
#include <bits/wordsize.h>
+#include <sys/sysinfo.h>
#endif
#ifdef __cplusplus
or other mallocs available that do this.
*/
-#if MALLOC_DEBUG
#include <assert.h>
-#else
-#undef assert
-#define assert(x) ((void)0)
-#endif
/*
#endif
#ifndef DEFAULT_MXFAST
-#define DEFAULT_MXFAST 64
+#define DEFAULT_MXFAST (64 * SIZE_SZ / 4)
#endif
#if __STD_C
static Void_t* _int_malloc(mstate, size_t);
+#ifdef ATOMIC_FASTBINS
+static void _int_free(mstate, mchunkptr, int);
+#else
static void _int_free(mstate, mchunkptr);
+#endif
static Void_t* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T);
static Void_t* _int_memalign(mstate, size_t, size_t);
static Void_t* _int_valloc(mstate, size_t);
*/
typedef struct malloc_chunk* mfastbinptr;
+#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */
-#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2)
+#define fastbin_index(sz) \
+ ((((unsigned int)(sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
+
/* The maximum fastbin request size we support */
-#define MAX_FAST_SIZE 80
+#define MAX_FAST_SIZE (80 * SIZE_SZ / 4)
#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1)
#define FASTCHUNKS_BIT (1U)
#define have_fastchunks(M) (((M)->flags & FASTCHUNKS_BIT) == 0)
+#ifdef ATOMIC_FASTBINS
+#define clear_fastchunks(M) catomic_or (&(M)->flags, FASTCHUNKS_BIT)
+#define set_fastchunks(M) catomic_and (&(M)->flags, ~FASTCHUNKS_BIT)
+#else
#define clear_fastchunks(M) ((M)->flags |= FASTCHUNKS_BIT)
#define set_fastchunks(M) ((M)->flags &= ~FASTCHUNKS_BIT)
+#endif
/*
NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous
#endif
/* Fastbins */
- mfastbinptr fastbins[NFASTBINS];
+ mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* Linked list */
struct malloc_state *next;
+#ifdef PER_THREAD
+ /* Linked list for free arenas. */
+ struct malloc_state *next_free;
+#endif
+
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
unsigned long trim_threshold;
INTERNAL_SIZE_T top_pad;
INTERNAL_SIZE_T mmap_threshold;
+#ifdef PER_THREAD
+ INTERNAL_SIZE_T arena_test;
+ INTERNAL_SIZE_T arena_max;
+#endif
/* Memory map support */
int n_mmaps;
static struct malloc_par mp_;
+#ifdef PER_THREAD
+/* Non public mallopt parameters. */
+#define M_ARENA_TEST -7
+#define M_ARENA_MAX -8
+#endif
+
+
/* Maximum size of memory handled in fastbins. */
static INTERNAL_SIZE_T global_max_fast;
/* Precondition: not enough current space to satisfy nb request */
assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE));
+#ifndef ATOMIC_FASTBINS
/* Precondition: all fastbins are consolidated */
assert(!have_fastchunks(av));
+#endif
if (av != &main_arena) {
set_head(chunk_at_offset(old_top, old_size), (2*SIZE_SZ)|PREV_INUSE);
set_foot(chunk_at_offset(old_top, old_size), (2*SIZE_SZ));
set_head(old_top, old_size|PREV_INUSE|NON_MAIN_ARENA);
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, old_top, 1);
+#else
_int_free(av, old_top);
+#endif
} else {
set_head(old_top, (old_size + 2*SIZE_SZ)|PREV_INUSE);
set_foot(old_top, (old_size + 2*SIZE_SZ));
/* If possible, release the rest. */
if (old_size >= MINSIZE) {
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, old_top, 1);
+#else
_int_free(av, old_top);
+#endif
}
}
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0));
- arena_get(ar_ptr, bytes);
+ arena_lookup(ar_ptr);
+#if 0
+ // XXX We need double-word CAS and fastbins must be extended to also
+ // XXX hold a generation counter for each entry.
+ if (ar_ptr) {
+ INTERNAL_SIZE_T nb; /* normalized request size */
+ checked_request2size(bytes, nb);
+ if (nb <= get_max_fast ()) {
+ long int idx = fastbin_index(nb);
+ mfastbinptr* fb = &fastbin (ar_ptr, idx);
+ mchunkptr pp = *fb;
+ mchunkptr v;
+ do
+ {
+ v = pp;
+ if (v == NULL)
+ break;
+ }
+ while ((pp = catomic_compare_and_exchange_val_acq (fb, v->fd, v)) != v);
+ if (v != 0) {
+ if (__builtin_expect (fastbin_index (chunksize (v)) != idx, 0))
+ malloc_printerr (check_action, "malloc(): memory corruption (fast)",
+ chunk2mem (v));
+ check_remalloced_chunk(ar_ptr, v, nb);
+ void *p = chunk2mem(v);
+ if (__builtin_expect (perturb_byte, 0))
+ alloc_perturb (p, bytes);
+ return p;
+ }
+ }
+ }
+#endif
+
+ arena_lock(ar_ptr, bytes);
if(!ar_ptr)
return 0;
victim = _int_malloc(ar_ptr, bytes);
#endif
ar_ptr = arena_for_chunk(p);
-#if THREAD_STATS
+#ifdef ATOMIC_FASTBINS
+ _int_free(ar_ptr, p, 0);
+#else
+# if THREAD_STATS
if(!mutex_trylock(&ar_ptr->mutex))
++(ar_ptr->stat_lock_direct);
else {
(void)mutex_lock(&ar_ptr->mutex);
++(ar_ptr->stat_lock_wait);
}
-#else
+# else
(void)mutex_lock(&ar_ptr->mutex);
-#endif
+# endif
_int_free(ar_ptr, p);
(void)mutex_unlock(&ar_ptr->mutex);
+#endif
}
#ifdef libc_hidden_def
libc_hidden_def (public_fREe)
(void)mutex_lock(&ar_ptr->mutex);
#endif
-#ifndef NO_THREADS
+#if !defined NO_THREADS && !defined PER_THREAD
/* As in malloc(), remember this arena for the next allocation. */
tsd_setspecific(arena_key, (Void_t *)ar_ptr);
#endif
if (newp != NULL)
{
MALLOC_COPY (newp, oldmem, oldsize - SIZE_SZ);
-#if THREAD_STATS
+#ifdef ATOMIC_FASTBINS
+ _int_free(ar_ptr, oldp, 0);
+#else
+# if THREAD_STATS
if(!mutex_trylock(&ar_ptr->mutex))
++(ar_ptr->stat_lock_direct);
else {
(void)mutex_lock(&ar_ptr->mutex);
++(ar_ptr->stat_lock_wait);
}
-#else
+# else
(void)mutex_lock(&ar_ptr->mutex);
-#endif
+# endif
_int_free(ar_ptr, oldp);
(void)mutex_unlock(&ar_ptr->mutex);
+#endif
}
}
INTERNAL_SIZE_T nb; /* normalized request size */
unsigned int idx; /* associated bin index */
mbinptr bin; /* associated bin */
- mfastbinptr* fb; /* associated fastbin */
mchunkptr victim; /* inspected/selected chunk */
INTERNAL_SIZE_T size; /* its size */
*/
if ((unsigned long)(nb) <= (unsigned long)(get_max_fast ())) {
- long int idx = fastbin_index(nb);
- fb = &(av->fastbins[idx]);
- if ( (victim = *fb) != 0) {
+ idx = fastbin_index(nb);
+ mfastbinptr* fb = &fastbin (av, idx);
+#ifdef ATOMIC_FASTBINS
+ mchunkptr pp = *fb;
+ do
+ {
+ victim = pp;
+ if (victim == NULL)
+ break;
+ }
+ while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim))
+ != victim);
+#else
+ victim = *fb;
+#endif
+ if (victim != 0) {
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
malloc_printerr (check_action, "malloc(): memory corruption (fast)",
chunk2mem (victim));
+#ifndef ATOMIC_FASTBINS
*fb = victim->fd;
+#endif
check_remalloced_chunk(av, victim, nb);
void *p = chunk2mem(victim);
if (__builtin_expect (perturb_byte, 0))
return p;
}
+#ifdef ATOMIC_FASTBINS
+ /* When we are using atomic ops to free fast chunks we can get
+ here for all block sizes. */
+ else if (have_fastchunks(av)) {
+ malloc_consolidate(av);
+ /* restore original bin index */
+ if (in_smallbin_range(nb))
+ idx = smallbin_index(nb);
+ else
+ idx = largebin_index(nb);
+ }
+#else
/*
If there is space available in fastbins, consolidate and retry,
to possibly avoid expanding memory. This can occur only if nb is
malloc_consolidate(av);
idx = smallbin_index(nb); /* restore original bin index */
}
+#endif
/*
Otherwise, relay to handle system-dependent cases
*/
static void
+#ifdef ATOMIC_FASTBINS
+_int_free(mstate av, mchunkptr p, int have_lock)
+#else
_int_free(mstate av, mchunkptr p)
+#endif
{
INTERNAL_SIZE_T size; /* its size */
mfastbinptr* fb; /* associated fastbin */
mchunkptr fwd; /* misc temp for linking */
const char *errstr = NULL;
+#ifdef ATOMIC_FASTBINS
+ int locked = 0;
+#endif
size = chunksize(p);
{
errstr = "free(): invalid pointer";
errout:
+#ifdef ATOMIC_FASTBINS
+ if (! have_lock && locked)
+ (void)mutex_unlock(&av->mutex);
+#endif
malloc_printerr (check_action, errstr, chunk2mem(p));
return;
}
goto errout;
}
+ if (__builtin_expect (perturb_byte, 0))
+ free_perturb (chunk2mem(p), size - SIZE_SZ);
+
set_fastchunks(av);
- fb = &(av->fastbins[fastbin_index(size)]);
+ fb = &fastbin (av, fastbin_index(size));
+
+#ifdef ATOMIC_FASTBINS
+ mchunkptr fd;
+ mchunkptr old = *fb;
+ do
+ {
+ /* Another simple check: make sure the top of the bin is not the
+ record we are going to add (i.e., double free). */
+ if (__builtin_expect (old == p, 0))
+ {
+ errstr = "double free or corruption (fasttop)";
+ goto errout;
+ }
+ p->fd = fd = old;
+ }
+ while ((old = catomic_compare_and_exchange_val_acq (fb, p, fd)) != fd);
+#else
/* Another simple check: make sure the top of the bin is not the
record we are going to add (i.e., double free). */
if (__builtin_expect (*fb == p, 0))
goto errout;
}
- if (__builtin_expect (perturb_byte, 0))
- free_perturb (chunk2mem(p), size - SIZE_SZ);
-
p->fd = *fb;
*fb = p;
+#endif
}
/*
*/
else if (!chunk_is_mmapped(p)) {
+#ifdef ATOMIC_FASTBINS
+ if (! have_lock) {
+# if THREAD_STATS
+ if(!mutex_trylock(&av->mutex))
+ ++(av->stat_lock_direct);
+ else {
+ (void)mutex_lock(&av->mutex);
+ ++(av->stat_lock_wait);
+ }
+# else
+ (void)mutex_lock(&av->mutex);
+# endif
+ locked = 1;
+ }
+#endif
+
nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the
}
}
+#ifdef ATOMIC_FASTBINS
+ if (! have_lock) {
+ assert (locked);
+ (void)mutex_unlock(&av->mutex);
+ }
+#endif
}
/*
If the chunk was allocated via mmap, release via munmap(). Note
because, except for the main arena, all the others might have
blocks in the high fast bins. It's not worth it anyway, just
search all bins all the time. */
- maxfb = &(av->fastbins[fastbin_index(get_max_fast ())]);
+ maxfb = &fastbin (av, fastbin_index(get_max_fast ()));
#else
- maxfb = &(av->fastbins[NFASTBINS - 1]);
+ maxfb = &fastbin (av, NFASTBINS - 1);
#endif
- fb = &(av->fastbins[0]);
+ fb = &fastbin (av, 0);
do {
- if ( (p = *fb) != 0) {
- *fb = 0;
-
+#ifdef ATOMIC_FASTBINS
+ p = atomic_exchange_acq (fb, 0);
+#else
+ p = *fb;
+#endif
+ if (p != 0) {
+#ifndef ATOMIC_FASTBINS
+ *fb = 0;
+#endif
do {
check_inuse_chunk(av, p);
nextp = p->fd;
}
}
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, oldp, 1);
+#else
_int_free(av, oldp);
+#endif
check_inuse_chunk(av, newp);
return chunk2mem(newp);
}
(av != &main_arena ? NON_MAIN_ARENA : 0));
/* Mark remainder as inuse so free() won't complain */
set_inuse_bit_at_offset(remainder, remainder_size);
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, remainder, 1);
+#else
_int_free(av, remainder);
+#endif
}
check_inuse_chunk(av, newp);
newmem = _int_malloc(av, nb - MALLOC_ALIGN_MASK);
if (newmem != 0) {
MALLOC_COPY(newmem, chunk2mem(oldp), oldsize - 2*SIZE_SZ);
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, oldp, 1);
+#else
_int_free(av, oldp);
+#endif
}
}
return newmem;
(av != &main_arena ? NON_MAIN_ARENA : 0));
set_inuse_bit_at_offset(newp, newsize);
set_head_size(p, leadsize | (av != &main_arena ? NON_MAIN_ARENA : 0));
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, p, 1);
+#else
_int_free(av, p);
+#endif
p = newp;
assert (newsize >= nb &&
set_head(remainder, remainder_size | PREV_INUSE |
(av != &main_arena ? NON_MAIN_ARENA : 0));
set_head_size(p, nb);
+#ifdef ATOMIC_FASTBINS
+ _int_free(av, remainder, 1);
+#else
_int_free(av, remainder);
+#endif
}
}
fastavail = 0;
for (i = 0; i < NFASTBINS; ++i) {
- for (p = av->fastbins[i]; p != 0; p = p->fd) {
+ for (p = fastbin (av, i); p != 0; p = p->fd) {
++nfastblocks;
fastavail += chunksize(p);
}
case M_PERTURB:
perturb_byte = value;
break;
+
+#ifdef PER_THREAD
+ case M_ARENA_TEST:
+ if (value > 0)
+ mp_.arena_test = value;
+ break;
+
+ case M_ARENA_MAX:
+ if (value > 0)
+ mp_.arena_max = value;
+ break;
+#endif
}
(void)mutex_unlock(&av->mutex);
return res;
/* Prototypes and definition for malloc implementation.
- Copyright (C) 1996, 1997, 1999, 2000, 2002-2004, 2005, 2007
+ Copyright (C) 1996, 1997, 1999, 2000, 2002-2004, 2005, 2007, 2009
Free Software Foundation, Inc.
This file is part of the GNU C Library.
#define M_MMAP_MAX -4
#define M_CHECK_ACTION -5
#define M_PERTURB -6
+#define M_ARENA_TEST -7
+#define M_ARENA_MAX -8
/* General SVID/XPG interface to tunable parameters. */
extern int mallopt __MALLOC_P ((int __param, int __val));
+2009-03-15 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Change to use cfi directives instead of
+ hand-coded unwind sections.
+
+2009-03-10 Ulrich Drepper <drepper@redhat.com>
+
+ * init.c (nptl_freeres): Compile only for SHARED.
+
2009-03-09 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Define
extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
#endif
+#ifdef SHARED
static void nptl_freeres (void);
-#ifdef SHARED
static const struct pthread_functions pthread_functions =
{
.ptr_pthread_attr_destroy = __pthread_attr_destroy,
#endif
+#ifdef SHARED
/* This function is called indirectly from the freeres code in libc. */
static void
__libc_freeres_fn_section
nptl_freeres (void)
{
-#ifdef SHARED
__unwind_freeres ();
-#endif
__free_stacks (0);
}
+#endif
/* For asynchronous cancellation we use a signal. This is the handler. */
-/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
.type __pthread_cond_timedwait, @function
.align 16
__pthread_cond_timedwait:
-.LSTARTCODE:
+ cfi_startproc
pushq %r12
-.Lpush_r12:
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(%r12, 0)
pushq %r13
-.Lpush_r13:
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(%r13, 0)
pushq %r14
-.Lpush_r14:
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(%r14, 0)
#define FRAME_SIZE 80
subq $FRAME_SIZE, %rsp
-.Lsubq:
+ cfi_adjust_cfa_offset(FRAME_SIZE)
cmpq $1000000000, 8(%rdx)
movl $EINVAL, %eax
cmoveq %r14, %rax
18: addq $FRAME_SIZE, %rsp
-.Laddq:
+ cfi_adjust_cfa_offset(-FRAME_SIZE)
popq %r14
-.Lpop_r14:
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(%r14)
popq %r13
-.Lpop_r13:
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(%r13)
popq %r12
-.Lpop_r12:
+ cfi_adjust_cfa_offset(-8)
+ cfi_restore(%r12)
retq
/* Initial locking failed. */
1:
-.LSbl1:
+ cfi_adjust_cfa_offset(3 * 8 + FRAME_SIZE)
+ cfi_rel_offset(%r12, FRAME_SIZE + 16)
+ cfi_rel_offset(%r13, FRAME_SIZE + 8)
+ cfi_rel_offset(%r14, FRAME_SIZE)
#if cond_lock != 0
addq $cond_lock, %rdi
#endif
js 6b
jmp 21b
#endif
-.LENDCODE:
+ cfi_endproc
.size __pthread_cond_timedwait, .-__pthread_cond_timedwait
versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
GLIBC_2_3_2)
-
-
- .section .eh_frame,"a",@progbits
-.LSTARTFRAME:
- .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
-.LSTARTCIE:
- .long 0 # CIE ID.
- .byte 1 # Version number.
-#ifdef SHARED
- .string "zR" # NUL-terminated augmentation
- # string.
-#else
- .ascii "\0" # NUL-terminated augmentation
- # string.
-#endif
- .uleb128 1 # Code alignment factor.
- .sleb128 -8 # Data alignment factor.
- .byte 16 # Return address register
- # column.
-#ifdef SHARED
- .uleb128 1 # Augmentation value length.
- .byte 0x1b # Encoding: DW_EH_PE_pcrel
- # + DW_EH_PE_sdata4.
-#endif
- .byte 0x0c # DW_CFA_def_cfa
- .uleb128 7
- .uleb128 8
- .byte 0x90 # DW_CFA_offset, column 0x8
- .uleb128 1
- .align 8
-.LENDCIE:
-
- .long .LENDFDE-.LSTARTFDE # Length of the FDE.
-.LSTARTFDE:
- .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
-#ifdef SHARED
- .long .LSTARTCODE-. # PC-relative start address
- # of the code
-#else
- .long .LSTARTCODE # Start address of the code.
-#endif
- .long .LENDCODE-.LSTARTCODE # Length of the code.
-#ifdef SHARED
- .uleb128 0 # No augmentation data.
-#endif
- .byte 0x40+.Lpush_r12-.LSTARTCODE # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 16
- .byte 0x8c # DW_CFA_offset %r12
- .uleb128 2
- .byte 0x40+.Lpush_r13-.Lpush_r12 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 24
- .byte 0x8d # DW_CFA_offset %r13
- .uleb128 3
- .byte 0x40+.Lpush_r14-.Lpush_r13 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 32
- .byte 0x84 # DW_CFA_offset %r14
- .uleb128 4
- .byte 0x40+.Lsubq-.Lpush_r14 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 32+FRAME_SIZE
- .byte 3 # DW_CFA_advance_loc2
- .2byte .Laddq-.Lsubq
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 32
- .byte 0x40+.Lpop_r14-.Laddq # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 24
- .byte 0xce # DW_CFA_restore %r14
- .byte 0x40+.Lpop_r13-.Lpop_r14 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 16
- .byte 0xcd # DW_CFA_restore %r13
- .byte 0x40+.Lpop_r12-.Lpop_r13 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 8
- .byte 0xcc # DW_CFA_restore %r12
- .byte 0x40+.LSbl1-.Lpop_r12 # DW_CFA_advance_loc+N
- .byte 14 # DW_CFA_def_cfa_offset
- .uleb128 32+FRAME_SIZE
- .byte 0x8c # DW_CFA_offset %r12
- .uleb128 2
- .byte 0x8d # DW_CFA_offset %r13
- .uleb128 3
- .byte 0x84 # DW_CFA_offset %r14
- .uleb128 4
- .align 8
-.LENDFDE:
+2009-03-19 Roland McGrath <roland@redhat.com>
+
+ * td_symbol_list.c (DB_LOOKUP_NAME, DB_LOOKUP_NAME_TH_UNIQUE):
+ Use STRINGIFY macro in place of #argument.
+
2009-02-27 Roland McGrath <roland@redhat.com>
* td_symbol_list.c (symbol_list_arr): Move initializer guts to ...
static const char *symbol_list_arr[] =
{
-# define DB_LOOKUP_NAME(idx, name) [idx] = #name,
-# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) [idx] = #name,
+# define DB_LOOKUP_NAME(idx, name) [idx] = STRINGIFY (name),
+# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) [idx] = STRINGIFY (name),
# include "db-symbols.h"
# undef DB_LOOKUP_NAME
# undef DB_LOOKUP_NAME_TH_UNIQUE
}
/* The preparations are done. */
- execv ("/proc/self/exe", argv);
+#ifdef PATH_MAX
+ char pathbuf[PATH_MAX];
+#else
+ char pathbuf[256];
+#endif
+ /* Try to exec the real nscd program so the process name (as reported
+ in /proc/PID/status) will be 'nscd', but fall back to /proc/self/exe
+ if readlink fails */
+ ssize_t n = readlink ("/proc/self/exe", pathbuf, sizeof (pathbuf) - 1);
+ if (n == -1)
+ execv ("/proc/self/exe", argv);
+ else
+ {
+ pathbuf[n] = '\0';
+ execv (pathbuf, argv);
+ }
/* If we come here, we will never be able to re-exec. */
dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
-# Copyright (C) 1991-2002, 2005-2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 1991-2002, 2005-2008, 2009 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
bug-strtok1 $(addprefix test-,$(strop-tests)) \
- bug-envz1 tst-strxfrm2 tst-endian
+ bug-envz1 tst-strxfrm2 tst-endian tst-svc2
distribute := memcopy.h pagecopy.h tst-svc.expect test-string.h \
str-two-way.h
-/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1997,2000,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se);
{
const char *char_ptr;
const unsigned long int *longword_ptr;
- unsigned long int longword, magic_bits, himagic, lomagic;
+ unsigned long int longword, himagic, lomagic;
/* Handle the first few characters by reading one character at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
The 1-bits make sure that carries propagate to the next 0-bit.
The 0-bits provide holes for carries to fall into. */
- magic_bits = 0x7efefeffL;
himagic = 0x80808080L;
lomagic = 0x01010101L;
if (sizeof (longword) > 4)
{
/* 64-bit version of the magic. */
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
- magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
himagic = ((himagic << 16) << 16) | himagic;
lomagic = ((lomagic << 16) << 16) | lomagic;
}
if *any of the four* bytes in the longword in question are zero. */
for (;;)
{
- /* We tentatively exit the loop if adding MAGIC_BITS to
- LONGWORD fails to change any of the hole bits of LONGWORD.
-
- 1) Is this safe? Will it catch all the zero bytes?
- Suppose there is a byte with all zeros. Any carry bits
- propagating from its left will fall into the hole at its
- least significant bit and stop. Since there will be no
- carry from its most significant bit, the LSB of the
- byte to the left will be unchanged, and the zero will be
- detected.
-
- 2) Is this worthwhile? Will it ignore everything except
- zero bytes? Suppose every byte of LONGWORD has a bit set
- somewhere. There will be a carry into bit 8. If bit 8
- is set, this will carry into bit 16. If bit 8 is clear,
- one of bits 9-15 must be set, so there will be a carry
- into bit 16. Similarly, there will be a carry into bit
- 24. If one of bits 24-30 is set, there will be a carry
- into bit 31, so all of the hole bits will be changed.
-
- The one misfire occurs when bits 24-30 are clear and bit
- 31 is set; in this case, the hole at bit 31 is not
- changed. If we had access to the processor carry flag,
- we could close this loophole by putting the fourth hole
- at bit 32!
-
- So it ignores everything except 128's, when they're aligned
- properly. */
-
longword = *longword_ptr++;
- if (
-#if 0
- /* Add MAGIC_BITS to LONGWORD. */
- (((longword + magic_bits)
-
- /* Set those bits that were unchanged by the addition. */
- ^ ~longword)
-
- /* Look at only the hole bits. If any of the hole bits
- are unchanged, most likely one of the bytes was a
- zero. */
- & ~magic_bits)
-#else
- ((longword - lomagic) & himagic)
-#endif
- != 0)
+ if (((longword - lomagic) & ~longword & himagic) != 0)
{
/* Which of the bytes was the zero? If none of them were, it was
a misfire; continue the search. */
/* Compare strings while treating digits characters numerically.
- Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2002, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <stdint.h>
#include <string.h>
#include <ctype.h>
/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
fractionnal parts, S_Z: idem but with leading Zeroes only */
#define S_N 0x0
-#define S_I 0x4
-#define S_F 0x8
-#define S_Z 0xC
+#define S_I 0x3
+#define S_F 0x6
+#define S_Z 0x9
/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
#define CMP 2
{
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
- unsigned char c1, c2;
- int state;
- int diff;
- /* Symbol(s) 0 [1-9] others (padding)
- Transition (10) 0 (01) d (00) x (11) - */
- static const unsigned int next_state[] =
+ /* Symbol(s) 0 [1-9] others
+ Transition (10) 0 (01) d (00) x */
+ static const uint8_t next_state[] =
{
- /* state x d 0 - */
- /* S_N */ S_N, S_I, S_Z, S_N,
- /* S_I */ S_N, S_I, S_I, S_I,
- /* S_F */ S_N, S_F, S_F, S_F,
- /* S_Z */ S_N, S_F, S_Z, S_Z
+ /* state x d 0 */
+ /* S_N */ S_N, S_I, S_Z,
+ /* S_I */ S_N, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z
};
- static const int result_type[] =
+ static const int8_t result_type[] =
{
- /* state x/x x/d x/0 x/- d/x d/d d/0 d/-
- 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
-
- /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
- CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
- /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP,
- +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
- /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
- CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
- /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
- -1, CMP, CMP, CMP
+ /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
+
+ /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
};
if (p1 == p2)
return 0;
- c1 = *p1++;
- c2 = *p2++;
+ unsigned char c1 = *p1++;
+ unsigned char c2 = *p2++;
/* Hint: '0' is a digit too. */
- state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
+ int state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
- while ((diff = c1 - c2) == 0 && c1 != '\0')
+ int diff;
+ while ((diff = c1 - c2) == 0)
{
+ if (c1 == '\0')
+ return diff;
+
state = next_state[state];
c1 = *p1++;
c2 = *p2++;
state |= (c1 == '0') + (isdigit (c1) != 0);
}
- state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
+ state = result_type[state * 3 | (((c2 == '0') + (isdigit (c2) != 0)))];
switch (state)
{
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static struct
+{
+ const char *str1;
+ const char *str2;
+} tests[] =
+ {
+ { "B0075022800016.gbp.corp.com", "B007502280067.gbp.corp.com" },
+ { "B0075022800016.gbp.corp.com", "B007502357019.GBP.CORP.COM" },
+ { "B007502280067.gbp.corp.com", "B007502357019.GBP.CORP.COM" }
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+compare (const char *str1, const char *str2, int exp)
+{
+ int c = strverscmp (str1, str2);
+ if (c != 0)
+ c /= abs (c);
+ return c != exp;
+}
+
+
+static int
+do_test (void)
+{
+ int res = 0;
+ for (int i = 0; i < ntests; ++i)
+ {
+ if (compare (tests[i].str1, tests[i].str2, -1))
+ {
+ printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str1, tests[i].str2);
+ res = 1;
+ }
+ if (compare (tests[i].str2, tests[i].str1, +1))
+ {
+ printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str2, tests[i].str1);
+ res = 1;
+ }
+ char *copy1 = strdupa (tests[i].str1);
+ if (compare (tests[i].str1, copy1, 0))
+ {
+ printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str1, copy1);
+ res = 1;
+ }
+ char *copy2 = strdupa (tests[i].str2);
+ if (compare (tests[i].str2, copy2, 0))
+ {
+ printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str2, copy2);
+ res = 1;
+ }
+ }
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
/* Relocate the given object (if it hasn't already been).
SCOPE is passed to _dl_lookup_symbol in symbol lookups.
- If LAZY is nonzero, don't relocate its PLT. */
+ If RTLD_LAZY is set in RELOC-MODE, don't relocate its PLT. */
extern void _dl_relocate_object (struct link_map *map,
struct r_scope_elem *scope[],
- int lazy, int consider_profiling)
+ int reloc_mode, int consider_profiling)
attribute_hidden;
/* Protect PT_GNU_RELRO area. */
/* Machine-dependent ELF dynamic relocation inline functions. i386 version.
- Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-2005, 2006, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
-#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+# if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_386_RELATIVE, 0))
{
-# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
/* This is defined in rtld.c, but nowhere in the static libc.a;
make the reference weak so static programs can still link.
This declaration cannot be done when compiling rtld.c
(i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
common defn for _dl_rtld_map, which is incompatible with a
weak decl in the same file. */
-# ifndef SHARED
+# ifndef SHARED
weak_extern (_dl_rtld_map);
-# endif
+# endif
if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
-# endif
+# endif
*reloc_addr += map->l_addr;
}
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
else if (__builtin_expect (r_type == R_386_NONE, 0))
return;
-# endif
+# endif
else
-#endif /* !RTLD_BOOTSTRAP and have no -z combreloc */
+# endif /* !RTLD_BOOTSTRAP and have no -z combreloc */
{
const Elf32_Sym *const refsym = sym;
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+ if (sym != NULL
+ && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
+ 0))
+ value = ((Elf32_Addr (*) (void)) value) ();
+
switch (r_type)
{
case R_386_GLOB_DAT:
*reloc_addr = value;
break;
-#if !defined RTLD_BOOTSTRAP || USE___THREAD
+# if !defined RTLD_BOOTSTRAP || USE___THREAD
case R_386_TLS_DTPMOD32:
-# ifdef RTLD_BOOTSTRAP
+# ifdef RTLD_BOOTSTRAP
/* During startup the dynamic linker is always the module
with index 1.
XXX If this relocation is necessary move before RESOLVE
call. */
*reloc_addr = 1;
-# else
+# else
/* Get the information from the link map returned by the
resolv function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
-# endif
+# endif
break;
case R_386_TLS_DTPOFF32:
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
if (sym != NULL)
*reloc_addr = sym->st_value;
-# endif
+# endif
break;
case R_386_TLS_DESC:
{
struct tlsdesc volatile *td =
(struct tlsdesc volatile *)reloc_addr;
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
if (! sym)
td->entry = _dl_tlsdesc_undefweak;
else
-# endif
+# endif
{
-# ifndef RTLD_BOOTSTRAP
-# ifndef SHARED
+# ifndef RTLD_BOOTSTRAP
+# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
-# else
+# else
if (!TRY_STATIC_TLS (map, sym_map))
{
td->arg = _dl_make_tlsdesc_dynamic
td->entry = _dl_tlsdesc_dynamic;
}
else
+# endif
# endif
-# endif
{
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
+ (ElfW(Word))td->arg);
}
case R_386_TLS_TPOFF32:
/* The offset is positive, backward from the thread pointer. */
-# ifdef RTLD_BOOTSTRAP
+# ifdef RTLD_BOOTSTRAP
*reloc_addr += map->l_tls_offset - sym->st_value;
-# else
+# else
/* We know the offset of object the symbol is contained in.
It is a positive value which will be subtracted from the
thread pointer. To get the variable position in the TLS
CHECK_STATIC_TLS (map, sym_map);
*reloc_addr += sym_map->l_tls_offset - sym->st_value;
}
-# endif
+# endif
break;
case R_386_TLS_TPOFF:
/* The offset is negative, forward from the thread pointer. */
-# ifdef RTLD_BOOTSTRAP
+# ifdef RTLD_BOOTSTRAP
*reloc_addr += sym->st_value - map->l_tls_offset;
-# else
+# else
/* We know the offset of object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
CHECK_STATIC_TLS (map, sym_map);
*reloc_addr += sym->st_value - sym_map->l_tls_offset;
}
-# endif
+# endif
break;
-#endif /* use TLS */
+# endif /* use TLS */
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
case R_386_32:
*reloc_addr += value;
break;
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
-#endif /* !RTLD_BOOTSTRAP */
+# endif /* !RTLD_BOOTSTRAP */
}
}
}
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
*reloc_addr = map->l_addr + reloc->r_addend;
else if (r_type != R_386_NONE)
{
-# ifndef RESOLVE_CONFLICT_FIND_MAP
+# ifndef RESOLVE_CONFLICT_FIND_MAP
const Elf32_Sym *const refsym = sym;
-# endif
+# endif
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+ if (sym != NULL
+ && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
+ 0))
+ value = ((Elf32_Addr (*) (void)) value) ();
+
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_GLOB_DAT:
case R_386_32:
*reloc_addr = value + reloc->r_addend;
break;
-# ifndef RESOLVE_CONFLICT_FIND_MAP
+# ifndef RESOLVE_CONFLICT_FIND_MAP
/* Not needed for dl-conflict.c. */
case R_386_PC32:
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
struct tlsdesc volatile *td =
(struct tlsdesc volatile *)reloc_addr;
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
if (!sym)
{
td->arg = (void*)reloc->r_addend;
td->entry = _dl_tlsdesc_undefweak;
}
else
-# endif
+# endif
{
-# ifndef RTLD_BOOTSTRAP
-# ifndef SHARED
+# ifndef RTLD_BOOTSTRAP
+# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
-# else
+# else
if (!TRY_STATIC_TLS (map, sym_map))
{
td->arg = _dl_make_tlsdesc_dynamic
td->entry = _dl_tlsdesc_dynamic;
}
else
-# endif
-# endif
+# endif
+# endif
{
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend);
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
-# endif /* !RESOLVE_CONFLICT_FIND_MAP */
+# endif /* !RESOLVE_CONFLICT_FIND_MAP */
default:
/* We add these checks in the version to relocate ld.so only
if we are still debugging. */
}
}
}
-#endif /* !RTLD_BOOTSTRAP */
+# endif /* !RTLD_BOOTSTRAP */
auto inline void
__attribute ((always_inline))
*reloc_addr += l_addr;
}
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
auto inline void
__attribute__ ((always_inline))
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
Elf32_Addr *const reloc_addr = reloc_addr_arg;
*reloc_addr = l_addr + reloc->r_addend;
}
-#endif /* !RTLD_BOOTSTRAP */
+# endif /* !RTLD_BOOTSTRAP */
auto inline void
__attribute__ ((always_inline))
const ElfW(Sym) *const symtab =
(const void *) D_PTR (map, l_info[DT_SYMTAB]);
-#ifdef RTLD_BOOTSTRAP
+# ifdef RTLD_BOOTSTRAP
/* The dynamic linker always uses versioning. */
assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
-#else
+# else
if (map->l_info[VERSYMIDX (DT_VERSYM)])
-#endif
+# endif
{
const ElfW(Half) *const version =
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
&map->l_versions[ndx],
(void *) (l_addr + r->r_offset));
}
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
else
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
(void *) (l_addr + r->r_offset));
-#endif
+# endif
}
}
else
_dl_reloc_bad_type (map, r_type, 1);
}
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
auto inline void
__attribute__ ((always_inline))
_dl_reloc_bad_type (map, r_type, 1);
}
-#endif /* !RTLD_BOOTSTRAP */
+# endif /* !RTLD_BOOTSTRAP */
#endif /* RESOLVE_MAP */
--- /dev/null
+powerpc/powerpc32/power5/fpu
-/* Copyright (C) 1992, 1997, 1998, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1997,1998,2000,2004,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-__alphasort64 (const void *a, const void *b)
+__alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
{
- return strcoll ((*(const struct dirent64 **) a)->d_name,
- (*(const struct dirent64 **) b)->d_name);
+ return strcoll ((*a)->d_name, (*b)->d_name);
}
#include <shlib-compat.h>
#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
int
-__old_alphasort64 (const void *a, const void *b);
+__old_alphasort64 (const struct __old_dirent64 **a,
+ const struct __old_dirent64 **b);
int
attribute_compat_text_section
-__old_alphasort64 (const void *a, const void *b)
+__old_alphasort64 (const struct __old_dirent64 **a,
+ const struct __old_dirent64 **b)
{
- return strcoll ((*(const struct __old_dirent64 **) a)->d_name,
- (*(const struct __old_dirent64 **) b)->d_name);
+ return strcoll ((*a)->d_name, (*b)->d_name);
}
compat_symbol (libc, __old_alphasort64, alphasort64, GLIBC_2_1);
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
int __old_scandir64 (__const char * __dir,
struct __old_dirent64 *** __namelist,
int (*__selector) (__const struct __old_dirent64 *),
- int (*__cmp) (__const void *, __const void *));
+ int (*__cmp) (__const struct __old_dirent64 **,
+ __const struct __old_dirent64 **));
#endif
-/* Copyright (C) 1992, 1997, 1998, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1992,1997,1998,2000,2004,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
#include <string.h>
int
-__versionsort64 (const void *a, const void *b)
+__versionsort64 (const struct dirent64 **a, const struct dirent64 **b)
{
- return __strverscmp ((*(const struct dirent64 **) a)->d_name,
- (*(const struct dirent64 **) b)->d_name);
+ return __strverscmp ((*a)->d_name, (*b)->d_name);
}
#include <shlib-compat.h>
#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
int
-__old_versionsort64 (const void *a, const void *b);
+__old_versionsort64 (const struct __old_dirent64 **a,
+ const struct __old_dirent64 **b);
int
attribute_compat_text_section
-__old_versionsort64 (const void *a, const void *b)
+__old_versionsort64 (const struct __old_dirent64 **a,
+ const struct __old_dirent64 **b)
{
- return __strverscmp ((*(const struct __old_dirent64 **) a)->d_name,
- (*(const struct __old_dirent64 **) b)->d_name);
+ return __strverscmp ((*a)->d_name, (*b)->d_name);
}
compat_symbol (libc, __old_versionsort64, versionsort64, GLIBC_2_1);
+#define alphasort64 rename_alphasort64
+
#include "../../dirent/alphasort.c"
+#undef alphasort64
+
weak_alias (alphasort, alphasort64)
+#define versionsort64 rename_versionsort64
+
#include "../../dirent/versionsort.c"
+#undef versionsort64
+
weak_alias (versionsort, versionsort64)
#include <stdlib.h>
#include <unistd.h>
+#ifdef USE_MULTIARCH
+# include "multiarch/init-arch.h"
+#endif
+
static const struct intel_02_cache_info
{
unsigned int idx;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
- int max_cpuid;
int max_cpuid_ex;
long int data = -1;
long int shared = -1;
unsigned int level;
unsigned int threads = 0;
+#ifdef USE_MULTIARCH
+ if (__cpu_features.kind == arch_kind_unknown)
+ __init_cpu_features ();
+# define is_intel __cpu_features.kind == arch_kind_intel
+# define is_amd __cpu_features.kind == arch_kind_amd
+# define max_cpuid __cpu_features.max_cpuid
+#else
+ int max_cpuid;
asm volatile ("cpuid"
: "=a" (max_cpuid), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "0" (0));
-
/* This spells out "GenuineIntel". */
- if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
+# define is_intel \
+ ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69
+ /* This spells out "AuthenticAMD". */
+# define is_amd \
+ ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65
+#endif
+
+ if (is_intel)
{
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, max_cpuid);
shared = handle_intel (_SC_LEVEL2_CACHE_SIZE, max_cpuid);
}
+#ifdef USE_MULTIARCH
+ eax = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax;
+ ebx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx;
+ ecx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx;
+ edx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx;
+#else
asm volatile ("cpuid"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "0" (1));
+#endif
/* Intel prefers SSSE3 instructions for memory/string routines
if they are avaiable. */
shared /= threads;
}
/* This spells out "AuthenticAMD". */
- else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+ else if (is_amd)
{
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version.
- Copyright (C) 2001-2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2005, 2006, 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>.
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
-#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+# if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0))
{
-# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
/* This is defined in rtld.c, but nowhere in the static libc.a;
make the reference weak so static programs can still link.
This declaration cannot be done when compiling rtld.c
(i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
common defn for _dl_rtld_map, which is incompatible with a
weak decl in the same file. */
-# ifndef SHARED
+# ifndef SHARED
weak_extern (GL(dl_rtld_map));
-# endif
+# endif
if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
-# endif
+# endif
*reloc_addr = map->l_addr + reloc->r_addend;
}
else
-#endif
+# endif
if (__builtin_expect (r_type == R_X86_64_NONE, 0))
return;
else
{
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
const Elf64_Sym *const refsym = sym;
-#endif
+# endif
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf64_Addr value = (sym == NULL ? 0
: (Elf64_Addr) sym_map->l_addr + sym->st_value);
-#if defined RTLD_BOOTSTRAP && !USE___THREAD
+ if (sym != NULL
+ && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
+ 0))
+ value = ((Elf64_Addr (*) (void)) value) ();
+
+# if defined RTLD_BOOTSTRAP && !USE___THREAD
assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT);
*reloc_addr = value + reloc->r_addend;
-#else
+# else
switch (r_type)
{
case R_X86_64_GLOB_DAT:
*reloc_addr = value + reloc->r_addend;
break;
-#ifndef RESOLVE_CONFLICT_FIND_MAP
+# ifndef RESOLVE_CONFLICT_FIND_MAP
case R_X86_64_DTPMOD64:
-# ifdef RTLD_BOOTSTRAP
+# ifdef RTLD_BOOTSTRAP
/* During startup the dynamic linker is always the module
with index 1.
XXX If this relocation is necessary move before RESOLVE
call. */
*reloc_addr = 1;
-# else
+# else
/* Get the information from the link map returned by the
resolve function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
-# endif
+# endif
break;
case R_X86_64_DTPOFF64:
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
if (sym != NULL)
*reloc_addr = sym->st_value + reloc->r_addend;
-# endif
+# endif
break;
case R_X86_64_TLSDESC:
{
struct tlsdesc volatile *td =
(struct tlsdesc volatile *)reloc_addr;
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
if (! sym)
{
td->arg = (void*)reloc->r_addend;
td->entry = _dl_tlsdesc_undefweak;
}
else
-# endif
+# endif
{
-# ifndef RTLD_BOOTSTRAP
-# ifndef SHARED
+# ifndef RTLD_BOOTSTRAP
+# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
-# else
+# else
if (!TRY_STATIC_TLS (map, sym_map))
{
td->arg = _dl_make_tlsdesc_dynamic
td->entry = _dl_tlsdesc_dynamic;
}
else
+# endif
# endif
-# endif
{
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend);
}
case R_X86_64_TPOFF64:
/* The offset is negative, forward from the thread pointer. */
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
if (sym != NULL)
-# endif
+# endif
{
-# ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
CHECK_STATIC_TLS (map, sym_map);
-# endif
+# endif
/* We know the offset of the object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
- sym_map->l_tls_offset);
}
break;
-#endif
+# endif
-#ifndef RTLD_BOOTSTRAP
+# ifndef RTLD_BOOTSTRAP
case R_X86_64_64:
*reloc_addr = value + reloc->r_addend;
break;
case R_X86_64_32:
- *(unsigned int *) reloc_addr = value + reloc->r_addend;
- if (value + reloc->r_addend > UINT_MAX)
+ value += reloc->r_addend;
+ *(unsigned int *) reloc_addr = value;
+
+ const char *fmt;
+ if (__builtin_expect (value > UINT_MAX, 0))
{
const char *strtab;
+ fmt = "\
+%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n";
+ print_err:
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
- _dl_error_printf ("\
-%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n",
+ _dl_error_printf (fmt,
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
}
break;
-# ifndef RESOLVE_CONFLICT_FIND_MAP
+# ifndef RESOLVE_CONFLICT_FIND_MAP
/* Not needed for dl-conflict.c. */
case R_X86_64_PC32:
- *(unsigned int *) reloc_addr = value + reloc->r_addend
- - (Elf64_Addr) reloc_addr;
- if (value + reloc->r_addend - (Elf64_Addr) reloc_addr
- != (int)(value + reloc->r_addend - (Elf64_Addr) reloc_addr))
+ value += reloc->r_addend - (Elf64_Addr) reloc_addr;
+ *(unsigned int *) reloc_addr = value;
+ if (__builtin_expect (value != (unsigned int) value, 0))
{
- const char *strtab;
-
- strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
-
- _dl_error_printf ("\
-%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n",
- rtld_progname ?: "<program name unknown>",
- strtab + refsym->st_name);
+ fmt = "\
+%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n";
+ goto print_err;
}
break;
case R_X86_64_COPY:
/* This can happen in trace mode if an object could not be
found. */
break;
+ memcpy (reloc_addr_arg, (void *) value,
+ MIN (sym->st_size, refsym->st_size));
if (__builtin_expect (sym->st_size > refsym->st_size, 0)
|| (__builtin_expect (sym->st_size < refsym->st_size, 0)
&& GLRO(dl_verbose)))
{
- const char *strtab;
-
- strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
- _dl_error_printf ("\
-%s: Symbol `%s' has different size in shared object, consider re-linking\n",
- rtld_progname ?: "<program name unknown>",
- strtab + refsym->st_name);
+ fmt = "\
+%s: Symbol `%s' has different size in shared object, consider re-linking\n";
+ goto print_err;
}
- memcpy (reloc_addr_arg, (void *) value,
- MIN (sym->st_size, refsym->st_size));
break;
-# endif
+# endif
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
-#endif
+# endif
}
#endif
}
--- /dev/null
+/* The ABI calls for the PLT stubs to pass the index of the relocation
+ and not its offset. In _dl_profile_fixup and _dl_call_pltexit we
+ also use the index. Therefore it is wasteful to compute the offset
+ in the trampoline just to reverse the operation immediately
+ afterwards. */
+#define reloc_offset reloc_arg * sizeof (PLTREL)
+#define reloc_index reloc_arg
+
+#include <elf/dl-runtime.c>
/* PLT trampolines. x86-64 version.
- Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
movq %r8, 40(%rsp)
movq %r9, 48(%rsp)
movq 64(%rsp), %rsi # Copy args pushed by PLT in register.
- movq %rsi, %r11 # Multiply by 24
- addq %r11, %rsi
- addq %r11, %rsi
- shlq $3, %rsi
- movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset
+ movq 56(%rsp), %rdi # %rdi: link_map, %rsi: reloc_index
call _dl_fixup # Call resolver.
movq %rax, %r11 # Save return value
movq 48(%rsp), %r9 # Get register content back.
.type _dl_runtime_profile, @function
.align 16
cfi_startproc
+
_dl_runtime_profile:
- subq $88, %rsp
- cfi_adjust_cfa_offset(104) # Incorporate PLT
- movq %rax, (%rsp) # Preserve registers otherwise clobbered.
- movq %rdx, 8(%rsp)
- movq %r8, 16(%rsp)
- movq %r9, 24(%rsp)
- movq %rcx, 32(%rsp)
- movq %rsi, 40(%rsp)
- movq %rdi, 48(%rsp)
- movq %rbp, 56(%rsp) # Information for auditors.
- leaq 104(%rsp), %rax
- movq %rax, 64(%rsp)
- leaq 8(%rsp), %rcx
- movq 104(%rsp), %rdx # Load return address if needed
- movq 96(%rsp), %rsi # Copy args pushed by PLT in register.
- movq %rsi,%r11 # Multiply by 24
- addq %r11,%rsi
- addq %r11,%rsi
- shlq $3, %rsi
- movq 88(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset
- leaq 72(%rsp), %r8
+ /* The La_x86_64_regs data structure pointed to by the
+ fourth paramater must be 16-byte aligned. This must
+ be explicitly enforced. We have the set up a dynamically
+ sized stack frame. %rbx points to the top half which
+ has a fixed size and preserves the original stack pointer. */
+
+ subq $32, %rsp # Allocate the local storage.
+ cfi_adjust_cfa_offset(48) # Incorporate PLT
+ movq %rbx, (%rsp)
+ cfi_rel_offset(%rbx, 0)
+
+ /* On the stack:
+ 56(%rbx) parameter #1
+ 48(%rbx) return address
+
+ 40(%rbx) reloc index
+ 32(%rbx) link_map
+
+ 24(%rbx) La_x86_64_regs pointer
+ 16(%rbx) framesize
+ 8(%rbx) rax
+ (%rbx) rbx
+ */
+
+ movq %rax, 8(%rsp)
+ movq %rsp, %rbx
+ cfi_def_cfa_register(%rbx)
+
+ /* Actively align the La_x86_64_regs structure. */
+ andq $0xfffffffffffffff0, %rsp
+ subq $192, %rsp # sizeof(La_x86_64_regs)
+ movq %rsp, 24(%rbx)
+
+ movq %rdx, (%rsp) # Fill the La_x86_64_regs structure.
+ movq %r8, 8(%rsp)
+ movq %r9, 16(%rsp)
+ movq %rcx, 24(%rsp)
+ movq %rsi, 32(%rsp)
+ movq %rdi, 40(%rsp)
+ movq %rbp, 48(%rsp)
+ leaq 48(%rbx), %rax
+ movq %rax, 56(%rsp)
+ movaps %xmm0, 64(%rsp)
+ movaps %xmm1, 80(%rsp)
+ movaps %xmm2, 96(%rsp)
+ movaps %xmm3, 112(%rsp)
+ movaps %xmm4, 128(%rsp)
+ movaps %xmm5, 144(%rsp)
+ movaps %xmm7, 160(%rsp)
+
+ movq %rsp, %rcx # La_x86_64_regs pointer to %rcx.
+ movq 48(%rbx), %rdx # Load return address if needed.
+ movq 40(%rbx), %rsi # Copy args pushed by PLT in register.
+ movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index
+ leaq 16(%rbx), %r8
call _dl_profile_fixup # Call resolver.
- movq %rax, %r11 # Save return value
- movq 8(%rsp), %rdx # Get back register content.
- movq 16(%rsp), %r8
- movq 24(%rsp), %r9
- movq (%rsp),%rax
- movq 72(%rsp), %r10
+
+ movq %rax, %r11 # Save return value.
+
+ movq 8(%rbx), %rax # Get back register content.
+ movq (%rsp), %rdx
+ movq 8(%rsp), %r8
+ movq 16(%rsp), %r9
+ movaps 64(%rsp), %xmm0
+ movaps 80(%rsp), %xmm1
+ movaps 96(%rsp), %xmm2
+ movaps 112(%rsp), %xmm3
+ movaps 128(%rsp), %xmm4
+ movaps 144(%rsp), %xmm5
+ movaps 160(%rsp), %xmm7
+
+ movq 16(%rbx), %r10 # Anything in framesize?
testq %r10, %r10
jns 1f
- movq 32(%rsp), %rcx
- movq 40(%rsp), %rsi
- movq 48(%rsp), %rdi
- addq $104,%rsp # Adjust stack
- cfi_adjust_cfa_offset (-104)
+
+ /* There's nothing in the frame size, so there
+ will be no call to the _dl_call_pltexit. */
+
+ movq 24(%rsp), %rcx # Get back registers content.
+ movq 32(%rsp), %rsi
+ movq 40(%rsp), %rdi
+
+ movq %rbx, %rsp
+ movq (%rsp), %rbx
+ cfi_restore(rbx)
+ cfi_def_cfa_register(%rsp)
+
+ addq $48, %rsp # Adjust the stack to the return value
+ # (eats the reloc index and link_map)
+ cfi_adjust_cfa_offset(-48)
jmp *%r11 # Jump to function address.
- /*
- +104 return address
- +96 PLT2
- +88 PLT1
- +80 free
- +72 free
- +64 %rsp
- +56 %rbp
- +48 %rdi
- +40 %rsi
- +32 %rcx
- +24 %r9
- +16 %r8
- +8 %rdx
- %rsp %rax
- */
- cfi_adjust_cfa_offset (104)
-1: movq %rbx, 72(%rsp)
- cfi_rel_offset (rbx, 72)
- leaq 112(%rsp), %rsi
- movq %rsp, %rbx
- cfi_def_cfa_register (%rbx)
- movq %r10, %rcx
+1:
+ cfi_adjust_cfa_offset(48)
+ cfi_rel_offset(%rbx, 0)
+ cfi_def_cfa_register(%rbx)
+
+ /* At this point we need to prepare new stack for the function
+ which has to be called. We copy the original stack to a
+ temporary buffer of the size specified by the 'framesize'
+ returned from _dl_profile_fixup */
+
+ leaq 56(%rbx), %rsi # stack
addq $8, %r10
andq $0xfffffffffffffff0, %r10
+ movq %r10, %rcx
subq %r10, %rsp
movq %rsp, %rdi
shrq $3, %rcx
rep
movsq
- movq 32(%rbx), %rcx
- movq 40(%rbx), %rsi
- movq 48(%rbx), %rdi
+
+ movq 24(%rdi), %rcx # Get back register content.
+ movq 32(%rdi), %rsi
+ movq 40(%rdi), %rdi
+
call *%r11
- movq %rbx, %rsp
- cfi_def_cfa_register (%rsp)
- subq $72, %rsp
- cfi_adjust_cfa_offset (72)
- movq %rsp, %rcx
- movq %rax, (%rcx)
+
+ mov 24(%rbx), %rsp # Drop the copied stack content
+
+ /* Now we have to prepare the La_x86_64_retval structure for the
+ _dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now,
+ so we just need to allocate the sizeof(La_x86_64_retval) space on
+ the stack, since the alignment has already been taken care of. */
+
+ subq $80, %rsp # sizeof(La_x86_64_retval)
+ movq %rsp, %rcx # La_x86_64_retval argument to %rcx.
+
+ movq %rax, (%rcx) # Fill in the La_x86_64_retval structure.
movq %rdx, 8(%rcx)
- /* Even though the stack is correctly aligned to allow using movaps
- we use movups. Some callers might provide an incorrectly aligned
- stack and we do not want to have it blow up here. */
- movups %xmm0, 16(%rcx)
- movups %xmm1, 32(%rcx)
+ movaps %xmm0, 16(%rcx)
+ movaps %xmm1, 32(%rcx)
fstpt 48(%rcx)
fstpt 64(%rcx)
- /*
- +176 return address
- +168 PLT2
- +160 PLT1
- +152 free
- +144 free
- +136 %rsp
- +128 %rbp
- +120 %rdi
- +112 %rsi
- +104 %rcx
- +96 %r9
- +88 %r8
- +80 %rdx
- +64 %st1 result
- +48 %st result
- +32 %xmm1 result
- +16 %xmm0 result
- +8 %rdx result
- %rsp %rax result
- */
- leaq 80(%rsp), %rdx
- movq 144(%rsp), %rbx
- cfi_restore (rbx)
- movq 168(%rsp), %rsi # Copy args pushed by PLT in register.
- movq %rsi,%r11 # Multiply by 24
- addq %r11,%rsi
- addq %r11,%rsi
- shlq $3, %rsi
- movq 160(%rsp), %rdi # %rdi: link_map, %rsi: reloc_offset
+
+ movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx.
+ movq 40(%rbx), %rsi # Copy args pushed by PLT in register.
+ movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index
call _dl_call_pltexit
- movq (%rsp), %rax
+
+ movq (%rsp), %rax # Restore return registers.
movq 8(%rsp), %rdx
- movups 16(%rsp), %xmm0
- movups 32(%rsp), %xmm1
+ movaps 16(%rsp), %xmm0
+ movaps 32(%rsp), %xmm1
fldt 64(%rsp)
fldt 48(%rsp)
- addq $176, %rsp
- cfi_adjust_cfa_offset (-176)
+
+ movq %rbx, %rsp
+ movq (%rsp), %rbx
+ cfi_restore(rbx)
+ cfi_def_cfa_register(%rsp)
+
+ addq $48, %rsp # Adjust the stack to the return value
+ # (eats the reloc index and link_map)
+ cfi_adjust_cfa_offset(-48)
retq
+
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile
#endif
--- /dev/null
+ifeq ($(subdir),csu)
+aux += init-arch
+endif
--- /dev/null
+/* Initialize CPU feature data.
+ This file is part of the GNU C Library.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>.
+
+ 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. */
+
+#include "init-arch.h"
+
+
+struct cpu_features __cpu_features attribute_hidden;
+
+
+void
+__init_cpu_features (void)
+{
+ unsigned int ebx;
+ unsigned int ecx;
+ unsigned int edx;
+
+ asm volatile ("cpuid"
+ : "=a" (__cpu_features.max_cpuid), "=b" (ebx), "=c" (ecx),
+ "=d" (edx)
+ : "0" (0));
+
+ /* This spells out "GenuineIntel". */
+ if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
+ {
+ __cpu_features.kind = arch_kind_intel;
+
+ asm volatile ("cpuid"
+ : "=a" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax),
+ "=b" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx),
+ "=c" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx),
+ "=d" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx)
+ : "0" (1));
+ }
+ /* This spells out "AuthenticAMD". */
+ else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+ {
+ __cpu_features.kind = arch_kind_amd;
+
+ asm volatile ("cpuid"
+ : "=a" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].eax),
+ "=b" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ebx),
+ "=c" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx),
+ "=d" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].edx)
+ : "0" (1));
+ }
+ else
+ __cpu_features.kind = arch_kind_other;
+}
--- /dev/null
+/* This file is part of the GNU C Library.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ 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. */
+
+#include <sys/param.h>
+
+enum
+ {
+ INTEL_CPUID_INDEX_1 = 0,
+ /* Keep the following line at the end. */
+ INTEL_CPUID_INDEX_MAX
+ };
+
+enum
+ {
+ AMD_CPUID_INDEX_1 = 0,
+ /* Keep the following line at the end. */
+ AMD_CPUID_INDEX_MAX
+ };
+
+extern struct cpu_features
+{
+ enum
+ {
+ arch_kind_unknown = 0,
+ arch_kind_intel,
+ arch_kind_amd,
+ arch_kind_other
+ } kind;
+ int max_cpuid;
+ struct
+ {
+ unsigned int eax;
+ unsigned int ebx;
+ unsigned int ecx;
+ unsigned int edx;
+ } cpuid[MAX (INTEL_CPUID_INDEX_MAX, AMD_CPUID_INDEX_MAX)];
+} __cpu_features attribute_hidden;
+
+
+extern void __init_cpu_features (void) attribute_hidden;
+#define INIT_ARCH()\
+ do \
+ if (__cpu_features.kind == arch_kind_unknown) \
+ __init_cpu_features (); \
+ while (0)
+
+/* Following are the feature tests used throughout libc. */
+
+#define INTEL_HAS_POPCOUNT \
+ (__cpu_features.kind == arch_kind_intel \
+ && (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx & (1 << 23)) != 0)
+
+#define AMD_HAS_POPCOUNT \
+ (__cpu_features.kind == arch_kind_amd \
+ && (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx & (1 << 23)) != 0)
--- /dev/null
+/* Count bits in CPU set. x86-64 multi-arch version.
+ This file is part of the GNU C Library.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>.
+
+ 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. */
+
+#ifdef SHARED
+# include <sched.h>
+# include "init-arch.h"
+
+# define __sched_cpucount static generic_cpucount
+# include <posix/sched_cpucount.c>
+# undef __sched_cpucount
+
+# define POPCNT(l) \
+ ({ __cpu_mask r; \
+ asm ("popcntq %1, %0" : "=r" (r) : "0" (l));\
+ r; })
+# define __sched_cpucount static popcount_cpucount
+# include <posix/sched_cpucount.c>
+# undef __sched_cpucount
+
+libc_ifunc (__sched_cpucount,
+ INTEL_HAS_POPCOUNT || AMD_HAS_POPCOUNT
+ ? popcount_cpucount : generic_cpucount);
+#else
+# include_next <sched_cpucount.c>
+#endif