aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elf32-i386.c5
-rw-r--r--bfd/elf64-x86-64.c5
-rw-r--r--bfd/elfxx-x86.h33
3 files changed, 43 insertions, 0 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 0d7f290..db6d1ac 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1393,6 +1393,11 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|| h->root.type == bfd_link_hash_defweak)
&& local_ref))
{
+ /* Skip __start_SECNAME/__stop_SECNAME when --gc-sections
+ -z start-stop-gc are used. */
+ if (elf_x86_start_stop_gc_p (link_info, h))
+ return true;
+
convert_load:
if (opcode == 0x8b)
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 25e2bb1..bb6df79 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1643,6 +1643,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section == bfd_und_section_ptr))))
{
+ /* Skip __start_SECNAME/__stop_SECNAME when --gc-sections
+ -z start-stop-gc are used. */
+ if (elf_x86_start_stop_gc_p (link_info, h))
+ return true;
+
/* Skip since R_X86_64_32/R_X86_64_32S may overflow. */
if (no_overflow)
return true;
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 8251f64..aab641a 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -731,3 +731,36 @@ extern void _bfd_x86_elf_link_report_relative_reloc
_bfd_x86_elf_merge_gnu_properties
#define elf_backend_fixup_gnu_properties \
_bfd_x86_elf_link_fixup_gnu_properties
+
+/* Return true if H is a __start_SECNAME/__stop_SECNAME symbol for the
+ SECNAME section which has been garbage collected by --gc-sections
+ -z start-stop-gc. */
+
+static inline bool
+elf_x86_start_stop_gc_p (struct bfd_link_info *link_info,
+ struct elf_link_hash_entry *h)
+{
+ if (h->start_stop
+ && link_info->gc_sections
+ && link_info->start_stop_gc)
+ {
+ asection *s = h->root.u.def.section;
+
+ do
+ {
+ /* Return false if any SECNAME section is kept. */
+ if (s->gc_mark)
+ return false;
+ s = bfd_get_next_section_by_name (s->owner, s);
+ }
+ while (s != NULL);
+
+ /* Return true only if all SECNAME sections have been garbage
+ collected. */
+ return true;
+ }
+
+ /* Return false if H isn't a __start_SECNAME/__stop_SECNAME symbol or
+ --gc-sections or -z start-stop-gc isn't used. */
+ return false;
+}