diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elf32-i386.c | 5 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 5 | ||||
-rw-r--r-- | bfd/elfxx-x86.h | 33 |
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; +} |