summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elf-bfd.h4
-rw-r--r--bfd/elflink.c33
2 files changed, 34 insertions, 3 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 92a8e02e591..83958e41e07 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2802,7 +2802,9 @@ extern asection _bfd_elf_large_com_section;
library, if any. A unique symbol can never be bound locally. */
#define SYMBOLIC_BIND(INFO, H) \
(!(H)->unique_global \
- && ((INFO)->symbolic || ((INFO)->dynamic && !(H)->dynamic)))
+ && ((INFO)->symbolic \
+ || (H)->start_stop \
+ || ((INFO)->dynamic && !(H)->dynamic)))
#ifdef __cplusplus
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f9886dc6457..d03160e2018 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -14261,17 +14261,46 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
const char *symbol, asection *sec)
{
struct bfd_link_hash_entry *h;
+ struct elf_link_hash_entry *eh;
h = bfd_generic_define_start_stop (info, symbol, sec);
- if (h != NULL)
+ eh = (struct elf_link_hash_entry *) h;
+ if (eh != NULL)
{
- struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
eh->start_stop = 1;
eh->u2.start_stop_section = sec;
+ }
+ else
+ {
+ /* Override definition from a shared object. */
+ h = bfd_link_hash_lookup (info->hash, symbol, FALSE, FALSE,
+ FALSE);
+ eh = (struct elf_link_hash_entry *) h;
+ if (eh != NULL && eh->def_dynamic)
+ {
+ eh->root.type = bfd_link_hash_defined;
+ eh->root.u.def.section = sec;
+ eh->root.u.def.value = 0;
+ eh->start_stop = 1;
+ eh->u2.start_stop_section = sec;
+ eh->def_dynamic = 0;
+ eh->def_regular = 1;
+ }
+ else
+ h = NULL;
+ }
+
+ if (h != NULL
+ && ELF_ST_VISIBILITY (eh->other) != STV_INTERNAL
+ && (!bfd_link_dll (info) || symbol[0] == '.'))
+ {
+ /* When building shared objects, don't mark __start and __stop
+ symbols as hidden to support dlsym. */
_bfd_elf_link_hash_hide_symbol (info, eh, TRUE);
if (ELF_ST_VISIBILITY (eh->other) != STV_INTERNAL)
eh->other = ((eh->other & ~ELF_ST_VISIBILITY (-1))
| STV_HIDDEN);
}
+
return h;
}