aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog21
-rw-r--r--bfd/elf-bfd.h16
-rw-r--r--bfd/elf32-i386.c12
-rw-r--r--bfd/elf64-x86-64.c28
-rw-r--r--bfd/elflink.c118
-rw-r--r--ld/ChangeLog46
-rw-r--r--ld/emultempl/elf32.em64
-rw-r--r--ld/ld.texinfo16
-rw-r--r--ld/ldlang.c115
-rw-r--r--ld/testsuite/ld-elf/pr21562a.d9
-rw-r--r--ld/testsuite/ld-elf/pr21562a.s8
-rw-r--r--ld/testsuite/ld-elf/pr21562a.t3
-rw-r--r--ld/testsuite/ld-elf/pr21562b.d9
-rw-r--r--ld/testsuite/ld-elf/pr21562b.s8
-rw-r--r--ld/testsuite/ld-elf/pr21562b.t5
-rw-r--r--ld/testsuite/ld-elf/pr21562c.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562c.t7
-rw-r--r--ld/testsuite/ld-elf/pr21562d.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562d.t5
-rw-r--r--ld/testsuite/ld-elf/pr21562e.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562f.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562g.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562h.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562i.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562j.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562k.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562l.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562m.d10
-rw-r--r--ld/testsuite/ld-elf/pr21562n.d10
-rw-r--r--ld/testsuite/ld-gc/gc.exp6
-rw-r--r--ld/testsuite/ld-gc/pr19161.d2
-rw-r--r--ld/testsuite/ld-gc/pr20022.d11
-rw-r--r--ld/testsuite/ld-gc/pr20022a.s8
-rw-r--r--ld/testsuite/ld-gc/pr20022b.s8
-rw-r--r--ld/testsuite/ld-gc/start.d2
-rw-r--r--ld/testsuite/ld-x86-64/lea1a.d2
-rw-r--r--ld/testsuite/ld-x86-64/lea1b.d2
-rw-r--r--ld/testsuite/ld-x86-64/lea1d.d2
-rw-r--r--ld/testsuite/ld-x86-64/lea1e.d2
39 files changed, 473 insertions, 182 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index acddb3a2ee..edff887d20 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,24 @@
+2017-06-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/20022
+ PR ld/21557
+ PR ld/21562
+ PR ld/21571
+ * elf-bfd.h (elf_link_hash_entry): Add start_stop. Change the
+ vtable field to a union.
+ (_bfd_elf_is_start_stop): Removed.
+ * elf32-i386.c (elf_i386_convert_load_reloc): Also check for
+ __start_SECNAME and __stop_SECNAME symbols.
+ * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
+ * elflink.c (_bfd_elf_is_start_stop): Removed.
+ (_bfd_elf_gc_mark_rsec): Check start_stop instead of calling
+ _bfd_elf_is_start_stop.
+ (elf_gc_propagate_vtable_entries_used): Skip __start_SECNAME and
+ __stop_SECNAME symbols. Updated.
+ (elf_gc_smash_unused_vtentry_relocs): Likewise.
+ (bfd_elf_gc_record_vtinherit): Likewise.
+ (bfd_elf_gc_record_vtentry): Likewise.
+
2017-06-13 Nick Clifton <nickc@redhat.com>
PR ld/21524
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 567b63a2de..fe15b93342 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -213,6 +213,9 @@ struct elf_link_hash_entry
/* Symbol is defined by a shared library with non-default visibility
in a read/write section. */
unsigned int protected_def : 1;
+ /* Symbol is __start_SECNAME or __stop_SECNAME to mark section
+ SECNAME. */
+ unsigned int start_stop : 1;
/* String table index in .dynstr if this is a dynamic symbol. */
unsigned long dynstr_index;
@@ -243,7 +246,15 @@ struct elf_link_hash_entry
struct bfd_elf_version_tree *vertree;
} verinfo;
- struct elf_link_virtual_table_entry *vtable;
+ union
+ {
+ /* For __start_SECNAME and __stop_SECNAME symbols, record the first
+ input section whose section name is SECNAME. */
+ asection *start_stop_section;
+
+ /* Vtable information. */
+ struct elf_link_virtual_table_entry *vtable;
+ } u2;
};
/* Will references to this symbol always reference the symbol
@@ -2445,9 +2456,6 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
extern bfd_boolean bfd_elf_gc_common_final_link
(bfd *, struct bfd_link_info *);
-extern asection *_bfd_elf_is_start_stop
- (const struct bfd_link_info *, struct elf_link_hash_entry *);
-
extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
(bfd_vma, void *);
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index f9142a98d5..6636551fb0 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1787,11 +1787,13 @@ convert_branch:
return TRUE;
/* def_regular is set by an assignment in a linker script in
- bfd_elf_record_link_assignment. */
- if ((h->def_regular
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && SYMBOL_REFERENCES_LOCAL (link_info, h))
+ bfd_elf_record_link_assignment. start_stop is set on
+ __start_SECNAME/__stop_SECNAME which mark section SECNAME. */
+ if (h->start_stop
+ || ((h->def_regular
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && SYMBOL_REFERENCES_LOCAL (link_info, h)))
{
convert_load:
if (opcode == 0x8b)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 53060197fe..ab6f06887e 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1920,21 +1920,25 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
}
/* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since
ld.so may use its link-time address. */
- else if ((h->def_regular
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && h != htab->elf.hdynamic
- && SYMBOL_REFERENCES_LOCAL (link_info, h))
+ else if (h->start_stop
+ || ((h->def_regular
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h != htab->elf.hdynamic
+ && SYMBOL_REFERENCES_LOCAL (link_info, h)))
{
/* bfd_link_hash_new or bfd_link_hash_undefined is
set by an assignment in a linker script in
- bfd_elf_record_link_assignment. */
- if (h->def_regular
- && (h->root.type == bfd_link_hash_new
- || h->root.type == bfd_link_hash_undefined
- || ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && h->root.u.def.section == bfd_und_section_ptr)))
+ bfd_elf_record_link_assignment. start_stop is set
+ on __start_SECNAME/__stop_SECNAME which mark section
+ SECNAME. */
+ if (h->start_stop
+ || (h->def_regular
+ && (h->root.type == bfd_link_hash_new
+ || h->root.type == bfd_link_hash_undefined
+ || ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section == bfd_und_section_ptr))))
{
/* Skip since R_X86_64_32/R_X86_64_32S may overflow. */
if (require_reloc_pc32)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f0ca33f155..9b0f544352 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12698,55 +12698,6 @@ elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
return NULL;
}
-/* For undefined __start_<name> and __stop_<name> symbols, return the
- first input section matching <name>. Return NULL otherwise. */
-
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- asection *s;
- const char *sec_name;
-
- if (h->root.type != bfd_link_hash_undefined
- && h->root.type != bfd_link_hash_undefweak)
- return NULL;
-
- s = h->root.u.undef.section;
- if (s != NULL)
- {
- if (s == (asection *) 0 - 1)
- return NULL;
- return s;
- }
-
- sec_name = NULL;
- if (strncmp (h->root.root.string, "__start_", 8) == 0)
- sec_name = h->root.root.string + 8;
- else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
- sec_name = h->root.root.string + 7;
-
- if (sec_name != NULL && *sec_name != '\0')
- {
- bfd *i;
-
- for (i = info->input_bfds; i != NULL; i = i->link.next)
- {
- s = bfd_get_section_by_name (i, sec_name);
- if (s != NULL)
- {
- h->root.u.undef.section = s;
- break;
- }
- }
- }
-
- if (s == NULL)
- h->root.u.undef.section = (asection *) 0 - 1;
-
- return s;
-}
-
/* COOKIE->rel describes a relocation against section SEC, which is
a section we've decided to keep. Return the section that contains
the relocation symbol, or NULL if no section contains it. */
@@ -12792,10 +12743,9 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
or __stop_XXX symbols. The linker will later define such
symbols for orphan input sections that have a name
representable as a C identifier. */
- asection *s = _bfd_elf_is_start_stop (info, h);
-
- if (s != NULL)
+ if (h->start_stop)
{
+ asection *s = h->u2.start_stop_section;
*start_stop = !s->gc_mark;
return s;
}
@@ -13136,26 +13086,28 @@ static bfd_boolean
elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
{
/* Those that are not vtables. */
- if (h->vtable == NULL || h->vtable->parent == NULL)
+ if (h->start_stop
+ || h->u2.vtable == NULL
+ || h->u2.vtable->parent == NULL)
return TRUE;
/* Those vtables that do not have parents, we cannot merge. */
- if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
+ if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
return TRUE;
/* If we've already been done, exit. */
- if (h->vtable->used && h->vtable->used[-1])
+ if (h->u2.vtable->used && h->u2.vtable->used[-1])
return TRUE;
/* Make sure the parent's table is up to date. */
- elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
+ elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
- if (h->vtable->used == NULL)
+ if (h->u2.vtable->used == NULL)
{
/* None of this table's entries were referenced. Re-use the
parent's table. */
- h->vtable->used = h->vtable->parent->vtable->used;
- h->vtable->size = h->vtable->parent->vtable->size;
+ h->u2.vtable->used = h->u2.vtable->parent->u2.vtable->used;
+ h->u2.vtable->size = h->u2.vtable->parent->u2.vtable->size;
}
else
{
@@ -13163,9 +13115,9 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
bfd_boolean *cu, *pu;
/* Or the parent's entries into ours. */
- cu = h->vtable->used;
+ cu = h->u2.vtable->used;
cu[-1] = TRUE;
- pu = h->vtable->parent->vtable->used;
+ pu = h->u2.vtable->parent->u2.vtable->used;
if (pu != NULL)
{
const struct elf_backend_data *bed;
@@ -13173,7 +13125,7 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
bed = get_elf_backend_data (h->root.u.def.section->owner);
log_file_align = bed->s->log_file_align;
- n = h->vtable->parent->vtable->size >> log_file_align;
+ n = h->u2.vtable->parent->u2.vtable->size >> log_file_align;
while (n--)
{
if (*pu)
@@ -13198,7 +13150,9 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
/* Take care of both those symbols that do not describe vtables as
well as those that are not loaded. */
- if (h->vtable == NULL || h->vtable->parent == NULL)
+ if (h->start_stop
+ || h->u2.vtable == NULL
+ || h->u2.vtable->parent == NULL)
return TRUE;
BFD_ASSERT (h->root.type == bfd_link_hash_defined
@@ -13220,11 +13174,11 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
if (rel->r_offset >= hstart && rel->r_offset < hend)
{
/* If the entry is in use, do nothing. */
- if (h->vtable->used
- && (rel->r_offset - hstart) < h->vtable->size)
+ if (h->u2.vtable->used
+ && (rel->r_offset - hstart) < h->u2.vtable->size)
{
bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
- if (h->vtable->used[entry])
+ if (h->u2.vtable->used[entry])
continue;
}
/* Otherwise, kill it. */
@@ -13448,11 +13402,11 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
return FALSE;
win:
- if (!child->vtable)
+ if (!child->u2.vtable)
{
- child->vtable = ((struct elf_link_virtual_table_entry *)
- bfd_zalloc (abfd, sizeof (*child->vtable)));
- if (!child->vtable)
+ child->u2.vtable = ((struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
+ if (!child->u2.vtable)
return FALSE;
}
if (!h)
@@ -13462,10 +13416,10 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
would be bad. It isn't worth paging in the local symbols to be
sure though; that case should simply be handled by the assembler. */
- child->vtable->parent = (struct elf_link_hash_entry *) -1;
+ child->u2.vtable->parent = (struct elf_link_hash_entry *) -1;
}
else
- child->vtable->parent = h;
+ child->u2.vtable->parent = h;
return TRUE;
}
@@ -13481,18 +13435,18 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
unsigned int log_file_align = bed->s->log_file_align;
- if (!h->vtable)
+ if (!h->u2.vtable)
{
- h->vtable = ((struct elf_link_virtual_table_entry *)
- bfd_zalloc (abfd, sizeof (*h->vtable)));
- if (!h->vtable)
+ h->u2.vtable = ((struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
+ if (!h->u2.vtable)
return FALSE;
}
- if (addend >= h->vtable->size)
+ if (addend >= h->u2.vtable->size)
{
size_t size, bytes, file_align;
- bfd_boolean *ptr = h->vtable->used;
+ bfd_boolean *ptr = h->u2.vtable->used;
/* While the symbol is undefined, we have to be prepared to handle
a zero size. */
@@ -13523,7 +13477,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
{
size_t oldbytes;
- oldbytes = (((h->vtable->size >> log_file_align) + 1)
+ oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
* sizeof (bfd_boolean));
memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
}
@@ -13535,11 +13489,11 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
return FALSE;
/* And arrange for that done flag to be at index -1. */
- h->vtable->used = ptr + 1;
- h->vtable->size = size;
+ h->u2.vtable->used = ptr + 1;
+ h->u2.vtable->size = size;
}
- h->vtable->used[addend >> log_file_align] = TRUE;
+ h->u2.vtable->used[addend >> log_file_align] = TRUE;
return TRUE;
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 309bb3a49f..dcfc602263 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,51 @@
2017-06-13 H.J. Lu <hongjiu.lu@intel.com>
+ PR ld/20022
+ PR ld/21557
+ PR ld/21562
+ PR ld/21571
+ * ld.texinfo: Update __start_SECNAME/__stop_SECNAME symbols.
+ * ldlang.c (lang_insert_orphan): Move handling of __start_SECNAME
+ and __stop_SECNAME symbols to ...
+ (lang_set_startof): Here. Also define __start_SECNAME and
+ __stop_SECNAME for -Ur.
+ * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Mark
+ referenced __start_SECNAME and __stop_SECNAME symbols as hidden
+ and set start_stop for garbage collection.
+ * testsuite/ld-elf/pr21562a.d: New file.
+ * testsuite/ld-elf/pr21562a.s: Likewise.
+ * testsuite/ld-elf/pr21562a.t: Likewise.
+ * testsuite/ld-elf/pr21562b.d: Likewise.
+ * testsuite/ld-elf/pr21562b.s: Likewise.
+ * testsuite/ld-elf/pr21562b.t: Likewise.
+ * testsuite/ld-elf/pr21562c.d: Likewise.
+ * testsuite/ld-elf/pr21562c.t: Likewise.
+ * testsuite/ld-elf/pr21562d.d: Likewise.
+ * testsuite/ld-elf/pr21562d.t: Likewise.
+ * testsuite/ld-elf/pr21562e.d: Likewise.
+ * testsuite/ld-elf/pr21562f.d: Likewise.
+ * testsuite/ld-elf/pr21562g.d: Likewise.
+ * testsuite/ld-elf/pr21562h.d: Likewise.
+ * testsuite/ld-elf/pr21562i.d: Likewise.
+ * testsuite/ld-elf/pr21562j.d: Likewise.
+ * testsuite/ld-elf/pr21562k.d: Likewise.
+ * testsuite/ld-elf/pr21562l.d: Likewise.
+ * testsuite/ld-elf/pr21562m.d: Likewise.
+ * testsuite/ld-elf/pr21562n.d: Likewise.
+ * testsuite/ld-gc/pr20022.d: Likewise.
+ * testsuite/ld-gc/pr20022a.s: Likewise.
+ * testsuite/ld-gc/pr20022b.s: Likewise.
+ * testsuite/ld-gc/gc.exp: Run PR ld/20022 tests.
+ * testsuite/ld-gc/pr19161.d: Also accept local __start_SECNAME
+ symbol.
+ * testsuite/ld-gc/start.d: Likewise.
+ * testsuite/ld-x86-64/lea1a.d: Updated.
+ * testsuite/ld-x86-64/lea1b.d: Updated.
+ * testsuite/ld-x86-64/lea1d.d: Updated.
+ * testsuite/ld-x86-64/lea1e.d: Likewise.
+
+2017-06-13 H.J. Lu <hongjiu.lu@intel.com>
+
* testsuite/ld-elf/sizeof.d: New file.
* testsuite/ld-elf/sizeof.s: Likewise.
* testsuite/ld-elf/startof.d: Likewise.
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)
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 790b52f025..44ad84b351 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4657,6 +4657,14 @@ SECTIONS @{
@end group
@end smallexample
+If an output section's name is the same as the input section's name
+and is representable as a C identifier, then the linker will
+automatically @pxref{PROVIDE} two symbols: __start_SECNAME and
+__stop_SECNAME, where SECNAME is the name of the section. These
+indicate the start address and end address of the output section
+respectively. Note: most section names are not representable as
+C identifiers because they contain a @samp{.} character.
+
@node Output Section Data
@subsection Output Section Data
@cindex data
@@ -5841,14 +5849,6 @@ The command line options @samp{--orphan-handling} and @samp{--unique}
(@pxref{Options,,Command Line Options}) can be used to control which
output sections an orphan is placed in.
-If an orphaned section's name is representable as a C identifier then
-the linker will automatically @pxref{PROVIDE} two symbols:
-__start_SECNAME and __stop_SECNAME, where SECNAME is the name of the
-section. These indicate the start address and end address of the
-orphaned section respectively. Note: most section names are not
-representable as C identifiers because they contain a @samp{.}
-character.
-
@node Location Counter
@subsection The Location Counter
@kindex .
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 252400bd51..f8e4f52879 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1829,8 +1829,6 @@ lang_insert_orphan (asection *s,
lang_statement_list_type *add_child)
{
lang_statement_list_type add;
- const char *ps;
- lang_assignment_statement_type *start_assign;
lang_output_section_statement_type *os;
lang_output_section_statement_type **os_tail;
@@ -1852,29 +1850,6 @@ lang_insert_orphan (asection *s,
os = lang_enter_output_section_statement (secname, address, normal_section,
NULL, NULL, NULL, constraint, 0);
- ps = NULL;
- start_assign = NULL;
- if (config.build_constructors && *os_tail == os)
- {
- /* If the name of the section is representable in C, then create
- symbols to mark the start and the end of the section. */
- for (ps = secname; *ps != '\0'; ps++)
- if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
- break;
- if (*ps == '\0')
- {
- char *symname;
-
- symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
- symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
- sprintf (symname + (symname[0] != 0), "__start_%s", secname);
- start_assign
- = lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
- FALSE));
- }
- }
-
if (add_child == NULL)
add_child = &os->children;
lang_add_section (add_child, s, NULL, os);
@@ -1894,27 +1869,6 @@ lang_insert_orphan (asection *s,
lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
NULL);
- if (start_assign != NULL)
- {
- char *symname;
- lang_assignment_statement_type *stop_assign;
- bfd_vma dot;
-
- symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
- symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
- sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
- stop_assign
- = lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
- FALSE));
- /* Evaluate the expression to define the symbol if referenced,
- before sizing dynamic sections. */
- dot = os->bfd_section->vma;
- exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
- dot += TO_ADDR (s->size);
- exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
- }
-
/* Restore the global list pointer. */
if (after != NULL)
pop_stat_ptr ();
@@ -5924,20 +5878,25 @@ section_for_dot (void)
return bfd_abs_section_ptr;
}
-/* Fix any .startof. or .sizeof. symbols. When the assemblers see the
- operator .startof. (section_name), it produces an undefined symbol
- .startof.section_name. Similarly, when it sees
+/* Fix any .startof., .sizeof., __start or __stop symbols. When the
+ assemblers see the operator .startof. (section_name), it produces
+ an undefined symbol .startof.section_name. Similarly, when it sees
.sizeof. (section_name), it produces an undefined symbol
- .sizeof.section_name. For all the output sections, we look for
- such symbols, and set them to the correct value. */
+ .sizeof.section_name. Also for ELF linker, __start_XXX or __stop_XXX
+ symbols should be resolved to the start and end of section XXX. For
+ all the output sections, we look for such symbols, and set them to
+ the correct value. */
static void
lang_set_startof (void)
{
asection *s;
+ char leading_char;
+ bfd_boolean is_elf = (bfd_get_flavour (link_info.output_bfd)
+ == bfd_target_elf_flavour);
+ bfd_boolean is_elocatable = bfd_link_relocatable (&link_info);
- if (bfd_link_relocatable (&link_info))
- return;
+ leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
{
@@ -5948,24 +5907,58 @@ lang_set_startof (void)
secname = bfd_get_section_name (link_info.output_bfd, s);
buf = (char *) xmalloc (10 + strlen (secname));
- sprintf (buf, ".startof.%s", secname);
- h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
- if (h != NULL && h->type == bfd_link_hash_undefined)
+ if (!is_elocatable)
+ {
+ sprintf (buf, ".startof.%s", secname);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+ TRUE);
+ if (h != NULL && h->type == bfd_link_hash_undefined)
+ {
+ h->type = bfd_link_hash_defined;
+ h->u.def.value = 0;
+ h->u.def.section = s;
+ }
+
+ sprintf (buf, ".sizeof.%s", secname);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+ TRUE);
+ if (h != NULL && h->type == bfd_link_hash_undefined)
+ {
+ h->type = bfd_link_hash_defined;
+ h->u.def.value = TO_ADDR (s->size);
+ h->u.def.section = bfd_abs_section_ptr;
+ }
+ }
+
+ buf[0] = leading_char;
+ sprintf (buf + (buf[0] != 0), "__start_%s", secname);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+ TRUE);
+ if (h != NULL
+ && (h->type == bfd_link_hash_undefined
+ || h->type == bfd_link_hash_undefweak))
{
h->type = bfd_link_hash_defined;
h->u.def.value = 0;
h->u.def.section = s;
+ if (is_elf)
+ ((struct elf_link_hash_entry *) h)->def_regular = 1;
}
- sprintf (buf, ".sizeof.%s", secname);
- h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
- if (h != NULL && h->type == bfd_link_hash_undefined)
+ buf[0] = leading_char;
+ sprintf (buf + (buf[0] != 0), "__stop_%s", secname);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+ TRUE);
+ if (h != NULL
+ && (h->type == bfd_link_hash_undefined
+ || h->type == bfd_link_hash_undefweak))
{
h->type = bfd_link_hash_defined;
h->u.def.value = TO_ADDR (s->size);
- h->u.def.section = bfd_abs_section_ptr;
+ h->u.def.section = s;
+ if (is_elf)
+ ((struct elf_link_hash_entry *) h)->def_regular = 1;
}
-
free (buf);
}
}
diff --git a/ld/testsuite/ld-elf/pr21562a.d b/ld/testsuite/ld-elf/pr21562a.d
new file mode 100644
index 0000000000..009dcfc05c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562a.s b/ld/testsuite/ld-elf/pr21562a.s
new file mode 100644
index 0000000000..ec36da4b8e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.s
@@ -0,0 +1,8 @@
+ .section scnfoo,"aw",%progbits
+ .zero 0x10
+
+ .globl bar
+ .data
+ .type bar, %object
+bar:
+ .dc.a __start_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562a.t b/ld/testsuite/ld-elf/pr21562a.t
new file mode 100644
index 0000000000..5e05ab3302
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.t
@@ -0,0 +1,3 @@
+SECTIONS {
+ scnfoo : { *(scnfoo) }
+}
diff --git a/ld/testsuite/ld-elf/pr21562b.d b/ld/testsuite/ld-elf/pr21562b.d
new file mode 100644
index 0000000000..a03dbad6a0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562b.s b/ld/testsuite/ld-elf/pr21562b.s
new file mode 100644
index 0000000000..1732ee24b2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.s
@@ -0,0 +1,8 @@
+ .section scnfoo,"aw",%progbits
+ .zero 0x10
+
+ .globl bar
+ .data
+ .type bar, %object
+bar:
+ .dc.a __stop_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562b.t b/ld/testsuite/ld-elf/pr21562b.t
new file mode 100644
index 0000000000..b30b521d40
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.t
@@ -0,0 +1,5 @@
+SECTIONS {
+ PROVIDE (__start_scnfoo = .);
+ scnfoo : { *(scnfoo) }
+ PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562c.d b/ld/testsuite/ld-elf/pr21562c.d
new file mode 100644
index 0000000000..9de035faac
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562c.t b/ld/testsuite/ld-elf/pr21562c.t
new file mode 100644
index 0000000000..f9cb901afb
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.t
@@ -0,0 +1,7 @@
+SECTIONS {
+ .foo : {
+ PROVIDE (__start_scnfoo = .);
+ *(scnfoo)
+ PROVIDE (__stop_scnfoo = .);
+ }
+}
diff --git a/ld/testsuite/ld-elf/pr21562d.d b/ld/testsuite/ld-elf/pr21562d.d
new file mode 100644
index 0000000000..e5344eff80
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562d.t b/ld/testsuite/ld-elf/pr21562d.t
new file mode 100644
index 0000000000..c0cea61f06
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.t
@@ -0,0 +1,5 @@
+SECTIONS {
+ PROVIDE (__start_scnfoo = .);
+ .foo : { *(scnfoo) }
+ PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562e.d b/ld/testsuite/ld-elf/pr21562e.d
new file mode 100644
index 0000000000..afaf7e56a6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562e.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562f.d b/ld/testsuite/ld-elf/pr21562f.d
new file mode 100644
index 0000000000..b9c324a47d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562f.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562g.d b/ld/testsuite/ld-elf/pr21562g.d
new file mode 100644
index 0000000000..a813594d27
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562g.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562h.d b/ld/testsuite/ld-elf/pr21562h.d
new file mode 100644
index 0000000000..6adabd7ba4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562h.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562i.d b/ld/testsuite/ld-elf/pr21562i.d
new file mode 100644
index 0000000000..49eb2ecb64
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562i.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562j.d b/ld/testsuite/ld-elf/pr21562j.d
new file mode 100644
index 0000000000..14bb03587d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562j.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562k.d b/ld/testsuite/ld-elf/pr21562k.d
new file mode 100644
index 0000000000..1bf1e93177
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562k.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562l.d b/ld/testsuite/ld-elf/pr21562l.d
new file mode 100644
index 0000000000..8297ec2b8e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562l.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562m.d b/ld/testsuite/ld-elf/pr21562m.d
new file mode 100644
index 0000000000..34f8df09aa
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562m.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562n.d b/ld/testsuite/ld-elf/pr21562n.d
new file mode 100644
index 0000000000..e4b1919c67
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562n.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+ \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp
index ba5c46b64f..364c73bf5d 100644
--- a/ld/testsuite/ld-gc/gc.exp
+++ b/ld/testsuite/ld-gc/gc.exp
@@ -119,6 +119,12 @@ if { [is_elf_format] && [check_shared_lib_support] } then {
run_dump_test "personality"
}
run_dump_test "pr18223"
+ if {![ld_assemble_flags $as $gasopt $srcdir/$subdir/pr20022a.s tmpdir/pr20022a.o]
+ || ![ld_link $ld tmpdir/pr20022.so "-shared --gc-sections tmpdir/pr20022a.o"] } then {
+ fail pr20022
+ } else {
+ run_dump_test "pr20022"
+ }
}
if { [is_remote host] || [which $CC] != 0 } {
diff --git a/ld/testsuite/ld-gc/pr19161.d b/ld/testsuite/ld-gc/pr19161.d
index c36e6638cd..baee8da3af 100644
--- a/ld/testsuite/ld-gc/pr19161.d
+++ b/ld/testsuite/ld-gc/pr19161.d
@@ -6,5 +6,5 @@
#xfail: mips64vr-*-* msp430-*-* powerpc*-*-eabivle rl78-*-* rx-*-* sh*-*-*
#...
-0*[1-9a-f]+[0-9a-f]*[ ](D)[ ]_*__start_my_section
+0*[1-9a-f]+[0-9a-f]*[ ](d|D)[ ]_*__start_my_section
#...
diff --git a/ld/testsuite/ld-gc/pr20022.d b/ld/testsuite/ld-gc/pr20022.d
new file mode 100644
index 0000000000..b51ec1903f
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022.d
@@ -0,0 +1,11 @@
+#source: pr20022b.s
+#ld: --gc-sections -e _start tmpdir/pr20022.so
+#readelf: -SsW
+#target: *-*-linux* *-*-gnu*
+#notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
+
+#...
+ \[[ 0-9]+\] _foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start__foo
+#pass
diff --git a/ld/testsuite/ld-gc/pr20022a.s b/ld/testsuite/ld-gc/pr20022a.s
new file mode 100644
index 0000000000..6bd346fe21
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022a.s
@@ -0,0 +1,8 @@
+ .data
+ .globl bar
+ .type bar,%object
+bar:
+ .dc.a __start__foo
+ .section _foo,"aw",%progbits
+foo:
+ .ascii "This is bar"
diff --git a/ld/testsuite/ld-gc/pr20022b.s b/ld/testsuite/ld-gc/pr20022b.s
new file mode 100644
index 0000000000..2306c59d76
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022b.s
@@ -0,0 +1,8 @@
+ .text
+ .globl _start
+_start:
+ .dc.a __start__foo
+ .dc.a bar
+ .section _foo,"aw",%progbits
+foo:
+ .ascii "This is foo"
diff --git a/ld/testsuite/ld-gc/start.d b/ld/testsuite/ld-gc/start.d
index 18e74c109c..9113b48204 100644
--- a/ld/testsuite/ld-gc/start.d
+++ b/ld/testsuite/ld-gc/start.d
@@ -5,5 +5,5 @@
#notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
#...
-[0-9a-f]+ D +__start__foo
+[0-9a-f]+ d +__start__foo
#...
diff --git a/ld/testsuite/ld-x86-64/lea1a.d b/ld/testsuite/ld-x86-64/lea1a.d
index 9b662cb839..28ea4b93fc 100644
--- a/ld/testsuite/ld-x86-64/lea1a.d
+++ b/ld/testsuite/ld-x86-64/lea1a.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <bar>
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__start_my_section>
-[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <__stop_my_section>
+[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <.*>
#pass
diff --git a/ld/testsuite/ld-x86-64/lea1b.d b/ld/testsuite/ld-x86-64/lea1b.d
index 9108149b3a..c7873cd97b 100644
--- a/ld/testsuite/ld-x86-64/lea1b.d
+++ b/ld/testsuite/ld-x86-64/lea1b.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <bar>
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__start_my_section>
-[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <__stop_my_section>
+[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <.*>
#pass
diff --git a/ld/testsuite/ld-x86-64/lea1d.d b/ld/testsuite/ld-x86-64/lea1d.d
index 4d708d22c3..70fc603894 100644
--- a/ld/testsuite/ld-x86-64/lea1d.d
+++ b/ld/testsuite/ld-x86-64/lea1d.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <bar>
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__start_my_section>
-[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <__stop_my_section>
+[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <.*>
#pass
diff --git a/ld/testsuite/ld-x86-64/lea1e.d b/ld/testsuite/ld-x86-64/lea1e.d
index da60137918..123fcd243c 100644
--- a/ld/testsuite/ld-x86-64/lea1e.d
+++ b/ld/testsuite/ld-x86-64/lea1e.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <bar>
[ ]*[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__start_my_section>
-[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <__stop_my_section>
+[ ]*[a-f0-9]+: 4c 8d 1d ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%rip\),%r11 # [a-f0-9]+ <.*>
#pass