From 02ecc8e968f7524f4c41cd7942adff4ff31afe5c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 15 Dec 2010 14:56:40 +0000 Subject: [PATCH] Add SORT_BY_INIT_PRIORITY. bfd/ 2010-12-15 H.J. Lu * elf.c (_bfd_elf_new_section_hook): Special handling for .init_array/.fini_array output sections. ld/ 2010-12-15 H.J. Lu * Makefile.am (GENSCRIPTS): Add @enable_initfini_array@. * NEWS: Mention SORT_BY_INIT_PRIORITY. * configure.in: Add AC_CANONICAL_BUILD. Add --enable-initfini-array. * genscripts.sh (ENABLE_INITFINI_ARRAY): New. * ld.h (sort_type): Add by_init_priority. * ld.texinfo: Document SORT_BY_INIT_PRIORITY. * ldgram.y (SORT_BY_INIT_PRIORITY): New. (wildcard_spec): Handle SORT_BY_INIT_PRIORITY. * ldlang.c (get_init_priority): New. (compare_section): Use get_init_priority for by_init_priority. * ldlex.l (SORT_BY_INIT_PRIORITY): New. * scripttempl/elf.sc: Support ENABLE_INITFINI_ARRAY. * Makefile.in: Regenerated. * aclocal.m4: Regenerated. * config.in: Likewise. * configure: Likewise. ld/testsuite/ 2010-12-15 H.J. Lu * ld-elf/elf.exp (array_tests): Add init-mixed. (array_tests_static): Likewise. Also delete tmpdir/init-mixed. * ld-elf/init-mixed.c: New. * ld-elf/init-mixed.out: Likewise. --- bfd/ChangeLog | 5 ++ bfd/elf.c | 13 +++- ld/ChangeLog | 30 +++++++++ ld/Makefile.am | 2 +- ld/Makefile.in | 3 +- ld/NEWS | 4 ++ ld/config.in | 3 + ld/configure | 56 ++++++++++++++++- ld/configure.in | 25 ++++++++ ld/genscripts.sh | 8 ++- ld/ld.h | 3 +- ld/ld.texinfo | 6 ++ ld/ldgram.y | 7 +++ ld/ldlang.c | 53 ++++++++++++++++ ld/ldlex.l | 1 + ld/scripttempl/elf.sc | 17 +++++- ld/testsuite/ChangeLog | 9 +++ ld/testsuite/ld-elf/elf.exp | 4 +- ld/testsuite/ld-elf/init-mixed.c | 98 ++++++++++++++++++++++++++++++ ld/testsuite/ld-elf/init-mixed.out | 1 + 20 files changed, 334 insertions(+), 14 deletions(-) create mode 100644 ld/testsuite/ld-elf/init-mixed.c create mode 100644 ld/testsuite/ld-elf/init-mixed.out diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8e1246178b4..fcf28439319 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2010-12-15 H.J. Lu + + * elf.c (_bfd_elf_new_section_hook): Special handling for + .init_array/.fini_array output sections. + 2010-12-13 Alan Modra * aoutx.h (aout_link_check_ar_symbols): Formatting. diff --git a/bfd/elf.c b/bfd/elf.c index 0e7cd9af6e4..de0ab61dcb6 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -2304,12 +2304,19 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec) anyway. We will set ELF section type and flags for all linker created sections. If user specifies BFD section flags, we will set ELF section type and flags based on BFD section flags in - elf_fake_sections. */ - if ((!sec->flags && abfd->direction != read_direction) + elf_fake_sections. Special handling for .init_array/.fini_array + output sections since they may contain .ctors/.dtors input + sections. We don't want _bfd_elf_init_private_section_data to + copy ELF section type from .ctors/.dtors input sections. */ + if (abfd->direction != read_direction || (sec->flags & SEC_LINKER_CREATED) != 0) { ssect = (*bed->get_sec_type_attr) (abfd, sec); - if (ssect != NULL) + if (ssect != NULL + && (!sec->flags + || (sec->flags & SEC_LINKER_CREATED) != 0 + || ssect->type == SHT_INIT_ARRAY + || ssect->type == SHT_FINI_ARRAY)) { elf_section_type (sec) = ssect->type; elf_section_flags (sec) = ssect->attr; diff --git a/ld/ChangeLog b/ld/ChangeLog index d41197b3385..c145a7e5ad9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,33 @@ +2010-12-15 H.J. Lu + + * Makefile.am (GENSCRIPTS): Add @enable_initfini_array@. + + * NEWS: Mention SORT_BY_INIT_PRIORITY. + + * configure.in: Add AC_CANONICAL_BUILD. + Add --enable-initfini-array. + + * genscripts.sh (ENABLE_INITFINI_ARRAY): New. + + * ld.h (sort_type): Add by_init_priority. + + * ld.texinfo: Document SORT_BY_INIT_PRIORITY. + + * ldgram.y (SORT_BY_INIT_PRIORITY): New. + (wildcard_spec): Handle SORT_BY_INIT_PRIORITY. + + * ldlang.c (get_init_priority): New. + (compare_section): Use get_init_priority for by_init_priority. + + * ldlex.l (SORT_BY_INIT_PRIORITY): New. + + * scripttempl/elf.sc: Support ENABLE_INITFINI_ARRAY. + + * Makefile.in: Regenerated. + * aclocal.m4: Regenerated. + * config.in: Likewise. + * configure: Likewise. + 2010-12-13 Alan Modra * ldlang.c (load_symbols): Correct last change. diff --git a/ld/Makefile.am b/ld/Makefile.am index d9e1bcca243..9f016df0ab5 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -611,7 +611,7 @@ stringify.sed: ${srcdir}/emultempl/$(STRINGIFY) # These all start with e so 'make clean' can find them. -GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ +GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em diff --git a/ld/Makefile.in b/ld/Makefile.in index 01511bcf6ee..3cb62347ea4 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -299,6 +299,7 @@ datarootdir = @datarootdir@ do_compare = @do_compare@ docdir = @docdir@ dvidir = @dvidir@ +enable_initfini_array = @enable_initfini_array@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ @@ -797,7 +798,7 @@ EMULATION_FILES = emultempl/pe.em emultempl/armcoff.em POTFILES = $(CFILES) $(HFILES) $(EMULATION_FILES) # These all start with e so 'make clean' can find them. -GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ +GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em diff --git a/ld/NEWS b/ld/NEWS index eaa5b0bca34..b303490cd0b 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,9 @@ -*- text -*- +* Added SORT_BY_INIT_PRIORITY to the linker script language to permit +sorting sections by numerical value of the GCC init_priority attribute +encoded in the section name. + Changes in 2.21: diff --git a/ld/config.in b/ld/config.in index f49327c11a7..929da9088f3 100644 --- a/ld/config.in +++ b/ld/config.in @@ -61,6 +61,9 @@ /* Define to 1 if you have the `glob' function. */ #undef HAVE_GLOB +/* Define .init_array/.fini_array sections are available and working. */ +#undef HAVE_INITFINI_ARRAY + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H diff --git a/ld/configure b/ld/configure index 088c721de77..a6802ddc318 100755 --- a/ld/configure +++ b/ld/configure @@ -609,6 +609,7 @@ EMUL_EXTRA_OFILES EMULATION_OFILES EMUL STRINGIFY +enable_initfini_array ENABLE_PLUGINS_FALSE ENABLE_PLUGINS_TRUE NATIVE_LIB_DIRS @@ -778,6 +779,7 @@ enable_fast_install with_gnu_ld enable_libtool_lock enable_nls +enable_initfini_array ' ac_precious_vars='build_alias host_alias @@ -1427,6 +1429,7 @@ Optional Features: optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-nls do not use Native Language Support + --enable-initfini-array use .init_array/.fini_array sections Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -2591,6 +2594,7 @@ test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -11622,7 +11626,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11625 "configure" +#line 11629 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11728,7 +11732,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11731 "configure" +#line 11735 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12944,6 +12948,54 @@ else fi +# Check whether --enable-initfini-array was given. +if test "${enable_initfini_array+set}" = set; then : + enableval=$enable_initfini_array; +else + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .preinit_array/.init_array/.fini_array support" >&5 +$as_echo_n "checking for .preinit_array/.init_array/.fini_array support... " >&6; } +if test "${gcc_cv_initfini_array+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x${build}" = "x${target}" ; then + if test "$cross_compiling" = yes; then : + gcc_cv_initfini_array=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +static int x = -1; +int main (void) { return x; } +int foo (void) { x = 0; } +int (*fp) (void) __attribute__ ((section (".init_array"))) = foo; +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gcc_cv_initfini_array=yes +else + gcc_cv_initfini_array=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + else + gcc_cv_initfini_array=no + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_initfini_array" >&5 +$as_echo "$gcc_cv_initfini_array" >&6; } + enable_initfini_array=$gcc_cv_initfini_array + +fi + + +if test $enable_initfini_array = yes; then + +$as_echo "#define HAVE_INITFINI_ARRAY 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a known getopt prototype in unistd.h" >&5 $as_echo_n "checking for a known getopt prototype in unistd.h... " >&6; } if test "${ld_cv_decl_getopt_unistd_h+set}" = set; then : diff --git a/ld/configure.in b/ld/configure.in index 85fe903d3b1..15d7685c025 100644 --- a/ld/configure.in +++ b/ld/configure.in @@ -5,6 +5,7 @@ AC_INIT AC_CONFIG_SRCDIR(ldmain.c) AC_CANONICAL_TARGET +AC_CANONICAL_BUILD AC_ISC_POSIX changequote(,)dnl @@ -175,6 +176,30 @@ if test x$enable_plugins = xno ; then fi AM_CONDITIONAL([ENABLE_PLUGINS], [test x$enable_plugins = xyes]) +AC_ARG_ENABLE(initfini-array, + [ --enable-initfini-array use .init_array/.fini_array sections], + [], [ +AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support, + gcc_cv_initfini_array, [dnl + if test "x${build}" = "x${target}" ; then + AC_RUN_IFELSE([AC_LANG_SOURCE([ +static int x = -1; +int main (void) { return x; } +int foo (void) { x = 0; } +int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;])], + [gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no], + [gcc_cv_initfini_array=no]) + else + gcc_cv_initfini_array=no + fi]) + enable_initfini_array=$gcc_cv_initfini_array +]) +AC_SUBST(enable_initfini_array) +if test $enable_initfini_array = yes; then + AC_DEFINE(HAVE_INITFINI_ARRAY, 1, + [Define .init_array/.fini_array sections are available and working.]) +fi + AC_MSG_CHECKING(for a known getopt prototype in unistd.h) AC_CACHE_VAL(ld_cv_decl_getopt_unistd_h, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [extern int getopt (int, char *const*, const char *);])], diff --git a/ld/genscripts.sh b/ld/genscripts.sh index c86631b500a..61981bdd81c 100755 --- a/ld/genscripts.sh +++ b/ld/genscripts.sh @@ -30,6 +30,7 @@ # default_emulation \ # native_lib_dirs \ # use_sysroot \ +# enable_initfini_array \ # this_emulation \ # optional: # tool_dir \ @@ -89,9 +90,10 @@ EMULATION_LIBPATH=$8 NATIVE_LIB_DIRS=$9 shift 9 use_sysroot=$1 -EMULATION_NAME=$2 -TOOL_LIB=$3 -CUSTOMIZER_SCRIPT=$4 +ENABLE_INITFINI_ARRAY=$2 +EMULATION_NAME=$3 +TOOL_LIB=$4 +CUSTOMIZER_SCRIPT=$5 # Can't use ${TOOL_LIB:-$target_alias} here due to an Ultrix shell bug. if [ "x${TOOL_LIB}" = "x" ] ; then diff --git a/ld/ld.h b/ld/ld.h index aa0979d6f27..21323d89f61 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -86,7 +86,8 @@ typedef enum {sort_none, sort_ascending, sort_descending} sort_order; /* A wildcard specification. */ typedef enum { - none, by_name, by_alignment, by_name_alignment, by_alignment_name + none, by_name, by_alignment, by_name_alignment, by_alignment_name, + by_init_priority } sort_type; extern sort_type sort_section; diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 4c58e4855c9..6d36dfb63dd 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -3911,6 +3911,12 @@ into ascending order by name before placing them in the output file. difference is @code{SORT_BY_ALIGNMENT} will sort sections into ascending order by alignment before placing them in the output file. +@cindex SORT_BY_INIT_PRIORITY +@code{SORT_BY_INIT_PRIORITY} is very similar to @code{SORT_BY_NAME}. The +difference is @code{SORT_BY_INIT_PRIORITY} will sort sections into +ascending order by numerical value of the GCC init_priority attribute +encoded in the section name before placing them in the output file. + @cindex SORT @code{SORT} is an alias for @code{SORT_BY_NAME}. diff --git a/ld/ldgram.y b/ld/ldgram.y index 69a84c72982..ed0aaa76259 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -126,6 +126,7 @@ static int error_index; %token SECTIONS PHDRS INSERT_K AFTER BEFORE %token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END %token SORT_BY_NAME SORT_BY_ALIGNMENT +%token SORT_BY_INIT_PRIORITY %token '{' '}' %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token INHIBIT_COMMON_ALLOCATION @@ -482,6 +483,12 @@ wildcard_spec: $$.sorted = by_name; $$.exclude_name_list = $5; } + | SORT_BY_INIT_PRIORITY '(' wildcard_name ')' + { + $$.name = $3; + $$.sorted = by_init_priority; + $$.exclude_name_list = NULL; + } ; exclude_name_list: diff --git a/ld/ldlang.c b/ld/ldlang.c index 6dc022989fd..32c4af3ef78 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -371,18 +371,70 @@ match_simple_wild (const char *pattern, const char *name) return TRUE; } +/* Return the numerical value of the init_priority attribute from + section name NAME. */ + +static unsigned long +get_init_priority (const char *name) +{ + char *end; + unsigned long init_priority; + + /* GCC uses the following section names for the init_priority + attribute with numerical values 101 and 65535 inclusive. A + lower value means a higher priority. + + 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the + decimal numerical value of the init_priority attribute. + The order of execution in .init_array is forward and + .fini_array is backward. + 2: .ctors.NNNN/.ctors.NNNN: Where NNNN is 65535 minus the + decimal numerical value of the init_priority attribute. + The order of execution in .ctors is backward and .dtors + is forward. + */ + if (strncmp (name, ".init_array.", 12) == 0 + || strncmp (name, ".fini_array.", 12) == 0) + { + init_priority = strtoul (name + 12, &end, 10); + return *end ? 0 : init_priority; + } + else if (strncmp (name, ".ctors.", 7) == 0 + || strncmp (name, ".dtors.", 7) == 0) + { + init_priority = strtoul (name + 7, &end, 10); + return *end ? 0 : 65535 - init_priority; + } + + return 0; +} + /* Compare sections ASEC and BSEC according to SORT. */ static int compare_section (sort_type sort, asection *asec, asection *bsec) { int ret; + unsigned long ainit_priority, binit_priority; switch (sort) { default: abort (); + case by_init_priority: + ainit_priority + = get_init_priority (bfd_get_section_name (asec->owner, asec)); + binit_priority + = get_init_priority (bfd_get_section_name (bsec->owner, bsec)); + if (ainit_priority == 0 || binit_priority == 0) + goto sort_by_name; + ret = ainit_priority - binit_priority; + if (ret) + break; + else + goto sort_by_name; + case by_alignment_name: ret = (bfd_section_alignment (bsec->owner, bsec) - bfd_section_alignment (asec->owner, asec)); @@ -391,6 +443,7 @@ compare_section (sort_type sort, asection *asec, asection *bsec) /* Fall through. */ case by_name: +sort_by_name: ret = strcmp (bfd_get_section_name (asec->owner, asec), bfd_get_section_name (bsec->owner, bsec)); break; diff --git a/ld/ldlex.l b/ld/ldlex.l index 7f038b32a4a..7560ca21492 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -297,6 +297,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* "SORT_BY_NAME" { RTOKEN(SORT_BY_NAME); } "SORT_BY_ALIGNMENT" { RTOKEN(SORT_BY_ALIGNMENT); } "SORT" { RTOKEN(SORT_BY_NAME); } +"SORT_BY_INIT_PRIORITY" { RTOKEN(SORT_BY_INIT_PRIORITY); } "NOLOAD" { RTOKEN(NOLOAD);} "DSECT" { RTOKEN(DSECT);} "COPY" { RTOKEN(COPY);} diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index f020a668da0..37f766737e6 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -222,18 +222,31 @@ test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS=" *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*}) ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} }" +if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then + SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))" + SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))" + CTORS_IN_INIT_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors))" + DTORS_IN_FINI_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .dtors))" +else + SORT_INIT_ARRAY="KEEP (*(SORT(.init_array.*)))" + SORT_FINI_ARRAY="KEEP (*(SORT(.fini_array.*)))" + CTORS_IN_INIT_ARRAY= + DTORS_IN_FINI_ARRAY= +fi INIT_ARRAY=".init_array ${RELOCATING-0} : { ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_start = .);}} - KEEP (*(SORT(.init_array.*))) + ${SORT_INIT_ARRAY} KEEP (*(.init_array)) + ${CTORS_IN_INIT_ARRAY} ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_end = .);}} }" FINI_ARRAY=".fini_array ${RELOCATING-0} : { ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_start = .);}} - KEEP (*(SORT(.fini_array.*))) + ${SORT_FINI_ARRAY} KEEP (*(.fini_array)) + ${DTORS_IN_FINI_ARRAY} ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_end = .);}} }" CTOR=".ctors ${CONSTRUCTING-0} : diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 379132cd6e2..3f0fc2be8ca 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2010-12-15 H.J. Lu + + * ld-elf/elf.exp (array_tests): Add init-mixed. + (array_tests_static): Likewise. + Also delete tmpdir/init-mixed. + + * ld-elf/init-mixed.c: New. + * ld-elf/init-mixed.out: Likewise. + 2010-12-11 Alan Modra * ld-elfvers/vers25a.dsym: Really include _? in match. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index fc216833c93..a1e70da4fd4 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -74,11 +74,13 @@ set array_tests { {"preinit array" "" "" {preinit.c} "preinit" "preinit.out"} {"init array" "" "" {init.c} "init" "init.out"} {"fini array" "" "" {fini.c} "fini" "fini.out"} + {"init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."} } set array_tests_static { {"static preinit array" "-static" "" {preinit.c} "preinit" "preinit.out"} {"static init array" "-static" "" {init.c} "init" "init.out"} {"static fini array" "-static" "" {fini.c} "fini" "fini.out"} + {"static init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."} } # NetBSD ELF systems do not currently support the .*_array sections. @@ -93,4 +95,4 @@ switch -regexp $target_triplet { } run_ld_link_exec_tests $xfails $array_tests_static -catch "exec rm -f tmpdir/preinit tmpdir/init tmpdir/fini" status +catch "exec rm -f tmpdir/preinit tmpdir/init tmpdir/fini tmpdir/init-mixed" status diff --git a/ld/testsuite/ld-elf/init-mixed.c b/ld/testsuite/ld-elf/init-mixed.c new file mode 100644 index 00000000000..1d0c72716a2 --- /dev/null +++ b/ld/testsuite/ld-elf/init-mixed.c @@ -0,0 +1,98 @@ +#include +#include + +#include "config.h" + +#ifdef HAVE_INITFINI_ARRAY +static int count; + +static void +init1005 () +{ + if (count != 0) + abort (); + count = 1005; +} +void (*const init_array1005[]) () + __attribute__ ((section (".init_array.01005"), aligned (sizeof (void *)))) + = { init1005 }; +static void +fini1005 () +{ + if (count != 1005) + abort (); +} +void (*const fini_array1005[]) () + __attribute__ ((section (".fini_array.01005"), aligned (sizeof (void *)))) + = { fini1005 }; + +static void +ctor1007 () +{ + if (count != 1005) + abort (); + count = 1007; +} +void (*const ctors1007[]) () + __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *)))) + = { ctor1007 }; +static void +dtor1007 () +{ + if (count != 1007) + abort (); + count = 1005; +} +void (*const dtors1007[]) () + __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *)))) + = { dtor1007 }; + +static void +init65530 () +{ + if (count != 1007) + abort (); + count = 65530; +} +void (*const init_array65530[]) () + __attribute__ ((section (".init_array.65530"), aligned (sizeof (void *)))) + = { init65530 }; +static void +fini65530 () +{ + if (count != 65530) + abort (); + count = 1007; +} +void (*const fini_array65530[]) () + __attribute__ ((section (".fini_array.65530"), aligned (sizeof (void *)))) + = { fini65530 }; + +static void +ctor65535 () +{ + if (count != 65530) + abort (); + count = 65535; +} +void (*const ctors65535[]) () + __attribute__ ((section (".ctors"), aligned (sizeof (void *)))) + = { ctor65535 }; +static void +dtor65535 () +{ + if (count != 65535) + abort (); + count = 65530; +} +void (*const dtors65535[]) () + __attribute__ ((section (".dtors"), aligned (sizeof (void *)))) + = { dtor65535 }; +#endif + +int +main () +{ + printf ("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/init-mixed.out b/ld/testsuite/ld-elf/init-mixed.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/ld/testsuite/ld-elf/init-mixed.out @@ -0,0 +1 @@ +OK -- 2.30.2