From ae35d725cf586347b2adb1a6fe4216e70fce16cf Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Wed, 27 Nov 2002 23:34:07 +0000 Subject: Make support for global constructors and global destructors be configurable, so people who do not need or want ctor/dtor support can disable it and make their binaries a little bit smaller. -Erik --- extra/Configs/Config.in | 17 +++++++++++++ extra/gcc-uClibc/Makefile | 17 +++++++++---- extra/gcc-uClibc/gcc-uClibc.c | 38 +++++++++++++++++++++++++----- extra/scripts/get-needed-libgcc-objects.sh | 2 +- libc/Makefile | 9 ++++++- libc/sysdeps/linux/arm/crt0.S | 4 ++++ libc/sysdeps/linux/common/Makefile | 15 +++++++----- libc/sysdeps/linux/i386/crt0.S | 9 +++++++ libc/sysdeps/linux/mips/crt0.S | 4 ++++ libc/sysdeps/linux/sh/crt0.S | 38 ++++++++++++++++++++++++++---- libpthread/Makefile | 2 ++ 11 files changed, 132 insertions(+), 23 deletions(-) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 089c1b40b..95c5ba7c2 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -60,6 +60,23 @@ config LDSO_LDD_SUPPORT application to function. Disabling this option will makes uClibc's shared library loader a little bit smaller. Most people will answer Y. +config UCLIBC_CTOR_DTOR + bool "Support global constructors and destructos" + default y + help + If you wish to build uClibc with support for global constructor + (ctor) and global destructor (dtor) support, then answer Y here. + When ctor/dtor support is enabled, binaries linked with uClibc must + also be linked with crtbegin.o and crtend.o which are provided by gcc + (the "*startfile:" and "*endfile:" settings in your gcc specs file + may need to be adjusted to include these files). This support will + also add a small amount of additional size to each binary compiled vs + uClibc. If you will be using uClibc with C++, or if you need the gcc + __attribute__((constructor)) and __attribute__((destructor)) to work, + then you definately want to answer Y here. If you don't need ctors + or dtors and want your binaries to be as small as possible, then + answer N. + config UCLIBC_HAS_THREADS bool "POSIX Threading Support" default y diff --git a/extra/gcc-uClibc/Makefile b/extra/gcc-uClibc/Makefile index 677b10f3a..1c64f856a 100644 --- a/extra/gcc-uClibc/Makefile +++ b/extra/gcc-uClibc/Makefile @@ -1,7 +1,7 @@ # Makefile for building a fake gcc/binutils toolchain # that simply spoofs the location of the C library # -# Copyright (C) 2000,2001 Erik Andersen +# Copyright (C) 2000-2002 Erik Andersen # TOPDIR = ../../ @@ -34,6 +34,11 @@ ifeq ($(strip $(HAS_ELF)),y) else @echo "#undef __HAS_ELF__" >> gcc-uClibc.h endif +ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) + @echo "#define __UCLIBC_CTOR_DTOR__ 1" >> gcc-uClibc.h +else + @echo "#undef __UCLIBC_CTOR_DTOR__" >> gcc-uClibc.h +endif gcc-uClibc: gcc-uClibc.h gcc-uClibc.c $(NATIVE_CC) $(NATIVE_CFLAGS) -Wl,-s gcc-uClibc.c -o $(TARGET_ARCH)-uclibc-gcc @@ -50,14 +55,16 @@ install: all install -d $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin; install -m 755 $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/ install -m 755 $(TARGET_ARCH)-uclibc-ld $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/ - ln -fs $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-g++ - ln -fs $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-c++ ln -fs $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-cc - ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/c++ - ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/g++ ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/gcc ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/cc ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-ld $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/ld +ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) + ln -fs $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-g++ + ln -fs $(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-c++ + ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/c++ + ln -fs $(SYSTEM_DEVEL_PREFIX)/bin/$(TARGET_ARCH)-uclibc-gcc $(PREFIX)$(DEVEL_TOOL_PREFIX)/bin/g++ +endif for app in addr2line ar as cpp gasp nm objcopy \ objdump ranlib size strings strip; do \ APPNAME=`which $(CROSS)$${app}`; \ diff --git a/extra/gcc-uClibc/gcc-uClibc.c b/extra/gcc-uClibc/gcc-uClibc.c index 8b7f53e7d..765521eae 100644 --- a/extra/gcc-uClibc/gcc-uClibc.c +++ b/extra/gcc-uClibc/gcc-uClibc.c @@ -83,10 +83,12 @@ static char *our_usr_lib_path = "-L"UCLIBC_DEVEL_PREFIX"/lib"; static char static_linking[] = "-static"; static char nostdinc[] = "-nostdinc"; -static char nostdinc_plus[] = "-nostdinc++"; static char nostartfiles[] = "-nostartfiles"; static char nodefaultlibs[] = "-nodefaultlibs"; static char nostdlib[] = "-nostdlib"; +#ifdef __UCLIBC_CTOR_DTOR__ +static char nostdinc_plus[] = "-nostdinc++"; +#endif extern void *xmalloc(size_t size) @@ -120,9 +122,8 @@ void xstrcat(char **string, ...) int main(int argc, char **argv) { int use_build_dir = 0, linking = 1, use_static_linking = 0; - int use_stdinc = 1, use_nostdinc_plus = 0, use_start = 1, use_stdlib = 1, use_pic = 0; + int use_stdinc = 1, use_start = 1, use_stdlib = 1, use_pic = 0; int source_count = 0, use_rpath = 0, verbose = 0; - int ctor_dtor = 1, cplusplus = 0; int i, j, k, l, m, n; char ** gcc_argv; char ** gcc_argument; @@ -141,15 +142,19 @@ int main(int argc, char **argv) char *our_lib_path[2]; char *crt0_path[2]; const char *application_name; +#ifdef __UCLIBC_CTOR_DTOR__ char *crti_path[2]; char *crtn_path[2]; - char *GPLUSPLUS_BIN = NULL; int len; + int ctor_dtor = 1, cplusplus = 0, use_nostdinc_plus = 0; + char *GPLUSPLUS_BIN = NULL; +#endif application_name = basename(argv[0]); if (application_name[0] == '-') application_name++; +#ifdef __UCLIBC_CTOR_DTOR__ /* We must use strstr since g++ might be named like a * cross compiler (i.e. arm-linux-g++). We must also * search carefully, in case we are searching something @@ -168,6 +173,7 @@ int main(int argc, char **argv) cplusplus = 1; use_nostdinc_plus = 1; } +#endif devprefix = getenv("UCLIBC_DEVEL_PREFIX"); if (!devprefix) { @@ -193,10 +199,12 @@ int main(int argc, char **argv) xstrcat(&(crt0_path[0]), devprefix, "/lib/crt0.o", NULL); xstrcat(&(crt0_path[1]), builddir, "/lib/crt0.o", NULL); +#ifdef __UCLIBC_CTOR_DTOR__ xstrcat(&(crti_path[0]), devprefix, "/lib/crti.o", NULL); xstrcat(&(crti_path[1]), builddir, "/lib/crti.o", NULL); xstrcat(&(crtn_path[0]), devprefix, "/lib/crtn.o", NULL); xstrcat(&(crtn_path[1]), builddir, "/lib/crtn.o", NULL); +#endif xstrcat(&(our_lib_path[0]), "-L", devprefix, "/lib", NULL); xstrcat(&(our_lib_path[1]), "-L", builddir, "/lib", NULL); @@ -267,11 +275,14 @@ int main(int argc, char **argv) } else if (strcmp(nostdlib,argv[i]) == 0) { use_start = 0; use_stdlib = 0; - } else if (strcmp(nostdinc_plus,argv[i]) == 0) { + } +#ifdef __UCLIBC_CTOR_DTOR__ + else if (strcmp(nostdinc_plus,argv[i]) == 0) { if (cplusplus==1) { use_nostdinc_plus = 0; } } +#endif break; case 's': if (strstr(argv[i],static_linking) != NULL) { @@ -310,10 +321,13 @@ int main(int argc, char **argv) } else if (strcmp("--uclibc-use-rpath",argv[i]) == 0) { use_rpath = 1; argv[i]='\0'; - } else if (strcmp("--uclibc-no-ctors",argv[i]) == 0) { + } +#ifdef __UCLIBC_CTOR_DTOR__ + else if (strcmp("--uclibc-no-ctors",argv[i]) == 0) { ctor_dtor = 0; argv[i]='\0'; } +#endif break; } } else { /* assume it is an existing source file */ @@ -325,9 +339,11 @@ int main(int argc, char **argv) gcc_argument = __builtin_alloca(sizeof(char*) * (argc + 20)); i = 0; k = 0; +#ifdef __UCLIBC_CTOR_DTOR__ if (cplusplus && GPLUSPLUS_BIN) gcc_argv[i++] = GPLUSPLUS_BIN; else +#endif gcc_argv[i++] = GCC_BIN; for ( j = 1 ; j < argc ; j++ ) { @@ -370,6 +386,7 @@ int main(int argc, char **argv) } if (use_stdinc && source_count) { gcc_argv[i++] = nostdinc; +#ifdef __UCLIBC_CTOR_DTOR__ if (cplusplus) { char *cppinc; if (use_nostdinc_plus) { @@ -382,6 +399,7 @@ int main(int argc, char **argv) gcc_argv[i++] = "-isystem"; gcc_argv[i++] = cppinc; } +#endif gcc_argv[i++] = "-isystem"; gcc_argv[i++] = uClibc_inc[use_build_dir]; gcc_argv[i++] = "-iwithprefix"; @@ -392,6 +410,7 @@ int main(int argc, char **argv) if (linking && source_count) { if (use_start) { +#ifdef __UCLIBC_CTOR_DTOR__ if (ctor_dtor) { gcc_argv[i++] = crti_path[use_build_dir]; if (use_pic) { @@ -400,6 +419,7 @@ int main(int argc, char **argv) gcc_argv[i++] = LIBGCC_DIR "crtbegin.o" ; } } +#endif gcc_argv[i++] = crt0_path[use_build_dir]; } for ( l = 0 ; l < k ; l++ ) { @@ -413,14 +433,17 @@ int main(int argc, char **argv) if (libraries[l]) gcc_argv[i++] = libraries[l]; } if (use_stdlib) { +#ifdef __UCLIBC_CTOR_DTOR__ if (cplusplus) { gcc_argv[ i++ ] = "-lstdc++"; gcc_argv[ i++ ] = "-lm"; } +#endif gcc_argv[i++] = "-lc"; gcc_argv[i++] = "-lgcc"; //gcc_argv[i++] = "-Wl,--end-group"; } +#ifdef __UCLIBC_CTOR_DTOR__ if (ctor_dtor) { if (use_pic) { gcc_argv[i++] = LIBGCC_DIR "crtendS.o" ; @@ -429,6 +452,7 @@ int main(int argc, char **argv) } gcc_argv[i++] = crtn_path[use_build_dir]; } +#endif } else { for ( l = 0 ; l < k ; l++ ) { if (gcc_argument[l]) gcc_argv[i++] = gcc_argument[l]; @@ -443,8 +467,10 @@ int main(int argc, char **argv) fflush(stdout); } //no need to free memory from xstrcat because we never return... +#ifdef __UCLIBC_CTOR_DTOR__ if (cplusplus && GPLUSPLUS_BIN) return execvp(GPLUSPLUS_BIN, gcc_argv); else +#endif return execvp(GCC_BIN, gcc_argv); } diff --git a/extra/scripts/get-needed-libgcc-objects.sh b/extra/scripts/get-needed-libgcc-objects.sh index 588634c8d..04e6737f9 100755 --- a/extra/scripts/get-needed-libgcc-objects.sh +++ b/extra/scripts/get-needed-libgcc-objects.sh @@ -18,7 +18,7 @@ echo Finding missing symbols in libc.a ... echo " partial linking..." rm -f libc.ldr -$LD $LDFLAGS -r -o libc.ldr ../../lib/crt0.o ../../lib/crti.o ../../lib/crtn.o --whole-archive ../libc.a +$LD $LDFLAGS -r -o libc.ldr $CRTOBJS --whole-archive ../libc.a if $NM --undefined-only libc.ldr 2>&1 | grep -v "^main$" | grep -v "^_GLOBAL_OFFSET_TABLE_$" | grep -v "_gp_disp" > sym.need ; then EXIT_WITH_ERROR=0 diff --git a/libc/Makefile b/libc/Makefile index 595f69e4a..4a5110f0e 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -30,6 +30,12 @@ TOPDIR=../ include $(TOPDIR)Rules.mak +ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) +CRTOBJS="../../lib/crti.o ../../lib/crt0.o ../../lib/crtn.o" +else +CRTOBJS="../../lib/crt0.o" +endif + DIRS = misc pwd_grp stdio string termios inet signal stdlib sysdeps unistd # Check if the target architecture has a version script for @@ -49,7 +55,8 @@ shared: $(TOPDIR)lib/$(LIBNAME) @rm -rf tmp @mkdir tmp $(AR) rv ./tmp/libgcc-need.a - @(cd tmp && CC=$(CC) LD=$(LD) LDFLAGS=$(CPU_LDFLAGS-y) NM=$(NM) AR=$(AR) LIBGCC=$(LIBGCC) \ + @(cd tmp && CC=$(CC) LD=$(LD) LDFLAGS=$(CPU_LDFLAGS-y) NM=$(NM) AR=$(AR) \ + LIBGCC=$(LIBGCC) CRTOBJS=$(CRTOBJS) \ /bin/sh $(TOPDIR)../extra/scripts/get-needed-libgcc-objects.sh) $(LD) $(LDFLAGS) $(VERSION_SCRIPT) -soname=$(SHARED_MAJORNAME) -o $(SHARED_FULLNAME) \ --whole-archive ./tmp/libgcc-need.a $(LIBNAME) --no-whole-archive \ diff --git a/libc/sysdeps/linux/arm/crt0.S b/libc/sysdeps/linux/arm/crt0.S index ad4865cc1..a930ff3f2 100644 --- a/libc/sysdeps/linux/arm/crt0.S +++ b/libc/sysdeps/linux/arm/crt0.S @@ -80,6 +80,7 @@ _start: ldr r2,[sp, #8] #endif +#ifdef __UCLIBC_CTOR_DTOR__ /* Store the address of _init in r3 as an argument to main() */ ldr r3, =_init @@ -89,6 +90,9 @@ _start: /* Ok, now run uClibc's main() -- shouldn't return */ bl __uClibc_start_main +#else + bl __uClibc_main +#endif /* Crash if somehow `exit' returns anyways. */ bl abort diff --git a/libc/sysdeps/linux/common/Makefile b/libc/sysdeps/linux/common/Makefile index f66c09f31..8e0ed9485 100644 --- a/libc/sysdeps/linux/common/Makefile +++ b/libc/sysdeps/linux/common/Makefile @@ -24,11 +24,6 @@ TOPDIR=../../../../ include $(TOPDIR)Rules.mak -SAFECFLAGS=$(WARNINGS) $(CPU_CFLAGS-y) $(OPTIMIZATION) -fno-builtin -ifeq ($(strip $(DOPIC)),y) -SAFECFLAGS+=-fPIC -endif - CSRC= waitpid.c getdnnm.c gethstnm.c getcwd.c \ mkfifo.c setegid.c wait.c getpagesize.c seteuid.c \ wait3.c setpgrp.c getdtablesize.c create_module.c ptrace.c \ @@ -44,13 +39,21 @@ COBJS=$(patsubst %.c,%.o, $(CSRC)) MSRC=syscalls.c MOBJ=$(shell ./list_syscalls.sh) +ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) +CTOR_TARGETS=$(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o +SAFECFLAGS=$(WARNINGS) $(CPU_CFLAGS-y) $(OPTIMIZATION) -fno-builtin +ifeq ($(strip $(DOPIC)),y) +SAFECFLAGS+=-fPIC +endif +endif + OBJ=$(COBJS) $(MOBJ) all: $(STR_SYSCALLS) $(OBJ) $(LIBC) $(LIBC): ar-target -ar-target: $(OBJ) $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o +ar-target: $(OBJ) $(CTOR_TARGETS) $(AR) $(ARFLAGS) $(LIBC) $(OBJ) (cd $(TOPDIR)lib/; ln -fs crt0.o crt1.o) diff --git a/libc/sysdeps/linux/i386/crt0.S b/libc/sysdeps/linux/i386/crt0.S index 97f1fde63..be66b9a2d 100644 --- a/libc/sysdeps/linux/i386/crt0.S +++ b/libc/sysdeps/linux/i386/crt0.S @@ -61,6 +61,7 @@ _start: pushl %ebp /* callers %ebp (frame pointer) */ movl %esp,%ebp /* mark callers stack frame as invalid */ +#ifdef __UCLIBC_CTOR_DTOR__ /* Push .init and .fini arguments to __uClibc_start_main() on the stack */ pushl $_fini pushl $_init @@ -72,6 +73,14 @@ _start: /* Ok, now run uClibc's main() -- shouldn't return */ call __uClibc_start_main +#else + /* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ + pushl %eax /* Environment pointer */ + pushl %ebx /* Argument pointer */ + pushl %ecx /* And the argument count */ + + call __uClibc_main +#endif /* Crash if somehow `exit' returns anyways. */ hlt diff --git a/libc/sysdeps/linux/mips/crt0.S b/libc/sysdeps/linux/mips/crt0.S index fd1f4b9d4..052229819 100644 --- a/libc/sysdeps/linux/mips/crt0.S +++ b/libc/sysdeps/linux/mips/crt0.S @@ -30,6 +30,7 @@ __start: addu a2, a0, 1 /* argv[0] program name (ordinal->cardinal) */ sll a2, a2, 2 /* multiple by 4 */ add a2, a2, a1 /* a2 now points to start of envp */ +#ifdef __UCLIBC_CTOR_DTOR__ la a3, _init /* a3 is address of _init */ addiu sp, sp, -24 /* 16 + 4 rounded up to multiple of 8 */ /* multiple of 8 for longlong/double support */ @@ -38,6 +39,9 @@ __start: /* Ok, now run uClibc's main() -- shouldn't return */ jal __uClibc_start_main +#else + jal __uClibc_main +#endif addiu sp, sp, 24 /* undo stack argument */ diff --git a/libc/sysdeps/linux/sh/crt0.S b/libc/sysdeps/linux/sh/crt0.S index e74ae86c4..a27775ed0 100644 --- a/libc/sysdeps/linux/sh/crt0.S +++ b/libc/sysdeps/linux/sh/crt0.S @@ -48,6 +48,34 @@ _start: mov.l @r15+,r4 mov r15, r5 +#if ! defined __UCLIBC_CTOR_DTOR__ + /* + * Setup the value for the environment pointer: + * r6 = (argc + 1) * 4 + * r6 += argv (in delay slot) + */ + mov r4,r6 + add #1,r6 + shll2 r6 + add r5, r6 + + /* jump to __uClibc_main (argc, argv, envp) */ + mov.l L_main, r0 + jsr @r0 + nop /* delay slot */ + + /* We should not get here. */ + mov.l L_abort, r0 + jmp @r0 + nop + +_start_end: + .align 2 + +L_main: + .long __uClibc_main /* in libuClibc.*.so */ + +#else /* __UCLIBC_CTOR_DTOR__ */ /* Push the finip argument to __uClibc_start_main() onto the stack */ mov.l L_fini,r6 mov.l r6,@-r15 @@ -72,10 +100,12 @@ _start: mov.l L_abort, r0 jmp @r0 nop - _start_end: .align 2 +L_main: + .long __uClibc_start_main /* in libuClibc.*.so */ + .weak _init .type _init,@function _init: @@ -87,13 +117,13 @@ _init: .weak _fini .set _fini,_init -L_main: - .long __uClibc_start_main /* in libuClibc.*.so */ - L_init: .long _init L_fini: .long _fini + +#endif + L_abort: .long abort diff --git a/libpthread/Makefile b/libpthread/Makefile index c98ef8bda..87e20749f 100644 --- a/libpthread/Makefile +++ b/libpthread/Makefile @@ -36,6 +36,7 @@ ifeq ($(strip $(DODEBUG)),y) endif endif +ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) ifeq ($(strip $(DOPIC)),y) START_FILES = $(TOPDIR)lib/crti.o $(LIBGCC_DIR)crtbeginS.o END_FILES = $(LIBGCC_DIR)crtendS.o $(TOPDIR)lib/crtn.o @@ -43,6 +44,7 @@ else START_FILES = $(TOPDIR)lib/crti.o $(LIBGCC_DIR)crtbegin.o END_FILES = $(LIBGCC_DIR)crtend.o $(TOPDIR)lib/crtn.o endif +endif ALL_SUBDIRS = linuxthreads linuxthreads_db -- cgit v1.2.3