diff options
author | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
---|---|---|
committer | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
commit | 15f34685e7a9b5caf761af2ebf6afa20438d440b (patch) | |
tree | dc04ce3cdf040f198743c15b64557824de174680 /libc/csu | |
parent | 1e848e0e775a36f6359161f5deb890942ef42ff3 (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/.cvsignore | 7 | ||||
-rw-r--r-- | libc/csu/Makefile | 236 | ||||
-rw-r--r-- | libc/csu/Versions | 26 | ||||
-rw-r--r-- | libc/csu/abi-note.S | 73 | ||||
-rw-r--r-- | libc/csu/check_fds.c | 102 | ||||
-rw-r--r-- | libc/csu/defs.awk | 27 | ||||
-rw-r--r-- | libc/csu/dso_handle.c | 22 | ||||
-rw-r--r-- | libc/csu/elf-init.c | 99 | ||||
-rw-r--r-- | libc/csu/errno-loc.c | 37 | ||||
-rw-r--r-- | libc/csu/errno.c | 53 | ||||
-rw-r--r-- | libc/csu/gmon-start.c | 79 | ||||
-rw-r--r-- | libc/csu/init-first.c | 59 | ||||
-rw-r--r-- | libc/csu/init.c | 27 | ||||
-rw-r--r-- | libc/csu/libc-start.c | 263 | ||||
-rw-r--r-- | libc/csu/libc-tls.c | 263 | ||||
-rw-r--r-- | libc/csu/start.c | 13 | ||||
-rw-r--r-- | libc/csu/sysdep.c | 2 | ||||
-rw-r--r-- | libc/csu/tst-atomic-long.c | 28 | ||||
-rw-r--r-- | libc/csu/tst-atomic.c | 386 | ||||
-rw-r--r-- | libc/csu/tst-empty.c | 6 | ||||
-rw-r--r-- | libc/csu/version.c | 79 |
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 |