diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2021-12-01 04:55:24 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2021-12-02 03:55:10 -0800 |
commit | 794f2bba0f338d467bbf9c55b5aba415ecd5e138 (patch) | |
tree | b36f058ec24e9f353d9dae0589fcd3d4f8a83dee /bfd | |
parent | c808def421f383a226198751d93239ded2b0d21d (diff) | |
download | gdb-794f2bba0f338d467bbf9c55b5aba415ecd5e138.zip gdb-794f2bba0f338d467bbf9c55b5aba415ecd5e138.tar.gz gdb-794f2bba0f338d467bbf9c55b5aba415ecd5e138.tar.bz2 |
x86: Skip __[start|stop]_SECNAME for --gc-sections -z start-stop-gc
Don't convert memory load to immediate load on __start_SECNAME and
__stop_SECNAME for --gc-sections -z start-stop-gc if all SECNAME
sections been garbage collected.
bfd/
PR ld/27491
* elf32-i386.c (elf_i386_convert_load_reloc): Skip __start_SECNAME
and __stop_SECNAME for --gc-sections -z start-stop-gc if the input
section been garbage collected.
* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
* elfxx-x86.h (elf_x86_start_stop_gc_p): New function.
ld/
PR ld/27491
* testsuite/ld-i386/i386.exp: Run PR ld/27491 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr27491-1.s: New file.
* testsuite/ld-i386/pr27491-1a.d: Likewise.
* testsuite/ld-i386/pr27491-1b.d: Likewise.
* testsuite/ld-i386/pr27491-1c.d: Likewise.
* testsuite/ld-i386/pr27491-2.d: Likewise.
* testsuite/ld-i386/pr27491-2.s: Likewise.
* testsuite/ld-i386/pr27491-3.d: Likewise.
* testsuite/ld-i386/pr27491-3.s: Likewise.
* testsuite/ld-i386/pr27491-4.d: Likewise.
* testsuite/ld-i386/pr27491-4a.s: Likewise.
* testsuite/ld-i386/pr27491-4b.s: Likewise.
* testsuite/ld-x86-64/pr27491-1.s: Likewise.
* testsuite/ld-x86-64/pr27491-1a.d: Likewise.
* testsuite/ld-x86-64/pr27491-1b.d: Likewise.
* testsuite/ld-x86-64/pr27491-1c.d: Likewise.
* testsuite/ld-x86-64/pr27491-2.d: Likewise.
* testsuite/ld-x86-64/pr27491-2.s: Likewise.
* testsuite/ld-x86-64/pr27491-3.d: Likewise.
* testsuite/ld-x86-64/pr27491-3.s: Likewise.
* testsuite/ld-x86-64/pr27491-4.d: Likewise.
* testsuite/ld-x86-64/pr27491-4a.s: Likewise.
* testsuite/ld-x86-64/pr27491-4b.s: Likewise.
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; +} |