aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl/elf32.em
diff options
context:
space:
mode:
Diffstat (limited to 'ld/emultempl/elf32.em')
-rw-r--r--ld/emultempl/elf32.em64
1 files changed, 60 insertions, 4 deletions
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 0260b7ac44..9468f7d29f 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1216,6 +1216,9 @@ gld${EMULATION_NAME}_after_open (void)
{
struct bfd_link_needed_list *needed, *l;
struct elf_link_hash_table *htab;
+ asection *s;
+ bfd *abfd;
+ char leading_char;
after_open_default ();
@@ -1239,8 +1242,6 @@ gld${EMULATION_NAME}_after_open (void)
if (emit_note_gnu_build_id != NULL)
{
- bfd *abfd;
-
/* Find an ELF input. */
for (abfd = link_info.input_bfds;
abfd != (bfd *) NULL; abfd = abfd->link.next)
@@ -1276,11 +1277,66 @@ gld${EMULATION_NAME}_after_open (void)
return;
}
+ leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+ /* Check for input sections whose names match references to
+ __start_SECNAME or __stop_SECNAME symbols. Mark the matched
+ symbols as hidden and set start_stop for garbage collection. */
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ for (s = abfd->sections; s; s = s->next)
+ {
+ const char *name = bfd_get_section_name (abfd, s);
+ const char *ps;
+
+ for (ps = name; *ps != '\0'; ps++)
+ if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
+ break;
+ if (*ps == '\0')
+ {
+ struct elf_link_hash_entry *h;
+ char *symbol = (char *) xmalloc (ps - name
+ + sizeof "__start_" + 1);
+
+ symbol[0] = leading_char;
+ sprintf (symbol + (leading_char != 0), "__start_%s", name);
+ h = elf_link_hash_lookup (elf_hash_table (&link_info),
+ symbol, FALSE, FALSE, TRUE);
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->u2.start_stop_section == NULL)
+ {
+ h->start_stop = 1;
+ h->u2.start_stop_section = s;
+ _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+ h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+ | STV_HIDDEN);
+ }
+
+ symbol[0] = leading_char;
+ sprintf (symbol + (leading_char != 0), "__stop_%s", name);
+ h = elf_link_hash_lookup (elf_hash_table (&link_info),
+ symbol, FALSE, FALSE, TRUE);
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->u2.start_stop_section == NULL)
+ {
+ h->start_stop = 1;
+ h->u2.start_stop_section = s;
+ _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+ h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+ | STV_HIDDEN);
+ }
+ }
+ }
+
if (!link_info.traditional_format)
{
- bfd *abfd, *elfbfd = NULL;
+ bfd *elfbfd = NULL;
bfd_boolean warn_eh_frame = FALSE;
- asection *s;
int seen_type = 0;
for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)