diff options
-rw-r--r-- | config.h.in | 4 | ||||
-rw-r--r-- | config.make.in | 1 | ||||
-rwxr-xr-x | configure | 69 | ||||
-rw-r--r-- | configure.ac | 50 | ||||
-rw-r--r-- | elf/Makefile | 17 | ||||
-rw-r--r-- | elf/dl-addr.c | 3 | ||||
-rw-r--r-- | elf/dl-lookup.c | 9 | ||||
-rw-r--r-- | elf/elf.h | 3 | ||||
-rw-r--r-- | elf/sprof.c | 6 | ||||
-rw-r--r-- | elf/tst-secondary.h | 3 | ||||
-rw-r--r-- | elf/tst-secondary1.c | 13 | ||||
-rw-r--r-- | elf/tst-secondary1mod.c | 4 | ||||
-rw-r--r-- | elf/tst-secondary2.c | 13 | ||||
-rw-r--r-- | elf/tst-secondary2mod.c | 12 | ||||
-rw-r--r-- | elf/tst-secondary3.c | 13 | ||||
-rw-r--r-- | elf/tst-secondary3mod.c | 13 | ||||
-rw-r--r-- | elf/tst-secondarymod.c | 9 |
17 files changed, 237 insertions, 5 deletions
diff --git a/config.h.in b/config.h.in index 2b9aa1a986..a1588561b7 100644 --- a/config.h.in +++ b/config.h.in @@ -24,6 +24,10 @@ /* Define if weak symbols are available via the `.weakext' directive. */ #undef HAVE_ASM_WEAKEXT_DIRECTIVE +/* Define if secondary symbols are available via the `.secondary' + directive. */ +#undef HAVE_ASM_SECONDARY_DIRECTIVE + /* Define to the assembler line separator character for multiple assembler instructions per line. Default is `;' */ #undef ASM_LINE_SEP diff --git a/config.make.in b/config.make.in index a9f5696077..ac115f085f 100644 --- a/config.make.in +++ b/config.make.in @@ -56,6 +56,7 @@ old-glibc-headers = @old_glibc_headers@ unwind-find-fde = @libc_cv_gcc_unwind_find_fde@ have-forced-unwind = @libc_cv_forced_unwind@ have-fpie = @libc_cv_fpie@ +have-secondary = @libc_cv_ld_secondary@ gnu89-inline-CFLAGS = @gnu89_inline@ have-ssp = @libc_cv_ssp@ have-selinux = @have_selinux@ diff --git a/configure b/configure index 45cc7cba2b..86feb6a79f 100755 --- a/configure +++ b/configure @@ -624,6 +624,7 @@ libc_cv_cc_loop_to_function libc_cv_cc_submachine libc_cv_cc_nofma exceptions +libc_cv_ld_secondary gnu89_inline libc_cv_ssp fno_unit_at_a_time @@ -6488,8 +6489,10 @@ if { ac_try='${CC-cc} $ASFLAGS -c conftest.s 1>&5' $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then libc_cv_asm_weak_directive=yes + libc_cv_asm_weak=.weak else libc_cv_asm_weak_directive=no + libc_cv_asm_weak= fi rm -f conftest* fi @@ -6518,6 +6521,7 @@ EOF $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then libc_cv_asm_weakext_directive=yes + libc_cv_asm_weak=.weakext else libc_cv_asm_weakext_directive=no fi @@ -6536,6 +6540,71 @@ elif test $libc_cv_asm_weakext_directive = yes; then fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .secondary assembler directive" >&5 +$as_echo_n "checking for .secondary assembler directive... " >&6; } +if ${libc_cv_asm_secondary_directive+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<EOF +${libc_cv_dot_text} +_sym: +.secondary _sym +EOF +test -n "$libc_cv_asm_weak" && cat >> conftest.s <<EOF +$libc_cv_asm_weak _sym +EOF +if ${CC-cc} -c $ASFLAGS -o conftest.o conftest.s 1>&5 2>&5; then + if $READELF -s conftest.o | fgrep _sym | fgrep SECOND > /dev/null; then + libc_cv_asm_secondary_directive=yes + else + libc_cv_asm_secondary_directive=no + fi +else + libc_cv_asm_secondary_directive=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_secondary_directive" >&5 +$as_echo "$libc_cv_asm_secondary_directive" >&6; } +if test $libc_cv_asm_secondary_directive = yes; then + $as_echo "#define HAVE_ASM_SECONDARY_DIRECTIVE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for secondary symbol in shared library" >&5 +$as_echo_n "checking for secondary symbol in shared library... " >&6; } +if ${libc_cv_ld_secondary+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<EOF +asm (".secondary foo"); +void foo (void) { } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS + -fPIC -shared -o conftest.so conftest.c + -nostartfiles -nostdlib + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + if $READELF -s conftest.so | fgrep foo | fgrep SECOND > /dev/null; then + libc_cv_ld_secondary=yes + else + libc_cv_ld_secondary=no + fi + else + libc_cv_ld_secondary=no + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_secondary" >&5 +$as_echo "$libc_cv_ld_secondary" >&6; } +else + libc_cv_ld_secondary=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld --no-whole-archive" >&5 $as_echo_n "checking for ld --no-whole-archive... " >&6; } if ${libc_cv_ld_no_whole_archive+:} false; then : diff --git a/configure.ac b/configure.ac index 7e9383a7f0..86632ca6b5 100644 --- a/configure.ac +++ b/configure.ac @@ -1628,8 +1628,10 @@ foo: EOF if AC_TRY_COMMAND(${CC-cc} $ASFLAGS -c conftest.s 1>&AS_MESSAGE_LOG_FD); then libc_cv_asm_weak_directive=yes + libc_cv_asm_weak=.weak else libc_cv_asm_weak_directive=no + libc_cv_asm_weak= fi rm -f conftest*]) @@ -1648,6 +1650,7 @@ baz: EOF if AC_TRY_COMMAND(${CC-cc} $ASFLAGS -c conftest.s 1>&AS_MESSAGE_LOG_FD); then libc_cv_asm_weakext_directive=yes + libc_cv_asm_weak=.weakext else libc_cv_asm_weakext_directive=no fi @@ -1661,6 +1664,53 @@ elif test $libc_cv_asm_weakext_directive = yes; then AC_DEFINE(HAVE_ASM_WEAKEXT_DIRECTIVE) fi +AC_CACHE_CHECK(for .secondary assembler directive, + libc_cv_asm_secondary_directive, [dnl +cat > conftest.s <<EOF +${libc_cv_dot_text} +_sym: +.secondary _sym +EOF +test -n "$libc_cv_asm_weak" && cat >> conftest.s <<EOF +$libc_cv_asm_weak _sym +EOF +if ${CC-cc} -c $ASFLAGS -o conftest.o conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then + if $READELF -s conftest.o | fgrep _sym | fgrep SECOND > /dev/null; then + libc_cv_asm_secondary_directive=yes + else + libc_cv_asm_secondary_directive=no + fi +else + libc_cv_asm_secondary_directive=no +fi +rm -f conftest*]) +if test $libc_cv_asm_secondary_directive = yes; then + AC_DEFINE(HAVE_ASM_SECONDARY_DIRECTIVE) + AC_CACHE_CHECK(for secondary symbol in shared library, + libc_cv_ld_secondary, [dnl +cat > conftest.c <<EOF +asm (".secondary foo"); +void foo (void) { } +EOF + if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS + -fPIC -shared -o conftest.so conftest.c + -nostartfiles -nostdlib + 1>&AS_MESSAGE_LOG_FD]) + then + if $READELF -s conftest.so | fgrep foo | fgrep SECOND > /dev/null; then + libc_cv_ld_secondary=yes + else + libc_cv_ld_secondary=no + fi + else + libc_cv_ld_secondary=no + fi + rm -f conftest*]) +else + libc_cv_ld_secondary=no +fi +AC_SUBST(libc_cv_ld_secondary) + AC_CACHE_CHECK(for ld --no-whole-archive, libc_cv_ld_no_whole_archive, [dnl cat > conftest.c <<\EOF _start () {} diff --git a/elf/Makefile b/elf/Makefile index 4ceeaf89be..31029c1e77 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -269,6 +269,12 @@ modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6 endif endif +ifeq (yes,$(have-secondary)) +tests += tst-secondary1 tst-secondary2 tst-secondary3 +modules-names += tst-secondarymod tst-secondary1mod tst-secondary2mod \ + tst-secondary3mod +endif + ifeq (yes,$(build-shared)) ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out @@ -1144,6 +1150,17 @@ $(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o) $(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o) $(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o) +LDFLAGS-tst-secondarymod.so = -Wl,-z,secondary + +$(objpfx)tst-secondary1: $(objpfx)tst-secondarymod.so \ + $(objpfx)tst-secondary1mod.so + +$(objpfx)tst-secondary2: $(objpfx)tst-secondarymod.so \ + $(objpfx)tst-secondary2mod.so + +$(objpfx)tst-secondary3: $(objpfx)tst-secondarymod.so \ + $(objpfx)tst-secondary3mod.so + $(objpfx)tst-unique1: $(libdl) $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \ $(objpfx)tst-unique1mod2.so diff --git a/elf/dl-addr.c b/elf/dl-addr.c index a025652c08..b4dd8887f5 100644 --- a/elf/dl-addr.c +++ b/elf/dl-addr.c @@ -87,7 +87,8 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, for (; (void *) symtab < (void *) symtabend; ++symtab) if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL - || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK) + || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK + || ELFW(ST_BIND) (symtab->st_info) == STB_SECONDARY) && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS && (symtab->st_shndx != SHN_UNDEF || symtab->st_value != 0) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 11cb44b451..7e35723aab 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -518,10 +518,15 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, switch (ELFW(ST_BIND) (sym->st_info)) { + case STB_SECONDARY: + /* Secondary definition. Use this value if we don't find + another. */ + goto dynamic_weak; case STB_WEAK: /* Weak definition. Use this value if we don't find another. */ if (__glibc_unlikely (GLRO(dl_dynamic_weak))) { +dynamic_weak: if (! result->s) { result->s = sym; @@ -857,7 +862,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, if (__glibc_unlikely (current_value.s == NULL)) { - if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) + if ((*ref == NULL + || (ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK + && ELFW(ST_BIND) ((*ref)->st_info) != STB_SECONDARY)) && skip_map == NULL && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) { diff --git a/elf/elf.h b/elf/elf.h index fbadda4377..4cc607480b 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -472,7 +472,8 @@ typedef struct #define STB_LOCAL 0 /* Local symbol */ #define STB_GLOBAL 1 /* Global symbol */ #define STB_WEAK 2 /* Weak symbol */ -#define STB_NUM 3 /* Number of defined types. */ +#define STB_SECONDARY 3 /* Secondary symbol */ +#define STB_NUM 4 /* Number of defined types. */ #define STB_LOOS 10 /* Start of OS-specific */ #define STB_GNU_UNIQUE 10 /* Unique symbol. */ #define STB_HIOS 12 /* End of OS-specific */ diff --git a/elf/sprof.c b/elf/sprof.c index ec3fde3848..9ed60956cd 100644 --- a/elf/sprof.c +++ b/elf/sprof.c @@ -1082,7 +1082,8 @@ read_symbols (struct shobj *shobj) newsym->name = &shobj->strtab[sym->st_name]; newsym->addr = sym->st_value; newsym->size = sym->st_size; - newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK; + newsym->weak = (ELFW(ST_BIND) (sym->st_info) == STB_SECONDARY + || ELFW(ST_BIND) (sym->st_info) == STB_WEAK); newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other) != STV_DEFAULT); newsym->ticks = 0; @@ -1140,7 +1141,8 @@ read_symbols (struct shobj *shobj) newsym->name = &strtab[symtab->st_name]; newsym->addr = symtab->st_value; newsym->size = symtab->st_size; - newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK; + newsym->weak = (ELFW(ST_BIND) (symtab->st_info) == STB_SECONDARY + || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK); newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other) != STV_DEFAULT); newsym->ticks = 0; diff --git a/elf/tst-secondary.h b/elf/tst-secondary.h new file mode 100644 index 0000000000..0487e25c60 --- /dev/null +++ b/elf/tst-secondary.h @@ -0,0 +1,3 @@ +#define GLOBAL 1 +#define WEAK 2 +#define SECONDARY 3 diff --git a/elf/tst-secondary1.c b/elf/tst-secondary1.c new file mode 100644 index 0000000000..f4d6edd722 --- /dev/null +++ b/elf/tst-secondary1.c @@ -0,0 +1,13 @@ +/* Verify that secdonary function is called. */ + +#include "tst-secondary.h" + +extern int bar (void); +extern void foo (void); + +int +main (void) +{ + foo (); + return bar () != SECONDARY; +} diff --git a/elf/tst-secondary1mod.c b/elf/tst-secondary1mod.c new file mode 100644 index 0000000000..cd0130cacd --- /dev/null +++ b/elf/tst-secondary1mod.c @@ -0,0 +1,4 @@ +void +foo (void) +{ +} diff --git a/elf/tst-secondary2.c b/elf/tst-secondary2.c new file mode 100644 index 0000000000..3f221cb172 --- /dev/null +++ b/elf/tst-secondary2.c @@ -0,0 +1,13 @@ +/* Verify that global function is called. */ + +#include "tst-secondary.h" + +extern int bar (void); +extern void foo (void); + +int +main (void) +{ + foo (); + return bar () != GLOBAL; +} diff --git a/elf/tst-secondary2mod.c b/elf/tst-secondary2mod.c new file mode 100644 index 0000000000..f9407a9b1c --- /dev/null +++ b/elf/tst-secondary2mod.c @@ -0,0 +1,12 @@ +#include "tst-secondary.h" + +int +bar (void) +{ + return GLOBAL; +} + +void +foo (void) +{ +} diff --git a/elf/tst-secondary3.c b/elf/tst-secondary3.c new file mode 100644 index 0000000000..b55baea6d6 --- /dev/null +++ b/elf/tst-secondary3.c @@ -0,0 +1,13 @@ +/* Verify that weak function is called. */ + +#include "tst-secondary.h" + +extern int bar (void); +extern void foo (void); + +int +main (void) +{ + foo (); + return bar () != WEAK; +} diff --git a/elf/tst-secondary3mod.c b/elf/tst-secondary3mod.c new file mode 100644 index 0000000000..edfb25bbb2 --- /dev/null +++ b/elf/tst-secondary3mod.c @@ -0,0 +1,13 @@ +#include "tst-secondary.h" + +int +__attribute__ ((weak)) +bar (void) +{ + return WEAK; +} + +void +foo (void) +{ +} diff --git a/elf/tst-secondarymod.c b/elf/tst-secondarymod.c new file mode 100644 index 0000000000..5363e99654 --- /dev/null +++ b/elf/tst-secondarymod.c @@ -0,0 +1,9 @@ +#include "tst-secondary.h" + +asm (".secondary bar"); + +int +bar (void) +{ + return SECONDARY; +} |