diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-06-30 12:53:04 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-09-10 09:34:03 -0700 |
commit | f10bae9a102a00ec97a38d009013c5aa616c847f (patch) | |
tree | 7dfdbcbc287ad0d79ca93b324a76dd9c65d46c41 | |
parent | 01b07c70ad77ef28b6a3661ed3142ebff35b6e69 (diff) | |
download | glibc-f10bae9a102a00ec97a38d009013c5aa616c847f.zip glibc-f10bae9a102a00ec97a38d009013c5aa616c847f.tar.gz glibc-f10bae9a102a00ec97a38d009013c5aa616c847f.tar.bz2 |
Add STB_SECONDARY support to ld.so
Enable STB_SECONDARY if it is supported by binutils. Add 3 STB_SECONDARY
tests.
* config.h.in: Add HAVE_ASM_SECONDARY_DIRECTIVE.
* config.make.in (have-secondary): New macro.
* configure.in: Check if STB_SECONDARY is supported by as/ld.
Define HAVE_ASM_SECONDARY_DIRECTIVE and set have-secondary to yes
if the .secondary assembly directive works.
* configure: Regenerated.
* elf/Makefile (tests): Add tst-secondary1 tst-secondary2
tst-secondary3 if STB_SECONDARY is supported by as/ld.
(modules-names): Add tst-secondarymod tst-secondary1mod
tst-secondary2mod tst-secondary3mod if STB_SECONDARY is supported
by as/ld.
(LDFLAGS-tst-secondarymod.so): New macro.
($(objpfx)tst-secondary1): New rule.
($(objpfx)tst-secondary2): Likewise.
($(objpfx)tst-secondary3): Likewise.
* elf/dl-addr.c (determine_info): Also check STB_SECONDARY.
* elf/dl-lookup.c (do_lookup_x): Handle STB_SECONDARY.
(_dl_lookup_symbol_x): Likewise.
* elf/sprof.c (read_symbols): Likewise.
* elf/elf.h (STB_SECONDARY): New.
(STB_NUM): Updated.
* elf/tst-secondary.h: New file.
* elf/tst-secondary1.c: Likewise.
* elf/tst-secondary1mod.c: Likewise.
* elf/tst-secondary2.c: Likewise.
* elf/tst-secondary2mod.c: Likewise.
* elf/tst-secondary3.c: Likewise.
* elf/tst-secondary3mod.c: Likewise.
* elf/tst-secondarymod.c: Likewise.
-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 695ca35..10ae6fb 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 ad4dd30..263e165 100644 --- a/config.make.in +++ b/config.make.in @@ -55,6 +55,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@ @@ -623,6 +623,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 @@ -6333,8 +6334,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 @@ -6363,6 +6366,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 @@ -6381,6 +6385,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 d89aaf0..bf60091 100644 --- a/configure.ac +++ b/configure.ac @@ -1577,8 +1577,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*]) @@ -1597,6 +1599,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 @@ -1610,6 +1613,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 e5b142c..1594536 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -254,6 +254,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 @@ -1120,6 +1126,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 a025652..b4dd888 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 5fa76ba..91f5abe 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -465,10 +465,15 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, found_it: 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; @@ -803,7 +808,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)) { @@ -447,7 +447,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 380b8d5..3fdae4b 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 0000000..0487e25 --- /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 0000000..f4d6edd7 --- /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 0000000..cd0130c --- /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 0000000..3f221cb --- /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 0000000..f9407a9 --- /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 0000000..b55baea --- /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 0000000..edfb25b --- /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 0000000..5363e99 --- /dev/null +++ b/elf/tst-secondarymod.c @@ -0,0 +1,9 @@ +#include "tst-secondary.h" + +asm (".secondary bar"); + +int +bar (void) +{ + return SECONDARY; +} |