summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile17
-rw-r--r--elf/dl-addr.c3
-rw-r--r--elf/dl-lookup.c9
-rw-r--r--elf/elf.h3
-rw-r--r--elf/sprof.c6
-rw-r--r--elf/tst-secondary.h3
-rw-r--r--elf/tst-secondary1.c13
-rw-r--r--elf/tst-secondary1mod.c4
-rw-r--r--elf/tst-secondary2.c13
-rw-r--r--elf/tst-secondary2mod.c12
-rw-r--r--elf/tst-secondary3.c13
-rw-r--r--elf/tst-secondary3mod.c13
-rw-r--r--elf/tst-secondarymod.c9
13 files changed, 113 insertions, 5 deletions
diff --git a/elf/Makefile b/elf/Makefile
index e5b142c7c6..15945367ec 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 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 5fa76ba675..91f5abe93f 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))
{
diff --git a/elf/elf.h b/elf/elf.h
index 496f08d515..5c9195d01c 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -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 380b8d5437..3fdae4b019 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;
+}