aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-03-01 11:40:51 +1030
committerAlan Modra <amodra@gmail.com>2021-03-01 14:26:39 +1030
commit7824c1d22fcab8a68162634d4293f4a6666ca43e (patch)
treeba713f8ed77d32992d3588a8cf837ec8f229482e /ld/ldlang.c
parent6a1224ec762f7dd59d7abd2e5dc3be26bb157cd1 (diff)
downloadgdb-7824c1d22fcab8a68162634d4293f4a6666ca43e.zip
gdb-7824c1d22fcab8a68162634d4293f4a6666ca43e.tar.gz
gdb-7824c1d22fcab8a68162634d4293f4a6666ca43e.tar.bz2
Weak references to __start_/__stop_ symbols
If a weak reference to a __start_foo or __stop_foo symbol ends up having no definition due to all the foo sections being removed for some reason, undef_start_stop currently makes the symbol strong undefined. That risks a linker undefined symbol error. Fix that by making the symbol undefweak and also undo some dynamic symbol state. Note that saving the state of the symbol type at the time lang_init_start_stop runs is not sufficient. The linker may have merged in a shared library reference by that point and made what was an undefweak in regular objects, a strong undefined. So it is necessary to look at the ELF symbol flags to decide whether an undefweak is the proper resolution. Something probably should be done for COFF/PE too, but I'm unsure how to do go about that. * ldlang.c (undef_start_stop): For ELF make undefined start/stop symbols undefweak if that was how they were referenced. Undo dynamic state too.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5ffc844..a77e8fa 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -6808,6 +6808,19 @@ undef_start_stop (struct bfd_link_hash_entry *h)
}
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
+ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
+ {
+ const struct elf_backend_data *bed;
+ struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
+ unsigned int was_forced = eh->forced_local;
+
+ bed = get_elf_backend_data (link_info.output_bfd);
+ (*bed->elf_backend_hide_symbol) (&link_info, eh, TRUE);
+ if (!eh->ref_regular_nonweak)
+ h->type = bfd_link_hash_undefweak;
+ eh->def_regular = 0;
+ eh->forced_local = was_forced;
+ }
}
}