mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
.
This commit is contained in:
parent
d6220e9ee3
commit
32c075e1f0
@ -407,9 +407,11 @@ LDFLAGS.so += $(combreloc-LDFLAGS)
|
||||
LDFLAGS-rtld += $(combreloc-LDFLAGS)
|
||||
endif
|
||||
|
||||
ifeq (yes,$(have-z-relro))
|
||||
relro-LDFLAGS = -Wl,-z,relro
|
||||
LDFLAGS.so += $(relro-LDFLAGS)
|
||||
LDFLAGS-rtld += $(relro-LDFLAGS)
|
||||
endif
|
||||
|
||||
ifeq (yes,$(have-hash-style))
|
||||
# For the time being we unconditionally use 'both'. At some time we
|
||||
|
@ -1233,7 +1233,10 @@ endif
|
||||
|
||||
ifeq ($(firstword $(sysd-sorted-done) f)$(firstword $(generating) f),tf)
|
||||
-include $(common-objpfx)tls.make
|
||||
config-tls := notls
|
||||
ifeq ($(use-tls),yes)
|
||||
config-tls := tls
|
||||
endif
|
||||
ifeq ($(use-thread),yes)
|
||||
config-tls := thread
|
||||
endif
|
||||
|
14
NEWS
14
NEWS
@ -1,13 +1,21 @@
|
||||
GNU C Library NEWS -- history of user-visible changes. 2006-10-11
|
||||
GNU C Library NEWS -- history of user-visible changes. 2006-09-29
|
||||
Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
See the end for copying conditions.
|
||||
|
||||
Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.6
|
||||
Version 2.5.1
|
||||
|
||||
* New Linux interfaces: epoll_pwait.
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
2337, 2749, 3213, 3291, 3306, 3320, 3322, 3334, 3348, 3352, 3369, 3429,
|
||||
3451, 3458, 3559, 3632, 3664, 3673, 3674, 3747, 3842, 3851, 3855, 3884,
|
||||
3902, 3919, 3944, 3954, 3955, 3957, 3995, 4069, 4070, 4074, 4076, 4101,
|
||||
4102, 4130, 4131, 4181, 4342, 4344, 4364, 4368, 4381, 4405, 4406, 4411,
|
||||
4438, 4439, 4465, 4512, 4514, 4586, 4702, 4858
|
||||
|
||||
Visit <http://sources.redhat.com/bugzilla/> for the details of each bug.
|
||||
|
||||
|
||||
Version 2.5
|
||||
|
4
README
4
README
@ -1,4 +1,4 @@
|
||||
This directory contains the version 2.5 release of the GNU C Library.
|
||||
This directory contains the version 2.5.1 release of the GNU C Library.
|
||||
|
||||
The GNU C Library is the standard system C library for all GNU systems,
|
||||
and is an important part of what makes up a GNU system. It provides the
|
||||
@ -52,7 +52,7 @@ The GNU C Library supports these configurations for using Linux kernels:
|
||||
|
||||
The code for other CPU configurations supported by volunteers outside of
|
||||
the core glibc maintenance effort is contained in the separate `ports'
|
||||
add-on. You can find glibc-ports-2.5 distributed separately in the
|
||||
add-on. You can find glibc-ports-2.5.1 distributed separately in the
|
||||
same place where you got the main glibc distribution files.
|
||||
Currently these configurations are known to work using the `ports' add-on:
|
||||
|
||||
|
@ -22,7 +22,6 @@ libc {
|
||||
GLIBC_2.3.4
|
||||
GLIBC_2.4
|
||||
GLIBC_2.5
|
||||
GLIBC_2.6
|
||||
%ifdef USE_IN_LIBIO
|
||||
HURD_CTHREADS_0.3
|
||||
%endif
|
||||
@ -83,7 +82,6 @@ libpthread {
|
||||
GLIBC_2.3.3
|
||||
GLIBC_2.3.4
|
||||
GLIBC_2.4
|
||||
GLIBC_2.6
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
libresolv {
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1997, 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997, 2002, 2003, 2006, 2007 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
|
||||
@ -26,7 +26,7 @@ distribute = argp-fmtstream.h argp-namefrob.h
|
||||
routines = $(addprefix argp-, ba fmtstream fs-xinl help parse pv \
|
||||
pvh xinl eexst)
|
||||
|
||||
tests = argp-test tst-argp1 bug-argp1
|
||||
tests = argp-test tst-argp1 bug-argp1 tst-argp2
|
||||
|
||||
CFLAGS-argp-help.c = $(uses-callbacks) -fexceptions
|
||||
CFLAGS-argp-parse.c = $(uses-callbacks)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Hierarchial argument parsing help output
|
||||
Copyright (C) 1995-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2003, 2004, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -672,9 +673,9 @@ hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
|
||||
{
|
||||
/* If one cluster is deeper than the other, use its ancestor at the same
|
||||
level, so that finding the common ancestor is straightforward. */
|
||||
while (cl1->depth < cl2->depth)
|
||||
while (cl1->depth > cl2->depth)
|
||||
cl1 = cl1->parent;
|
||||
while (cl2->depth < cl1->depth)
|
||||
while (cl2->depth > cl1->depth)
|
||||
cl2 = cl2->parent;
|
||||
|
||||
/* Now reduce both clusters to their ancestors at the point where both have
|
||||
@ -987,7 +988,7 @@ static const char *
|
||||
filter_doc (const char *doc, int key, const struct argp *argp,
|
||||
const struct argp_state *state)
|
||||
{
|
||||
if (argp->help_filter)
|
||||
if (argp && argp->help_filter)
|
||||
/* We must apply a user filter to this output. */
|
||||
{
|
||||
void *input = __argp_input (argp, state);
|
||||
|
101
argp/tst-argp2.c
Normal file
101
argp/tst-argp2.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
|
||||
|
||||
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 <argp.h>
|
||||
|
||||
static const struct argp_option opt1[] =
|
||||
{
|
||||
{ "opt1", '1', "NUMBER", 0, "Option 1" },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const struct argp_option opt2[] =
|
||||
{
|
||||
{ "opt2", '2', "NUMBER", 0, "Option 2" },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const struct argp_option opt3[] =
|
||||
{
|
||||
{ "opt3", '3', "NUMBER", 0, "Option 3" },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const struct argp_option opt4[] =
|
||||
{
|
||||
{ "opt4", '4', "NUMBER", 0, "Option 4" },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static const struct argp_option opt5[] =
|
||||
{
|
||||
{ "opt5", '5', "NUMBER", 0, "Option 5" },
|
||||
{ NULL, 0, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static struct argp argp5 =
|
||||
{
|
||||
opt5, NULL, "args doc5", "doc5", NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static struct argp argp4 =
|
||||
{
|
||||
opt4, NULL, "args doc4", "doc4", NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static struct argp argp3 =
|
||||
{
|
||||
opt3, NULL, "args doc3", "doc3", NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static struct argp_child children2[] =
|
||||
{
|
||||
{ &argp4, 0, "child3", 3 },
|
||||
{ &argp5, 0, "child4", 4 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
static struct argp argp2 =
|
||||
{
|
||||
opt2, NULL, "args doc2", "doc2", children2, NULL, NULL
|
||||
};
|
||||
|
||||
static struct argp_child children1[] =
|
||||
{
|
||||
{ &argp2, 0, "child1", 1 },
|
||||
{ &argp3, 0, "child2", 2 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
static struct argp argp1 =
|
||||
{
|
||||
opt1, NULL, "args doc1", "doc1", children1, NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
argp_help (&argp1, stdout, ARGP_HELP_LONG, (char *) "tst-argp2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996-2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 1996.
|
||||
|
||||
@ -246,7 +246,7 @@ print_version (FILE *stream, struct argp_state *state)
|
||||
Copyright (C) %s Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
"), "2007");
|
||||
"), "2006");
|
||||
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
|
||||
}
|
||||
|
||||
|
23
config.h.in
23
config.h.in
@ -19,6 +19,9 @@
|
||||
/* Defined if building with SELinux support & audit libs are detected. */
|
||||
#undef HAVE_LIBAUDIT
|
||||
|
||||
/* Defined if building with SELinux support & libcap libs are detected. */
|
||||
#undef HAVE_LIBCAP
|
||||
|
||||
/* Define if using XCOFF. Set by --with-xcoff. */
|
||||
#undef HAVE_XCOFF
|
||||
|
||||
@ -120,6 +123,23 @@
|
||||
/* Define if the linker supports the -z combreloc option. */
|
||||
#undef HAVE_Z_COMBRELOC
|
||||
|
||||
/* Define if the assembler supported .protected. */
|
||||
#undef HAVE_PROTECTED
|
||||
|
||||
/* Define if the assembler supported .hidden. */
|
||||
#undef HAVE_HIDDEN
|
||||
|
||||
/* Define if the compiler supports __attribute__ ((visibility (...))). */
|
||||
#undef HAVE_VISIBILITY_ATTRIBUTE
|
||||
|
||||
/* Define if the compiler doesn't support __attribute__ ((visibility (...)))
|
||||
together with __asm__ redirection properly. */
|
||||
#undef HAVE_BROKEN_VISIBILITY_ATTRIBUTE
|
||||
|
||||
/* Define if the compiler doesn't support __attribute__ ((alias (...)))
|
||||
together with __asm__ redirection properly. */
|
||||
#undef HAVE_BROKEN_ALIAS_ATTRIBUTE
|
||||
|
||||
/* Define if _rtld_local structure should be forced into .sdata section. */
|
||||
#undef HAVE_SDATA_SECTION
|
||||
|
||||
@ -171,6 +191,9 @@
|
||||
/* Defined if forced unwind support is available. */
|
||||
#undef HAVE_FORCED_UNWIND
|
||||
|
||||
/* Defined if the linker supports the -z relro option. */
|
||||
#undef HAVE_Z_RELRO
|
||||
|
||||
/* Defined of libidn is available. */
|
||||
#undef HAVE_LIBIDN
|
||||
|
||||
|
@ -38,9 +38,14 @@ c++-sysincludes = @CXX_SYSINCLUDES@
|
||||
all-warnings = @all_warnings@
|
||||
|
||||
elf = @elf@
|
||||
have-protected = @libc_cv_asm_protected_directive@
|
||||
have-z-nodelete = @libc_cv_z_nodelete@
|
||||
have-z-nodlopen = @libc_cv_z_nodlopen@
|
||||
have-z-initfirst = @libc_cv_z_initfirst@
|
||||
have-z-combreloc = @libc_cv_z_combreloc@
|
||||
have-z-execstack = @libc_cv_z_execstack@
|
||||
have-initfini = @libc_cv_have_initfini@
|
||||
have-z-relro = @libc_cv_z_relro@
|
||||
have-Bgroup = @libc_cv_Bgroup@
|
||||
have-as-needed = @libc_cv_as_needed@
|
||||
libgcc_s_suffix = @libc_cv_libgcc_s_suffix@
|
||||
|
81
configure
vendored
81
configure
vendored
@ -313,7 +313,7 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_cc_with_libunwind libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie libc_cv_hashstyle fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie libc_cv_hashstyle fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@ -864,7 +864,7 @@ Optional Features:
|
||||
[default=no]
|
||||
--enable-shared build shared library [default=yes if GNU ld &
|
||||
ELF]
|
||||
--enable-profile build profiled library [default=no]
|
||||
--enable-profile build profiled library [default=yes]
|
||||
--enable-omitfp build undebuggable optimized library
|
||||
[default=no]
|
||||
--enable-bounded build with runtime bounds checking
|
||||
@ -1543,7 +1543,7 @@ if test "${enable_profile+set}" = set; then
|
||||
enableval="$enable_profile"
|
||||
profile=$enableval
|
||||
else
|
||||
profile=no
|
||||
profile=yes
|
||||
fi;
|
||||
# Check whether --enable-omitfp or --disable-omitfp was given.
|
||||
if test "${enable_omitfp+set}" = set; then
|
||||
@ -5339,15 +5339,22 @@ EOF
|
||||
(exit $ac_status); }; }; then
|
||||
libc_cv_asm_protected_directive=yes
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: assembler support for symbol visibility is required" >&5
|
||||
echo "$as_me: error: assembler support for symbol visibility is required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
libc_cv_asm_protected_directive=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_asm_protected_directive" >&5
|
||||
echo "${ECHO_T}$libc_cv_asm_protected_directive" >&6
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_PROTECTED 1
|
||||
_ACEOF
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_HIDDEN 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
if test $libc_cv_asm_protected_directive = yes; then
|
||||
echo "$as_me:$LINENO: checking whether __attribute__((visibility())) is supported" >&5
|
||||
echo $ECHO_N "checking whether __attribute__((visibility())) is supported... $ECHO_C" >&6
|
||||
@ -5376,10 +5383,11 @@ EOF
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_visibility_attribute" >&5
|
||||
echo "${ECHO_T}$libc_cv_visibility_attribute" >&6
|
||||
if test $libc_cv_visibility_attribute != yes; then
|
||||
{ { echo "$as_me:$LINENO: error: compiler support for visibility attribute is required" >&5
|
||||
echo "$as_me: error: compiler support for visibility attribute is required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
if test $libc_cv_visibility_attribute = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_VISIBILITY_ATTRIBUTE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -5411,9 +5419,10 @@ fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_broken_visibility_attribute" >&5
|
||||
echo "${ECHO_T}$libc_cv_broken_visibility_attribute" >&6
|
||||
if test $libc_cv_broken_visibility_attribute = yes; then
|
||||
{ { echo "$as_me:$LINENO: error: working compiler support for visibility attribute is required" >&5
|
||||
echo "$as_me: error: working compiler support for visibility attribute is required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_BROKEN_VISIBILITY_ATTRIBUTE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -5448,9 +5457,10 @@ fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_broken_alias_attribute" >&5
|
||||
echo "${ECHO_T}$libc_cv_broken_alias_attribute" >&6
|
||||
if test $libc_cv_broken_alias_attribute = yes; then
|
||||
{ { echo "$as_me:$LINENO: error: working alias attribute support required" >&5
|
||||
echo "$as_me: error: working alias attribute support required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_BROKEN_ALIAS_ATTRIBUTE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
if test $libc_cv_visibility_attribute = yes; then
|
||||
@ -5562,15 +5572,14 @@ EOF
|
||||
then
|
||||
libc_cv_z_nodelete=yes
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: linker with -z nodelete support required" >&5
|
||||
echo "$as_me: error: linker with -z nodelete support required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
libc_cv_z_nodelete=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_z_nodelete" >&5
|
||||
echo "${ECHO_T}$libc_cv_z_nodelete" >&6
|
||||
|
||||
|
||||
echo "$as_me:$LINENO: checking for -z nodlopen option" >&5
|
||||
echo $ECHO_N "checking for -z nodlopen option... $ECHO_C" >&6
|
||||
if test "${libc_cv_z_nodlopen+set}" = set; then
|
||||
@ -5591,15 +5600,14 @@ EOF
|
||||
then
|
||||
libc_cv_z_nodlopen=yes
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: linker with -z nodlopen support required" >&5
|
||||
echo "$as_me: error: linker with -z nodlopen support required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
libc_cv_z_nodlopen=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_z_nodlopen" >&5
|
||||
echo "${ECHO_T}$libc_cv_z_nodlopen" >&6
|
||||
|
||||
|
||||
echo "$as_me:$LINENO: checking for -z initfirst option" >&5
|
||||
echo $ECHO_N "checking for -z initfirst option... $ECHO_C" >&6
|
||||
if test "${libc_cv_z_initfirst+set}" = set; then
|
||||
@ -5620,18 +5628,15 @@ EOF
|
||||
then
|
||||
libc_cv_z_initfirst=yes
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: linker with -z initfirst support required" >&5
|
||||
echo "$as_me: error: linker with -z initfirst support required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
libc_cv_z_initfirst=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_z_initfirst" >&5
|
||||
echo "${ECHO_T}$libc_cv_z_initfirst" >&6
|
||||
|
||||
case "$base_machine" in
|
||||
i[34567]86 | x86_64 | powerpc* | s390* | sparc* | alpha*)
|
||||
echo "$as_me:$LINENO: checking for -z relro option" >&5
|
||||
|
||||
echo "$as_me:$LINENO: checking for -z relro option" >&5
|
||||
echo $ECHO_N "checking for -z relro option... $ECHO_C" >&6
|
||||
if test "${libc_cv_z_relro+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
@ -5657,14 +5662,13 @@ else
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_z_relro" >&5
|
||||
echo "${ECHO_T}$libc_cv_z_relro" >&6
|
||||
if test "$libc_cv_z_relro" = no; then
|
||||
{ { echo "$as_me:$LINENO: error: linker with -z relro support required" >&5
|
||||
echo "$as_me: error: linker with -z relro support required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
if test $libc_cv_z_relro = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_Z_RELRO 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking for -Bgroup option" >&5
|
||||
echo $ECHO_N "checking for -Bgroup option... $ECHO_C" >&6
|
||||
@ -8506,7 +8510,12 @@ s,@PERL@,$PERL,;t t
|
||||
s,@INSTALL_INFO@,$INSTALL_INFO,;t t
|
||||
s,@BISON@,$BISON,;t t
|
||||
s,@VERSIONING@,$VERSIONING,;t t
|
||||
s,@libc_cv_asm_protected_directive@,$libc_cv_asm_protected_directive,;t t
|
||||
s,@libc_cv_cc_with_libunwind@,$libc_cv_cc_with_libunwind,;t t
|
||||
s,@libc_cv_z_nodelete@,$libc_cv_z_nodelete,;t t
|
||||
s,@libc_cv_z_nodlopen@,$libc_cv_z_nodlopen,;t t
|
||||
s,@libc_cv_z_initfirst@,$libc_cv_z_initfirst,;t t
|
||||
s,@libc_cv_z_relro@,$libc_cv_z_relro,;t t
|
||||
s,@libc_cv_Bgroup@,$libc_cv_Bgroup,;t t
|
||||
s,@libc_cv_libgcc_s_suffix@,$libc_cv_libgcc_s_suffix,;t t
|
||||
s,@libc_cv_as_needed@,$libc_cv_as_needed,;t t
|
||||
|
44
configure.in
44
configure.in
@ -131,9 +131,9 @@ AC_ARG_ENABLE([shared],
|
||||
[shared=default])
|
||||
AC_ARG_ENABLE([profile],
|
||||
AC_HELP_STRING([--enable-profile],
|
||||
[build profiled library @<:@default=no@:>@]),
|
||||
[build profiled library @<:@default=yes@:>@]),
|
||||
[profile=$enableval],
|
||||
[profile=no])
|
||||
[profile=yes])
|
||||
AC_ARG_ENABLE([omitfp],
|
||||
AC_HELP_STRING([--enable-omitfp],
|
||||
[build undebuggable optimized library @<:@default=no@:>@]),
|
||||
@ -1259,9 +1259,12 @@ EOF
|
||||
if AC_TRY_COMMAND(${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
||||
libc_cv_asm_protected_directive=yes
|
||||
else
|
||||
AC_MSG_ERROR(assembler support for symbol visibility is required)
|
||||
libc_cv_asm_protected_directive=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_asm_protected_directive)
|
||||
AC_DEFINE(HAVE_PROTECTED)
|
||||
AC_DEFINE(HAVE_HIDDEN)
|
||||
|
||||
if test $libc_cv_asm_protected_directive = yes; then
|
||||
AC_CACHE_CHECK(whether __attribute__((visibility())) is supported,
|
||||
@ -1280,8 +1283,8 @@ EOF
|
||||
fi
|
||||
rm -f conftest.[cs]
|
||||
])
|
||||
if test $libc_cv_visibility_attribute != yes; then
|
||||
AC_MSG_ERROR(compiler support for visibility attribute is required)
|
||||
if test $libc_cv_visibility_attribute = yes; then
|
||||
AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -1304,7 +1307,7 @@ changequote([,])dnl
|
||||
rm -f conftest.c conftest.s
|
||||
])
|
||||
if test $libc_cv_broken_visibility_attribute = yes; then
|
||||
AC_MSG_ERROR(working compiler support for visibility attribute is required)
|
||||
AC_DEFINE(HAVE_BROKEN_VISIBILITY_ATTRIBUTE)
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -1328,7 +1331,7 @@ EOF
|
||||
rm -f conftest.c conftest.s
|
||||
])
|
||||
if test $libc_cv_broken_alias_attribute = yes; then
|
||||
AC_MSG_ERROR(working alias attribute support required)
|
||||
AC_DEFINE(HAVE_BROKEN_ALIAS_ATTRIBUTE)
|
||||
fi
|
||||
|
||||
if test $libc_cv_visibility_attribute = yes; then
|
||||
@ -1400,9 +1403,10 @@ EOF
|
||||
then
|
||||
libc_cv_z_nodelete=yes
|
||||
else
|
||||
AC_MSG_ERROR(linker with -z nodelete support required)
|
||||
libc_cv_z_nodelete=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_z_nodelete)
|
||||
|
||||
AC_CACHE_CHECK(for -z nodlopen option,
|
||||
libc_cv_z_nodlopen, [dnl
|
||||
@ -1416,9 +1420,10 @@ EOF
|
||||
then
|
||||
libc_cv_z_nodlopen=yes
|
||||
else
|
||||
AC_MSG_ERROR(linker with -z nodlopen support required)
|
||||
libc_cv_z_nodlopen=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_z_nodlopen)
|
||||
|
||||
AC_CACHE_CHECK(for -z initfirst option,
|
||||
libc_cv_z_initfirst, [dnl
|
||||
@ -1432,16 +1437,13 @@ EOF
|
||||
then
|
||||
libc_cv_z_initfirst=yes
|
||||
else
|
||||
AC_MSG_ERROR(linker with -z initfirst support required)
|
||||
libc_cv_z_initfirst=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_z_initfirst)
|
||||
|
||||
case "$base_machine" in
|
||||
changequote(,)dnl
|
||||
i[34567]86 | x86_64 | powerpc* | s390* | sparc* | alpha*)
|
||||
changequote([,])dnl
|
||||
AC_CACHE_CHECK(for -z relro option,
|
||||
libc_cv_z_relro, [dnl
|
||||
AC_CACHE_CHECK(for -z relro option,
|
||||
libc_cv_z_relro, [dnl
|
||||
libc_cv_z_relro=no
|
||||
if AC_TRY_COMMAND([${CC-cc} -v --help 2>&1|grep "z relro" 1>&AS_MESSAGE_LOG_FD])
|
||||
then
|
||||
@ -1450,12 +1452,10 @@ changequote([,])dnl
|
||||
libc_cv_z_relro=yes
|
||||
fi
|
||||
fi])
|
||||
if test "$libc_cv_z_relro" = no; then
|
||||
AC_MSG_ERROR(linker with -z relro support required)
|
||||
fi
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
AC_SUBST(libc_cv_z_relro)
|
||||
if test $libc_cv_z_relro = yes; then
|
||||
AC_DEFINE(HAVE_Z_RELRO)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(for -Bgroup option,
|
||||
libc_cv_Bgroup, [dnl
|
||||
|
@ -5,7 +5,7 @@ libc {
|
||||
# helper functions
|
||||
__libc_init_first; __libc_start_main;
|
||||
|
||||
%if !HAVE___THREAD
|
||||
%if !(USE_TLS && HAVE___THREAD)
|
||||
# global variables
|
||||
_errno;
|
||||
|
||||
@ -18,7 +18,7 @@ libc {
|
||||
gnu_get_libc_release; gnu_get_libc_version;
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
%if HAVE___THREAD
|
||||
%if USE_TLS && HAVE___THREAD
|
||||
# This version is for the TLS symbol, GLIBC_2.0 is the old object symbol.
|
||||
errno;
|
||||
%endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1998-2003, 2004, 2005 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
|
||||
@ -30,7 +30,11 @@ extern int __libc_multiple_libcs;
|
||||
#include <tls.h>
|
||||
#ifndef SHARED
|
||||
# include <dl-osinfo.h>
|
||||
extern void __pthread_initialize_minimal (void);
|
||||
extern void __pthread_initialize_minimal (void)
|
||||
# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
|
||||
__attribute__ ((weak))
|
||||
# endif
|
||||
;
|
||||
# ifndef THREAD_SET_STACK_GUARD
|
||||
/* Only exported for architectures that don't store the stack guard canary
|
||||
in thread local area. */
|
||||
@ -136,8 +140,13 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
|
||||
/* Initialize the thread library at least a bit since the libgcc
|
||||
functions are using thread functions if these are available and
|
||||
we need to setup errno. */
|
||||
__pthread_initialize_minimal ();
|
||||
we need to setup errno. If there is no thread library and we
|
||||
handle TLS the function is defined in the libc to initialized the
|
||||
TLS handling. */
|
||||
# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
|
||||
if (__pthread_initialize_minimal)
|
||||
# endif
|
||||
__pthread_initialize_minimal ();
|
||||
#endif
|
||||
|
||||
# ifndef SHARED
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Initialization code for TLS in statically linked application.
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2004, 2005 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
|
||||
@ -29,6 +29,7 @@
|
||||
#error makefile bug, this file is for static only
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
extern ElfW(Phdr) *_dl_phdr;
|
||||
extern size_t _dl_phnum;
|
||||
|
||||
@ -142,19 +143,19 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
The initialized value of _dl_tls_static_size is provided by dl-open.c
|
||||
to request some surplus that permits dynamic loading of modules with
|
||||
IE-model TLS. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
|
||||
tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
tcb_offset = roundup (tcbsize, align ?: 1);
|
||||
tlsblock = __sbrk (tcb_offset + memsz + max_align
|
||||
+ TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
|
||||
tlsblock += TLS_PRE_TCB_SIZE;
|
||||
#else
|
||||
# else
|
||||
/* In case a model with a different layout for the TCB and DTV
|
||||
is defined add another #elif here and in the following #ifs. */
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* Align the TLS block. */
|
||||
tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
|
||||
@ -165,16 +166,16 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
// static_dtv[1].counter = 0; would be needed if not already done
|
||||
|
||||
/* Initialize the TLS block. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
|
||||
- roundup (memsz, align ?: 1));
|
||||
static_map.l_tls_offset = roundup (memsz, align ?: 1);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
|
||||
static_map.l_tls_offset = tcb_offset;
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
static_dtv[2].pointer.is_static = true;
|
||||
/* sbrk gives us zero'd memory, so we don't need to clear the remainder. */
|
||||
memcpy (static_dtv[2].pointer.val, initimage, filesz);
|
||||
@ -182,16 +183,16 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
/* Install the pointer to the dtv. */
|
||||
|
||||
/* Initialize the thread pointer. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
|
||||
|
||||
const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
INSTALL_DTV (tlsblock, static_dtv);
|
||||
const char *lossage = TLS_INIT_TP (tlsblock, 0);
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
if (__builtin_expect (lossage != NULL, 0))
|
||||
__libc_fatal (lossage);
|
||||
|
||||
@ -211,11 +212,11 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
|
||||
memsz = roundup (memsz, align ?: 1);
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
memsz += tcbsize;
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
memsz += tcb_offset;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
|
||||
}
|
||||
@ -229,11 +230,11 @@ _dl_tls_setup (void)
|
||||
{
|
||||
init_slotinfo ();
|
||||
init_static_tls (
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
TLS_TCB_SIZE,
|
||||
#else
|
||||
# else
|
||||
0,
|
||||
#endif
|
||||
# endif
|
||||
TLS_TCB_ALIGN);
|
||||
return 0;
|
||||
}
|
||||
@ -247,3 +248,16 @@ __pthread_initialize_minimal (void)
|
||||
{
|
||||
__libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
|
||||
}
|
||||
|
||||
#elif defined NONTLS_INIT_TP
|
||||
|
||||
/* This is the minimal initialization function used when libpthread is
|
||||
not used. */
|
||||
void
|
||||
__attribute__ ((weak))
|
||||
__pthread_initialize_minimal (void)
|
||||
{
|
||||
NONTLS_INIT_TP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
113
csu/tst-atomic.c
113
csu/tst-atomic.c
@ -1,5 +1,5 @@
|
||||
/* Tests for atomic.h macros.
|
||||
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
|
||||
|
||||
@ -379,117 +379,6 @@ do_test (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef catomic_compare_and_exchange_val_acq
|
||||
mem = 24;
|
||||
if (catomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24
|
||||
|| mem != 35)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_val_acq test 1 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = 12;
|
||||
if (catomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12
|
||||
|| mem != 12)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_val_acq test 2 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -15;
|
||||
if (catomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15
|
||||
|| mem != -56)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_val_acq test 3 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -1;
|
||||
if (catomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1
|
||||
|| mem != -1)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_val_acq test 4 failed");
|
||||
ret = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
mem = 24;
|
||||
if (catomic_compare_and_exchange_bool_acq (&mem, 35, 24)
|
||||
|| mem != 35)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_bool_acq test 1 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = 12;
|
||||
if (! catomic_compare_and_exchange_bool_acq (&mem, 10, 15)
|
||||
|| mem != 12)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_bool_acq test 2 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -15;
|
||||
if (catomic_compare_and_exchange_bool_acq (&mem, -56, -15)
|
||||
|| mem != -56)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_bool_acq test 3 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -1;
|
||||
if (! catomic_compare_and_exchange_bool_acq (&mem, 17, 0)
|
||||
|| mem != -1)
|
||||
{
|
||||
puts ("catomic_compare_and_exchange_bool_acq test 4 failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = 2;
|
||||
if (catomic_exchange_and_add (&mem, 11) != 2
|
||||
|| mem != 13)
|
||||
{
|
||||
puts ("catomic_exchange_and_add test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -21;
|
||||
catomic_add (&mem, 22);
|
||||
if (mem != 1)
|
||||
{
|
||||
puts ("catomic_add test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = -1;
|
||||
catomic_increment (&mem);
|
||||
if (mem != 0)
|
||||
{
|
||||
puts ("catomic_increment test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = 2;
|
||||
if (catomic_increment_val (&mem) != 3)
|
||||
{
|
||||
puts ("catomic_increment_val test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mem = 17;
|
||||
catomic_decrement (&mem);
|
||||
if (mem != 16)
|
||||
{
|
||||
puts ("catomic_decrement test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (catomic_decrement_val (&mem) != 15)
|
||||
{
|
||||
puts ("catomic_decrement_val test failed");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1992-2006, 2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2002, 2003, 2004, 2006 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
|
||||
@ -25,7 +25,7 @@ static const char __libc_version[] = VERSION;
|
||||
|
||||
static const char banner[] =
|
||||
"GNU C Library "RELEASE" release version "VERSION", by Roland McGrath et al.\n\
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.\n\
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions.\n\
|
||||
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
|
||||
PARTICULAR PURPOSE.\n\
|
||||
@ -34,6 +34,9 @@ Compiled by GNU CC version "__VERSION__".\n"
|
||||
#ifdef GLIBC_OLDEST_ABI
|
||||
"The oldest ABI supported: " GLIBC_OLDEST_ABI ".\n"
|
||||
#endif
|
||||
#ifdef USE_TLS
|
||||
"Thread-local storage support included.\n"
|
||||
#endif
|
||||
"For bug reporting instructions, please see:\n\
|
||||
<http://www.gnu.org/software/libc/bugs.html>.\n";
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#! /bin/sh
|
||||
# Copyright (C) 1998,1999,2001,2003,2004,2006,2007
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright (C) 1998,1999,2001,2003,2004,2006 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
# Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
@ -40,7 +39,7 @@ if test $# -eq 0; then
|
||||
;;
|
||||
--v | --ve | --ver | --vers | --versi | --versio | --version)
|
||||
echo 'catchsegv (GNU libc) @VERSION@'
|
||||
echo 'Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
echo 'Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
Written by Ulrich Drepper.'
|
||||
|
@ -64,7 +64,7 @@ do_version() {
|
||||
printf $"Copyright (C) %s Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
" "2007"
|
||||
" "2006"
|
||||
printf $"Written by %s.
|
||||
" "Ulrich Drepper"
|
||||
exit 0
|
||||
@ -161,32 +161,32 @@ if test -n "$data"; then
|
||||
while read fct; do
|
||||
read file
|
||||
if test "$fct" != '??' -a "$file" != '??:0'; then
|
||||
format_line $fct $file
|
||||
format_line "$fct" "$file"
|
||||
fi
|
||||
done
|
||||
else
|
||||
fifo=$(mktemp -u ${TMPDIR:-/tmp}/xtrace.XXXXXX)
|
||||
fifo=$(mktemp -ut xtrace.XXXXXX) || exit
|
||||
trap 'rm -f "$fifo"; exit 1' HUP INT QUIT TERM PIPE
|
||||
mkfifo -m 0600 $fifo || exit 1
|
||||
trap 'rm $fifo; exit 1' SIGINT SIGTERM SIGPIPE
|
||||
|
||||
# Now start the program and let it write to the FIFO.
|
||||
$TERMINAL_PROG -T "xtrace - $program $*" -e /bin/sh -c "LD_PRELOAD=$pcprofileso PCPROFILE_OUTPUT=$fifo $program $*; read < $fifo" &
|
||||
termpid=$!
|
||||
$pcprofiledump -u $fifo |
|
||||
$pcprofiledump -u "$fifo" |
|
||||
while read line; do
|
||||
echo $line |
|
||||
echo "$line" |
|
||||
sed 's/this = \([^,]*\).*/\1/' |
|
||||
addr2line -fC -e $program
|
||||
addr2line -fC -e "$program"
|
||||
done |
|
||||
while read fct; do
|
||||
read file
|
||||
if test "$fct" != '??' -a "$file" != '??:0'; then
|
||||
format_line $fct $file
|
||||
format_line "$fct" "$file"
|
||||
fi
|
||||
done
|
||||
read -p "Press return here to close $TERMINAL_PROG($program)."
|
||||
echo > $fifo
|
||||
rm $fifo
|
||||
echo > "$fifo"
|
||||
rm "$fifo"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
@ -41,7 +41,10 @@ endif
|
||||
ifeq (yes,$(build-shared))
|
||||
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
|
||||
bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
|
||||
bug-atexit3 tstatexit
|
||||
bug-atexit3
|
||||
ifeq (yes,$(have-protected))
|
||||
tests += tstatexit
|
||||
endif
|
||||
endif
|
||||
modules-names = glreflib1 glreflib2 failtestmod defaultmod1 defaultmod2 \
|
||||
errmsg1mod modatexit modcxaatexit \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* dlinfo -- Get information from the dynamic linker.
|
||||
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2006, 2007 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
|
||||
@ -32,7 +32,9 @@ dlinfo (void *handle, int request, void *arg)
|
||||
|
||||
#else
|
||||
|
||||
# include <dl-tls.h>
|
||||
# ifdef USE_TLS
|
||||
# include <dl-tls.h>
|
||||
# endif
|
||||
|
||||
struct dlinfo_args
|
||||
{
|
||||
@ -56,9 +58,8 @@ dlinfo_doit (void *argsblock)
|
||||
/* Find the highest-addressed object that CALLER is not below. */
|
||||
for (nsid = 0; nsid < DL_NNS; ++nsid)
|
||||
for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end)
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end
|
||||
&& (l->l_contiguous || _dl_addr_inside_object (l, caller)))
|
||||
break;
|
||||
|
||||
if (l == NULL)
|
||||
@ -95,14 +96,18 @@ RTLD_SELF used in code not dynamically loaded"));
|
||||
|
||||
case RTLD_DI_TLS_MODID:
|
||||
*(size_t *) args->arg = 0;
|
||||
#ifdef USE_TLS
|
||||
*(size_t *) args->arg = l->l_tls_modid;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case RTLD_DI_TLS_DATA:
|
||||
{
|
||||
void *data = NULL;
|
||||
#ifdef USE_TLS
|
||||
if (l->l_tls_modid != 0)
|
||||
data = _dl_tls_get_addr_soft (l);
|
||||
#endif
|
||||
*(void **) args->arg = data;
|
||||
break;
|
||||
}
|
||||
|
14
elf/Makefile
14
elf/Makefile
@ -159,8 +159,8 @@ endif
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
constload1 order $(tests-vis-$(have-protected)) noload filter unload \
|
||||
reldep reldep2 reldep3 reldep4 nodelete nodelete2 \
|
||||
nodlopen nodlopen2 neededtest neededtest2 \
|
||||
reldep reldep2 reldep3 reldep4 $(tests-nodelete-$(have-z-nodelete)) \
|
||||
$(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \
|
||||
neededtest3 neededtest4 unload2 lateglobal initfirst global \
|
||||
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
|
||||
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
|
||||
@ -175,6 +175,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
# reldep9
|
||||
test-srcs = tst-pathopt
|
||||
tests-vis-yes = vismain
|
||||
tests-nodelete-yes = nodelete nodelete2
|
||||
tests-nodlopen-yes = nodlopen nodlopen2
|
||||
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
|
||||
endif
|
||||
ifeq (yesyes,$(have-fpie)$(build-shared))
|
||||
@ -184,9 +186,8 @@ tests: $(objpfx)tst-leaks1-mem
|
||||
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
testobj1_1 failobj constload2 constload3 unloadmod \
|
||||
dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
|
||||
nodelmod1 nodelmod2 nodelmod3 nodelmod4 \
|
||||
nodel2mod1 nodel2mod2 nodel2mod3 \
|
||||
nodlopenmod nodlopenmod2 filtmod1 filtmod2 \
|
||||
$(modules-nodelete-$(have-z-nodelete)) \
|
||||
$(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
|
||||
reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
|
||||
reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \
|
||||
neededobj1 neededobj2 neededobj3 neededobj4 \
|
||||
@ -220,6 +221,9 @@ ifeq (yesyes,$(have-fpie)$(build-shared))
|
||||
modules-names += tst-piemod1
|
||||
endif
|
||||
modules-vis-yes = vismod1 vismod2 vismod3
|
||||
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4 \
|
||||
nodel2mod1 nodel2mod2 nodel2mod3
|
||||
modules-nodlopen-yes = nodlopenmod nodlopenmod2
|
||||
modules-execstack-yes = tst-execstack-mod
|
||||
extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
|
||||
# We need this variable to be sure the test modules get the right CPPFLAGS.
|
||||
|
@ -439,7 +439,7 @@ save_cache (const char *cache_name)
|
||||
}
|
||||
|
||||
if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache data failed."));
|
||||
|
||||
close (fd);
|
||||
|
||||
|
242
elf/dl-addr.c
242
elf/dl-addr.c
@ -1,5 +1,5 @@
|
||||
/* Locate the shared object symbol nearest a given address.
|
||||
Copyright (C) 1996-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2004, 2005, 2006, 2007 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
|
||||
@ -22,139 +22,149 @@
|
||||
#include <ldsodefs.h>
|
||||
|
||||
|
||||
static void
|
||||
__attribute ((always_inline))
|
||||
determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
|
||||
struct link_map **mapp, const ElfW(Sym) **symbolp)
|
||||
{
|
||||
/* Now we know what object the address lies in. */
|
||||
info->dli_fname = match->l_name;
|
||||
info->dli_fbase = (void *) match->l_map_start;
|
||||
|
||||
/* If this is the main program the information is incomplete. */
|
||||
if (__builtin_expect (match->l_name[0], 'a') == '\0'
|
||||
&& match->l_type == lt_executable)
|
||||
info->dli_fname = _dl_argv[0];
|
||||
|
||||
const ElfW(Sym) *symtab
|
||||
= (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
|
||||
const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
|
||||
|
||||
ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
|
||||
|
||||
const ElfW(Sym) *matchsym = NULL;
|
||||
if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
|
||||
{
|
||||
/* We look at all symbol table entries referenced by the hash
|
||||
table. */
|
||||
for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
|
||||
{
|
||||
Elf32_Word symndx = match->l_gnu_buckets[bucket];
|
||||
if (symndx != 0)
|
||||
{
|
||||
const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
|
||||
|
||||
do
|
||||
{
|
||||
/* The hash table never references local symbols so
|
||||
we can omit that test here. */
|
||||
if ((symtab[symndx].st_shndx != SHN_UNDEF
|
||||
|| symtab[symndx].st_value != 0)
|
||||
#ifdef USE_TLS
|
||||
&& ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
|
||||
#endif
|
||||
&& DL_ADDR_SYM_MATCH (match, &symtab[symndx],
|
||||
matchsym, addr)
|
||||
&& symtab[symndx].st_name < strtabsize)
|
||||
matchsym = (ElfW(Sym) *) &symtab[symndx];
|
||||
|
||||
++symndx;
|
||||
}
|
||||
while ((*hasharr++ & 1u) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ElfW(Sym) *symtabend;
|
||||
if (match->l_info[DT_HASH] != NULL)
|
||||
symtabend = (symtab
|
||||
+ ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
|
||||
else
|
||||
/* There is no direct way to determine the number of symbols in the
|
||||
dynamic symbol table and no hash table is present. The ELF
|
||||
binary is ill-formed but what shall we do? Use the beginning of
|
||||
the string table which generally follows the symbol table. */
|
||||
symtabend = (const ElfW(Sym) *) strtab;
|
||||
|
||||
for (; (void *) symtab < (void *) symtabend; ++symtab)
|
||||
if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
|
||||
|| ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
|
||||
#ifdef USE_TLS
|
||||
&& ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
|
||||
#endif
|
||||
&& (symtab->st_shndx != SHN_UNDEF
|
||||
|| symtab->st_value != 0)
|
||||
&& DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
|
||||
&& symtab->st_name < strtabsize)
|
||||
matchsym = (ElfW(Sym) *) symtab;
|
||||
}
|
||||
|
||||
if (mapp)
|
||||
*mapp = match;
|
||||
if (symbolp)
|
||||
*symbolp = matchsym;
|
||||
|
||||
if (matchsym)
|
||||
{
|
||||
/* We found a symbol close by. Fill in its name and exact
|
||||
address. */
|
||||
lookup_t matchl = LOOKUP_VALUE (match);
|
||||
|
||||
info->dli_sname = strtab + matchsym->st_name;
|
||||
info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No symbol matches. We return only the containing object. */
|
||||
info->dli_sname = NULL;
|
||||
info->dli_saddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
_dl_addr (const void *address, Dl_info *info,
|
||||
struct link_map **mapp, const ElfW(Sym) **symbolp)
|
||||
{
|
||||
const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
|
||||
int result = 0;
|
||||
|
||||
/* Protect against concurrent loads and unloads. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
|
||||
/* Find the highest-addressed object that ADDRESS is not below. */
|
||||
struct link_map *match = NULL;
|
||||
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
|
||||
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next)
|
||||
if (addr >= l->l_map_start && addr < l->l_map_end)
|
||||
if (addr >= l->l_map_start && addr < l->l_map_end
|
||||
&& (l->l_contiguous || _dl_addr_inside_object (l, addr)))
|
||||
{
|
||||
/* We know ADDRESS lies within L if in any shared object.
|
||||
Make sure it isn't past the end of L's segments. */
|
||||
size_t n = l->l_phnum;
|
||||
if (n > 0)
|
||||
{
|
||||
do
|
||||
--n;
|
||||
while (l->l_phdr[n].p_type != PT_LOAD);
|
||||
if (addr >= (l->l_addr +
|
||||
l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
|
||||
/* Off the end of the highest-addressed shared object. */
|
||||
continue;
|
||||
}
|
||||
|
||||
match = l;
|
||||
break;
|
||||
determine_info (addr, l, info, mapp, symbolp);
|
||||
result = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
if (match != NULL)
|
||||
{
|
||||
/* Now we know what object the address lies in. */
|
||||
info->dli_fname = match->l_name;
|
||||
info->dli_fbase = (void *) match->l_map_start;
|
||||
|
||||
/* If this is the main program the information is incomplete. */
|
||||
if (__builtin_expect (match->l_name[0], 'a') == '\0'
|
||||
&& match->l_type == lt_executable)
|
||||
info->dli_fname = _dl_argv[0];
|
||||
|
||||
const ElfW(Sym) *symtab
|
||||
= (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
|
||||
const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
|
||||
|
||||
ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
|
||||
|
||||
const ElfW(Sym) *matchsym = NULL;
|
||||
if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
|
||||
{
|
||||
/* We look at all symbol table entries referenced by the
|
||||
hash table. */
|
||||
for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
|
||||
{
|
||||
Elf32_Word symndx = match->l_gnu_buckets[bucket];
|
||||
if (symndx != 0)
|
||||
{
|
||||
const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
|
||||
|
||||
do
|
||||
{
|
||||
/* The hash table never references local symbols
|
||||
so we can omit that test here. */
|
||||
if ((symtab[symndx].st_shndx != SHN_UNDEF
|
||||
|| symtab[symndx].st_value != 0)
|
||||
&& ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
|
||||
&& DL_ADDR_SYM_MATCH (match, &symtab[symndx],
|
||||
matchsym, addr)
|
||||
&& symtab[symndx].st_name < strtabsize)
|
||||
matchsym = (ElfW(Sym) *) &symtab[symndx];
|
||||
|
||||
++symndx;
|
||||
}
|
||||
while ((*hasharr++ & 1u) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ElfW(Sym) *symtabend;
|
||||
if (match->l_info[DT_HASH] != NULL)
|
||||
symtabend = (symtab
|
||||
+ ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
|
||||
else
|
||||
/* There is no direct way to determine the number of symbols in the
|
||||
dynamic symbol table and no hash table is present. The ELF
|
||||
binary is ill-formed but what shall we do? Use the beginning of
|
||||
the string table which generally follows the symbol table. */
|
||||
symtabend = (const ElfW(Sym) *) strtab;
|
||||
|
||||
for (; (void *) symtab < (void *) symtabend; ++symtab)
|
||||
if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
|
||||
|| ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
|
||||
&& ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
|
||||
&& (symtab->st_shndx != SHN_UNDEF
|
||||
|| symtab->st_value != 0)
|
||||
&& DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
|
||||
&& symtab->st_name < strtabsize)
|
||||
matchsym = (ElfW(Sym) *) symtab;
|
||||
}
|
||||
|
||||
if (mapp)
|
||||
*mapp = match;
|
||||
if (symbolp)
|
||||
*symbolp = matchsym;
|
||||
|
||||
if (matchsym)
|
||||
{
|
||||
/* We found a symbol close by. Fill in its name and exact
|
||||
address. */
|
||||
lookup_t matchl = LOOKUP_VALUE (match);
|
||||
|
||||
info->dli_sname = strtab + matchsym->st_name;
|
||||
info->dli_saddr = DL_SYMBOL_ADDRESS (matchl, matchsym);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No symbol matches. We return only the containing object. */
|
||||
info->dli_sname = NULL;
|
||||
info->dli_saddr = NULL;
|
||||
}
|
||||
|
||||
result = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
|
||||
return result;
|
||||
}
|
||||
libc_hidden_def (_dl_addr)
|
||||
|
||||
/* Return non-zero if ADDR lies within one of L's segments. */
|
||||
int
|
||||
internal_function
|
||||
_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
|
||||
{
|
||||
int n = l->l_phnum;
|
||||
const ElfW(Addr) reladdr = addr - l->l_addr;
|
||||
|
||||
while (--n >= 0)
|
||||
if (l->l_phdr[n].p_type == PT_LOAD
|
||||
&& reladdr - l->l_phdr[n].p_vaddr >= 0
|
||||
&& reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -256,7 +256,11 @@ _dl_load_cache_lookup (const char *name)
|
||||
platform = 1ULL << platform;
|
||||
|
||||
/* Only accept hwcap if it's for the right platform. */
|
||||
#define _DL_HWCAP_TLS_MASK (1LL << 63)
|
||||
#ifdef USE_TLS
|
||||
# define _DL_HWCAP_TLS_MASK (1LL << 63)
|
||||
#else
|
||||
# define _DL_HWCAP_TLS_MASK 0
|
||||
#endif
|
||||
#define HWCAP_CHECK \
|
||||
if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion)) \
|
||||
continue; \
|
||||
|
158
elf/dl-close.c
158
elf/dl-close.c
@ -1,5 +1,5 @@
|
||||
/* Close a shared object opened by `_dl_open'.
|
||||
Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2005, 2006, 2007 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
|
||||
@ -31,6 +31,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sysdep-cancel.h>
|
||||
#include <tls.h>
|
||||
|
||||
|
||||
/* Type of the constructor functions. */
|
||||
@ -41,6 +42,7 @@ typedef void (*fini_t) (void);
|
||||
#define IDX_STILL_USED -1
|
||||
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Returns true we an non-empty was found. */
|
||||
static bool
|
||||
remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
@ -102,13 +104,12 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
/* No non-entry in this list element. */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
_dl_close_worker (struct link_map *map)
|
||||
{
|
||||
Lmid_t ns = map->l_ns;
|
||||
|
||||
/* One less direct use. */
|
||||
--map->l_direct_opencount;
|
||||
|
||||
@ -131,11 +132,16 @@ _dl_close_worker (struct link_map *map)
|
||||
return;
|
||||
}
|
||||
|
||||
Lmid_t nsid = map->l_ns;
|
||||
struct link_namespaces *ns = &GL(dl_ns)[nsid];
|
||||
|
||||
retry:
|
||||
dl_close_state = pending;
|
||||
|
||||
#ifdef USE_TLS
|
||||
bool any_tls = false;
|
||||
const unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
|
||||
#endif
|
||||
const unsigned int nloaded = ns->_ns_nloaded;
|
||||
char used[nloaded];
|
||||
char done[nloaded];
|
||||
struct link_map *maps[nloaded];
|
||||
@ -143,7 +149,7 @@ _dl_close_worker (struct link_map *map)
|
||||
/* Run over the list and assign indexes to the link maps and enter
|
||||
them into the MAPS array. */
|
||||
int idx = 0;
|
||||
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
|
||||
for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next)
|
||||
{
|
||||
l->l_idx = idx;
|
||||
maps[idx] = l;
|
||||
@ -220,20 +226,22 @@ _dl_close_worker (struct link_map *map)
|
||||
}
|
||||
|
||||
/* Sort the entries. */
|
||||
_dl_sort_fini (GL(dl_ns)[ns]._ns_loaded, maps, nloaded, used, ns);
|
||||
_dl_sort_fini (ns->_ns_loaded, maps, nloaded, used, nsid);
|
||||
|
||||
/* Call all termination functions at once. */
|
||||
#ifdef SHARED
|
||||
bool do_audit = GLRO(dl_naudit) > 0 && !GL(dl_ns)[ns]._ns_loaded->l_auditing;
|
||||
bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
|
||||
#endif
|
||||
bool unload_any = false;
|
||||
bool scope_mem_left = false;
|
||||
unsigned int unload_global = 0;
|
||||
unsigned int first_loaded = ~0;
|
||||
for (unsigned int i = 0; i < nloaded; ++i)
|
||||
{
|
||||
struct link_map *imap = maps[i];
|
||||
|
||||
/* All elements must be in the same namespace. */
|
||||
assert (imap->l_ns == ns);
|
||||
assert (imap->l_ns == nsid);
|
||||
|
||||
if (!used[i])
|
||||
{
|
||||
@ -248,7 +256,7 @@ _dl_close_worker (struct link_map *map)
|
||||
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
|
||||
0))
|
||||
_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
|
||||
imap->l_name, ns);
|
||||
imap->l_name, nsid);
|
||||
|
||||
if (imap->l_info[DT_FINI_ARRAY] != NULL)
|
||||
{
|
||||
@ -291,6 +299,9 @@ _dl_close_worker (struct link_map *map)
|
||||
/* We indeed have an object to remove. */
|
||||
unload_any = true;
|
||||
|
||||
if (imap->l_global)
|
||||
++unload_global;
|
||||
|
||||
/* Remember where the first dynamically loaded object is. */
|
||||
if (i < first_loaded)
|
||||
first_loaded = i;
|
||||
@ -334,7 +345,7 @@ _dl_close_worker (struct link_map *map)
|
||||
struct link_map *tmap = (struct link_map *)
|
||||
((char *) imap->l_scope[cnt]
|
||||
- offsetof (struct link_map, l_searchlist));
|
||||
assert (tmap->l_ns == ns);
|
||||
assert (tmap->l_ns == nsid);
|
||||
if (tmap->l_idx == IDX_STILL_USED)
|
||||
++remain;
|
||||
else
|
||||
@ -399,18 +410,18 @@ _dl_close_worker (struct link_map *map)
|
||||
|
||||
struct r_scope_elem **old = imap->l_scope;
|
||||
|
||||
if (RTLD_SINGLE_THREAD_P)
|
||||
imap->l_scope = newp;
|
||||
else
|
||||
{
|
||||
__rtld_mrlock_change (imap->l_scope_lock);
|
||||
imap->l_scope = newp;
|
||||
__rtld_mrlock_done (imap->l_scope_lock);
|
||||
}
|
||||
imap->l_scope = newp;
|
||||
|
||||
/* No user anymore, we can free it now. */
|
||||
if (old != imap->l_scope_mem)
|
||||
free (old);
|
||||
{
|
||||
if (_dl_scope_free (old))
|
||||
/* If _dl_scope_free used THREAD_GSCOPE_WAIT (),
|
||||
no need to repeat it. */
|
||||
scope_mem_left = false;
|
||||
}
|
||||
else
|
||||
scope_mem_left = true;
|
||||
|
||||
imap->l_scope_max = new_size;
|
||||
}
|
||||
@ -435,7 +446,7 @@ _dl_close_worker (struct link_map *map)
|
||||
/* Auditing checkpoint: we will start deleting objects. */
|
||||
if (__builtin_expect (do_audit, 0))
|
||||
{
|
||||
struct link_map *head = GL(dl_ns)[ns]._ns_loaded;
|
||||
struct link_map *head = ns->_ns_loaded;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
@ -452,13 +463,55 @@ _dl_close_worker (struct link_map *map)
|
||||
#endif
|
||||
|
||||
/* Notify the debugger we are about to remove some loaded objects. */
|
||||
struct r_debug *r = _dl_debug_initialize (0, ns);
|
||||
struct r_debug *r = _dl_debug_initialize (0, nsid);
|
||||
r->r_state = RT_DELETE;
|
||||
_dl_debug_state ();
|
||||
|
||||
if (unload_global)
|
||||
{
|
||||
/* Some objects are in the global scope list. Remove them. */
|
||||
struct r_scope_elem *ns_msl = ns->_ns_main_searchlist;
|
||||
unsigned int i;
|
||||
unsigned int j = 0;
|
||||
unsigned int cnt = ns_msl->r_nlist;
|
||||
|
||||
while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed)
|
||||
--cnt;
|
||||
|
||||
if (cnt + unload_global == ns_msl->r_nlist)
|
||||
/* Speed up removing most recently added objects. */
|
||||
j = cnt;
|
||||
else
|
||||
for (i = 0; i < cnt; i++)
|
||||
if (ns_msl->r_list[i]->l_removed == 0)
|
||||
{
|
||||
if (i != j)
|
||||
ns_msl->r_list[j] = ns_msl->r_list[i];
|
||||
j++;
|
||||
}
|
||||
ns_msl->r_nlist = j;
|
||||
}
|
||||
|
||||
if (!RTLD_SINGLE_THREAD_P
|
||||
&& (unload_global
|
||||
|| scope_mem_left
|
||||
|| (GL(dl_scope_free_list) != NULL
|
||||
&& GL(dl_scope_free_list)->count)))
|
||||
{
|
||||
struct dl_scope_free_list *fsl;
|
||||
|
||||
THREAD_GSCOPE_WAIT ();
|
||||
/* Now we can free any queued old scopes. */
|
||||
if ((fsl = GL(dl_scope_free_list)) != NULL)
|
||||
while (fsl->count > 0)
|
||||
free (fsl->list[--fsl->count]);
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
size_t tls_free_start;
|
||||
size_t tls_free_end;
|
||||
tls_free_start = tls_free_end = NO_TLS_OFFSET;
|
||||
#endif
|
||||
|
||||
/* Check each element of the search list to see if all references to
|
||||
it are gone. */
|
||||
@ -471,24 +524,8 @@ _dl_close_worker (struct link_map *map)
|
||||
|
||||
/* That was the last reference, and this was a dlopen-loaded
|
||||
object. We can unmap it. */
|
||||
if (__builtin_expect (imap->l_global, 0))
|
||||
{
|
||||
/* This object is in the global scope list. Remove it. */
|
||||
unsigned int cnt = GL(dl_ns)[ns]._ns_main_searchlist->r_nlist;
|
||||
|
||||
do
|
||||
--cnt;
|
||||
while (GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt] != imap);
|
||||
|
||||
/* The object was already correctly registered. */
|
||||
while (++cnt
|
||||
< GL(dl_ns)[ns]._ns_main_searchlist->r_nlist)
|
||||
GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt - 1]
|
||||
= GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt];
|
||||
|
||||
--GL(dl_ns)[ns]._ns_main_searchlist->r_nlist;
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Remove the object from the dtv slotinfo array if it uses TLS. */
|
||||
if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
|
||||
{
|
||||
@ -507,7 +544,7 @@ _dl_close_worker (struct link_map *map)
|
||||
this search list, going in either direction. When the
|
||||
whole chunk is at the end of the used area then we can
|
||||
reclaim it. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
if (tls_free_start == NO_TLS_OFFSET
|
||||
|| (size_t) imap->l_tls_offset == tls_free_start)
|
||||
{
|
||||
@ -547,7 +584,7 @@ _dl_close_worker (struct link_map *map)
|
||||
= tls_free_end - imap->l_tls_blocksize;
|
||||
}
|
||||
}
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
if ((size_t) imap->l_tls_offset == tls_free_end)
|
||||
/* Extend the contiguous chunk being reclaimed. */
|
||||
tls_free_end -= imap->l_tls_blocksize;
|
||||
@ -564,11 +601,12 @@ _dl_close_worker (struct link_map *map)
|
||||
tls_free_start = imap->l_tls_offset;
|
||||
tls_free_end = tls_free_start + imap->l_tls_blocksize;
|
||||
}
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We can unmap all the maps at once. We determined the
|
||||
start address and length when we loaded the object and
|
||||
@ -581,12 +619,12 @@ _dl_close_worker (struct link_map *map)
|
||||
else
|
||||
{
|
||||
#ifdef SHARED
|
||||
assert (ns != LM_ID_BASE);
|
||||
assert (nsid != LM_ID_BASE);
|
||||
#endif
|
||||
GL(dl_ns)[ns]._ns_loaded = imap->l_next;
|
||||
ns->_ns_loaded = imap->l_next;
|
||||
}
|
||||
|
||||
--GL(dl_ns)[ns]._ns_nloaded;
|
||||
--ns->_ns_nloaded;
|
||||
if (imap->l_next != NULL)
|
||||
imap->l_next->l_prev = imap->l_prev;
|
||||
|
||||
@ -634,6 +672,7 @@ _dl_close_worker (struct link_map *map)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* If we removed any object which uses TLS bump the generation counter. */
|
||||
if (any_tls)
|
||||
{
|
||||
@ -643,12 +682,13 @@ _dl_close_worker (struct link_map *map)
|
||||
if (tls_free_end == GL(dl_tls_static_used))
|
||||
GL(dl_tls_static_used) = tls_free_start;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have deleted all objects. */
|
||||
if (__builtin_expect (do_audit, 0))
|
||||
{
|
||||
struct link_map *head = GL(dl_ns)[ns]._ns_loaded;
|
||||
struct link_map *head = ns->_ns_loaded;
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
{
|
||||
@ -702,6 +742,7 @@ _dl_close (void *_map)
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_TLS
|
||||
static bool __libc_freeres_fn_section
|
||||
free_slotinfo (struct dtv_slotinfo_list **elemp)
|
||||
{
|
||||
@ -728,45 +769,52 @@ free_slotinfo (struct dtv_slotinfo_list **elemp)
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
libc_freeres_fn (free_mem)
|
||||
{
|
||||
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
|
||||
if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
|
||||
&& (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
|
||||
for (Lmid_t nsid = 0; nsid < DL_NNS; ++nsid)
|
||||
if (__builtin_expect (GL(dl_ns)[nsid]._ns_global_scope_alloc, 0) != 0
|
||||
&& (GL(dl_ns)[nsid]._ns_main_searchlist->r_nlist
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
== GLRO(dl_initial_searchlist).r_nlist))
|
||||
{
|
||||
/* All object dynamically loaded by the program are unloaded. Free
|
||||
the memory allocated for the global scope variable. */
|
||||
struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
|
||||
struct link_map **old = GL(dl_ns)[nsid]._ns_main_searchlist->r_list;
|
||||
|
||||
/* Put the old map in. */
|
||||
GL(dl_ns)[ns]._ns_main_searchlist->r_list
|
||||
GL(dl_ns)[nsid]._ns_main_searchlist->r_list
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
= GLRO(dl_initial_searchlist).r_list;
|
||||
/* Signal that the original map is used. */
|
||||
GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
|
||||
GL(dl_ns)[nsid]._ns_global_scope_alloc = 0;
|
||||
|
||||
/* Now free the old map. */
|
||||
free (old);
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL)
|
||||
{
|
||||
/* Free the memory allocated for the dtv slotinfo array. We can do
|
||||
this only if all modules which used this memory are unloaded. */
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
if (GL(dl_initial_dtv) == NULL)
|
||||
/* There was no initial TLS setup, it was set up later when
|
||||
it used the normal malloc. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
|
||||
else
|
||||
#endif
|
||||
# endif
|
||||
/* The first element of the list does not have to be deallocated.
|
||||
It was allocated in the dynamic linker (i.e., with a different
|
||||
malloc), and in the static library it's in .bss space. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *scope_free_list = GL(dl_scope_free_list);
|
||||
GL(dl_scope_free_list) = NULL;
|
||||
free (scope_free_list);
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ DST not allowed in SUID/SGID programs")); \
|
||||
processed. */ \
|
||||
if (fatal) \
|
||||
_dl_signal_error (0, __str, NULL, N_("\
|
||||
empty dynamic string token substitution")); \
|
||||
empty dynamics string token substitution")); \
|
||||
else \
|
||||
{ \
|
||||
/* This is for DT_AUXILIARY. */ \
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Handling of dynamic sring tokens.
|
||||
Copyright (C) 1999,2001,2002,2003,2004,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999,2001,2002,2003,2004,2006,2007
|
||||
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
|
||||
@ -50,7 +51,7 @@
|
||||
\
|
||||
First get the origin string if it is not available yet. \
|
||||
This can only happen for the map of the executable. */ \
|
||||
DL_DST_REQ_STATIC \
|
||||
DL_DST_REQ_STATIC (l) \
|
||||
if ((l)->l_origin == NULL) \
|
||||
{ \
|
||||
assert ((l)->l_name[0] == '\0'); \
|
||||
@ -68,9 +69,9 @@
|
||||
__len; })
|
||||
|
||||
#ifdef SHARED
|
||||
# define DL_DST_REQ_STATIC /* nothing */
|
||||
# define DL_DST_REQ_STATIC(l) /* nothing */
|
||||
#else
|
||||
# define DL_DST_REQ_STATIC \
|
||||
# define DL_DST_REQ_STATIC(l) \
|
||||
if ((l) == NULL) \
|
||||
{ \
|
||||
const char *origin = _dl_get_origin (); \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Manage function descriptors. Generic version.
|
||||
Copyright (C) 1999-2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999,2000,2001,2002,2003,2004 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
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
#ifndef COMPARE_AND_SWAP
|
||||
# define COMPARE_AND_SWAP(ptr, old, new) \
|
||||
(catomic_compare_and_exchange_bool_acq (ptr, new, old) == 0)
|
||||
(atomic_compare_and_exchange_bool_acq (ptr, new, old) == 0)
|
||||
#endif
|
||||
|
||||
ElfW(Addr) _dl_boot_fptr_table [ELF_MACHINE_BOOT_FPTR_TABLE_LEN];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Get loaded objects program headers.
|
||||
Copyright (C) 2001,2002,2003,2004,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001,2002,2003,2004,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
|
||||
|
||||
@ -54,9 +54,9 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
|
||||
nloaded += GL(dl_ns)[cnt]._ns_nloaded;
|
||||
|
||||
if (caller >= (const void *) l->l_map_start
|
||||
&& caller < (const void *) l->l_map_end)
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
&& caller < (const void *) l->l_map_end
|
||||
&& (l->l_contiguous
|
||||
|| _dl_addr_inside_object (l, (ElfW(Addr)) caller)))
|
||||
ns = cnt;
|
||||
}
|
||||
|
||||
@ -70,9 +70,11 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
|
||||
info.dlpi_subs = GL(dl_load_adds) - nloaded;
|
||||
info.dlpi_tls_modid = 0;
|
||||
info.dlpi_tls_data = NULL;
|
||||
#ifdef USE_TLS
|
||||
info.dlpi_tls_modid = l->l_tls_modid;
|
||||
if (info.dlpi_tls_modid != 0)
|
||||
info.dlpi_tls_data = _dl_tls_get_addr_soft (l);
|
||||
#endif
|
||||
ret = callback (&info, sizeof (struct dl_phdr_info), data);
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Handle loading and unloading shared objects for internal libc purposes.
|
||||
Copyright (C) 1999-2002,2004,2005,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999,2000,2001,2002,2004,2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Map in a shared object's segments from the file.
|
||||
Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2005, 2006, 2007 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
|
||||
@ -1078,6 +1078,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
|
||||
break;
|
||||
|
||||
case PT_TLS:
|
||||
#ifdef USE_TLS
|
||||
if (ph->p_memsz == 0)
|
||||
/* Nothing to do for an empty segment. */
|
||||
break;
|
||||
@ -1105,7 +1106,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
if (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0)
|
||||
/* We are loading the executable itself when the dynamic linker
|
||||
was executed directly. The setup will happen later. */
|
||||
@ -1114,7 +1115,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
|
||||
/* In a static binary there is no way to tell if we dynamically
|
||||
loaded libpthread. */
|
||||
if (GL(dl_error_catch_tsd) == &_dl_initial_error_catch_tsd)
|
||||
#endif
|
||||
# endif
|
||||
{
|
||||
/* We have not yet loaded libpthread.
|
||||
We can do the TLS setup right now! */
|
||||
@ -1147,6 +1148,7 @@ cannot allocate TLS data structures for initial thread");
|
||||
_dl_deallocate_tls (tcb, 1);
|
||||
goto call_lose;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Uh-oh, the binary expects TLS support but we cannot
|
||||
provide it. */
|
||||
@ -1223,6 +1225,8 @@ cannot allocate TLS data structures for initial thread");
|
||||
loadcmds[nloadcmds - 1].mapstart - c->mapend,
|
||||
PROT_NONE);
|
||||
|
||||
l->l_contiguous = 1;
|
||||
|
||||
goto postmap;
|
||||
}
|
||||
|
||||
@ -1242,6 +1246,7 @@ cannot allocate TLS data structures for initial thread");
|
||||
/* Remember which part of the address space this object uses. */
|
||||
l->l_map_start = c->mapstart + l->l_addr;
|
||||
l->l_map_end = l->l_map_start + maplength;
|
||||
l->l_contiguous = !has_holes;
|
||||
|
||||
while (c < &loadcmds[nloadcmds])
|
||||
{
|
||||
@ -1385,7 +1390,7 @@ cannot allocate TLS data structures for initial thread");
|
||||
requires that it be executable. We must change the
|
||||
protection of the variable which contains the flags used in
|
||||
the mprotect calls. */
|
||||
#ifdef SHARED
|
||||
#if defined HAVE_Z_RELRO && defined SHARED
|
||||
if ((mode & (__RTLD_DLOPEN | __RTLD_AUDIT)) == __RTLD_DLOPEN)
|
||||
{
|
||||
const uintptr_t p = (uintptr_t) &__stack_prot & -GLRO(dl_pagesize);
|
||||
@ -1422,9 +1427,11 @@ cannot enable executable stack as shared object requires");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Adjust the address of the TLS initialization image. */
|
||||
if (l->l_tls_initimage != NULL)
|
||||
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
|
||||
#endif
|
||||
|
||||
/* We are done mapping in the file. We no longer need the descriptor. */
|
||||
if (__builtin_expect (__close (fd) != 0, 0))
|
||||
@ -1928,10 +1935,11 @@ open_path (const char *name, size_t namelen, int preloaded,
|
||||
must not be freed using the general free() in libc. */
|
||||
if (sps->malloced)
|
||||
free (sps->dirs);
|
||||
|
||||
#ifdef HAVE_Z_RELRO
|
||||
/* rtld_search_dirs is attribute_relro, therefore avoid writing
|
||||
into it. */
|
||||
if (sps != &rtld_search_dirs)
|
||||
#endif
|
||||
sps->dirs = (void *) -1;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Look up a symbol in the loaded objects.
|
||||
Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2005, 2006, 2007 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
|
||||
@ -25,6 +25,7 @@
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-hash.h>
|
||||
#include <dl-machine.h>
|
||||
#include <sysdep-cancel.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <tls.h>
|
||||
|
||||
@ -228,17 +229,13 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
||||
|
||||
/* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
|
||||
up a versioned symbol. */
|
||||
assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
|
||||
assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY)) == 0);
|
||||
|
||||
size_t i = 0;
|
||||
if (__builtin_expect (skip_map != NULL, 0))
|
||||
{
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
while ((*scope)->r_list[i] != skip_map)
|
||||
++i;
|
||||
|
||||
assert (i < (*scope)->r_nlist);
|
||||
}
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
while ((*scope)->r_list[i] != skip_map)
|
||||
++i;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
for (size_t start = i; *scope != NULL; start = 0, ++scope)
|
||||
@ -341,9 +338,8 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
||||
&& add_dependency (undef_map, current_value.m) < 0)
|
||||
/* Something went wrong. Perhaps the object we tried to reference
|
||||
was just removed. Try finding another definition. */
|
||||
return _dl_lookup_symbol_x (undef_name, undef_map, ref,
|
||||
symbol_scope, version, type_class,
|
||||
flags, skip_map);
|
||||
return _dl_lookup_symbol_x (undef_name, undef_map, ref, symbol_scope,
|
||||
version, type_class, flags, skip_map);
|
||||
|
||||
/* The object is used. */
|
||||
current_value.m->l_used = 1;
|
||||
@ -449,10 +445,12 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
conflict = 1;
|
||||
}
|
||||
|
||||
# ifdef USE_TLS
|
||||
if (value->s
|
||||
&& (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_TLS, 0)))
|
||||
type_class = 4;
|
||||
# endif
|
||||
|
||||
if (conflict
|
||||
|| GLRO(dl_trace_prelink_map) == undef_map
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Minimal replacements for basic facilities used in the dynamic linker.
|
||||
Copyright (C) 1995-1998,2000-2002,2004,2005,2006
|
||||
Copyright (C) 1995-1998,2000-2002,2004-2006,2007
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@ -75,14 +75,21 @@ __libc_memalign (size_t align, size_t n)
|
||||
alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + align - 1)
|
||||
& ~(align - 1));
|
||||
|
||||
if (alloc_ptr + n >= alloc_end)
|
||||
if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr)
|
||||
{
|
||||
/* Insufficient space left; allocate another page. */
|
||||
caddr_t page;
|
||||
size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
|
||||
if (__builtin_expect (nup == 0, 0))
|
||||
{
|
||||
if (n)
|
||||
return NULL;
|
||||
nup = GLRO(dl_pagesize);
|
||||
}
|
||||
page = __mmap (0, nup, PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||
assert (page != MAP_FAILED);
|
||||
if (page == MAP_FAILED)
|
||||
return NULL;
|
||||
if (page != alloc_end)
|
||||
alloc_ptr = page;
|
||||
alloc_end = page + nup;
|
||||
@ -108,7 +115,14 @@ calloc (size_t nmemb, size_t size)
|
||||
/* New memory from the trivial malloc above is always already cleared.
|
||||
(We make sure that's true in the rare occasion it might not be,
|
||||
by clearing memory in free, below.) */
|
||||
return malloc (nmemb * size);
|
||||
size_t bytes = nmemb * size;
|
||||
|
||||
#define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2))
|
||||
if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0)
|
||||
&& size != 0 && bytes / size != nmemb)
|
||||
return NULL;
|
||||
|
||||
return malloc (bytes);
|
||||
}
|
||||
|
||||
/* This will rarely be called. */
|
||||
@ -264,7 +278,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group)
|
||||
while (*nptr >= '0' && *nptr <= '9')
|
||||
{
|
||||
unsigned long int digval = *nptr - '0';
|
||||
if (result > LONG_MAX / 10
|
||||
if (result > ULONG_MAX / 10
|
||||
|| (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
|
||||
{
|
||||
errno = ERANGE;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Storage management for the chain of loaded shared objects.
|
||||
Copyright (C) 1995-2002, 2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2002, 2004 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
|
||||
@ -64,7 +64,7 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||
new->l_name = realname;
|
||||
new->l_type = type;
|
||||
new->l_loader = loader;
|
||||
#if NO_TLS_OFFSET != 0
|
||||
#if defined USE_TLS && NO_TLS_OFFSET != 0
|
||||
new->l_tls_offset = NO_TLS_OFFSET;
|
||||
#endif
|
||||
new->l_ns = nsid;
|
||||
@ -85,11 +85,6 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||
new->l_scope = new->l_scope_mem;
|
||||
new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
|
||||
|
||||
/* No need to initialize the scope lock if the initializer is zero. */
|
||||
#if _RTLD_MRLOCK_INITIALIZER != 0
|
||||
__rtld_mrlock_initialize (new->l_scope_lock);
|
||||
#endif
|
||||
|
||||
/* Counter for the scopes we have to handle. */
|
||||
idx = 0;
|
||||
|
||||
|
139
elf/dl-open.c
139
elf/dl-open.c
@ -1,5 +1,5 @@
|
||||
/* Load a shared object at runtime, relocate it, and run its initializer.
|
||||
Copyright (C) 1996-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2004, 2005, 2006, 2007 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
|
||||
@ -32,6 +32,7 @@
|
||||
#include <bp-sym.h>
|
||||
#include <caller.h>
|
||||
#include <sysdep-cancel.h>
|
||||
#include <tls.h>
|
||||
|
||||
#include <dl-dst.h>
|
||||
|
||||
@ -97,17 +98,17 @@ add_to_global (struct link_map *new)
|
||||
in an realloc() call. Therefore we allocate a completely new
|
||||
array the first time we have to add something to the locale scope. */
|
||||
|
||||
if (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc == 0)
|
||||
struct link_namespaces *ns = &GL(dl_ns)[new->l_ns];
|
||||
if (ns->_ns_global_scope_alloc == 0)
|
||||
{
|
||||
/* This is the first dynamic object given global scope. */
|
||||
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc
|
||||
= GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add + 8;
|
||||
ns->_ns_global_scope_alloc
|
||||
= ns->_ns_main_searchlist->r_nlist + to_add + 8;
|
||||
new_global = (struct link_map **)
|
||||
malloc (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc
|
||||
* sizeof (struct link_map *));
|
||||
malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
||||
if (new_global == NULL)
|
||||
{
|
||||
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc = 0;
|
||||
ns->_ns_global_scope_alloc = 0;
|
||||
nomem:
|
||||
_dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
||||
N_("cannot extend global scope"));
|
||||
@ -115,29 +116,39 @@ add_to_global (struct link_map *new)
|
||||
}
|
||||
|
||||
/* Copy over the old entries. */
|
||||
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list
|
||||
= memcpy (new_global,
|
||||
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list,
|
||||
(GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist
|
||||
ns->_ns_main_searchlist->r_list
|
||||
= memcpy (new_global, ns->_ns_main_searchlist->r_list,
|
||||
(ns->_ns_main_searchlist->r_nlist
|
||||
* sizeof (struct link_map *)));
|
||||
}
|
||||
else if (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add
|
||||
> GL(dl_ns)[new->l_ns]._ns_global_scope_alloc)
|
||||
else if (ns->_ns_main_searchlist->r_nlist + to_add
|
||||
> ns->_ns_global_scope_alloc)
|
||||
{
|
||||
/* We have to extend the existing array of link maps in the
|
||||
main map. */
|
||||
struct link_map **old_global
|
||||
= GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
|
||||
size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
|
||||
|
||||
new_global = (struct link_map **)
|
||||
realloc (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list,
|
||||
((GL(dl_ns)[new->l_ns]._ns_global_scope_alloc + to_add + 8)
|
||||
* sizeof (struct link_map *)));
|
||||
malloc (new_nalloc * sizeof (struct link_map *));
|
||||
if (new_global == NULL)
|
||||
goto nomem;
|
||||
|
||||
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc += to_add + 8;
|
||||
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list = new_global;
|
||||
memcpy (new_global, old_global,
|
||||
ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
||||
|
||||
ns->_ns_global_scope_alloc = new_nalloc;
|
||||
ns->_ns_main_searchlist->r_list = new_global;
|
||||
|
||||
if (!RTLD_SINGLE_THREAD_P)
|
||||
THREAD_GSCOPE_WAIT ();
|
||||
|
||||
free (old_global);
|
||||
}
|
||||
|
||||
/* Now add the new entries. */
|
||||
unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
|
||||
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||
{
|
||||
struct link_map *map = new->l_searchlist.r_list[cnt];
|
||||
@ -145,15 +156,49 @@ add_to_global (struct link_map *new)
|
||||
if (map->l_global == 0)
|
||||
{
|
||||
map->l_global = 1;
|
||||
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list[GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist]
|
||||
= map;
|
||||
++GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist;
|
||||
ns->_ns_main_searchlist->r_list[new_nlist++] = map;
|
||||
}
|
||||
}
|
||||
atomic_write_barrier ();
|
||||
ns->_ns_main_searchlist->r_nlist = new_nlist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_dl_scope_free (struct r_scope_elem **old)
|
||||
{
|
||||
struct dl_scope_free_list *fsl;
|
||||
#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0]))
|
||||
|
||||
if (RTLD_SINGLE_THREAD_P)
|
||||
free (old);
|
||||
else if ((fsl = GL(dl_scope_free_list)) == NULL)
|
||||
{
|
||||
GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl));
|
||||
if (fsl == NULL)
|
||||
{
|
||||
THREAD_GSCOPE_WAIT ();
|
||||
free (old);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fsl->list[0] = old;
|
||||
fsl->count = 1;
|
||||
}
|
||||
}
|
||||
else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE)
|
||||
fsl->list[fsl->count++] = old;
|
||||
else
|
||||
{
|
||||
THREAD_GSCOPE_WAIT ();
|
||||
while (fsl->count > 0)
|
||||
free (fsl->list[--fsl->count]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dl_open_worker (void *a)
|
||||
@ -161,10 +206,12 @@ dl_open_worker (void *a)
|
||||
struct dl_open_args *args = a;
|
||||
const char *file = args->file;
|
||||
int mode = args->mode;
|
||||
struct link_map *new, *l;
|
||||
struct link_map *new;
|
||||
int lazy;
|
||||
unsigned int i;
|
||||
#ifdef USE_TLS
|
||||
bool any_tls = false;
|
||||
#endif
|
||||
struct link_map *call_map = NULL;
|
||||
|
||||
/* Check whether _dl_open() has been called from a valid DSO. */
|
||||
@ -186,13 +233,14 @@ dl_open_worker (void *a)
|
||||
By default we assume this is the main application. */
|
||||
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
struct link_map *l;
|
||||
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
|
||||
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
|
||||
if (caller_dlopen >= (const void *) l->l_map_start
|
||||
&& caller_dlopen < (const void *) l->l_map_end)
|
||||
&& caller_dlopen < (const void *) l->l_map_end
|
||||
&& (l->l_contiguous
|
||||
|| _dl_addr_inside_object (l, (ElfW(Addr)) caller_dlopen)))
|
||||
{
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
assert (ns == l->l_ns);
|
||||
call_map = l;
|
||||
goto found_caller;
|
||||
@ -325,7 +373,7 @@ dl_open_worker (void *a)
|
||||
/* Relocate the objects loaded. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later objects. */
|
||||
|
||||
l = new;
|
||||
struct link_map *l = new;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
while (1)
|
||||
@ -417,17 +465,10 @@ dl_open_worker (void *a)
|
||||
memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
|
||||
struct r_scope_elem **old = imap->l_scope;
|
||||
|
||||
if (RTLD_SINGLE_THREAD_P)
|
||||
imap->l_scope = newp;
|
||||
else
|
||||
{
|
||||
__rtld_mrlock_change (imap->l_scope_lock);
|
||||
imap->l_scope = newp;
|
||||
__rtld_mrlock_done (imap->l_scope_lock);
|
||||
}
|
||||
imap->l_scope = newp;
|
||||
|
||||
if (old != imap->l_scope_mem)
|
||||
free (old);
|
||||
_dl_scope_free (old);
|
||||
|
||||
imap->l_scope_max = new_size;
|
||||
}
|
||||
@ -439,6 +480,7 @@ dl_open_worker (void *a)
|
||||
atomic_write_barrier ();
|
||||
imap->l_scope[cnt] = &new->l_searchlist;
|
||||
}
|
||||
#if USE_TLS
|
||||
/* Only add TLS memory if this object is loaded now and
|
||||
therefore is not yet initialized. */
|
||||
else if (! imap->l_init_called
|
||||
@ -453,11 +495,11 @@ dl_open_worker (void *a)
|
||||
if (imap->l_need_tls_init)
|
||||
{
|
||||
imap->l_need_tls_init = 0;
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
/* Update the slot information data for at least the
|
||||
generation of the DSO we are allocating data for. */
|
||||
_dl_update_slotinfo (imap->l_tls_modid);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
GL(dl_init_static_tls) (imap);
|
||||
assert (imap->l_need_tls_init == 0);
|
||||
@ -466,12 +508,15 @@ dl_open_worker (void *a)
|
||||
/* We have to bump the generation counter. */
|
||||
any_tls = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_TLS
|
||||
/* Bump the generation number if necessary. */
|
||||
if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
||||
_dl_fatal_printf (N_("\
|
||||
TLS generation counter wrapped! Please report this."));
|
||||
#endif
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
_dl_init (new, args->argc, args->argv, args->env);
|
||||
@ -568,6 +613,7 @@ no more namespaces available for dlmopen()"));
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
/* Maybe some of the modules which were loaded use TLS.
|
||||
Since it will be removed in the following _dl_close call
|
||||
we have to mark the dtv array as having gaps to fill the
|
||||
@ -577,6 +623,7 @@ no more namespaces available for dlmopen()"));
|
||||
up. */
|
||||
if ((mode & __RTLD_AUDIT) == 0)
|
||||
GL(dl_tls_dtv_gaps) = true;
|
||||
#endif
|
||||
|
||||
_dl_close_worker (args.map);
|
||||
}
|
||||
@ -650,3 +697,21 @@ show_scope (struct link_map *new)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_IN_rtld
|
||||
/* Return non-zero if ADDR lies within one of L's segments. */
|
||||
int
|
||||
internal_function
|
||||
_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
|
||||
{
|
||||
int n = l->l_phnum;
|
||||
const ElfW(Addr) reladdr = addr - l->l_addr;
|
||||
|
||||
while (--n >= 0)
|
||||
if (l->l_phdr[n].p_type == PT_LOAD
|
||||
&& reladdr - l->l_phdr[n].p_vaddr >= 0
|
||||
&& reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Profiling of shared libraries.
|
||||
Copyright (C) 1997-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
Based on the BSD mcount implementation.
|
||||
@ -509,24 +509,24 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
|
||||
size_t newfromidx;
|
||||
to_index = (data[narcs].self_pc
|
||||
/ (HASHFRACTION * sizeof (*tos)));
|
||||
newfromidx = catomic_exchange_and_add (&fromidx, 1) + 1;
|
||||
newfromidx = atomic_exchange_and_add (&fromidx, 1) + 1;
|
||||
froms[newfromidx].here = &data[narcs];
|
||||
froms[newfromidx].link = tos[to_index];
|
||||
tos[to_index] = newfromidx;
|
||||
catomic_increment (&narcs);
|
||||
atomic_increment (&narcs);
|
||||
}
|
||||
|
||||
/* If we still have no entry stop searching and insert. */
|
||||
if (*topcindex == 0)
|
||||
{
|
||||
uint_fast32_t newarc = catomic_exchange_and_add (narcsp, 1);
|
||||
uint_fast32_t newarc = atomic_exchange_and_add (narcsp, 1);
|
||||
|
||||
/* In rare cases it could happen that all entries in FROMS are
|
||||
occupied. So we cannot count this anymore. */
|
||||
if (newarc >= fromlimit)
|
||||
goto done;
|
||||
|
||||
*topcindex = catomic_exchange_and_add (&fromidx, 1) + 1;
|
||||
*topcindex = atomic_exchange_and_add (&fromidx, 1) + 1;
|
||||
fromp = &froms[*topcindex];
|
||||
|
||||
fromp->here = &data[newarc];
|
||||
@ -534,7 +534,7 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
|
||||
data[newarc].self_pc = selfpc;
|
||||
data[newarc].count = 0;
|
||||
fromp->link = 0;
|
||||
catomic_increment (&narcs);
|
||||
atomic_increment (&narcs);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -547,7 +547,7 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
|
||||
}
|
||||
|
||||
/* Increment the counter. */
|
||||
catomic_increment (&fromp->here->count);
|
||||
atomic_increment (&fromp->here->count);
|
||||
|
||||
done:
|
||||
;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Relocate a shared object and resolve its references to other loaded objects.
|
||||
Copyright (C) 1995-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2004, 2005 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
|
||||
@ -35,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* We are trying to perform a static TLS relocation in MAP, but it was
|
||||
dynamically loaded. This can only work if there is enough surplus in
|
||||
the static TLS area already allocated for each running thread. If this
|
||||
@ -55,7 +56,7 @@ _dl_allocate_static_tls (struct link_map *map)
|
||||
cannot allocate memory in static TLS block"));
|
||||
}
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
size_t freebytes;
|
||||
size_t n;
|
||||
size_t blsize;
|
||||
@ -72,7 +73,7 @@ cannot allocate memory in static TLS block"));
|
||||
- map->l_tls_firstbyte_offset);
|
||||
|
||||
map->l_tls_offset = GL(dl_tls_static_used) = offset;
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
size_t used;
|
||||
size_t check;
|
||||
|
||||
@ -86,9 +87,9 @@ cannot allocate memory in static TLS block"));
|
||||
|
||||
map->l_tls_offset = offset;
|
||||
GL(dl_tls_static_used) = used;
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* If the object is not yet relocated we cannot initialize the
|
||||
static TLS region. Delay it. */
|
||||
@ -114,13 +115,13 @@ cannot allocate memory in static TLS block"));
|
||||
void
|
||||
_dl_nothread_init_static_tls (struct link_map *map)
|
||||
{
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
void *dest = (char *) THREAD_SELF - map->l_tls_offset;
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* Fill in the DTV slot so that a later LD/GD access will find it. */
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
@ -132,6 +133,7 @@ _dl_nothread_init_static_tls (struct link_map *map)
|
||||
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
|
||||
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* On-demand PLT fixup for shared objects.
|
||||
Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2006, 2007 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
|
||||
@ -26,6 +26,8 @@
|
||||
#include <ldsodefs.h>
|
||||
#include <sysdep-cancel.h>
|
||||
#include "dynamic-link.h"
|
||||
#include <tls.h>
|
||||
|
||||
|
||||
#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|
||||
|| ELF_MACHINE_NO_REL
|
||||
@ -93,15 +95,19 @@ _dl_fixup (
|
||||
version = NULL;
|
||||
}
|
||||
|
||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
||||
__rtld_mrlock_lock (l->l_scope_lock);
|
||||
/* We need to keep the scope around so do some locking. This is
|
||||
not necessary for objects which cannot be unloaded or when
|
||||
we are not using any threads (yet). */
|
||||
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
||||
if (!RTLD_SINGLE_THREAD_P)
|
||||
THREAD_GSCOPE_SET_FLAG ();
|
||||
|
||||
result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
|
||||
l->l_scope, version, ELF_RTYPE_CLASS_PLT,
|
||||
DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
|
||||
version, ELF_RTYPE_CLASS_PLT, flags, NULL);
|
||||
|
||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
||||
/* We are done with the global scope. */
|
||||
if (!RTLD_SINGLE_THREAD_P)
|
||||
THREAD_GSCOPE_RESET_FLAG ();
|
||||
|
||||
/* Currently result contains the base load address (or link map)
|
||||
of the object that defines sym. Now add in the symbol
|
||||
@ -181,16 +187,20 @@ _dl_profile_fixup (
|
||||
version = NULL;
|
||||
}
|
||||
|
||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
||||
__rtld_mrlock_lock (l->l_scope_lock);
|
||||
/* We need to keep the scope around so do some locking. This is
|
||||
not necessary for objects which cannot be unloaded or when
|
||||
we are not using any threads (yet). */
|
||||
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
||||
if (!RTLD_SINGLE_THREAD_P)
|
||||
THREAD_GSCOPE_SET_FLAG ();
|
||||
|
||||
result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym,
|
||||
l->l_scope, version,
|
||||
ELF_RTYPE_CLASS_PLT,
|
||||
DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
|
||||
&defsym, l->l_scope, version,
|
||||
ELF_RTYPE_CLASS_PLT, flags, NULL);
|
||||
|
||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
||||
/* We are done with the global scope. */
|
||||
if (!RTLD_SINGLE_THREAD_P)
|
||||
THREAD_GSCOPE_RESET_FLAG ();
|
||||
|
||||
/* Currently result contains the base load address (or link map)
|
||||
of the object that defines sym. Now add in the symbol
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Support for dynamic linking code in static libc.
|
||||
Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2005, 2006, 2007 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
|
||||
@ -98,7 +98,9 @@ int _dl_starting_up = 1;
|
||||
hp_timing_t _dl_cpuclock_offset;
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
|
||||
#endif
|
||||
|
||||
size_t _dl_pagesize;
|
||||
|
||||
@ -132,6 +134,11 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function
|
||||
= _dl_make_stack_executable;
|
||||
|
||||
|
||||
/* Function in libpthread to wait for termination of lookups. */
|
||||
void (*_dl_wait_lookup_done) (void);
|
||||
|
||||
struct dl_scope_free_list *_dl_scope_free_list;
|
||||
|
||||
#ifdef NEED_DL_SYSINFO
|
||||
/* Needed for improved syscall handling on at least x86/Linux. */
|
||||
uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT;
|
||||
|
23
elf/dl-sym.c
23
elf/dl-sym.c
@ -1,5 +1,5 @@
|
||||
/* Look up a symbol in a shared object loaded by `dlopen'.
|
||||
Copyright (C) 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2002,2004,2006,2007 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
|
||||
@ -26,10 +26,12 @@
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-hash.h>
|
||||
#include <sysdep-cancel.h>
|
||||
#include <dl-tls.h>
|
||||
#ifdef USE_TLS
|
||||
# include <dl-tls.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SHARED
|
||||
#if defined USE_TLS && defined SHARED
|
||||
/* Systems which do not have tls_index also probably have to define
|
||||
DONT_USE_TLS_INDEX. */
|
||||
|
||||
@ -98,10 +100,9 @@ do_sym (void *handle, const char *name, void *who,
|
||||
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
|
||||
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
|
||||
l = l->l_next)
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end)
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end
|
||||
&& (l->l_contiguous || _dl_addr_inside_object (l, caller)))
|
||||
{
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
match = l;
|
||||
break;
|
||||
}
|
||||
@ -113,15 +114,13 @@ do_sym (void *handle, const char *name, void *who,
|
||||
the initial binary. And then the more complex part
|
||||
where the object is dynamically loaded and the scope
|
||||
array can change. */
|
||||
if (match->l_type != lt_loaded || RTLD_SINGLE_THREAD_P)
|
||||
if (RTLD_SINGLE_THREAD_P)
|
||||
result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
|
||||
match->l_scope, vers, 0,
|
||||
flags | DL_LOOKUP_ADD_DEPENDENCY,
|
||||
NULL);
|
||||
else
|
||||
{
|
||||
__rtld_mrlock_lock (match->l_scope_lock);
|
||||
|
||||
struct call_dl_lookup_args args;
|
||||
args.name = name;
|
||||
args.map = match;
|
||||
@ -129,13 +128,15 @@ do_sym (void *handle, const char *name, void *who,
|
||||
args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY;
|
||||
args.refp = &ref;
|
||||
|
||||
THREAD_GSCOPE_SET_FLAG ();
|
||||
|
||||
const char *objname;
|
||||
const char *errstring = NULL;
|
||||
bool malloced;
|
||||
int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
|
||||
call_dl_lookup, &args);
|
||||
|
||||
__rtld_mrlock_unlock (match->l_scope_lock);
|
||||
THREAD_GSCOPE_RESET_FLAG ();
|
||||
|
||||
if (__builtin_expect (errstring != NULL, 0))
|
||||
{
|
||||
@ -182,7 +183,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||
{
|
||||
void *value;
|
||||
|
||||
#ifdef SHARED
|
||||
#if defined USE_TLS && defined SHARED
|
||||
if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS)
|
||||
/* The found symbol is a thread-local storage variable.
|
||||
Return the address for to the current thread. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Operating system support for run-time dynamic linker. Generic Unix version.
|
||||
Copyright (C) 1995-1998, 2000-2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-1998, 2000-2005, 2007 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
|
||||
@ -405,8 +405,25 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* For TLS enabled builds always add 'tls'. */
|
||||
++cnt;
|
||||
#else
|
||||
if (cnt == 0)
|
||||
{
|
||||
/* If we no have platform name and no important capability we only
|
||||
have the base directory to search. */
|
||||
result = (struct r_strlenpair *) malloc (sizeof (*result));
|
||||
if (result == NULL)
|
||||
goto no_memory;
|
||||
|
||||
result[0].str = (char *) result; /* Does not really matter. */
|
||||
result[0].len = 0;
|
||||
|
||||
*sz = 1;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create temporary data structure to generate result table. */
|
||||
temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
|
||||
@ -448,11 +465,11 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||
temp[m].len = platform_len;
|
||||
++m;
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
temp[m].str = "tls";
|
||||
temp[m].len = 3;
|
||||
++m;
|
||||
|
||||
#endif
|
||||
assert (m == cnt);
|
||||
|
||||
/* Determine the total size of all strings together. */
|
||||
@ -460,9 +477,21 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||
total = temp[0].len + 1;
|
||||
else
|
||||
{
|
||||
total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
|
||||
for (n = 1; n + 1 < cnt; ++n)
|
||||
total += (1UL << (cnt - 3)) * (temp[n].len + 1);
|
||||
total = temp[0].len + temp[cnt - 1].len + 2;
|
||||
if (cnt > 2)
|
||||
{
|
||||
total <<= 1;
|
||||
for (n = 1; n + 1 < cnt; ++n)
|
||||
total += temp[n].len + 1;
|
||||
if (cnt > 3
|
||||
&& (cnt >= sizeof (size_t) * 8
|
||||
|| total + (sizeof (*result) << 3)
|
||||
>= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
|
||||
_dl_signal_error (ENOMEM, NULL, NULL,
|
||||
N_("cannot create capability list"));
|
||||
|
||||
total <<= cnt - 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* The result structure: we use a very compressed way to store the
|
||||
@ -470,8 +499,13 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||
*sz = 1 << cnt;
|
||||
result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
|
||||
if (result == NULL)
|
||||
_dl_signal_error (ENOMEM, NULL, NULL,
|
||||
N_("cannot create capability list"));
|
||||
{
|
||||
#ifndef USE_TLS
|
||||
no_memory:
|
||||
#endif
|
||||
_dl_signal_error (ENOMEM, NULL, NULL,
|
||||
N_("cannot create capability list"));
|
||||
}
|
||||
|
||||
if (cnt == 1)
|
||||
{
|
||||
|
79
elf/dl-tls.c
79
elf/dl-tls.c
@ -26,26 +26,30 @@
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <tls.h>
|
||||
#include <dl-tls.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
/* We don't need any of this if TLS is not supported. */
|
||||
#ifdef USE_TLS
|
||||
|
||||
# include <dl-tls.h>
|
||||
# include <ldsodefs.h>
|
||||
|
||||
/* Amount of excess space to allocate in the static TLS area
|
||||
to allow dynamic loading of modules defining IE-model TLS data. */
|
||||
#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100
|
||||
# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100
|
||||
|
||||
/* Value used for dtv entries for which the allocation is delayed. */
|
||||
#define TLS_DTV_UNALLOCATED ((void *) -1l)
|
||||
# define TLS_DTV_UNALLOCATED ((void *) -1l)
|
||||
|
||||
|
||||
/* Out-of-memory handler. */
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
static void
|
||||
__attribute__ ((__noreturn__))
|
||||
oom (void)
|
||||
{
|
||||
_dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
|
||||
size_t
|
||||
@ -109,7 +113,7 @@ _dl_next_tls_modid (void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
void
|
||||
internal_function
|
||||
_dl_determine_tlsoffset (void)
|
||||
@ -154,7 +158,7 @@ _dl_determine_tlsoffset (void)
|
||||
memory requirement for the next TLS block is smaller than the
|
||||
gap. */
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
/* We simply start with zero. */
|
||||
size_t offset = 0;
|
||||
|
||||
@ -201,7 +205,7 @@ _dl_determine_tlsoffset (void)
|
||||
GL(dl_tls_static_used) = offset;
|
||||
GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align)
|
||||
+ TLS_TCB_SIZE);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
/* The TLS blocks start right after the TCB. */
|
||||
size_t offset = TLS_TCB_SIZE;
|
||||
|
||||
@ -245,9 +249,9 @@ _dl_determine_tlsoffset (void)
|
||||
GL(dl_tls_static_used) = offset;
|
||||
GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS,
|
||||
TLS_TCB_ALIGN);
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* The alignment requirement for the static TLS block. */
|
||||
GL(dl_tls_static_align) = max_align;
|
||||
@ -284,7 +288,7 @@ _dl_tls_setup (void)
|
||||
return 0;
|
||||
}
|
||||
rtld_hidden_def (_dl_tls_setup)
|
||||
#endif
|
||||
# endif
|
||||
|
||||
static void *
|
||||
internal_function
|
||||
@ -333,13 +337,13 @@ _dl_allocate_tls_storage (void)
|
||||
void *result;
|
||||
size_t size = GL(dl_tls_static_size);
|
||||
|
||||
#if TLS_DTV_AT_TP
|
||||
# if TLS_DTV_AT_TP
|
||||
/* Memory layout is:
|
||||
[ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
|
||||
^ This should be returned. */
|
||||
size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
|
||||
& ~(GL(dl_tls_static_align) - 1);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* Allocate a correctly aligned chunk of memory. */
|
||||
result = __libc_memalign (GL(dl_tls_static_align), size);
|
||||
@ -348,14 +352,14 @@ _dl_allocate_tls_storage (void)
|
||||
/* Allocate the DTV. */
|
||||
void *allocated = result;
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
/* The TCB follows the TLS blocks. */
|
||||
result = (char *) result + size - TLS_TCB_SIZE;
|
||||
|
||||
/* Clear the TCB data structure. We can't ask the caller (i.e.
|
||||
libpthread) to do it, because we will initialize the DTV et al. */
|
||||
memset (result, '\0', TLS_TCB_SIZE);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
result = (char *) result + size - GL(dl_tls_static_size);
|
||||
|
||||
/* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
|
||||
@ -363,7 +367,7 @@ _dl_allocate_tls_storage (void)
|
||||
initialize the DTV et al. */
|
||||
memset ((char *) result - TLS_PRE_TCB_SIZE, '\0',
|
||||
TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
result = allocate_dtv (result);
|
||||
if (result == NULL)
|
||||
@ -424,14 +428,14 @@ _dl_allocate_tls_init (void *result)
|
||||
|
||||
assert (map->l_tls_modid == cnt);
|
||||
assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
|
||||
dest = (char *) result - map->l_tls_offset;
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
dest = (char *) result + map->l_tls_offset;
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* Copy the initialization image and clear the BSS part. */
|
||||
dtv[map->l_tls_modid].pointer.val = dest;
|
||||
@ -487,21 +491,21 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
|
||||
|
||||
if (dealloc_tcb)
|
||||
{
|
||||
#if TLS_TCB_AT_TP
|
||||
# if TLS_TCB_AT_TP
|
||||
/* The TCB follows the TLS blocks. Back up to free the whole block. */
|
||||
tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE;
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
/* Back up the TLS_PRE_TCB_SIZE bytes. */
|
||||
tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
|
||||
& ~(GL(dl_tls_static_align) - 1);
|
||||
#endif
|
||||
# endif
|
||||
free (tcb);
|
||||
}
|
||||
}
|
||||
rtld_hidden_def (_dl_deallocate_tls)
|
||||
|
||||
|
||||
#ifdef SHARED
|
||||
# ifdef SHARED
|
||||
/* The __tls_get_addr function has two basic forms which differ in the
|
||||
arguments. The IA-64 form takes two parameters, the module ID and
|
||||
offset. The form used, among others, on IA-32 takes a reference to
|
||||
@ -509,15 +513,15 @@ rtld_hidden_def (_dl_deallocate_tls)
|
||||
form seems to be more often used (in the moment) so we default to
|
||||
it. Users of the IA-64 form have to provide adequate definitions
|
||||
of the following macros. */
|
||||
# ifndef GET_ADDR_ARGS
|
||||
# define GET_ADDR_ARGS tls_index *ti
|
||||
# endif
|
||||
# ifndef GET_ADDR_MODULE
|
||||
# define GET_ADDR_MODULE ti->ti_module
|
||||
# endif
|
||||
# ifndef GET_ADDR_OFFSET
|
||||
# define GET_ADDR_OFFSET ti->ti_offset
|
||||
# endif
|
||||
# ifndef GET_ADDR_ARGS
|
||||
# define GET_ADDR_ARGS tls_index *ti
|
||||
# endif
|
||||
# ifndef GET_ADDR_MODULE
|
||||
# define GET_ADDR_MODULE ti->ti_module
|
||||
# endif
|
||||
# ifndef GET_ADDR_OFFSET
|
||||
# define GET_ADDR_OFFSET ti->ti_offset
|
||||
# endif
|
||||
|
||||
|
||||
static void *
|
||||
@ -728,7 +732,7 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||
|
||||
return (char *) p + GET_ADDR_OFFSET;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
|
||||
/* Look up the module's TLS block as for __tls_get_addr,
|
||||
@ -836,3 +840,4 @@ cannot create TLS data structures"));
|
||||
listp->slotinfo[idx].map = l;
|
||||
listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
||||
}
|
||||
#endif /* use TLS */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Look up a symbol in the loaded objects.
|
||||
Copyright (C) 1995-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2004, 2005, 2006, 2007 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
|
||||
@ -29,8 +29,13 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||
const struct r_found_version *const version, int flags,
|
||||
struct link_map *skip, int type_class)
|
||||
{
|
||||
struct link_map **list = scope->r_list;
|
||||
size_t n = scope->r_nlist;
|
||||
/* Make sure we read the value before proceeding. Otherwise we
|
||||
might use r_list pointing to the initial scope and r_nlist being
|
||||
the value after a resize. That is the only path in dl-open.c not
|
||||
protected by GSCOPE. A read barrier here might be to expensive. */
|
||||
__asm volatile ("" : "+r" (n), "+m" (scope->r_list));
|
||||
struct link_map **list = scope->r_list;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* This file defines standard ELF types, structures, and macros.
|
||||
Copyright (C) 1995-2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2003,2004,2005,2006 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
|
||||
@ -1511,9 +1511,8 @@ typedef struct
|
||||
#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
|
||||
#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
|
||||
#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
|
||||
#define R_MIPS_GLOB_DAT 51
|
||||
/* Keep this the last entry. */
|
||||
#define R_MIPS_NUM 52
|
||||
#define R_MIPS_NUM 51
|
||||
|
||||
/* Legal values for p_type field of Elf32_Phdr. */
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
@ -287,7 +286,7 @@ print_version (FILE *stream, struct argp_state *state)
|
||||
Copyright (C) %s Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
"), "2007");
|
||||
"), "2006");
|
||||
fprintf (stream, gettext ("Written by %s.\n"),
|
||||
"Andreas Jaeger");
|
||||
}
|
||||
@ -559,7 +558,7 @@ manual_link (char *library)
|
||||
/* Do some sanity checks first. */
|
||||
if (lstat64 (real_library, &stat_buf))
|
||||
{
|
||||
error (0, errno, _("Cannot lstat %s"), library);
|
||||
error (0, errno, _("Can't lstat %s"), library);
|
||||
free (path);
|
||||
return;
|
||||
}
|
||||
@ -707,10 +706,10 @@ search_dir (const struct dir_entry *entry)
|
||||
+ 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
|
||||
continue;
|
||||
}
|
||||
len += strlen (entry->path);
|
||||
len += strlen (entry->path) + 2;
|
||||
if (len > file_name_len)
|
||||
{
|
||||
file_name_len = len + 1;
|
||||
file_name_len = len;
|
||||
file_name = alloca (file_name_len);
|
||||
if (!opt_chroot)
|
||||
real_file_name = file_name;
|
||||
@ -718,10 +717,10 @@ search_dir (const struct dir_entry *entry)
|
||||
sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
|
||||
if (opt_chroot)
|
||||
{
|
||||
len = strlen (dir_name) + strlen (direntry->d_name);
|
||||
len = strlen (dir_name) + strlen (direntry->d_name) + 2;
|
||||
if (len > real_file_name_len)
|
||||
{
|
||||
real_file_name_len = len + 1;
|
||||
real_file_name_len = len;
|
||||
real_file_name = alloca (real_file_name_len);
|
||||
}
|
||||
sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
|
||||
@ -1167,14 +1166,9 @@ set_hwcap (void)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
/* Set locale via LC_ALL. */
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
/* Set the text message domain. */
|
||||
textdomain (_libc_intl_domainname);
|
||||
int remaining;
|
||||
|
||||
/* Parse and process arguments. */
|
||||
int remaining;
|
||||
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
|
||||
|
||||
/* Remaining arguments are additional directories if opt_manual_link
|
||||
@ -1191,7 +1185,9 @@ main (int argc, char **argv)
|
||||
add_dir (argv[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
|
||||
#endif
|
||||
|
||||
set_hwcap ();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#! @BASH@
|
||||
# Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2004, 2005, 2006 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
|
||||
@ -39,7 +39,7 @@ while test $# -gt 0; do
|
||||
printf $"Copyright (C) %s Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
" "2007"
|
||||
" "2006"
|
||||
printf $"Written by %s and %s.
|
||||
" "Roland McGrath" "Ulrich Drepper"
|
||||
exit 0
|
||||
|
71
elf/rtld.c
71
elf/rtld.c
@ -1,5 +1,5 @@
|
||||
/* Run time dynamic linker.
|
||||
Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2006, 2007 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
|
||||
@ -207,7 +207,8 @@ DL_SYSINFO_IMPLEMENTATION
|
||||
is fine, too. The latter is important here. We can avoid setting
|
||||
up a temporary link map for ld.so if we can mark _rtld_global as
|
||||
hidden. */
|
||||
#ifdef PI_STATIC_AND_HIDDEN
|
||||
#if defined PI_STATIC_AND_HIDDEN && defined HAVE_HIDDEN \
|
||||
&& defined HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define DONT_USE_BOOTSTRAP_MAP 1
|
||||
#endif
|
||||
|
||||
@ -291,7 +292,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||
GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
|
||||
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
|
||||
/* Copy the TLS related data if necessary. */
|
||||
#ifndef DONT_USE_BOOTSTRAP_MAP
|
||||
#if USE_TLS && !defined DONT_USE_BOOTSTRAP_MAP
|
||||
# if USE___THREAD
|
||||
assert (info->l.l_tls_modid != 0);
|
||||
GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize;
|
||||
@ -399,7 +400,7 @@ _dl_start (void *arg)
|
||||
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
|
||||
elf_get_dynamic_info (&bootstrap_map, NULL);
|
||||
|
||||
#if NO_TLS_OFFSET != 0
|
||||
#if defined USE_TLS && NO_TLS_OFFSET != 0
|
||||
bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
|
||||
#endif
|
||||
|
||||
@ -700,6 +701,7 @@ match_version (const char *string, struct link_map *map)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
static bool tls_init_tp_called;
|
||||
|
||||
static void *
|
||||
@ -771,6 +773,7 @@ cannot allocate TLS data structures for initial thread");
|
||||
|
||||
return tcbp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC_REENTRANT
|
||||
/* _dl_error_catch_tsd points to this for the single-threaded case.
|
||||
@ -858,14 +861,18 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
hp_timing_t stop;
|
||||
hp_timing_t diff;
|
||||
#endif
|
||||
#ifdef USE_TLS
|
||||
void *tcbp = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC_REENTRANT
|
||||
/* Explicit initialization since the reloc would just be more work. */
|
||||
GL(dl_error_catch_tsd) = &_dl_initial_error_catch_tsd;
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
|
||||
#endif
|
||||
|
||||
#if defined SHARED && defined _LIBC_REENTRANT \
|
||||
&& defined __rtld_lock_default_lock_recursive
|
||||
@ -1150,6 +1157,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
break;
|
||||
|
||||
case PT_TLS:
|
||||
#ifdef USE_TLS
|
||||
if (ph->p_memsz > 0)
|
||||
{
|
||||
/* Note that in the case the dynamic linker we duplicate work
|
||||
@ -1169,6 +1177,10 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
/* This image gets the ID one. */
|
||||
GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1;
|
||||
}
|
||||
#else
|
||||
_dl_fatal_printf ("\
|
||||
ld.so does not support TLS, but program uses it!\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PT_GNU_STACK:
|
||||
@ -1180,12 +1192,13 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
main_map->l_relro_size = ph->p_memsz;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Adjust the address of the TLS initialization image in case
|
||||
the executable is actually an ET_DYN object. */
|
||||
if (main_map->l_tls_initimage != NULL)
|
||||
main_map->l_tls_initimage
|
||||
= (char *) main_map->l_tls_initimage + main_map->l_addr;
|
||||
#ifdef USE_TLS
|
||||
/* Adjust the address of the TLS initialization image in case
|
||||
the executable is actually an ET_DYN object. */
|
||||
if (main_map->l_tls_initimage != NULL)
|
||||
main_map->l_tls_initimage
|
||||
= (char *) main_map->l_tls_initimage + main_map->l_addr;
|
||||
#endif
|
||||
if (! main_map->l_map_end)
|
||||
main_map->l_map_end = ~0;
|
||||
if (! main_map->l_text_end)
|
||||
@ -1388,10 +1401,12 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Add the dynamic linker to the TLS list if it also uses TLS. */
|
||||
if (GL(dl_rtld_map).l_tls_blocksize != 0)
|
||||
/* Assign a module ID. Do this before loading any audit modules. */
|
||||
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||||
#endif
|
||||
|
||||
/* If we have auditing DSOs to load, do it now. */
|
||||
if (__builtin_expect (audit_list != NULL, 0))
|
||||
@ -1399,8 +1414,15 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
/* Iterate over all entries in the list. The order is important. */
|
||||
struct audit_ifaces *last_audit = NULL;
|
||||
struct audit_list *al = audit_list->next;
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Since we start using the auditing DSOs right away we need to
|
||||
initialize the data structures now. */
|
||||
tcbp = init_tls ();
|
||||
#endif
|
||||
do
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
int tls_idx = GL(dl_tls_max_dtv_idx);
|
||||
|
||||
/* Now it is time to determine the layout of the static TLS
|
||||
@ -1408,11 +1430,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
always allocate the static block, we never defer it even if
|
||||
no DF_STATIC_TLS bit is set. The reason is that we know
|
||||
glibc will use the static model. */
|
||||
|
||||
/* Since we start using the auditing DSOs right away we need to
|
||||
initialize the data structures now. */
|
||||
tcbp = init_tls ();
|
||||
|
||||
#endif
|
||||
struct dlmopen_args dlmargs;
|
||||
dlmargs.fname = al->name;
|
||||
dlmargs.map = NULL;
|
||||
@ -1527,7 +1545,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
assert (GL(dl_ns)[ns]._ns_loaded == NULL);
|
||||
assert (GL(dl_ns)[ns]._ns_nloaded == 0);
|
||||
|
||||
#ifdef USE_TLS
|
||||
GL(dl_tls_max_dtv_idx) = tls_idx;
|
||||
#endif
|
||||
goto not_loaded;
|
||||
}
|
||||
}
|
||||
@ -1803,6 +1823,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
_dl_receive_error (print_missing_version, version_check_doit, &args);
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* We do not initialize any of the TLS functionality unless any of the
|
||||
initial modules uses TLS. This makes dynamic loading of modules with
|
||||
TLS impossible, but to support it requires either eagerly doing setup
|
||||
@ -1813,6 +1834,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
bool was_tls_init_tp_called = tls_init_tp_called;
|
||||
if (tcbp == NULL)
|
||||
tcbp = init_tls ();
|
||||
#endif
|
||||
|
||||
/* Set up the stack checker's canary. */
|
||||
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
|
||||
@ -1869,12 +1891,13 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
(size_t) l->l_map_start,
|
||||
(int) sizeof l->l_addr * 2,
|
||||
(size_t) l->l_addr);
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (l->l_tls_modid)
|
||||
_dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid,
|
||||
(int) sizeof l->l_tls_offset * 2,
|
||||
(size_t) l->l_tls_offset);
|
||||
else
|
||||
#endif
|
||||
_dl_printf ("\n");
|
||||
}
|
||||
}
|
||||
@ -1942,8 +1965,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
lookup_t result;
|
||||
|
||||
result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], main_map,
|
||||
&ref, main_map->l_scope,
|
||||
NULL, ELF_RTYPE_CLASS_PLT,
|
||||
&ref, main_map->l_scope, NULL,
|
||||
ELF_RTYPE_CLASS_PLT,
|
||||
DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
|
||||
loadbase = LOOKUP_VALUE_ADDRESS (result);
|
||||
@ -1985,8 +2008,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
{
|
||||
/* Mark the link map as not yet relocated again. */
|
||||
GL(dl_rtld_map).l_relocated = 0;
|
||||
_dl_relocate_object (&GL(dl_rtld_map),
|
||||
main_map->l_scope, 0, 0);
|
||||
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
|
||||
@ -2157,9 +2180,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
if (l->l_relro_size)
|
||||
_dl_protect_relro (l);
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Add object to slot information data if necessasy. */
|
||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||
_dl_add_to_slotinfo (l);
|
||||
#endif
|
||||
}
|
||||
|
||||
_dl_sysdep_start_cleanup ();
|
||||
@ -2206,9 +2231,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy),
|
||||
consider_profiling);
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Add object to slot information data if necessasy. */
|
||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||
_dl_add_to_slotinfo (l);
|
||||
#endif
|
||||
|
||||
l = l->l_prev;
|
||||
}
|
||||
@ -2237,6 +2264,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
# define NONTLS_INIT_TP do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
||||
++GL(dl_tls_generation);
|
||||
|
||||
@ -2254,6 +2282,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
_dl_fatal_printf ("cannot set up thread-local storage: %s\n",
|
||||
lossage);
|
||||
}
|
||||
#else
|
||||
NONTLS_INIT_TP;
|
||||
#endif
|
||||
|
||||
if (! prelinked && rtld_multiple_ref)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Read and display shared object profiling data.
|
||||
Copyright (C) 1997-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -357,7 +357,7 @@ Copyright (C) %s Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
"),
|
||||
"2007");
|
||||
"2006");
|
||||
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,8 @@ tf (void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
#define N 10
|
||||
pthread_t th[N];
|
||||
@ -54,6 +53,3 @@ do_test (void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
@ -9,6 +9,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname[] = "tst-tlsmod2.so";
|
||||
int result = 0;
|
||||
int *foop;
|
||||
@ -82,6 +83,9 @@ do_test (void)
|
||||
dlclose (h);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,18 +3,21 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#include "tls-macros.h"
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
|
||||
/* Two common 'int' variables in TLS. */
|
||||
COMMON_INT_DEF(foo);
|
||||
COMMON_INT_DEF(bar);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
int result = 0;
|
||||
int *ap, *bp;
|
||||
|
||||
@ -79,6 +82,9 @@ do_test (void)
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include <tls.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
#if defined USE_TLS && defined HAVE___THREAD \
|
||||
&& defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
# define USE_TLS__THREAD
|
||||
|
||||
struct A
|
||||
|
@ -6,9 +6,9 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#if HAVE___THREAD
|
||||
#if USE_TLS && HAVE___THREAD
|
||||
|
||||
# define AL 4096
|
||||
#define AL 4096
|
||||
struct foo
|
||||
{
|
||||
int i;
|
||||
@ -55,11 +55,11 @@ do_test (void)
|
||||
return result;
|
||||
}
|
||||
|
||||
# define TEST_FUNCTION do_test ()
|
||||
#define TEST_FUNCTION do_test ()
|
||||
|
||||
#else
|
||||
|
||||
# define TEST_FUNCTION 0
|
||||
#define TEST_FUNCTION 0
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -3,18 +3,21 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#include "tls-macros.h"
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
|
||||
/* Two 'int' variables in TLS. */
|
||||
VAR_INT_DEF(foo);
|
||||
VAR_INT_DEF(bar);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
int result = 0;
|
||||
int *ap, *bp;
|
||||
|
||||
@ -79,6 +82,9 @@ do_test (void)
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,13 +3,15 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#include "tls-macros.h"
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
|
||||
/* One define int variable, two externs. */
|
||||
COMMON_INT_DECL(foo);
|
||||
VAR_INT_DECL(bar);
|
||||
VAR_INT_DEF(baz);
|
||||
#endif
|
||||
|
||||
|
||||
extern int in_dso (void);
|
||||
@ -19,6 +21,7 @@ extern int in_dso (void);
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
int result = 0;
|
||||
int *ap, *bp, *cp;
|
||||
|
||||
@ -64,6 +67,9 @@ do_test (void)
|
||||
result |= in_dso ();
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname[] = "tst-tlsmod2.so";
|
||||
int result = 0;
|
||||
int *foop;
|
||||
@ -46,6 +47,9 @@ do_test (void)
|
||||
dlclose (h);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname[] = "tst-tlsmod2.so";
|
||||
int result = 0;
|
||||
int *foop;
|
||||
@ -62,6 +63,9 @@ do_test (void)
|
||||
dlclose (h);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname[] = "tst-tlsmod2.so";
|
||||
int result = 0;
|
||||
int *foop;
|
||||
@ -80,6 +81,9 @@ do_test (void)
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname[] = "tst-tlsmod3.so";
|
||||
int result = 0;
|
||||
int (*fp) (void);
|
||||
@ -51,6 +52,9 @@ do_test (void)
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname1[] = "$ORIGIN/tst-tlsmod3.so";
|
||||
static const char modname2[] = "$ORIGIN/tst-tlsmod4.so";
|
||||
int result = 0;
|
||||
@ -164,6 +165,9 @@ do_test (void)
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef USE_TLS
|
||||
static const char modname1[] = "tst-tlsmod5.so";
|
||||
static const char modname2[] = "tst-tlsmod6.so";
|
||||
int result = 0;
|
||||
@ -32,6 +33,9 @@ do_test (void)
|
||||
dlclose (h2);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
#include "tls-macros.h"
|
||||
|
||||
|
||||
@ -9,6 +10,7 @@
|
||||
COMMON_INT_DEF(foo);
|
||||
VAR_INT_DEF(bar);
|
||||
VAR_INT_DECL(baz);
|
||||
#endif
|
||||
|
||||
extern int in_dso (void);
|
||||
|
||||
@ -16,6 +18,7 @@ int
|
||||
in_dso (void)
|
||||
{
|
||||
int result = 0;
|
||||
#ifdef USE_TLS
|
||||
int *ap, *bp, *cp;
|
||||
|
||||
/* Get variables using initial exec model. */
|
||||
@ -59,6 +62,7 @@ in_dso (void)
|
||||
printf ("baz = %d\n", *cp);
|
||||
result = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <tls.h>
|
||||
|
||||
#if defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
#if defined USE_TLS && defined HAVE___THREAD \
|
||||
&& defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
__thread int a[2] __attribute__ ((tls_model ("initial-exec")));
|
||||
#else
|
||||
int a[2];
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <tls.h>
|
||||
|
||||
#if defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
#if defined USE_TLS && defined HAVE___THREAD \
|
||||
&& defined HAVE_TLS_MODEL_ATTRIBUTE
|
||||
__thread int b[2] __attribute__ ((tls_model ("initial-exec")));
|
||||
#else
|
||||
int b[2];
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#if HAVE___THREAD
|
||||
#if USE_TLS && HAVE___THREAD
|
||||
|
||||
# define AL 4096
|
||||
#define AL 4096
|
||||
struct foo
|
||||
{
|
||||
int i;
|
||||
@ -15,9 +15,9 @@ static __thread struct foo f;
|
||||
static struct foo g;
|
||||
|
||||
|
||||
# ifndef FCT
|
||||
# define FCT in_dso1
|
||||
# endif
|
||||
#ifndef FCT
|
||||
# define FCT in_dso1
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
#include "tls-macros.h"
|
||||
|
||||
|
||||
@ -34,3 +35,4 @@ in_dso (int n, int *caller_foop)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#include "tls-macros.h"
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
extern int in_dso (int n, int *caller_foop);
|
||||
|
||||
@ -37,3 +38,4 @@ in_dso2 (void)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#include "tls-macros.h"
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
|
||||
COMMON_INT_DEF(baz);
|
||||
@ -34,3 +35,4 @@ in_dso (int n, int *caller_bazp)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
#include "tls-macros.h"
|
||||
|
||||
COMMON_INT_DEF(foo);
|
||||
#endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
#include "tls-macros.h"
|
||||
|
||||
COMMON_INT_DEF(bar);
|
||||
#endif
|
||||
|
@ -69,8 +69,8 @@ _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
|
||||
* check that we are profiling
|
||||
* and that we aren't recursively invoked.
|
||||
*/
|
||||
if (catomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
|
||||
GMON_PROF_ON))
|
||||
if (atomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
|
||||
GMON_PROF_ON))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Charset name normalization.
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001,2002,2003,2004,2005,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
|
||||
|
||||
@ -30,7 +30,7 @@ strip (char *wp, const char *s)
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (__isalnum_l (*s, _nl_C_locobj_ptr)
|
||||
|| *s == '_' || *s == '-' || *s == '.' || *s == ',')
|
||||
|| *s == '_' || *s == '-' || *s == '.' || *s == ',' || *s == ':')
|
||||
*wp++ = __toupper_l (*s, _nl_C_locobj_ptr);
|
||||
else if (*s == '/')
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Get descriptor for character set conversion.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,1998,1999,2000,2001,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -38,7 +38,7 @@ iconv_open (const char *tocode, const char *fromcode)
|
||||
int res;
|
||||
|
||||
/* Normalize the name. We remove all characters beside alpha-numeric,
|
||||
'_', '-', '/', and '.'. */
|
||||
'_', '-', '/', '.', and ':'. */
|
||||
tocode_len = strlen (tocode);
|
||||
tocode_conv = (char *) alloca (tocode_len + 3);
|
||||
strip (tocode_conv, tocode);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert text in given files from the specified from-set to the to-set.
|
||||
Copyright (C) 1998-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
@ -426,7 +426,7 @@ print_version (FILE *stream, struct argp_state *state)
|
||||
Copyright (C) %s Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
"), "2007");
|
||||
"), "2006");
|
||||
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Generate fastloading iconv module configuration files.
|
||||
Copyright (C) 2000-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000-2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
@ -395,7 +395,7 @@ print_version (FILE *stream, struct argp_state *state)
|
||||
Copyright (C) %s Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
"), "2007");
|
||||
"), "2006");
|
||||
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# GNU libc iconv configuration.
|
||||
# Copyright (C) 1997-2004, 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997-2004, 2005, 2007 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
|
||||
@ -1376,7 +1376,7 @@ module INTERNAL INIS-CYRILLIC// INIS-CYRILLIC 1
|
||||
# from to module cost
|
||||
alias ISO-IR-98// ISO_2033//
|
||||
alias ISO_2033-1983// ISO_2033//
|
||||
alias E13B/ ISO_2033//
|
||||
alias E13B// ISO_2033//
|
||||
alias CSISO2033// ISO_2033//
|
||||
module ISO_2033// INTERNAL ISO_2033 1
|
||||
module INTERNAL ISO_2033// ISO_2033 1
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Mapping tables for JOHAB handling.
|
||||
Copyright (C) 1998, 1999, 2000-2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000-2002, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jungshik Shin <jshin@pantheon.yale.edu>
|
||||
and Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
@ -239,7 +239,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
|
||||
if (__builtin_expect (ch2 < 0x31, 0) \
|
||||
|| (__builtin_expect (ch2 > 0x7e, 0) && ch2 < 0x91) \
|
||||
|| __builtin_expect (ch2, 0) == 0xff \
|
||||
|| (__builtin_expect (ch, 0) == 0xd9 && ch2 > 0xe5) \
|
||||
|| (__builtin_expect (ch, 0) == 0xd9 && ch2 > 0xe8) \
|
||||
|| (__builtin_expect (ch, 0) == 0xda \
|
||||
&& ch2 > 0xa0 && ch2 < 0xd4) \
|
||||
|| (__builtin_expect (ch, 0) == 0xde && ch2 > 0xf1)) \
|
||||
@ -386,7 +386,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
|
||||
break; \
|
||||
} \
|
||||
if (__builtin_expect (written == __UNKNOWN_10646_CHAR, 0) \
|
||||
|| (outptr[0] == 0x22 && outptr[1] > 0x65)) \
|
||||
|| (outptr[0] == 0x22 && outptr[1] > 0x68)) \
|
||||
{ \
|
||||
UNICODE_TAG_HANDLER (ch, 4); \
|
||||
STANDARD_TO_LOOP_ERR_HANDLER (4); \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Conversion tables for KS C 5601-1992 based encoding conversion.
|
||||
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 2000, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jungshik Shin <jshin@pantheon.yale.edu>, 1998.
|
||||
|
||||
@ -412,7 +412,8 @@ const uint16_t __ksc5601_sym_to_ucs[] =
|
||||
[0x0098] = 0x2669, [0x0099] = 0x266a, [0x009a] = 0x266c, [0x009b] = 0x327f,
|
||||
[0x009c] = 0x321c, [0x009d] = 0x2116, [0x009e] = 0x33c7, [0x009f] = 0x2122,
|
||||
[0x00a0] = 0x33c2, [0x00a1] = 0x33d8, [0x00a2] = 0x2121, [0x00a3] = 0x20ac,
|
||||
[0x00a4] = 0x00ae, [0x00bc] = 0xff01, [0x00bd] = 0xff02, [0x00be] = 0xff03,
|
||||
[0x00a4] = 0x00ae, [0x00a5] = 0x327e,
|
||||
[0x00bc] = 0xff01, [0x00bd] = 0xff02, [0x00be] = 0xff03,
|
||||
[0x00bf] = 0xff04, [0x00c0] = 0xff05, [0x00c1] = 0xff06, [0x00c2] = 0xff07,
|
||||
[0x00c3] = 0xff08, [0x00c4] = 0xff09, [0x00c5] = 0xff0a, [0x00c6] = 0xff0b,
|
||||
[0x00c7] = 0xff0c, [0x00c8] = 0xff0d, [0x00c9] = 0xff0e, [0x00ca] = 0xff0f,
|
||||
@ -917,6 +918,7 @@ const struct map __ksc5601_sym_from_ucs[KSC5601_SYMBOL] =
|
||||
{0x3273, "\x28\x44"}, {0x3274, "\x28\x45"}, {0x3275, "\x28\x46"},
|
||||
{0x3276, "\x28\x47"}, {0x3277, "\x28\x48"}, {0x3278, "\x28\x49"},
|
||||
{0x3279, "\x28\x4a"}, {0x327a, "\x28\x4b"}, {0x327b, "\x28\x4c"},
|
||||
{0x327e, "\x22\x68"},
|
||||
{0x327f, "\x22\x5e"}, {0x3380, "\x27\x49"}, {0x3381, "\x27\x4a"},
|
||||
{0x3382, "\x27\x4b"}, {0x3383, "\x27\x4c"}, {0x3384, "\x27\x4d"},
|
||||
{0x3388, "\x27\x3a"}, {0x3389, "\x27\x3b"}, {0x338a, "\x27\x5c"},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Access functions for KS C 5601-1992 based encoding conversion.
|
||||
Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000, 2003, 2007 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
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#define KSC5601_HANGUL 2350
|
||||
#define KSC5601_HANJA 4888
|
||||
#define KSC5601_SYMBOL 988
|
||||
#define KSC5601_SYMBOL 989
|
||||
|
||||
#include <gconv.h>
|
||||
#include <stdint.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Mapping tables for UHC handling.
|
||||
Copyright (C) 1998, 1999, 2000-2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000-2002, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jungshik Shin <jshin@pantheon.yale.edu>, 1998.
|
||||
|
||||
@ -3135,7 +3135,8 @@ static const char uhc_hangul_from_ucs[11172][2] =
|
||||
else \
|
||||
{ \
|
||||
ch = ksc5601_to_ucs4 (&inptr, 2, 0x80); \
|
||||
if (__builtin_expect (ch == __UNKNOWN_10646_CHAR, 0)) \
|
||||
if (__builtin_expect (ch == __UNKNOWN_10646_CHAR, 0) \
|
||||
|| __builtin_expect (ch == 0x327e, 0)) \
|
||||
{ \
|
||||
/* Illegal. */ \
|
||||
STANDARD_FROM_LOOP_ERR_HANDLER (2); \
|
||||
@ -3207,15 +3208,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
|
||||
{ \
|
||||
size_t written = ucs4_to_ksc5601_sym (ch, outptr, outend - outptr); \
|
||||
\
|
||||
if (__builtin_expect (ch == 0x327e, 0) \
|
||||
|| __builtin_expect (written == __UNKNOWN_10646_CHAR, 0)) \
|
||||
{ \
|
||||
UNICODE_TAG_HANDLER (ch, 4); \
|
||||
STANDARD_TO_LOOP_ERR_HANDLER (4); \
|
||||
} \
|
||||
if (__builtin_expect (written == 0, 0)) \
|
||||
{ \
|
||||
result = __GCONV_FULL_OUTPUT; \
|
||||
break; \
|
||||
} \
|
||||
if (__builtin_expect (written == __UNKNOWN_10646_CHAR, 0)) \
|
||||
{ \
|
||||
UNICODE_TAG_HANDLER (ch, 4); \
|
||||
STANDARD_TO_LOOP_ERR_HANDLER (4); \
|
||||
} \
|
||||
\
|
||||
*outptr++ |= 0x80; \
|
||||
|
367
include/atomic.h
367
include/atomic.h
@ -21,31 +21,6 @@
|
||||
#ifndef _ATOMIC_H
|
||||
#define _ATOMIC_H 1
|
||||
|
||||
/* This header defines three types of macros:
|
||||
|
||||
- atomic arithmetic and logic operation on memory. They all
|
||||
have the prefix "atomic_".
|
||||
|
||||
- conditionally atomic operations of the same kinds. These
|
||||
always behave identical but can be faster when atomicity
|
||||
is not really needed since only one thread has access to
|
||||
the memory location. In that case the code is slower in
|
||||
the multi-thread case. The interfaces have the prefix
|
||||
"catomic_".
|
||||
|
||||
- support functions like barriers. They also have the preifx
|
||||
"atomic_".
|
||||
|
||||
Architectures must provide a few lowlevel macros (the compare
|
||||
and exchange definitions). All others are optional. They
|
||||
should only be provided if the architecture has specific
|
||||
support for the operation.
|
||||
|
||||
As <atomic.h> macros are usually heavily nested and often use local
|
||||
variables to make sure side-effects are evaluated properly, use for
|
||||
macro local variables a per-macro unique prefix. This file uses
|
||||
__atgN_ prefix where N is different in each macro. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bits/atomic.h>
|
||||
@ -55,33 +30,33 @@
|
||||
and following args. */
|
||||
#define __atomic_val_bysize(pre, post, mem, ...) \
|
||||
({ \
|
||||
__typeof (*mem) __atg1_result; \
|
||||
__typeof (*mem) __result; \
|
||||
if (sizeof (*mem) == 1) \
|
||||
__atg1_result = pre##_8_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_8_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 2) \
|
||||
__atg1_result = pre##_16_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_16_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 4) \
|
||||
__atg1_result = pre##_32_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_32_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 8) \
|
||||
__atg1_result = pre##_64_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_64_##post (mem, __VA_ARGS__); \
|
||||
else \
|
||||
abort (); \
|
||||
__atg1_result; \
|
||||
__result; \
|
||||
})
|
||||
#define __atomic_bool_bysize(pre, post, mem, ...) \
|
||||
({ \
|
||||
int __atg2_result; \
|
||||
int __result; \
|
||||
if (sizeof (*mem) == 1) \
|
||||
__atg2_result = pre##_8_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_8_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 2) \
|
||||
__atg2_result = pre##_16_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_16_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 4) \
|
||||
__atg2_result = pre##_32_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_32_##post (mem, __VA_ARGS__); \
|
||||
else if (sizeof (*mem) == 8) \
|
||||
__atg2_result = pre##_64_##post (mem, __VA_ARGS__); \
|
||||
__result = pre##_64_##post (mem, __VA_ARGS__); \
|
||||
else \
|
||||
abort (); \
|
||||
__atg2_result; \
|
||||
__result; \
|
||||
})
|
||||
|
||||
|
||||
@ -95,29 +70,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined catomic_compare_and_exchange_val_acq \
|
||||
&& defined __arch_c_compare_and_exchange_val_32_acq
|
||||
# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
|
||||
__atomic_val_bysize (__arch_c_compare_and_exchange_val,acq, \
|
||||
mem, newval, oldval)
|
||||
#else
|
||||
# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
|
||||
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_compare_and_exchange_val_rel
|
||||
# define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
|
||||
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_compare_and_exchange_val_rel
|
||||
# define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \
|
||||
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
|
||||
#endif
|
||||
|
||||
|
||||
/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
|
||||
Return zero if *MEM was changed or non-zero if no exchange happened. */
|
||||
#ifndef atomic_compare_and_exchange_bool_acq
|
||||
@ -129,26 +87,8 @@
|
||||
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
|
||||
({ /* Cannot use __oldval here, because macros later in this file might \
|
||||
call this macro with __oldval argument. */ \
|
||||
__typeof (oldval) __atg3_old = (oldval); \
|
||||
atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \
|
||||
!= __atg3_old; \
|
||||
})
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_compare_and_exchange_bool_acq
|
||||
# ifdef __arch_c_compare_and_exchange_bool_32_acq
|
||||
# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
|
||||
__atomic_bool_bysize (__arch_c_compare_and_exchange_bool,acq, \
|
||||
mem, newval, oldval)
|
||||
# else
|
||||
# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
|
||||
({ /* Cannot use __oldval here, because macros later in this file might \
|
||||
call this macro with __oldval argument. */ \
|
||||
__typeof (oldval) __atg4_old = (oldval); \
|
||||
catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old) \
|
||||
!= __atg4_old; \
|
||||
__typeof (oldval) __old = (oldval); \
|
||||
atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \
|
||||
})
|
||||
# endif
|
||||
#endif
|
||||
@ -160,26 +100,21 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_compare_and_exchange_bool_rel
|
||||
# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
|
||||
catomic_compare_and_exchange_bool_acq (mem, newval, oldval)
|
||||
#endif
|
||||
|
||||
|
||||
/* Store NEWVALUE in *MEM and return the old value. */
|
||||
#ifndef atomic_exchange_acq
|
||||
# define atomic_exchange_acq(mem, newvalue) \
|
||||
({ __typeof (*(mem)) __atg5_oldval; \
|
||||
__typeof (mem) __atg5_memp = (mem); \
|
||||
__typeof (*(mem)) __atg5_value = (newvalue); \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __value = (newvalue); \
|
||||
\
|
||||
do \
|
||||
__atg5_oldval = *__atg5_memp; \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \
|
||||
__atg5_oldval), 0)); \
|
||||
__oldval = *__memp; \
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__value, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
\
|
||||
__atg5_oldval; })
|
||||
__oldval; })
|
||||
#endif
|
||||
|
||||
#ifndef atomic_exchange_rel
|
||||
@ -190,124 +125,72 @@
|
||||
/* Add VALUE to *MEM and return the old value of *MEM. */
|
||||
#ifndef atomic_exchange_and_add
|
||||
# define atomic_exchange_and_add(mem, value) \
|
||||
({ __typeof (*(mem)) __atg6_oldval; \
|
||||
__typeof (mem) __atg6_memp = (mem); \
|
||||
__typeof (*(mem)) __atg6_value = (value); \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __value = (value); \
|
||||
\
|
||||
do \
|
||||
__atg6_oldval = *__atg6_memp; \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg6_memp, \
|
||||
__atg6_oldval \
|
||||
+ __atg6_value, \
|
||||
__atg6_oldval), 0)); \
|
||||
__oldval = *__memp; \
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__oldval \
|
||||
+ __value,\
|
||||
__oldval),\
|
||||
0)); \
|
||||
\
|
||||
__atg6_oldval; })
|
||||
__oldval; })
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_exchange_and_add
|
||||
# define catomic_exchange_and_add(mem, value) \
|
||||
({ __typeof (*(mem)) __atg7_oldv; \
|
||||
__typeof (mem) __atg7_memp = (mem); \
|
||||
__typeof (*(mem)) __atg7_value = (value); \
|
||||
\
|
||||
do \
|
||||
__atg7_oldv = *__atg7_memp; \
|
||||
while (__builtin_expect \
|
||||
(catomic_compare_and_exchange_bool_acq (__atg7_memp, \
|
||||
__atg7_oldv \
|
||||
+ __atg7_value, \
|
||||
__atg7_oldv), 0)); \
|
||||
\
|
||||
__atg7_oldv; })
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_max
|
||||
# define atomic_max(mem, value) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg8_oldval; \
|
||||
__typeof (mem) __atg8_memp = (mem); \
|
||||
__typeof (*(mem)) __atg8_value = (value); \
|
||||
__typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __value = (value); \
|
||||
do { \
|
||||
__atg8_oldval = *__atg8_memp; \
|
||||
if (__atg8_oldval >= __atg8_value) \
|
||||
__oldval = *__memp; \
|
||||
if (__oldval >= __value) \
|
||||
break; \
|
||||
} while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\
|
||||
__atg8_oldval), 0)); \
|
||||
} while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__value, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_max
|
||||
# define catomic_max(mem, value) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg9_oldv; \
|
||||
__typeof (mem) __atg9_memp = (mem); \
|
||||
__typeof (*(mem)) __atg9_value = (value); \
|
||||
do { \
|
||||
__atg9_oldv = *__atg9_memp; \
|
||||
if (__atg9_oldv >= __atg9_value) \
|
||||
break; \
|
||||
} while (__builtin_expect \
|
||||
(catomic_compare_and_exchange_bool_acq (__atg9_memp, \
|
||||
__atg9_value, \
|
||||
__atg9_oldv), 0)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_min
|
||||
# define atomic_min(mem, value) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg10_oldval; \
|
||||
__typeof (mem) __atg10_memp = (mem); \
|
||||
__typeof (*(mem)) __atg10_value = (value); \
|
||||
__typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __value = (value); \
|
||||
do { \
|
||||
__atg10_oldval = *__atg10_memp; \
|
||||
if (__atg10_oldval <= __atg10_value) \
|
||||
__oldval = *__memp; \
|
||||
if (__oldval <= __value) \
|
||||
break; \
|
||||
} while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg10_memp, \
|
||||
__atg10_value, \
|
||||
__atg10_oldval), 0)); \
|
||||
} while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__value, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_add
|
||||
# define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_add
|
||||
# define catomic_add(mem, value) \
|
||||
(void) catomic_exchange_and_add ((mem), (value))
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_increment
|
||||
# define atomic_increment(mem) atomic_add ((mem), 1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_increment
|
||||
# define catomic_increment(mem) catomic_add ((mem), 1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_increment_val
|
||||
# define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_increment_val
|
||||
# define catomic_increment_val(mem) (catomic_exchange_and_add ((mem), 1) + 1)
|
||||
#endif
|
||||
|
||||
|
||||
/* Add one to *MEM and return true iff it's now zero. */
|
||||
#ifndef atomic_increment_and_test
|
||||
# define atomic_increment_and_test(mem) \
|
||||
@ -320,21 +203,11 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_decrement
|
||||
# define catomic_decrement(mem) catomic_add ((mem), -1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_decrement_val
|
||||
# define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef catomic_decrement_val
|
||||
# define catomic_decrement_val(mem) (catomic_exchange_and_add ((mem), -1) - 1)
|
||||
#endif
|
||||
|
||||
|
||||
/* Subtract 1 from *MEM and return true iff it's now zero. */
|
||||
#ifndef atomic_decrement_and_test
|
||||
# define atomic_decrement_and_test(mem) \
|
||||
@ -345,34 +218,35 @@
|
||||
/* Decrement *MEM if it is > 0, and return the old value. */
|
||||
#ifndef atomic_decrement_if_positive
|
||||
# define atomic_decrement_if_positive(mem) \
|
||||
({ __typeof (*(mem)) __atg11_oldval; \
|
||||
__typeof (mem) __atg11_memp = (mem); \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
__atg11_oldval = *__atg11_memp; \
|
||||
if (__builtin_expect (__atg11_oldval <= 0, 0)) \
|
||||
__oldval = *__memp; \
|
||||
if (__builtin_expect (__oldval <= 0, 0)) \
|
||||
break; \
|
||||
} \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg11_memp, \
|
||||
__atg11_oldval - 1, \
|
||||
__atg11_oldval), 0)); \
|
||||
__atg11_oldval; })
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__oldval \
|
||||
- 1, \
|
||||
__oldval),\
|
||||
0));\
|
||||
__oldval; })
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_add_negative
|
||||
# define atomic_add_negative(mem, value) \
|
||||
({ __typeof (value) __atg12_value = (value); \
|
||||
atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; })
|
||||
({ __typeof (value) __aan_value = (value); \
|
||||
atomic_exchange_and_add (mem, __aan_value) < -__aan_value; })
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef atomic_add_zero
|
||||
# define atomic_add_zero(mem, value) \
|
||||
({ __typeof (value) __atg13_value = (value); \
|
||||
atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; })
|
||||
({ __typeof (value) __aaz_value = (value); \
|
||||
atomic_exchange_and_add (mem, __aaz_value) == -__aaz_value; })
|
||||
#endif
|
||||
|
||||
|
||||
@ -384,102 +258,55 @@
|
||||
|
||||
#ifndef atomic_bit_test_set
|
||||
# define atomic_bit_test_set(mem, bit) \
|
||||
({ __typeof (*(mem)) __atg14_old; \
|
||||
__typeof (mem) __atg14_memp = (mem); \
|
||||
__typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __mask = ((__typeof (*(mem))) 1 << (bit)); \
|
||||
\
|
||||
do \
|
||||
__atg14_old = (*__atg14_memp); \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg14_memp, \
|
||||
__atg14_old | __atg14_mask,\
|
||||
__atg14_old), 0)); \
|
||||
__oldval = (*__memp); \
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__oldval \
|
||||
| __mask, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
\
|
||||
__atg14_old & __atg14_mask; })
|
||||
#endif
|
||||
|
||||
/* Atomically *mem &= mask. */
|
||||
#ifndef atomic_and
|
||||
# define atomic_and(mem, mask) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg15_old; \
|
||||
__typeof (mem) __atg15_memp = (mem); \
|
||||
__typeof (*(mem)) __atg15_mask = (mask); \
|
||||
\
|
||||
do \
|
||||
__atg15_old = (*__atg15_memp); \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg15_memp, \
|
||||
__atg15_old & __atg15_mask, \
|
||||
__atg15_old), 0)); \
|
||||
} while (0)
|
||||
__oldval & __mask; })
|
||||
#endif
|
||||
|
||||
/* Atomically *mem &= mask and return the old value of *mem. */
|
||||
#ifndef atomic_and_val
|
||||
# define atomic_and_val(mem, mask) \
|
||||
({ __typeof (*(mem)) __atg16_old; \
|
||||
__typeof (mem) __atg16_memp = (mem); \
|
||||
__typeof (*(mem)) __atg16_mask = (mask); \
|
||||
#ifndef atomic_and
|
||||
# define atomic_and(mem, mask) \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __mask = (mask); \
|
||||
\
|
||||
do \
|
||||
__atg16_old = (*__atg16_memp); \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg16_memp, \
|
||||
__atg16_old & __atg16_mask,\
|
||||
__atg16_old), 0)); \
|
||||
__oldval = (*__memp); \
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__oldval \
|
||||
& __mask, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
\
|
||||
__atg16_old; })
|
||||
__oldval; })
|
||||
#endif
|
||||
|
||||
/* Atomically *mem |= mask and return the old value of *mem. */
|
||||
#ifndef atomic_or
|
||||
# define atomic_or(mem, mask) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg17_old; \
|
||||
__typeof (mem) __atg17_memp = (mem); \
|
||||
__typeof (*(mem)) __atg17_mask = (mask); \
|
||||
\
|
||||
do \
|
||||
__atg17_old = (*__atg17_memp); \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg17_memp, \
|
||||
__atg17_old | __atg17_mask, \
|
||||
__atg17_old), 0)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef catomic_or
|
||||
# define catomic_or(mem, mask) \
|
||||
do { \
|
||||
__typeof (*(mem)) __atg18_old; \
|
||||
__typeof (mem) __atg18_memp = (mem); \
|
||||
__typeof (*(mem)) __atg18_mask = (mask); \
|
||||
\
|
||||
do \
|
||||
__atg18_old = (*__atg18_memp); \
|
||||
while (__builtin_expect \
|
||||
(catomic_compare_and_exchange_bool_acq (__atg18_memp, \
|
||||
__atg18_old | __atg18_mask,\
|
||||
__atg18_old), 0)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Atomically *mem |= mask and return the old value of *mem. */
|
||||
#ifndef atomic_or_val
|
||||
# define atomic_or_val(mem, mask) \
|
||||
({ __typeof (*(mem)) __atg19_old; \
|
||||
__typeof (mem) __atg19_memp = (mem); \
|
||||
__typeof (*(mem)) __atg19_mask = (mask); \
|
||||
({ __typeof (*(mem)) __oldval; \
|
||||
__typeof (mem) __memp = (mem); \
|
||||
__typeof (*(mem)) __mask = (mask); \
|
||||
\
|
||||
do \
|
||||
__atg19_old = (*__atg19_memp); \
|
||||
while (__builtin_expect \
|
||||
(atomic_compare_and_exchange_bool_acq (__atg19_memp, \
|
||||
__atg19_old | __atg19_mask,\
|
||||
__atg19_old), 0)); \
|
||||
__oldval = (*__memp); \
|
||||
while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
|
||||
__oldval \
|
||||
| __mask, \
|
||||
__oldval),\
|
||||
0)); \
|
||||
\
|
||||
__atg19_old; })
|
||||
__oldval; })
|
||||
#endif
|
||||
|
||||
#ifndef atomic_full_barrier
|
||||
|
@ -47,9 +47,6 @@ libc_hidden_proto (_dl_addr)
|
||||
|
||||
/* Close an object previously opened by _dl_open. */
|
||||
extern void _dl_close (void *map) attribute_hidden;
|
||||
/* Same as above, but without locking and safety checks for user
|
||||
provided map arguments. */
|
||||
extern void _dl_close_worker (struct link_map *map) attribute_hidden;
|
||||
|
||||
/* Look up NAME in shared object HANDLE (which may be RTLD_DEFAULT or
|
||||
RTLD_NEXT). WHO is the calling function, for RTLD_NEXT. Returns
|
||||
|
@ -19,7 +19,7 @@ extern int rtld_errno attribute_hidden;
|
||||
|
||||
# else
|
||||
|
||||
# include <tls.h>
|
||||
# include <tls.h> /* Defines USE_TLS. */
|
||||
|
||||
# if USE___THREAD
|
||||
# undef errno
|
||||
|
@ -114,13 +114,6 @@
|
||||
# define _weak_alias(name, aliasname) \
|
||||
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
|
||||
|
||||
/* Same as WEAK_ALIAS, but mark symbol as hidden. */
|
||||
# define weak_hidden_alias(name, aliasname) \
|
||||
_weak_hidden_alias (name, aliasname)
|
||||
# define _weak_hidden_alias(name, aliasname) \
|
||||
extern __typeof (name) aliasname \
|
||||
__attribute__ ((weak, alias (#name), __visibility__ ("hidden")));
|
||||
|
||||
/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */
|
||||
# define weak_extern(symbol) _weak_extern (weak symbol)
|
||||
# define _weak_extern(expr) _Pragma (#expr)
|
||||
@ -128,7 +121,6 @@
|
||||
# else
|
||||
|
||||
# define weak_alias(name, aliasname) strong_alias(name, aliasname)
|
||||
# define weak_hidden_alias(name, aliasname) strong_alias(name, aliasname)
|
||||
# define weak_extern(symbol) /* Nothing. */
|
||||
|
||||
# endif
|
||||
@ -294,42 +286,27 @@ requires at runtime the shared libraries from the glibc version used \
|
||||
for linking")
|
||||
#endif
|
||||
|
||||
/* Declare SYMBOL to be TYPE (`function' or `object') of SIZE bytes
|
||||
alias to ORIGINAL, when the assembler supports such declarations
|
||||
(such as in ELF).
|
||||
/* Declare SYMBOL to be TYPE (`function' or `object') and of SIZE bytes,
|
||||
when the assembler supports such declarations (such as in ELF).
|
||||
This is only necessary when defining something in assembly, or playing
|
||||
funny alias games where the size should be other than what the compiler
|
||||
thinks it is. */
|
||||
#define declare_symbol_alias(symbol, original, type, size) \
|
||||
declare_symbol_alias_1 (symbol, original, type, size)
|
||||
#define declare_symbol(symbol, type, size) \
|
||||
declare_symbol_1 (symbol, type, size)
|
||||
#ifdef ASM_TYPE_DIRECTIVE_PREFIX
|
||||
# ifdef __ASSEMBLER__
|
||||
# define declare_symbol_alias_1(symbol, original, type, size) \
|
||||
strong_alias (original, symbol); \
|
||||
# define declare_symbol_1(symbol, type, size) \
|
||||
.type C_SYMBOL_NAME (symbol), \
|
||||
declare_symbol_alias_1_paste (ASM_TYPE_DIRECTIVE_PREFIX, type); \
|
||||
.size C_SYMBOL_NAME (symbol), size
|
||||
# define declare_symbol_alias_1_paste(a, b) \
|
||||
declare_symbol_alias_1_paste_1 (a,b)
|
||||
# define declare_symbol_alias_1_paste_1(a,b) a##b
|
||||
declare_symbol_1_paste (ASM_TYPE_DIRECTIVE_PREFIX, type), size
|
||||
# define declare_symbol_1_paste(a, b) declare_symbol_1_paste_1 (a,b)
|
||||
# define declare_symbol_1_paste_1(a,b) a##b
|
||||
# else /* Not __ASSEMBLER__. */
|
||||
# define declare_symbol_alias_1(symbol, original, type, size) \
|
||||
asm (declare_symbol_alias_1_stringify (ASM_GLOBAL_DIRECTIVE) \
|
||||
" " __SYMBOL_PREFIX #symbol \
|
||||
"\n\t" declare_symbol_alias_1_alias (symbol, original) \
|
||||
"\n\t.type " __SYMBOL_PREFIX #symbol ", " \
|
||||
declare_symbol_alias_1_stringify (ASM_TYPE_DIRECTIVE_PREFIX) #type \
|
||||
# define declare_symbol_1(symbol, type, size) \
|
||||
asm (".type " __SYMBOL_PREFIX #symbol ", " \
|
||||
declare_symbol_1_stringify (ASM_TYPE_DIRECTIVE_PREFIX) #type \
|
||||
"\n\t.size " __SYMBOL_PREFIX #symbol ", " #size);
|
||||
# define declare_symbol_alias_1_stringify(x) \
|
||||
declare_symbol_alias_1_stringify_1 (x)
|
||||
# define declare_symbol_alias_1_stringify_1(x) #x
|
||||
# ifdef HAVE_ASM_SET_DIRECTIVE
|
||||
# define declare_symbol_alias_1_alias(symbol, original) \
|
||||
".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX #original
|
||||
# else
|
||||
# define declare_symbol_alias_1_alias(symbol, original) \
|
||||
__SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX #original
|
||||
# endif /* HAVE_ASM_SET_DIRECTIVE */
|
||||
# define declare_symbol_1_stringify(x) declare_symbol_1_stringify_1 (x)
|
||||
# define declare_symbol_1_stringify_1(x) #x
|
||||
# endif /* __ASSEMBLER__ */
|
||||
#else
|
||||
# define declare_symbol_1(symbol, type, size) /* Nothing. */
|
||||
@ -454,7 +431,8 @@ for linking")
|
||||
strong_alias(real, name)
|
||||
#endif
|
||||
|
||||
#if defined SHARED || defined LIBC_NONSHARED
|
||||
#if defined HAVE_VISIBILITY_ATTRIBUTE \
|
||||
&& (defined SHARED || defined LIBC_NONSHARED)
|
||||
# define attribute_hidden __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
# define attribute_hidden
|
||||
@ -466,7 +444,11 @@ for linking")
|
||||
# define attribute_tls_model_ie
|
||||
#endif
|
||||
|
||||
#define attribute_relro __attribute__ ((section (".data.rel.ro")))
|
||||
#ifdef HAVE_Z_RELRO
|
||||
# define attribute_relro __attribute__ ((section (".data.rel.ro")))
|
||||
#else
|
||||
# define attribute_relro
|
||||
#endif
|
||||
|
||||
/* Handling on non-exported internal names. We have to do this only
|
||||
for shared code. */
|
||||
@ -475,9 +457,14 @@ for linking")
|
||||
# define INTDEF(name) strong_alias (name, name##_internal)
|
||||
# define INTVARDEF(name) \
|
||||
_INTVARDEF (name, name##_internal)
|
||||
# define _INTVARDEF(name, aliasname) \
|
||||
# if defined HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define _INTVARDEF(name, aliasname) \
|
||||
extern __typeof (name) aliasname __attribute__ ((alias (#name), \
|
||||
visibility ("hidden")));
|
||||
# else
|
||||
# define _INTVARDEF(name, aliasname) \
|
||||
extern __typeof (name) aliasname __attribute__ ((alias (#name)));
|
||||
# endif
|
||||
# define INTDEF2(name, newname) strong_alias (name, newname##_internal)
|
||||
# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal)
|
||||
#else
|
||||
@ -562,10 +549,16 @@ for linking")
|
||||
versioned_symbol (libc, __real_foo, foo, GLIBC_2_1);
|
||||
libc_hidden_ver (__real_foo, foo) */
|
||||
|
||||
#if defined SHARED && defined DO_VERSIONING && !defined NO_HIDDEN
|
||||
#if defined SHARED && defined DO_VERSIONING \
|
||||
&& !defined HAVE_BROKEN_ALIAS_ATTRIBUTE && !defined NO_HIDDEN
|
||||
# ifndef __ASSEMBLER__
|
||||
# define __hidden_proto_hiddenattr(attrs...) \
|
||||
# if !defined HAVE_VISIBILITY_ATTRIBUTE \
|
||||
|| defined HAVE_BROKEN_VISIBILITY_ATTRIBUTE
|
||||
# define __hidden_proto_hiddenattr(attrs...)
|
||||
# else
|
||||
# define __hidden_proto_hiddenattr(attrs...) \
|
||||
__attribute__ ((visibility ("hidden"), ##attrs))
|
||||
# endif
|
||||
# define hidden_proto(name, attrs...) \
|
||||
__hidden_proto (name, __GI_##name, ##attrs)
|
||||
# define __hidden_proto(name, internal, attrs...) \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Data structure for communication from the run-time dynamic linker for
|
||||
loaded ELF shared objects.
|
||||
Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2006, 2007 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
|
||||
@ -44,7 +44,6 @@ extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
|
||||
#include <dl-lookupcfg.h>
|
||||
#include <tls.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <rtld-lowlevel.h>
|
||||
|
||||
|
||||
/* Some internal data structures of the dynamic linker used in the
|
||||
@ -122,7 +121,7 @@ struct link_map
|
||||
are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>. */
|
||||
|
||||
ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
|
||||
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
|
||||
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
|
||||
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
|
||||
ElfW(Addr) l_entry; /* Entry point location. */
|
||||
ElfW(Half) l_phnum; /* Number of program header entries. */
|
||||
@ -183,6 +182,9 @@ struct link_map
|
||||
is interested in the PLT interception.*/
|
||||
unsigned int l_removed:1; /* Nozero if the object cannot be used anymore
|
||||
since it is removed. */
|
||||
unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
|
||||
mprotected or if no holes are present at
|
||||
all. */
|
||||
|
||||
/* Array with version names. */
|
||||
unsigned int l_nversions;
|
||||
@ -220,8 +222,6 @@ struct link_map
|
||||
/* This is an array defining the lookup scope for this link map.
|
||||
There are initially at most three different scope lists. */
|
||||
struct r_scope_elem **l_scope;
|
||||
/* We need to protect using the SCOPEREC. */
|
||||
__rtld_mrlock_define (, l_scope_lock)
|
||||
|
||||
/* A similar array, this time only with the local scope. This is
|
||||
used occasionally. */
|
||||
@ -261,6 +261,7 @@ struct link_map
|
||||
const ElfW(Sym) *ret;
|
||||
} l_lookup_cache;
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Thread-local storage related info. */
|
||||
|
||||
/* Start of the initialization image. */
|
||||
@ -273,13 +274,14 @@ struct link_map
|
||||
size_t l_tls_align;
|
||||
/* Offset of first byte module alignment. */
|
||||
size_t l_tls_firstbyte_offset;
|
||||
#ifndef NO_TLS_OFFSET
|
||||
# define NO_TLS_OFFSET 0
|
||||
#endif
|
||||
# ifndef NO_TLS_OFFSET
|
||||
# define NO_TLS_OFFSET 0
|
||||
# endif
|
||||
/* For objects present at startup time: offset in the static TLS block. */
|
||||
ptrdiff_t l_tls_offset;
|
||||
/* Index of the module in the dtv array. */
|
||||
size_t l_tls_modid;
|
||||
#endif
|
||||
|
||||
/* Information used to change permission after the relocations are
|
||||
done. */
|
||||
|
@ -42,4 +42,6 @@ libnsl_hidden_proto (__nis_default_group)
|
||||
libnsl_hidden_proto (__nis_default_access)
|
||||
libnsl_hidden_proto (nis_clone_object)
|
||||
|
||||
extern const_nis_name __nis_domain_of (const_nis_name) __THROW;
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Macros for managing ABI-compatibility definitions using ELF symbol versions.
|
||||
Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2002 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
|
||||
@ -44,8 +44,6 @@
|
||||
in the GLIBC_2.0 version and obsoleted in the GLIBC_2.2 version. */
|
||||
|
||||
# define SHLIB_COMPAT(lib, introduced, obsoleted) \
|
||||
_SHLIB_COMPAT (lib, introduced, obsoleted)
|
||||
# define _SHLIB_COMPAT(lib, introduced, obsoleted) \
|
||||
((IS_IN_##lib - 0) \
|
||||
&& (!(ABI_##lib##_##obsoleted - 0) \
|
||||
|| ((ABI_##lib##_##introduced - 0) < (ABI_##lib##_##obsoleted - 0))))
|
||||
@ -64,17 +62,13 @@
|
||||
shlib-versions if that is newer. */
|
||||
|
||||
# define versioned_symbol(lib, local, symbol, version) \
|
||||
versioned_symbol_1 (lib, local, symbol, version)
|
||||
# define versioned_symbol_1(lib, local, symbol, version) \
|
||||
versioned_symbol_2 (local, symbol, VERSION_##lib##_##version)
|
||||
# define versioned_symbol_2(local, symbol, name) \
|
||||
versioned_symbol_1 (local, symbol, VERSION_##lib##_##version)
|
||||
# define versioned_symbol_1(local, symbol, name) \
|
||||
default_symbol_version (local, symbol, name)
|
||||
|
||||
# define compat_symbol(lib, local, symbol, version) \
|
||||
compat_symbol_1 (lib, local, symbol, version)
|
||||
# define compat_symbol_1(lib, local, symbol, version) \
|
||||
compat_symbol_2 (local, symbol, VERSION_##lib##_##version)
|
||||
# define compat_symbol_2(local, symbol, name) \
|
||||
compat_symbol_1 (local, symbol, VERSION_##lib##_##version)
|
||||
# define compat_symbol_1(local, symbol, name) \
|
||||
symbol_version (local, symbol, name)
|
||||
|
||||
#else
|
||||
|
@ -131,6 +131,7 @@ libc_hidden_proto (__vsnprintf_chk)
|
||||
libc_hidden_proto (__vfprintf_chk)
|
||||
|
||||
# if !defined NOT_IN_libc && defined SHARED && defined DO_VERSIONING \
|
||||
&& defined HAVE_VISIBILITY_ATTRIBUTE && !defined HAVE_BROKEN_ALIAS_ATTRIBUTE\
|
||||
&& !defined NO_HIDDEN
|
||||
/* Special gcc builtins. */
|
||||
extern size_t __builtin_fwrite (const void *, size_t, size_t, void *)
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
#include <misc/sys/cdefs.h>
|
||||
|
||||
/* The compiler will optimize based on the knowledge the parameter is
|
||||
not NULL. This will omit tests. A robust implementation cannot allow
|
||||
this so when compiling glibc itself we ignore this attribute. */
|
||||
#undef __nonnull
|
||||
#define __nonnull(params)
|
||||
|
||||
extern void __chk_fail (void) __attribute__ ((__noreturn__));
|
||||
libc_hidden_proto (__chk_fail)
|
||||
rtld_hidden_proto (__chk_fail)
|
||||
|
@ -12,4 +12,7 @@ extern int __mprotect (void *__addr, size_t __len, int __prot);
|
||||
/* This one is Linux specific. */
|
||||
extern void *__mremap (void *__addr, size_t __old_len,
|
||||
size_t __new_len, int __flags, ...);
|
||||
|
||||
libc_hidden_proto (madvise);
|
||||
|
||||
#endif
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
#include_next <tls.h>
|
||||
|
||||
#if HAVE___THREAD && (!defined NOT_IN_libc || defined IS_IN_libpthread)
|
||||
#if USE_TLS && HAVE___THREAD \
|
||||
&& (!defined NOT_IN_libc || defined IS_IN_libpthread)
|
||||
|
||||
# define USE___THREAD 1
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1991-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1991-2006, 2007 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
|
||||
@ -52,7 +52,7 @@ routines := htonl htons \
|
||||
aux := check_pf ifreq
|
||||
|
||||
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
|
||||
tst-gethnm test-ifaddrs bug-if1
|
||||
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt
|
||||
|
||||
include ../Rules
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2006.
|
||||
|
||||
@ -51,7 +51,7 @@ add_padding (uint8_t *extbuf, int offset, int npad)
|
||||
{
|
||||
if (npad == 1)
|
||||
extbuf[offset] = IP6OPT_PAD1;
|
||||
else
|
||||
else if (npad > 0)
|
||||
{
|
||||
struct ip6_opt *pad_opt = (struct ip6_opt *) (extbuf + offset);
|
||||
|
||||
@ -102,21 +102,17 @@ inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type,
|
||||
int data_offset = offset + sizeof (struct ip6_opt);
|
||||
int npad = (align - data_offset % align) & (align - 1);
|
||||
|
||||
/* Now we can check whether the buffer is large enough. */
|
||||
if (data_offset + npad + len > extlen)
|
||||
return -1;
|
||||
|
||||
if (npad != 0)
|
||||
{
|
||||
if (extbuf != NULL)
|
||||
add_padding (extbuf, offset, npad);
|
||||
|
||||
offset += npad;
|
||||
}
|
||||
|
||||
/* Now prepare the option itself. */
|
||||
if (extbuf != NULL)
|
||||
{
|
||||
/* Now we can check whether the buffer is large enough. */
|
||||
if (data_offset + npad + len > extlen)
|
||||
return -1;
|
||||
|
||||
add_padding (extbuf, offset, npad);
|
||||
|
||||
offset += npad;
|
||||
|
||||
/* Now prepare the option itself. */
|
||||
struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);
|
||||
|
||||
opt->ip6o_type = type;
|
||||
@ -124,6 +120,8 @@ inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type,
|
||||
|
||||
*databufp = opt + 1;
|
||||
}
|
||||
else
|
||||
offset += npad;
|
||||
|
||||
return offset + sizeof (struct ip6_opt) + len;
|
||||
}
|
||||
@ -145,12 +143,14 @@ inet6_opt_finish (void *extbuf, socklen_t extlen, int offset)
|
||||
/* Required padding at the end. */
|
||||
int npad = (8 - (offset & 7)) & 7;
|
||||
|
||||
/* Make sure the buffer is large enough. */
|
||||
if (offset + npad > extlen)
|
||||
return -1;
|
||||
|
||||
if (extbuf != NULL)
|
||||
add_padding (extbuf, offset, npad);
|
||||
{
|
||||
/* Make sure the buffer is large enough. */
|
||||
if (offset + npad > extlen)
|
||||
return -1;
|
||||
|
||||
add_padding (extbuf, offset, npad);
|
||||
}
|
||||
|
||||
return offset + npad;
|
||||
}
|
||||
|
207
inet/test-inet6_opt.c
Normal file
207
inet/test-inet6_opt.c
Normal file
@ -0,0 +1,207 @@
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define OPT_X 42
|
||||
#define OPT_Y 43
|
||||
#define OPT_Z 44
|
||||
|
||||
static void *
|
||||
encode_inet6_opt (socklen_t *elp)
|
||||
{
|
||||
void *eb = NULL;
|
||||
socklen_t el;
|
||||
int cl;
|
||||
void *db;
|
||||
int offset;
|
||||
uint8_t val1;
|
||||
uint16_t val2;
|
||||
uint32_t val4;
|
||||
uint64_t val8;
|
||||
|
||||
*elp = 0;
|
||||
#define CHECK() \
|
||||
if (cl == -1) \
|
||||
{ \
|
||||
printf ("cl == -1 on line %d\n", __LINE__); \
|
||||
free (eb); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
/* Estimate the length */
|
||||
cl = inet6_opt_init (NULL, 0);
|
||||
CHECK ();
|
||||
cl = inet6_opt_append (NULL, 0, cl, OPT_X, 12, 8, NULL);
|
||||
CHECK ();
|
||||
cl = inet6_opt_append (NULL, 0, cl, OPT_Y, 7, 4, NULL);
|
||||
CHECK ();
|
||||
cl = inet6_opt_append (NULL, 0, cl, OPT_Z, 7, 1, NULL);
|
||||
CHECK ();
|
||||
cl = inet6_opt_finish (NULL, 0, cl);
|
||||
CHECK ();
|
||||
el = cl;
|
||||
|
||||
eb = malloc (el + 8);
|
||||
if (eb == NULL)
|
||||
{
|
||||
puts ("malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
/* Canary. */
|
||||
memcpy (eb + el, "deadbeef", 8);
|
||||
|
||||
cl = inet6_opt_init (eb, el);
|
||||
CHECK ();
|
||||
|
||||
cl = inet6_opt_append (eb, el, cl, OPT_X, 12, 8, &db);
|
||||
CHECK ();
|
||||
val4 = 0x12345678;
|
||||
offset = inet6_opt_set_val (db, 0, &val4, sizeof (val4));
|
||||
val8 = 0x0102030405060708LL;
|
||||
inet6_opt_set_val (db, offset, &val8, sizeof (val8));
|
||||
|
||||
cl = inet6_opt_append (eb, el, cl, OPT_Y, 7, 4, &db);
|
||||
CHECK ();
|
||||
val1 = 0x01;
|
||||
offset = inet6_opt_set_val (db, 0, &val1, sizeof (val1));
|
||||
val2 = 0x1331;
|
||||
offset = inet6_opt_set_val (db, offset, &val2, sizeof (val2));
|
||||
val4 = 0x01020304;
|
||||
inet6_opt_set_val (db, offset, &val4, sizeof (val4));
|
||||
|
||||
cl = inet6_opt_append (eb, el, cl, OPT_Z, 7, 1, &db);
|
||||
CHECK ();
|
||||
inet6_opt_set_val (db, 0, (void *) "abcdefg", 7);
|
||||
|
||||
cl = inet6_opt_finish (eb, el, cl);
|
||||
CHECK ();
|
||||
|
||||
if (memcmp (eb + el, "deadbeef", 8) != 0)
|
||||
{
|
||||
puts ("Canary corrupted");
|
||||
free (eb);
|
||||
return NULL;
|
||||
}
|
||||
*elp = el;
|
||||
return eb;
|
||||
}
|
||||
|
||||
int
|
||||
decode_inet6_opt (void *eb, socklen_t el)
|
||||
{
|
||||
int ret = 0;
|
||||
int seq = 0;
|
||||
int cl = 0;
|
||||
int offset;
|
||||
uint8_t type;
|
||||
socklen_t len;
|
||||
uint8_t val1;
|
||||
uint16_t val2;
|
||||
uint32_t val4;
|
||||
uint64_t val8;
|
||||
void *db;
|
||||
char buf[8];
|
||||
|
||||
while ((cl = inet6_opt_next (eb, el, cl, &type, &len, &db)) != -1)
|
||||
switch (type)
|
||||
{
|
||||
case OPT_X:
|
||||
if (seq++ != 0)
|
||||
{
|
||||
puts ("OPT_X is not first");
|
||||
ret = 1;
|
||||
}
|
||||
if (len != 12)
|
||||
{
|
||||
printf ("OPT_X's length %d != 12\n", len);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, 0, &val4, sizeof (val4));
|
||||
if (val4 != 0x12345678)
|
||||
{
|
||||
printf ("OPT_X's val4 %x != 0x12345678\n", val4);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, offset, &val8, sizeof (val8));
|
||||
if (offset != len || val8 != 0x0102030405060708LL)
|
||||
{
|
||||
printf ("OPT_X's val8 %llx != 0x0102030405060708\n",
|
||||
(long long) val8);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case OPT_Y:
|
||||
if (seq++ != 1)
|
||||
{
|
||||
puts ("OPT_Y is not second");
|
||||
ret = 1;
|
||||
}
|
||||
if (len != 7)
|
||||
{
|
||||
printf ("OPT_Y's length %d != 7\n", len);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, 0, &val1, sizeof (val1));
|
||||
if (val1 != 0x01)
|
||||
{
|
||||
printf ("OPT_Y's val1 %x != 0x01\n", val1);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, offset, &val2, sizeof (val2));
|
||||
if (val2 != 0x1331)
|
||||
{
|
||||
printf ("OPT_Y's val2 %x != 0x1331\n", val2);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, offset, &val4, sizeof (val4));
|
||||
if (offset != len || val4 != 0x01020304)
|
||||
{
|
||||
printf ("OPT_Y's val4 %x != 0x01020304\n", val4);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case OPT_Z:
|
||||
if (seq++ != 2)
|
||||
{
|
||||
puts ("OPT_Z is not third");
|
||||
ret = 1;
|
||||
}
|
||||
if (len != 7)
|
||||
{
|
||||
printf ("OPT_Z's length %d != 7\n", len);
|
||||
ret = 1;
|
||||
}
|
||||
offset = inet6_opt_get_val (db, 0, buf, 7);
|
||||
if (offset != len || memcmp (buf, "abcdefg", 7) != 0)
|
||||
{
|
||||
buf[7] = '\0';
|
||||
printf ("OPT_Z's buf \"%s\" != \"abcdefg\"\n", buf);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown option %d\n", type);
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
if (seq != 3)
|
||||
{
|
||||
puts ("Didn't see all of OPT_X, OPT_Y and OPT_Z");
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
void *eb;
|
||||
socklen_t el;
|
||||
eb = encode_inet6_opt (&el);
|
||||
if (eb == NULL)
|
||||
return 1;
|
||||
if (decode_inet6_opt (eb, el))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
17
io/Makefile
17
io/Makefile
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1992-2002,2003,2005,2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992-2002,2003,2005,2006, 2007 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
|
||||
@ -66,7 +66,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
|
||||
tst-openat tst-unlinkat tst-fstatat tst-futimesat \
|
||||
tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
|
||||
tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
|
||||
tst-mknodat tst-mkfifoat tst-ttyname_r
|
||||
tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5
|
||||
|
||||
distribute := ftwtest-sh
|
||||
|
||||
@ -90,6 +90,19 @@ CFLAGS-posix_fallocate64.c = -fexceptions
|
||||
CFLAGS-test-stat.c = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
||||
CFLAGS-test-lfs.c = -D_LARGEFILE64_SOURCE
|
||||
|
||||
ifeq (yes,$(have-protected))
|
||||
CFLAGS-stat.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-fstat.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-lstat.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-mknod.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-stat64.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-fstat64.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-lstat64.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-fstatat.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-fstatat64.c = -DHAVE_DOT_HIDDEN
|
||||
CFLAGS-mknodat.c = -DHAVE_DOT_HIDDEN
|
||||
endif
|
||||
|
||||
test-stat2-ARGS = Makefile . $(objpfx)test-stat2
|
||||
|
||||
tst-statvfs-ARGS = $(objpfx)tst-statvfs tst-statvfs.c /tmp
|
||||
|
25
io/bug-ftw5.c
Normal file
25
io/bug-ftw5.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <errno.h>
|
||||
#include <ftw.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int
|
||||
fn (const char *file, const struct stat *sb, int flag, struct FTW *s)
|
||||
{
|
||||
puts (file);
|
||||
return FTW_STOP;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (nftw ("/", fn, 0, FTW_CHDIR | FTW_ACTIONRETVAL) < 0)
|
||||
{
|
||||
printf ("nftw / FTW_CHDIR: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
12
io/fstat.c
12
io/fstat.c
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 2001, 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 1998, 2001 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
|
||||
@ -47,10 +47,16 @@
|
||||
#undef fstat
|
||||
#undef __fstat
|
||||
int
|
||||
attribute_hidden
|
||||
__fstat (int fd, struct stat *buf)
|
||||
{
|
||||
return __fxstat (_STAT_VER, fd, buf);
|
||||
}
|
||||
|
||||
weak_hidden_alias (__fstat, fstat)
|
||||
weak_alias (__fstat, fstat)
|
||||
|
||||
/* Hide the symbol so that no definition but the one locally in the
|
||||
executable or DSO is used. */
|
||||
#ifdef HAVE_DOT_HIDDEN
|
||||
asm (".hidden\tfstat");
|
||||
asm (".hidden\t__fstat");
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user