diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index f368986dd05..c7ef031979e 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2628,6 +2628,8 @@ extern bool _bfd_elf_maybe_strip_eh_frame_hdr extern bool _bfd_elf_sframe_present (struct bfd_link_info *) ATTRIBUTE_HIDDEN; +extern bool _bfd_elf_sframe_present_input_bfds + (struct bfd_link_info *) ATTRIBUTE_HIDDEN; extern bool _bfd_elf_parse_sframe (bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *) ATTRIBUTE_HIDDEN; diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c index 33e4df5b1c7..77d9d33d602 100644 --- a/bfd/elf-sframe.c +++ b/bfd/elf-sframe.c @@ -171,6 +171,24 @@ sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, return value; } +/* Return true if any of the input BFDs contains at least one .sframe + section. */ + +bool +_bfd_elf_sframe_present_input_bfds (struct bfd_link_info *info) +{ + /* Find if any input file has an .sframe section. */ + for (bfd *pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && bfd_count_sections (pbfd) != 0) + { + asection *sec = bfd_get_section_by_name (pbfd, ".sframe"); + if (sec != NULL) + return true; + } + return false; +} + /* Return true if there is at least one non-empty .sframe section in input files. Can only be called after ld has mapped input to output sections, and before sections are stripped. */ diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 8ad10ce6bd1..b6a903db42a 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -4309,7 +4309,15 @@ elf_s390_create_dynamic_sections (bfd *dynobj, } /* Create .sframe section for .plt section. */ - if (!info->discard_sframe) + bool gen_plt_sframe_p = !info->discard_sframe + && _bfd_elf_sframe_present_input_bfds (info); + + /* Do not make SFrame sections for dynobj unconditionally. If there + are no SFrame sections for any input files, skip creating the linker + created SFrame sections too. Since SFrame sections are marked KEEP, + prohibiting these linker-created SFrame sections when unnecessary, + helps avoid creating of empty SFrame sections in the output. */ + if (gen_plt_sframe_p) { flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 901b858fb34..b450aed4038 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -4827,7 +4827,16 @@ _bfd_x86_elf_link_setup_gnu_properties } /* .sframe sections are emitted for AMD64 ABI only. */ - if (ABI_64_P (info->output_bfd) && !info->discard_sframe) + bool gen_plt_sframe_p = ABI_64_P (info->output_bfd) + && !info->discard_sframe + && _bfd_elf_sframe_present_input_bfds (info); + + /* Do not make SFrame sections for dynobj unconditionally. If there + are no SFrame sections for any input files, skip creating the linker + created SFrame sections too. Since SFrame sections are marked KEEP, + prohibiting these linker-created SFrame sections, when unnecessary, + helps avoid creation of empty SFrame sections in the output. */ + if (gen_plt_sframe_p) { flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY diff --git a/ld/testsuite/ld-s390/no-sframe.ld b/ld/testsuite/ld-s390/no-sframe.ld new file mode 100644 index 00000000000..13224d84573 --- /dev/null +++ b/ld/testsuite/ld-s390/no-sframe.ld @@ -0,0 +1,6 @@ +ENTRY(_start) +SECTIONS +{ + . = SIZEOF_HEADERS; + .text : { *(.text) } +} diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp index 0fdfb39c5aa..80536e2e39a 100644 --- a/ld/testsuite/ld-s390/s390.exp +++ b/ld/testsuite/ld-s390/s390.exp @@ -192,6 +192,9 @@ if [istarget "s390x-*-*"] { if { ![skip_sframe_tests] } { run_dump_test "sframe-simple-1" run_dump_test "sframe-plt-1" + # Test --discard-sframe run_dump_test "sframe-command-line-1" + # Test --no-ld-generated-unwind-info + run_dump_test "sframe-command-line-2" } } diff --git a/ld/testsuite/ld-s390/sframe-command-line-2.d b/ld/testsuite/ld-s390/sframe-command-line-2.d new file mode 100644 index 00000000000..941e845139d --- /dev/null +++ b/ld/testsuite/ld-s390/sframe-command-line-2.d @@ -0,0 +1,10 @@ +#as: +#source: sframe-foo.s +#ld: --no-ld-generated-unwind-info -T no-sframe.ld -e foo +#objdump: -hw +#name: No interaction between --no-ld-generated-unwind-info and SFrame + +#failif +#... + [0-9] .sframe .* +#... diff --git a/ld/testsuite/ld-sframe/no-ld-generated-sframe.d b/ld/testsuite/ld-sframe/no-ld-generated-sframe.d new file mode 100644 index 00000000000..bc9396e6ff4 --- /dev/null +++ b/ld/testsuite/ld-sframe/no-ld-generated-sframe.d @@ -0,0 +1,10 @@ +#as: +#source: test.s +#ld: -T no-sframe.ld +#objdump: -hw +#name: No SFrame section in output with no --gsframe + +#failif +#... + [0-9] .sframe .* +#... diff --git a/ld/testsuite/ld-sframe/no-sframe.ld b/ld/testsuite/ld-sframe/no-sframe.ld new file mode 100644 index 00000000000..13224d84573 --- /dev/null +++ b/ld/testsuite/ld-sframe/no-sframe.ld @@ -0,0 +1,6 @@ +ENTRY(_start) +SECTIONS +{ + . = SIZEOF_HEADERS; + .text : { *(.text) } +} diff --git a/ld/testsuite/ld-sframe/test.s b/ld/testsuite/ld-sframe/test.s new file mode 100644 index 00000000000..31e8ea8e7b6 --- /dev/null +++ b/ld/testsuite/ld-sframe/test.s @@ -0,0 +1,11 @@ + .text + .globl foo + .type foo, @function +foo: + .cfi_startproc + .cfi_def_cfa_offset 16 + .cfi_endproc + + .globl _start +_start: + .long foo diff --git a/ld/testsuite/ld-x86-64/no-sframe.ld b/ld/testsuite/ld-x86-64/no-sframe.ld new file mode 100644 index 00000000000..13224d84573 --- /dev/null +++ b/ld/testsuite/ld-x86-64/no-sframe.ld @@ -0,0 +1,6 @@ +ENTRY(_start) +SECTIONS +{ + . = SIZEOF_HEADERS; + .text : { *(.text) } +} diff --git a/ld/testsuite/ld-x86-64/sframe-command-line-2.d b/ld/testsuite/ld-x86-64/sframe-command-line-2.d new file mode 100644 index 00000000000..941e845139d --- /dev/null +++ b/ld/testsuite/ld-x86-64/sframe-command-line-2.d @@ -0,0 +1,10 @@ +#as: +#source: sframe-foo.s +#ld: --no-ld-generated-unwind-info -T no-sframe.ld -e foo +#objdump: -hw +#name: No interaction between --no-ld-generated-unwind-info and SFrame + +#failif +#... + [0-9] .sframe .* +#... diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 8bed9b566bc..5608c42a0db 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -588,7 +588,10 @@ run_dump_test "tls-le-pic-3-x32" if { ![skip_sframe_tests] } { run_dump_test "sframe-simple-1" run_dump_test "sframe-link-1" + # Test --discard-sframe run_dump_test "sframe-command-line-1" + # Test --no-ld-generated-unwind-info + run_dump_test "sframe-command-line-2" run_dump_test "sframe-reloc-1" run_dump_test "sframe-plt-1" run_dump_test "sframe-ibt-plt-1"