summaryrefslogtreecommitdiff
path: root/libc/csu
diff options
context:
space:
mode:
authorgcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2006-08-17 01:18:26 +0000
committergcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2006-08-17 01:18:26 +0000
commit15f34685e7a9b5caf761af2ebf6afa20438d440b (patch)
treedc04ce3cdf040f198743c15b64557824de174680 /libc/csu
parent1e848e0e775a36f6359161f5deb890942ef42ff3 (diff)
Import glibc-mainline for 2006-08-16
git-svn-id: svn://svn.eglibc.org/fsf/trunk@4 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/csu')
-rw-r--r--libc/csu/.cvsignore7
-rw-r--r--libc/csu/Makefile236
-rw-r--r--libc/csu/Versions26
-rw-r--r--libc/csu/abi-note.S73
-rw-r--r--libc/csu/check_fds.c102
-rw-r--r--libc/csu/defs.awk27
-rw-r--r--libc/csu/dso_handle.c22
-rw-r--r--libc/csu/elf-init.c99
-rw-r--r--libc/csu/errno-loc.c37
-rw-r--r--libc/csu/errno.c53
-rw-r--r--libc/csu/gmon-start.c79
-rw-r--r--libc/csu/init-first.c59
-rw-r--r--libc/csu/init.c27
-rw-r--r--libc/csu/libc-start.c263
-rw-r--r--libc/csu/libc-tls.c263
-rw-r--r--libc/csu/start.c13
-rw-r--r--libc/csu/sysdep.c2
-rw-r--r--libc/csu/tst-atomic-long.c28
-rw-r--r--libc/csu/tst-atomic.c386
-rw-r--r--libc/csu/tst-empty.c6
-rw-r--r--libc/csu/version.c79
21 files changed, 1887 insertions, 0 deletions
diff --git a/libc/csu/.cvsignore b/libc/csu/.cvsignore
new file mode 100644
index 000000000..da6e41b95
--- /dev/null
+++ b/libc/csu/.cvsignore
@@ -0,0 +1,7 @@
+*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
+*.gz *.Z *.tar *.tgz
+=*
+TODO COPYING* AUTHORS copyr-* copying.*
+glibc-*
+distinfo
+specs
diff --git a/libc/csu/Makefile b/libc/csu/Makefile
new file mode 100644
index 000000000..0e2ae07cf
--- /dev/null
+++ b/libc/csu/Makefile
@@ -0,0 +1,236 @@
+# Makefile for csu code for GNU C library.
+# Copyright (C) 1995-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
+# 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.
+
+# This directory contains the C startup code (that which calls main). This
+# consists of the startfile, built from start.c and installed as crt0.o
+# (traditionally) or crt1.o (for ELF). In ELF we also install crti.o and
+# crtn.o, special "initializer" and "finalizer" files used in the link
+# to make the .init and .fini sections work right; both these files are
+# built (in an arcane manner) from initfini.c.
+
+subdir := csu
+
+routines = init-first libc-start $(libc-init) sysdep version check_fds \
+ libc-tls elf-init dso_handle
+aux = errno
+elide-routines.os = libc-tls
+static-only-routines = elf-init
+csu-dummies = $(filter-out $(start-installed-name),crt1.o Mcrt1.o)
+extra-objs = start.o gmon-start.o \
+ $(start-installed-name) g$(start-installed-name) $(csu-dummies) \
+ S$(start-installed-name)
+omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
+ b$(start-installed-name) $(csu-dummies) \
+ S$(start-installed-name))
+install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies)
+distribute = initfini.c gmon-start.c start.c defs.awk \
+ abi-note.S init.c c not-cancel.h
+generated = version-info.h
+before-compile = $(objpfx)version-info.h
+
+tests := tst-empty tst-atomic tst-atomic-long
+tests-static := tst-empty
+
+all: # Make this the default target; it will be defined in Rules.
+
+include ../Makeconfig
+
+ifeq (yes,$(build-shared))
+extra-objs += S$(start-installed-name)
+install-lib += S$(start-installed-name)
+generated += start.os
+endif
+
+ifeq (yes,$(build-bounded))
+extra-objs += b$(start-installed-name)
+install-lib += b$(start-installed-name)
+generated += start.ob
+endif
+
+ifneq ($(start-installed-name),$(static-start-installed-name))
+extra-objs += $(static-start-installed-name) g$(static-start-installed-name)
+omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \
+ g$(static-start-installed-name))
+install-lib += $(static-start-installed-name) g$(static-start-installed-name)
+endif
+
+ifeq (yes,$(elf))
+before-compile += $(objpfx)abi-tag.h
+generated += abi-tag.h
+endif
+
+ifeq ($(have-initfini),yes)
+
+CPPFLAGS += -DHAVE_INITFINI
+
+# These are the special initializer/finalizer files. They are always the
+# first and last file in the link. crti.o ... crtn.o define the global
+# "functions" _init and _fini to run the .init and .fini sections.
+crtstuff = crti crtn
+
+install-lib += $(crtstuff:=.o)
+extra-objs += $(crtstuff:=.o)
+generated += $(crtstuff:=.S) initfini.s defs.h
+omit-deps += $(crtstuff)
+
+# Special rules for the building of crti.o and crtn.o
+$(crtstuff:%=$(objpfx)%.o): %.o: %.S $(objpfx)defs.h
+ $(compile.S) -g0 $(ASFLAGS-.os) -o $@
+
+CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions $(fno-unit-at-a-time)
+
+vpath initfini.c $(sysdirs)
+
+$(objpfx)initfini.s: initfini.c $(before-compile)
+ $(compile.c) -S $(CFLAGS-initfini.s) -finhibit-size-directive \
+ $(patsubst -f%,-fno-%,$(exceptions)) -o $@
+
+# We only have one kind of startup code files. Static binaries and
+# shared libraries are build using the PIC version.
+$(objpfx)crti.S: $(objpfx)initfini.s
+ sed -n -e '1,/@HEADER_ENDS/p' \
+ -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
+ -e '/@TRAILER_BEGINS/,$$p' $< > $@
+
+$(objpfx)crtn.S: $(objpfx)initfini.s
+ sed -n -e '1,/@HEADER_ENDS/p' \
+ -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
+ -e '/@TRAILER_BEGINS/,$$p' $< > $@
+
+# These explicit rules are necessary when the $(objpfx) subdirectory
+# did not exist at the time make considered the implicit rules using it.
+# This comes up with a fresh build using no_deps=t.
+$(patsubst %,$(objpfx)crt%.o,i n): %.o: %.S
+
+$(objpfx)defs.h: $(objpfx)initfini.s
+ sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \
+ $(AWK) -f defs.awk > $@
+
+endif
+
+ifeq (yes,$(elf))
+extra-objs += abi-note.o init.o
+asm-CPPFLAGS += -I$(objpfx).
+endif
+
+include ../Rules
+
+# Make these in the lib pass so they're available in time to link things with.
+subdir_lib: $(extra-objs:%=$(objpfx)%)
+
+define link-relocatable
+$(CC) -nostdlib -nostartfiles -r -o $@ $^
+endef
+
+ifndef start-installed-name-rule
+ifeq (yes,$(elf))
+# We link the ELF startfile along with a SHT_NOTE section indicating
+# the kernel ABI the binaries linked with this library will require.
+$(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
+ $(objpfx)init.o
+ $(link-relocatable)
+$(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \
+ $(objpfx)init.o
+ $(link-relocatable)
+$(objpfx)b$(start-installed-name): $(objpfx)start.ob $(objpfx)abi-note.ob \
+ $(objpfx)init.ob
+ $(link-relocatable)
+else
+# The startfile is installed under different names, so we just call our
+# source file `start.c' and copy to the installed name after compiling.
+$(objpfx)$(start-installed-name): $(objpfx)start.o
+ rm -f $@
+ ln $< $@
+$(objpfx)S$(start-installed-name): $(objpfx)start.os
+ rm -f $@
+ ln $< $@
+$(objpfx)b$(start-installed-name): $(objpfx)start.ob
+ rm -f $@
+ ln $< $@
+endif
+endif
+
+# The profiling startfile is made by linking together the normal
+# startfile with gmon-start.o, which defines a constructor function
+# to turn on profiling code at startup.
+$(addprefix $(objpfx),$(sort g$(start-installed-name) \
+ g$(static-start-installed-name))): \
+ $(objpfx)g%: $(objpfx)% $(objpfx)gmon-start.o
+ $(link-relocatable)
+
+# These extra files are sometimes expected by system standard linking
+# procedures, but we have nothing for them to do. So compile empty files.
+$(addprefix $(objpfx),$(filter-out $(start-installed-name), $(csu-dummies))):\
+ $(before-compile)
+ $(COMPILE.c) -o $@ -x c /dev/null
+
+# These headers are used by the startup code.
+$(objpfx)abi-tag.h: $(..)abi-tags
+ $(make-target-directory)
+ rm -f $@.new
+ sed -e 's/#.*$$//' -e '/^[ ]*$$/d' $< | \
+ while read conf tagos tagver; do \
+ test `expr '$(config-machine)-$(config-vendor)-$(config-os)' \
+ : "$$conf"` != 0 || continue; \
+ ( echo "$$tagos" | \
+ sed -e 's/[^0-9xXa-fA-F ]//' \
+ -e 's/^/#define __ABI_TAG_OS /'; \
+ echo "#ifndef __ABI_TAG_VERSION"; \
+ echo "$$tagver" | \
+ sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$$//' \
+ -e 's/ /,/g' -e 's/^/# define __ABI_TAG_VERSION /'; \
+ echo "#endif" ) > $@.new; \
+ done
+ if test -r $@.new; then mv -f $@.new $@; \
+ else echo >&2 'This configuration not matched in $<'; exit 1; fi
+
+all-Banner-files = $(wildcard $(addsuffix /Banner,\
+ $(sort $(subdir-srcdirs) \
+ $(sysdeps-srcdirs))))
+$(objpfx)version-info.h: $(common-objpfx)config.make $(all-Banner-files)
+ $(make-target-directory)
+ (case $(config-os) in \
+ linux*) version=`(printf '%s\n%s\n' \
+ '#include <linux/version.h>' \
+ UTS_RELEASE \
+ | $(CC) $(CPPFLAGS) -E -P - -DNOT_IN_libc=1 | \
+ sed -e 's/"\([^"]*\)".*/\1/p' -e d) 2>/dev/null`;\
+ if [ -z "$$version" ]; then \
+ if [ -r /proc/version ]; then \
+ version=`sed 's/.*Linux version \([^ ]*\) .*/>>\1<</' \
+ < /proc/version`; \
+ else \
+ version=`uname -r`; \
+ fi; \
+ fi; \
+ os=`uname -s 2> /dev/null`; \
+ if [ -z "$$os" ]; then \
+ os=Linux; \
+ fi; \
+ printf '"Compiled on a %s %s system on %s.\\n"\n' \
+ "$$os" "$$version" "`date +%Y-%m-%d`";; \
+ *) ;; \
+ esac; \
+ files="$(all-Banner-files)"; \
+ if test -n "$$files"; then \
+ printf '"Available extensions:\\n"\n'; \
+ sed -e '/^#/d' -e 's/^[[:space:]]*/ /' \
+ -e 's/^\(.*\)$$/\"\1\\n\"/' $$files; \
+ fi) > $@T
+ mv -f $@T $@
diff --git a/libc/csu/Versions b/libc/csu/Versions
new file mode 100644
index 000000000..a1321a9df
--- /dev/null
+++ b/libc/csu/Versions
@@ -0,0 +1,26 @@
+%include <tls.h>
+
+libc {
+ GLIBC_2.0 {
+ # helper functions
+ __libc_init_first; __libc_start_main;
+
+%if !(USE_TLS && HAVE___THREAD)
+ # global variables
+ _errno;
+
+ # variables in normal name space
+ errno;
+%endif
+ }
+ GLIBC_2.1 {
+ # New special glibc functions.
+ gnu_get_libc_release; gnu_get_libc_version;
+ }
+ GLIBC_PRIVATE {
+%if USE_TLS && HAVE___THREAD
+ # This version is for the TLS symbol, GLIBC_2.0 is the old object symbol.
+ errno;
+%endif
+ }
+}
diff --git a/libc/csu/abi-note.S b/libc/csu/abi-note.S
new file mode 100644
index 000000000..19c50d04f
--- /dev/null
+++ b/libc/csu/abi-note.S
@@ -0,0 +1,73 @@
+/* Special .init and .fini section support.
+ Copyright (C) 1997, 2001, 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
+ 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.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ 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. */
+
+/* Define an ELF note identifying the operating-system ABI that the
+ executable was created for. The ELF note information identifies a
+ particular OS or coordinated development effort within which the
+ ELF header's e_machine value plus (for dynamically linked programs)
+ the PT_INTERP dynamic linker name and DT_NEEDED shared library
+ names fully identify the runtime environment required by an
+ executable.
+
+ The general format of ELF notes is as follows.
+ Offsets and lengths are bytes or (parenthetical references) to the
+ values in other fields.
+
+offset length contents
+0 4 length of name
+4 4 length of data
+8 4 note type
+12 (0) vendor name
+ - null-terminated ASCII string, padded to 4-byte alignment
+12+(0) (4) note data,
+
+ The GNU project and cooperating development efforts (including the
+ Linux community) use note type 1 and a vendor name string of "GNU"
+ for a note descriptor that indicates ABI requirements. The note data
+ is four 32-bit words. The first of these is an operating system
+ number (0=Linux, 1=Hurd, 2=Solaris, ...) and the remaining three
+ identify the earliest release of that OS that supports this ABI.
+ See abi-tags (top level) for details. */
+
+#include <config.h>
+#include <abi-tag.h> /* OS-specific ABI tag value */
+
+/* The linker (GNU ld 2.8 and later) recognizes an allocated section whose
+ name begins with `.note' and creates a PT_NOTE program header entry
+ pointing at it. */
+
+ .section ".note.ABI-tag", "a"
+ .p2align 2
+ .long 1f - 0f /* name length */
+ .long 3f - 2f /* data length */
+ .long 1 /* note type */
+0: .asciz "GNU" /* vendor name */
+1: .p2align 2
+2: .long __ABI_TAG_OS /* note data: the ABI tag */
+ .long __ABI_TAG_VERSION
+3: .p2align 2 /* pad out section */
diff --git a/libc/csu/check_fds.c b/libc/csu/check_fds.c
new file mode 100644
index 000000000..10ba3da39
--- /dev/null
+++ b/libc/csu/check_fds.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2000, 2002, 2003, 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
+ 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 <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+/* Try to get a machine dependent instruction which will make the
+ program crash. This is used in case everything else fails. */
+#include <abort-instr.h>
+#ifndef ABORT_INSTRUCTION
+/* No such instruction is available. */
+# define ABORT_INSTRUCTION
+#endif
+
+#include <device-nrs.h>
+#include <not-cancel.h>
+
+
+/* Should other OSes (e.g., Hurd) have different versions which can
+ be written in a better way? */
+static void
+check_one_fd (int fd, int mode)
+{
+ /* Note that fcntl() with this parameter is not a cancellation point. */
+ if (__builtin_expect (__libc_fcntl (fd, F_GETFD), 0) == -1
+ && errno == EBADF)
+ {
+ const char *name;
+ dev_t dev;
+
+ /* For writable descriptors we use /dev/full. */
+ if ((mode & O_ACCMODE) == O_WRONLY)
+ {
+ name = _PATH_DEV "full";
+ dev = makedev (DEV_FULL_MAJOR, DEV_FULL_MINOR);
+ }
+ else
+ {
+ name = _PATH_DEVNULL;
+ dev = makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR);
+ }
+
+ /* Something is wrong with this descriptor, it's probably not
+ opened. Open /dev/null so that the SUID program we are
+ about to start does not accidently use this descriptor. */
+ int nullfd = open_not_cancel (name, mode, 0);
+
+ /* We are very paranoid here. With all means we try to ensure
+ that we are actually opening the /dev/null device and nothing
+ else.
+
+ Note that the following code assumes that STDIN_FILENO,
+ STDOUT_FILENO, STDERR_FILENO are the three lowest file
+ decsriptor numbers, in this order. */
+ struct stat64 st;
+ if (__builtin_expect (nullfd != fd, 0)
+ || __builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) != 0
+ || __builtin_expect (S_ISCHR (st.st_mode), 1) == 0
+ || st.st_rdev != dev)
+ /* We cannot even give an error message here since it would
+ run into the same problems. */
+ while (1)
+ /* Try for ever and ever. */
+ ABORT_INSTRUCTION;
+ }
+}
+
+
+void
+__libc_check_standard_fds (void)
+{
+ /* This is really paranoid but some people actually are. If /dev/null
+ should happen to be a symlink to somewhere else and not the device
+ commonly known as "/dev/null" we bail out. We can detect this with
+ the O_NOFOLLOW flag for open() but only on some system. */
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+ /* Check all three standard file descriptors. */
+ check_one_fd (STDIN_FILENO, O_WRONLY | O_NOFOLLOW);
+ check_one_fd (STDOUT_FILENO, O_RDONLY | O_NOFOLLOW);
+ check_one_fd (STDERR_FILENO, O_RDONLY | O_NOFOLLOW);
+}
diff --git a/libc/csu/defs.awk b/libc/csu/defs.awk
new file mode 100644
index 000000000..7ca5a3364
--- /dev/null
+++ b/libc/csu/defs.awk
@@ -0,0 +1,27 @@
+/^[ ]*\.endp/ { need_endp = 1 }
+/^[ ]*\.end/ { need_end = 1 }
+/^[ ]*\.align/ { if($2 > max) max = $2; }
+
+END {
+ if(need_endp)
+ {
+ print "#define END_INIT .endp _init";
+ print "#define END_FINI .endp _fini";
+ } else if(need_end)
+ {
+ print "#define END_INIT .end _init";
+ print "#define END_FINI .end _fini";
+ }
+ else
+ {
+ print "#define END_INIT";
+ print "#define END_FINI";
+ }
+ if(max)
+ print "#define ALIGN .align", max;
+ else
+ print "#define ALIGN";
+
+ print "#include <libc-symbols.h>";
+ print "weak_extern (__gmon_start__)";
+}
diff --git a/libc/csu/dso_handle.c b/libc/csu/dso_handle.c
new file mode 100644
index 000000000..fd295f244
--- /dev/null
+++ b/libc/csu/dso_handle.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2002, 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
+ 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. */
+
+/* We have to define __dso_handle ourselves since we do not use gcc's
+ crtbegin files. */
+const void *const __dso_handle __attribute__ ((__visibility__ ("hidden")))
+ = &__dso_handle;
diff --git a/libc/csu/elf-init.c b/libc/csu/elf-init.c
new file mode 100644
index 000000000..27eae1550
--- /dev/null
+++ b/libc/csu/elf-init.c
@@ -0,0 +1,99 @@
+/* Startup support for ELF initializers/finalizers in the main executable.
+ 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
+ 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.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ 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 <stddef.h>
+
+
+/* These magic symbols are provided by the linker. */
+extern void (*__preinit_array_start []) (int, char **, char **)
+ attribute_hidden;
+extern void (*__preinit_array_end []) (int, char **, char **)
+ attribute_hidden;
+extern void (*__init_array_start []) (int, char **, char **)
+ attribute_hidden;
+extern void (*__init_array_end []) (int, char **, char **)
+ attribute_hidden;
+extern void (*__fini_array_start []) (void) attribute_hidden;
+extern void (*__fini_array_end []) (void) attribute_hidden;
+
+
+/* These function symbols are provided for the .init/.fini section entry
+ points automagically by the linker. */
+extern void _init (void);
+extern void _fini (void);
+
+/* These functions are passed to __libc_start_main by the startup code.
+ These get statically linked into each program. For dynamically linked
+ programs, this module will come from libc_nonshared.a and differs from
+ the libc.a module in that it doesn't call the preinit array. */
+
+void
+__libc_csu_init (int argc, char **argv, char **envp)
+{
+ /* For dynamically linked executables the preinit array is executed by
+ the dynamic linker (before initializing any shared object. */
+
+#ifndef LIBC_NONSHARED
+ /* For static executables, preinit happens rights before init. */
+ {
+ const size_t size = __preinit_array_end - __preinit_array_start;
+ size_t i;
+ for (i = 0; i < size; i++)
+ (*__preinit_array_start [i]) (argc, argv, envp);
+ }
+#endif
+
+ _init ();
+
+ const size_t size = __init_array_end - __init_array_start;
+ for (size_t i = 0; i < size; i++)
+ (*__init_array_start [i]) (argc, argv, envp);
+}
+
+/* This function should not be used anymore. We run the executable's
+ destructor now just like any other. We cannot remove the function,
+ though. */
+void
+__libc_csu_fini (void)
+{
+#ifndef LIBC_NONSHARED
+ size_t i = __fini_array_end - __fini_array_start;
+ while (i-- > 0)
+ (*__fini_array_start [i]) ();
+
+ _fini ();
+#endif
+}
diff --git a/libc/csu/errno-loc.c b/libc/csu/errno-loc.c
new file mode 100644
index 000000000..633590f4f
--- /dev/null
+++ b/libc/csu/errno-loc.c
@@ -0,0 +1,37 @@
+/* MT support function to get address of `errno' variable, non-threaded
+ version.
+ Copyright (C) 1996, 1998, 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
+ 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 <errno.h>
+#include <tls.h>
+
+#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO
+#undef errno
+extern int errno;
+#endif
+
+int *
+#if ! USE___THREAD
+weak_const_function
+#endif
+__errno_location (void)
+{
+ return &errno;
+}
+libc_hidden_def (__errno_location)
diff --git a/libc/csu/errno.c b/libc/csu/errno.c
new file mode 100644
index 000000000..03d661b71
--- /dev/null
+++ b/libc/csu/errno.c
@@ -0,0 +1,53 @@
+/* Definition of `errno' variable. Canonical version.
+ Copyright (C) 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
+ 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 <errno.h>
+#include <tls.h>
+#include <dl-sysdep.h>
+#undef errno
+
+#if RTLD_PRIVATE_ERRNO
+
+/* Code compiled for rtld refers only to this name. */
+int rtld_errno attribute_hidden;
+
+#elif USE___THREAD
+
+__thread int errno;
+extern __thread int __libc_errno __attribute__ ((alias ("errno")))
+ attribute_hidden;
+
+#else
+
+/* This differs from plain `int errno;' in that it doesn't create
+ a common definition, but a plain symbol that resides in .bss,
+ which can have an alias. */
+int errno __attribute__ ((nocommon));
+strong_alias (errno, _errno)
+
+/* We declare these with compat_symbol so that they are not visible at
+ link time. Programs must use the accessor functions. RTLD is special,
+ since it's not exported from there at any time. */
+# if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
+# include <shlib-compat.h>
+compat_symbol (libc, errno, errno, GLIBC_2_0);
+compat_symbol (libc, _errno, _errno, GLIBC_2_0);
+# endif
+
+#endif
diff --git a/libc/csu/gmon-start.c b/libc/csu/gmon-start.c
new file mode 100644
index 000000000..d11c9b953
--- /dev/null
+++ b/libc/csu/gmon-start.c
@@ -0,0 +1,79 @@
+/* Code to enable profiling at program startup.
+ Copyright (C) 1995,1996,1997,2000,2001,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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sys/types.h>
+#include <sys/gmon.h>
+#include <stdlib.h>
+#include <unistd.h>
+#define __ASSEMBLY__
+#include <entry.h>
+
+/* Beginning and end of our code segment. We cannot declare them
+ as the external functions since we want the addresses of those
+ labels. Taking the address of a function may have different
+ meanings on different platforms. */
+#ifdef ENTRY_POINT_DECL
+ENTRY_POINT_DECL(extern)
+#else
+extern void ENTRY_POINT;
+#endif
+extern void etext;
+
+#ifndef TEXT_START
+# ifdef ENTRY_POINT_DECL
+# define TEXT_START ENTRY_POINT
+# else
+# define TEXT_START &ENTRY_POINT
+# endif
+#endif
+
+#ifndef HAVE_INITFINI
+/* This function gets called at startup by the normal constructor
+ mechanism. We link this file together with start.o to produce gcrt1.o,
+ so this constructor will be first in the list. */
+
+extern void __gmon_start__ (void) __attribute__ ((constructor));
+#else
+/* In ELF and COFF, we cannot use the normal constructor mechanism to call
+ __gmon_start__ because gcrt1.o appears before crtbegin.o in the link.
+ Instead crti.o calls it specially (see initfini.c). */
+extern void __gmon_start__ (void);
+#endif
+
+void
+__gmon_start__ (void)
+{
+#ifdef HAVE_INITFINI
+ /* Protect from being called more than once. Since crti.o is linked
+ into every shared library, each of their init functions will call us. */
+ static int called;
+
+ if (called)
+ return;
+
+ called = 1;
+#endif
+
+ /* Start keeping profiling records. */
+ __monstartup ((u_long) TEXT_START, (u_long) &etext);
+
+ /* Call _mcleanup before exiting; it will write out gmon.out from the
+ collected data. */
+ atexit (&_mcleanup);
+}
diff --git a/libc/csu/init-first.c b/libc/csu/init-first.c
new file mode 100644
index 000000000..fa21274c7
--- /dev/null
+++ b/libc/csu/init-first.c
@@ -0,0 +1,59 @@
+/* Initialization code run first thing by the ELF startup code. Stub version.
+ Copyright (C) 1995, 1997, 1998, 2001, 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
+ 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 <unistd.h>
+#include <sys/types.h>
+
+/* Set nonzero if we have to be prepared for more then one libc being
+ used in the process. Safe assumption if initializer never runs. */
+int __libc_multiple_libcs attribute_hidden = 1;
+
+extern void __libc_init (int, char **, char **);
+#ifdef USE_NONOPTION_FLAGS
+extern void __getopt_clean_environment (char **);
+#endif
+
+#ifdef SHARED
+void
+__libc_init_first (void)
+{
+}
+#endif
+
+#ifdef SHARED
+/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT
+ pointer in the dynamic section based solely on that. It is convention
+ for this function to be in the `.init' section, but the symbol name is
+ the only thing that really matters!! */
+void _init
+#else
+void __libc_init_first
+#endif
+(int argc, char *arg0, ...)
+{
+ char **argv = &arg0, **envp = &argv[argc + 1];
+
+ __environ = envp;
+ __libc_init (argc, argv, envp);
+
+#ifdef USE_NONOPTION_FLAGS
+ /* This is a hack to make the special getopt in GNU libc working. */
+ __getopt_clean_environment (envp);
+#endif
+}
diff --git a/libc/csu/init.c b/libc/csu/init.c
new file mode 100644
index 000000000..129609e08
--- /dev/null
+++ b/libc/csu/init.c
@@ -0,0 +1,27 @@
+/* Special startup support.
+ Copyright (C) 1997, 1998 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
+ 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. */
+
+#if defined USE_IN_LIBIO && defined __GNUC__ && __GNUC__ >= 2
+
+#include <_G_config.h>
+
+/* This records which stdio is linked against in the application. */
+const int _IO_stdin_used = _G_IO_IO_FILE_VERSION;
+
+#endif
diff --git a/libc/csu/libc-start.c b/libc/csu/libc-start.c
new file mode 100644
index 000000000..194db6b1e
--- /dev/null
+++ b/libc/csu/libc-start.c
@@ -0,0 +1,263 @@
+/* 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
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <bp-start.h>
+#include <bp-sym.h>
+
+extern void __libc_init_first (int argc, char **argv, char **envp);
+
+extern int __libc_multiple_libcs;
+
+#include <tls.h>
+#ifndef SHARED
+# include <dl-osinfo.h>
+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. */
+uintptr_t __stack_chk_guard attribute_relro;
+# endif
+#endif
+
+#ifdef HAVE_PTR_NTHREADS
+/* We need atomic operations. */
+# include <atomic.h>
+#endif
+
+
+#ifdef LIBC_START_MAIN
+# ifdef LIBC_START_DISABLE_INLINE
+# define STATIC static
+# else
+# define STATIC static inline __attribute__ ((always_inline))
+# endif
+#else
+# define STATIC
+# define LIBC_START_MAIN BP_SYM (__libc_start_main)
+#endif
+
+#ifdef MAIN_AUXVEC_ARG
+/* main gets passed a pointer to the auxiliary. */
+# define MAIN_AUXVEC_DECL , void *
+# define MAIN_AUXVEC_PARAM , auxvec
+#else
+# define MAIN_AUXVEC_DECL
+# define MAIN_AUXVEC_PARAM
+#endif
+
+STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
+ MAIN_AUXVEC_DECL),
+ int argc,
+ char *__unbounded *__unbounded ubp_av,
+#ifdef LIBC_START_MAIN_AUXVEC_ARG
+ ElfW(auxv_t) *__unbounded auxvec,
+#endif
+ __typeof (main) init,
+ void (*fini) (void),
+ void (*rtld_fini) (void),
+ void *__unbounded stack_end)
+ __attribute__ ((noreturn));
+
+
+/* Note: the fini parameter is ignored here for shared library. It
+ is registered with __cxa_atexit. This had the disadvantage that
+ finalizers were called in more than one place. */
+STATIC int
+LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
+ int argc, char *__unbounded *__unbounded ubp_av,
+#ifdef LIBC_START_MAIN_AUXVEC_ARG
+ ElfW(auxv_t) *__unbounded auxvec,
+#endif
+ __typeof (main) init,
+ void (*fini) (void),
+ void (*rtld_fini) (void), void *__unbounded stack_end)
+{
+#if __BOUNDED_POINTERS__
+ char **argv;
+#else
+# define argv ubp_av
+#endif
+
+ /* Result of the 'main' function. */
+ int result;
+
+ __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
+
+#ifndef SHARED
+ char *__unbounded *__unbounded ubp_ev = &ubp_av[argc + 1];
+
+ INIT_ARGV_and_ENVIRON;
+
+ /* Store the lowest stack address. This is done in ld.so if this is
+ the code for the DSO. */
+ __libc_stack_end = stack_end;
+
+# ifdef HAVE_AUX_VECTOR
+ /* First process the auxiliary vector since we need to find the
+ program header to locate an eventually present PT_TLS entry. */
+# ifndef LIBC_START_MAIN_AUXVEC_ARG
+ ElfW(auxv_t) *__unbounded auxvec;
+ {
+ char *__unbounded *__unbounded evp = ubp_ev;
+ while (*evp++ != NULL)
+ ;
+ auxvec = (ElfW(auxv_t) *__unbounded) evp;
+ }
+# endif
+ _dl_aux_init (auxvec);
+# endif
+# ifdef DL_SYSDEP_OSCHECK
+ if (!__libc_multiple_libcs)
+ {
+ /* This needs to run to initiliaze _dl_osversion before TLS
+ setup might check it. */
+ DL_SYSDEP_OSCHECK (__libc_fatal);
+ }
+# endif
+
+ /* 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. 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
+ /* Set up the stack checker's canary. */
+ uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
+# ifdef THREAD_SET_STACK_GUARD
+ THREAD_SET_STACK_GUARD (stack_chk_guard);
+# else
+ __stack_chk_guard = stack_chk_guard;
+# endif
+#endif
+
+ /* Register the destructor of the dynamic linker if there is any. */
+ if (__builtin_expect (rtld_fini != NULL, 1))
+ __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
+
+#ifndef SHARED
+ /* Call the initializer of the libc. This is only needed here if we
+ are compiling for the static library in which case we haven't
+ run the constructors in `_dl_start_user'. */
+ __libc_init_first (argc, argv, __environ);
+
+ /* Register the destructor of the program, if any. */
+ if (fini)
+ __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
+
+ /* Some security at this point. Prevent starting a SUID binary where
+ the standard file descriptors are not opened. We have to do this
+ only for statically linked applications since otherwise the dynamic
+ loader did the work already. */
+ if (__builtin_expect (__libc_enable_secure, 0))
+ __libc_check_standard_fds ();
+#endif
+
+ /* Call the initializer of the program, if any. */
+#ifdef SHARED
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+ GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
+#endif
+ if (init)
+ (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
+
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new object. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->preinit != NULL)
+ afct->preinit (&head->l_audit[cnt].cookie);
+
+ afct = afct->next;
+ }
+ }
+#endif
+
+#ifdef SHARED
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+ GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
+#endif
+
+#ifdef HAVE_CLEANUP_JMP_BUF
+ /* Memory for the cancellation buffer. */
+ struct pthread_unwind_buf unwind_buf;
+
+ int not_first_call;
+ not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
+ if (__builtin_expect (! not_first_call, 1))
+ {
+ struct pthread *self = THREAD_SELF;
+
+ /* Store old info. */
+ unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
+ unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
+
+ /* Store the new cleanup handler info. */
+ THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
+
+ /* Run the program. */
+ result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
+ }
+ else
+ {
+ /* Remove the thread-local data. */
+# ifdef SHARED
+ __libc_pthread_functions.ptr__nptl_deallocate_tsd ();
+# else
+ extern void __nptl_deallocate_tsd (void) __attribute ((weak));
+ __nptl_deallocate_tsd ();
+# endif
+
+ /* One less thread. Decrement the counter. If it is zero we
+ terminate the entire process. */
+ result = 0;
+# ifdef SHARED
+ unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads;
+# else
+ extern unsigned int __nptl_nthreads __attribute ((weak));
+ unsigned int *const ptr = &__nptl_nthreads;
+# endif
+
+ if (! atomic_decrement_and_test (ptr))
+ /* Not much left to do but to exit the thread, not the process. */
+ __exit_thread (0);
+ }
+#else
+ /* Nothing fancy, just call the function. */
+ result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
+#endif
+
+ exit (result);
+}
diff --git a/libc/csu/libc-tls.c b/libc/csu/libc-tls.c
new file mode 100644
index 000000000..3544e396d
--- /dev/null
+++ b/libc/csu/libc-tls.c
@@ -0,0 +1,263 @@
+/* Initialization code for TLS in statically linked application.
+ 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
+ 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 <errno.h>
+#include <ldsodefs.h>
+#include <tls.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+
+#ifdef SHARED
+ #error makefile bug, this file is for static only
+#endif
+
+#ifdef USE_TLS
+extern ElfW(Phdr) *_dl_phdr;
+extern size_t _dl_phnum;
+
+
+static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
+
+
+static struct
+{
+ struct dtv_slotinfo_list si;
+ /* The dtv_slotinfo_list data structure does not include the actual
+ information since it is defined as an array of size zero. We define
+ here the necessary entries. Note that it is not important whether
+ there is padding or not since we will always access the information
+ through the 'si' element. */
+ struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
+} static_slotinfo;
+
+/* Fake link map for the application. */
+static struct link_map static_map;
+
+
+/* Highest dtv index currently needed. */
+size_t _dl_tls_max_dtv_idx;
+/* Flag signalling whether there are gaps in the module ID allocation. */
+bool _dl_tls_dtv_gaps;
+/* Information about the dtv slots. */
+struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
+/* Number of modules in the static TLS block. */
+size_t _dl_tls_static_nelem;
+/* Size of the static TLS block. Giving this initialized value
+ preallocates some surplus bytes in the static TLS area. */
+size_t _dl_tls_static_size = 2048;
+/* Size actually allocated in the static TLS block. */
+size_t _dl_tls_static_used;
+/* Alignment requirement of the static TLS block. */
+size_t _dl_tls_static_align;
+
+/* Generation counter for the dtv. */
+size_t _dl_tls_generation;
+
+
+/* Additional definitions needed by TLS initialization. */
+#ifdef TLS_INIT_HELPER
+TLS_INIT_HELPER
+#endif
+
+static inline void
+init_slotinfo (void)
+{
+ /* Create the slotinfo list. */
+ static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
+ - (char *) &static_slotinfo.si.slotinfo[0])
+ / sizeof static_slotinfo.si.slotinfo[0]);
+ // static_slotinfo.si.next = NULL; already zero
+
+ /* The slotinfo list. Will be extended by the code doing dynamic
+ linking. */
+ GL(dl_tls_max_dtv_idx) = 1;
+ GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
+}
+
+static inline void
+init_static_tls (size_t memsz, size_t align)
+{
+ /* That is the size of the TLS memory for this object. 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. */
+ GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
+ TLS_TCB_ALIGN);
+ GL(dl_tls_static_used) = memsz;
+ /* The alignment requirement for the static TLS block. */
+ GL(dl_tls_static_align) = align;
+ /* Number of elements in the static TLS block. */
+ GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+}
+
+void
+__libc_setup_tls (size_t tcbsize, size_t tcbalign)
+{
+ void *tlsblock;
+ size_t memsz = 0;
+ size_t filesz = 0;
+ void *initimage = NULL;
+ size_t align = 0;
+ size_t max_align = tcbalign;
+ size_t tcb_offset;
+ ElfW(Phdr) *phdr;
+
+ /* Look through the TLS segment if there is any. */
+ if (_dl_phdr != NULL)
+ for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
+ if (phdr->p_type == PT_TLS)
+ {
+ /* Remember the values we need. */
+ memsz = phdr->p_memsz;
+ filesz = phdr->p_filesz;
+ initimage = (void *) phdr->p_vaddr;
+ align = phdr->p_align;
+ if (phdr->p_align > max_align)
+ max_align = phdr->p_align;
+ break;
+ }
+
+ /* We have to set up the TCB block which also (possibly) contains
+ 'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
+ Instead we use 'sbrk' which would only uses 'errno' if it fails.
+ In this case we are right away out of memory and the user gets
+ what she/he deserves.
+
+ 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
+ tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
+ tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
+# 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
+ /* 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
+
+ /* Align the TLS block. */
+ tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
+ & ~(max_align - 1));
+
+ /* Initialize the dtv. [0] is the length, [1] the generation counter. */
+ static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2;
+ // static_dtv[1].counter = 0; would be needed if not already done
+
+ /* Initialize the TLS block. */
+# 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
+ 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
+ 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);
+
+ /* Install the pointer to the dtv. */
+
+ /* Initialize the thread pointer. */
+# 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
+ 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
+ if (__builtin_expect (lossage != NULL, 0))
+ __libc_fatal (lossage);
+
+ /* We have to create a fake link map which normally would be created
+ by the dynamic linker. It just has to have enough information to
+ make the TLS routines happy. */
+ static_map.l_tls_align = align;
+ static_map.l_tls_blocksize = memsz;
+ static_map.l_tls_initimage = initimage;
+ static_map.l_tls_initimage_size = filesz;
+ static_map.l_type = lt_executable;
+ static_map.l_tls_modid = 1;
+
+ init_slotinfo ();
+ // static_slotinfo.si.slotinfo[1].gen = 0; already zero
+ static_slotinfo.si.slotinfo[1].map = &static_map;
+
+ memsz = roundup (memsz, align ?: 1);
+
+# if TLS_TCB_AT_TP
+ memsz += tcbsize;
+# elif TLS_DTV_AT_TP
+ memsz += tcb_offset;
+# endif
+
+ init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
+}
+
+/* This is called only when the data structure setup was skipped at startup,
+ when there was no need for it then. Now we have dynamically loaded
+ something needing TLS, or libpthread needs it. */
+int
+internal_function
+_dl_tls_setup (void)
+{
+ init_slotinfo ();
+ init_static_tls (
+# if TLS_TCB_AT_TP
+ TLS_TCB_SIZE,
+# else
+ 0,
+# endif
+ TLS_TCB_ALIGN);
+ return 0;
+}
+
+
+/* This is the minimal initialization function used when libpthread is
+ not used. */
+void
+__attribute__ ((weak))
+__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
diff --git a/libc/csu/start.c b/libc/csu/start.c
new file mode 100644
index 000000000..08f985c48
--- /dev/null
+++ b/libc/csu/start.c
@@ -0,0 +1,13 @@
+/* This file should define the low-level program entry point,
+ which should set up `__environ', and then do:
+ __libc_init(argc, argv, __environ);
+ exit(main(argc, argv, __environ));
+
+ This file should be prepared to be the first thing in the text section (on
+ Unix systems), or otherwise appropriately special. */
+
+/* The first piece of initialized data. */
+int __data_start = 0;
+#ifdef HAVE_WEAK_SYMBOLS
+weak_alias (__data_start, data_start)
+#endif
diff --git a/libc/csu/sysdep.c b/libc/csu/sysdep.c
new file mode 100644
index 000000000..5442eee00
--- /dev/null
+++ b/libc/csu/sysdep.c
@@ -0,0 +1,2 @@
+/* This file should contain any system-dependent functions
+ that will be used by many parts of the library. */
diff --git a/libc/csu/tst-atomic-long.c b/libc/csu/tst-atomic-long.c
new file mode 100644
index 000000000..75a71ebd5
--- /dev/null
+++ b/libc/csu/tst-atomic-long.c
@@ -0,0 +1,28 @@
+/* Tests for atomic.h macros.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ 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 <bits/wordsize.h>
+
+#define atomic_t long
+#if __WORDSIZE == 64
+# define TEST_ATOMIC64 1
+#endif
+
+#include "tst-atomic.c"
diff --git a/libc/csu/tst-atomic.c b/libc/csu/tst-atomic.c
new file mode 100644
index 000000000..7a2e3d086
--- /dev/null
+++ b/libc/csu/tst-atomic.c
@@ -0,0 +1,386 @@
+/* Tests for atomic.h macros.
+ 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.
+
+ 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 <stdio.h>
+#include <atomic.h>
+
+#ifndef atomic_t
+# define atomic_t int
+#endif
+
+/* Test various atomic.h macros. */
+static int
+do_test (void)
+{
+ atomic_t mem;
+ int ret = 0;
+
+#ifdef atomic_compare_and_exchange_val_acq
+ mem = 24;
+ if (atomic_compare_and_exchange_val_acq (&mem, 35, 24) != 24
+ || mem != 35)
+ {
+ puts ("atomic_compare_and_exchange_val_acq test 1 failed");
+ ret = 1;
+ }
+
+ mem = 12;
+ if (atomic_compare_and_exchange_val_acq (&mem, 10, 15) != 12
+ || mem != 12)
+ {
+ puts ("atomic_compare_and_exchange_val_acq test 2 failed");
+ ret = 1;
+ }
+
+ mem = -15;
+ if (atomic_compare_and_exchange_val_acq (&mem, -56, -15) != -15
+ || mem != -56)
+ {
+ puts ("atomic_compare_and_exchange_val_acq test 3 failed");
+ ret = 1;
+ }
+
+ mem = -1;
+ if (atomic_compare_and_exchange_val_acq (&mem, 17, 0) != -1
+ || mem != -1)
+ {
+ puts ("atomic_compare_and_exchange_val_acq test 4 failed");
+ ret = 1;
+ }
+#endif
+
+ mem = 24;
+ if (atomic_compare_and_exchange_bool_acq (&mem, 35, 24)
+ || mem != 35)
+ {
+ puts ("atomic_compare_and_exchange_bool_acq test 1 failed");
+ ret = 1;
+ }
+
+ mem = 12;
+ if (! atomic_compare_and_exchange_bool_acq (&mem, 10, 15)
+ || mem != 12)
+ {
+ puts ("atomic_compare_and_exchange_bool_acq test 2 failed");
+ ret = 1;
+ }
+
+ mem = -15;
+ if (atomic_compare_and_exchange_bool_acq (&mem, -56, -15)
+ || mem != -56)
+ {
+ puts ("atomic_compare_and_exchange_bool_acq test 3 failed");
+ ret = 1;
+ }
+
+ mem = -1;
+ if (! atomic_compare_and_exchange_bool_acq (&mem, 17, 0)
+ || mem != -1)
+ {
+ puts ("atomic_compare_and_exchange_bool_acq test 4 failed");
+ ret = 1;
+ }
+
+ mem = 64;
+ if (atomic_exchange_acq (&mem, 31) != 64
+ || mem != 31)
+ {
+ puts ("atomic_exchange_acq test failed");
+ ret = 1;
+ }
+
+ mem = 2;
+ if (atomic_exchange_and_add (&mem, 11) != 2
+ || mem != 13)
+ {
+ puts ("atomic_exchange_and_add test failed");
+ ret = 1;
+ }
+
+ mem = -21;
+ atomic_add (&mem, 22);
+ if (mem != 1)
+ {
+ puts ("atomic_add test failed");
+ ret = 1;
+ }
+
+ mem = -1;
+ atomic_increment (&mem);
+ if (mem != 0)
+ {
+ puts ("atomic_increment test failed");
+ ret = 1;
+ }
+
+ mem = 2;
+ if (atomic_increment_val (&mem) != 3)
+ {
+ puts ("atomic_increment_val test failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ if (atomic_increment_and_test (&mem)
+ || mem != 1)
+ {
+ puts ("atomic_increment_and_test test 1 failed");
+ ret = 1;
+ }
+
+ mem = 35;
+ if (atomic_increment_and_test (&mem)
+ || mem != 36)
+ {
+ puts ("atomic_increment_and_test test 2 failed");
+ ret = 1;
+ }
+
+ mem = -1;
+ if (! atomic_increment_and_test (&mem)
+ || mem != 0)
+ {
+ puts ("atomic_increment_and_test test 3 failed");
+ ret = 1;
+ }
+
+ mem = 17;
+ atomic_decrement (&mem);
+ if (mem != 16)
+ {
+ puts ("atomic_decrement test failed");
+ ret = 1;
+ }
+
+ if (atomic_decrement_val (&mem) != 15)
+ {
+ puts ("atomic_decrement_val test failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ if (atomic_decrement_and_test (&mem)
+ || mem != -1)
+ {
+ puts ("atomic_decrement_and_test test 1 failed");
+ ret = 1;
+ }
+
+ mem = 15;
+ if (atomic_decrement_and_test (&mem)
+ || mem != 14)
+ {
+ puts ("atomic_decrement_and_test test 2 failed");
+ ret = 1;
+ }
+
+ mem = 1;
+ if (! atomic_decrement_and_test (&mem)
+ || mem != 0)
+ {
+ puts ("atomic_decrement_and_test test 3 failed");
+ ret = 1;
+ }
+
+ mem = 1;
+ if (atomic_decrement_if_positive (&mem) != 1
+ || mem != 0)
+ {
+ puts ("atomic_decrement_if_positive test 1 failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ if (atomic_decrement_if_positive (&mem) != 0
+ || mem != 0)
+ {
+ puts ("atomic_decrement_if_positive test 2 failed");
+ ret = 1;
+ }
+
+ mem = -1;
+ if (atomic_decrement_if_positive (&mem) != -1
+ || mem != -1)
+ {
+ puts ("atomic_decrement_if_positive test 3 failed");
+ ret = 1;
+ }
+
+ mem = -12;
+ if (! atomic_add_negative (&mem, 10)
+ || mem != -2)
+ {
+ puts ("atomic_add_negative test 1 failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ if (atomic_add_negative (&mem, 100)
+ || mem != 100)
+ {
+ puts ("atomic_add_negative test 2 failed");
+ ret = 1;
+ }
+
+ mem = 15;
+ if (atomic_add_negative (&mem, -10)
+ || mem != 5)
+ {
+ puts ("atomic_add_negative test 3 failed");
+ ret = 1;
+ }
+
+ mem = -12;
+ if (atomic_add_negative (&mem, 14)
+ || mem != 2)
+ {
+ puts ("atomic_add_negative test 4 failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ if (! atomic_add_negative (&mem, -1)
+ || mem != -1)
+ {
+ puts ("atomic_add_negative test 5 failed");
+ ret = 1;
+ }
+
+ mem = -31;
+ if (atomic_add_negative (&mem, 31)
+ || mem != 0)
+ {
+ puts ("atomic_add_negative test 6 failed");
+ ret = 1;
+ }
+
+ mem = -34;
+ if (atomic_add_zero (&mem, 31)
+ || mem != -3)
+ {
+ puts ("atomic_add_zero test 1 failed");
+ ret = 1;
+ }
+
+ mem = -36;
+ if (! atomic_add_zero (&mem, 36)
+ || mem != 0)
+ {
+ puts ("atomic_add_zero test 2 failed");
+ ret = 1;
+ }
+
+ mem = 113;
+ if (atomic_add_zero (&mem, -13)
+ || mem != 100)
+ {
+ puts ("atomic_add_zero test 3 failed");
+ ret = 1;
+ }
+
+ mem = -18;
+ if (atomic_add_zero (&mem, 20)
+ || mem != 2)
+ {
+ puts ("atomic_add_zero test 4 failed");
+ ret = 1;
+ }
+
+ mem = 10;
+ if (atomic_add_zero (&mem, -20)
+ || mem != -10)
+ {
+ puts ("atomic_add_zero test 5 failed");
+ ret = 1;
+ }
+
+ mem = 10;
+ if (! atomic_add_zero (&mem, -10)
+ || mem != 0)
+ {
+ puts ("atomic_add_zero test 6 failed");
+ ret = 1;
+ }
+
+ mem = 0;
+ atomic_bit_set (&mem, 1);
+ if (mem != 2)
+ {
+ puts ("atomic_bit_set test 1 failed");
+ ret = 1;
+ }
+
+ mem = 8;
+ atomic_bit_set (&mem, 3);
+ if (mem != 8)
+ {
+ puts ("atomic_bit_set test 2 failed");
+ ret = 1;
+ }
+
+#ifdef TEST_ATOMIC64
+ mem = 16;
+ atomic_bit_set (&mem, 35);
+ if (mem != 0x800000010LL)
+ {
+ puts ("atomic_bit_set test 3 failed");
+ ret = 1;
+ }
+#endif
+
+ mem = 0;
+ if (atomic_bit_test_set (&mem, 1)
+ || mem != 2)
+ {
+ puts ("atomic_bit_test_set test 1 failed");
+ ret = 1;
+ }
+
+ mem = 8;
+ if (! atomic_bit_test_set (&mem, 3)
+ || mem != 8)
+ {
+ puts ("atomic_bit_test_set test 2 failed");
+ ret = 1;
+ }
+
+#ifdef TEST_ATOMIC64
+ mem = 16;
+ if (atomic_bit_test_set (&mem, 35)
+ || mem != 0x800000010LL)
+ {
+ puts ("atomic_bit_test_set test 3 failed");
+ ret = 1;
+ }
+
+ mem = 0x100000000LL;
+ if (! atomic_bit_test_set (&mem, 32)
+ || mem != 0x100000000LL)
+ {
+ puts ("atomic_bit_test_set test 4 failed");
+ ret = 1;
+ }
+#endif
+
+ return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/csu/tst-empty.c b/libc/csu/tst-empty.c
new file mode 100644
index 000000000..980dcd60f
--- /dev/null
+++ b/libc/csu/tst-empty.c
@@ -0,0 +1,6 @@
+/* The most useful C program known to man. */
+int
+main (void)
+{
+ return 0;
+}
diff --git a/libc/csu/version.c b/libc/csu/version.c
new file mode 100644
index 000000000..2196d2043
--- /dev/null
+++ b/libc/csu/version.c
@@ -0,0 +1,79 @@
+/* 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
+ 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 "version.h"
+#include <tls.h>
+#include <gnu/libc-version.h>
+
+static const char __libc_release[] = RELEASE;
+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) 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\
+Compiled by GNU CC version "__VERSION__".\n"
+#include "version-info.h"
+#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";
+
+#include <unistd.h>
+
+extern void __libc_print_version (void);
+void
+__libc_print_version (void)
+{
+ __write (STDOUT_FILENO, banner, sizeof banner - 1);
+}
+
+extern const char *__gnu_get_libc_release (void);
+const char *
+__gnu_get_libc_release (void)
+{
+ return __libc_release;
+}
+weak_alias (__gnu_get_libc_release, gnu_get_libc_release)
+
+extern const char *__gnu_get_libc_version (void);
+const char *
+__gnu_get_libc_version (void)
+{
+ return __libc_version;
+}
+weak_alias (__gnu_get_libc_version, gnu_get_libc_version)
+
+#ifdef HAVE_ELF
+/* This function is the entry point for the shared object.
+ Running the library as a program will get here. */
+
+extern void __libc_main (void) __attribute__ ((noreturn));
+void
+__libc_main (void)
+{
+ __libc_print_version ();
+ _exit (0);
+}
+#endif