diff options
author | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-11-18 11:51:13 +0000 |
---|---|---|
committer | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-11-18 11:51:13 +0000 |
commit | 99fabbc9739a87ba3433e66792e93b773896790e (patch) | |
tree | 6a52b12cc648532f3b38fd102cec221a207188ba /ld | |
parent | 40d9d2fd796a184f04a83ca4442fd78034b5e00b (diff) | |
download | fsf-binutils-gdb-99fabbc9739a87ba3433e66792e93b773896790e.zip fsf-binutils-gdb-99fabbc9739a87ba3433e66792e93b773896790e.tar.gz fsf-binutils-gdb-99fabbc9739a87ba3433e66792e93b773896790e.tar.bz2 |
Support SHF_GNU_RETAIN ELF section flag
The SHF_GNU_RETAIN section flag is an extension to the GNU ELF OSABI.
It is defined as follows:
=========================================================
Section Attribute Flags
+-------------------------------------+
| Name | Value |
+-------------------------------------+
| SHF_GNU_RETAIN | 0x200000 (1 << 21) |
+-------------------------------------+
SHF_GNU_RETAIN
The link editor should not garbage collect the section.
=========================================================
The .section directive accepts the "R" flag, which indicates
SHF_GNU_RETAIN should be applied to the section.
There is not a direct mapping of SHF_GNU_RETAIN to the BFD
section flag SEC_KEEP. Keeping these flags distinct allows
SHF_GNU_RETAIN sections to be explicitly removed by placing them in
/DISCARD/.
bfd/ChangeLog:
* elf-bfd.h (enum elf_gnu_osabi): Add elf_gnu_osabi_retain.
(struct elf_obj_tdata): Increase has_gnu_osabi to 4 bits.
* elf.c (_bfd_elf_make_section_from_shdr): Set elf_gnu_osabi_retain
for SHF_GNU_RETAIN.
(_bfd_elf_final_write_processing): Report if SHF_GNU_RETAIN is
not supported by the OSABI.
Adjust error messages.
* elflink.c (elf_link_input_bfd): Copy enabled has_gnu_osabi bits from
input BFD to output BFD.
(bfd_elf_gc_sections): gc_mark the section if SHF_GNU_RETAIN is set.
binutils/ChangeLog:
* NEWS: Announce SHF_GNU_RETAIN support.
* readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN.
Recognize SHF_GNU_RETAIN and SHF_GNU_MBIND only for supported OSABIs.
* testsuite/binutils-all/readelf.exp: Run new tests.
Don't run run_dump_test when there isn't an assembler available.
* testsuite/lib/binutils-common.exp (supports_gnu_osabi): Adjust
comment.
* testsuite/binutils-all/readelf-maskos-1a.d: New test.
* testsuite/binutils-all/readelf-maskos-1b.d: New test.
* testsuite/binutils-all/readelf-maskos.s: New test.
* testsuite/binutils-all/retain1.s: New test.
* testsuite/binutils-all/retain1a.d: New test.
* testsuite/binutils-all/retain1b.d: New test.
gas/ChangeLog:
* NEWS: Announce SHF_GNU_RETAIN support.
* config/obj-elf.c (obj_elf_change_section): Merge SHF_GNU_RETAIN bit
between section declarations.
(obj_elf_parse_section_letters): Handle 'R' flag.
Handle numeric flag values within the SHF_MASKOS range.
(obj_elf_section): Validate SHF_GNU_RETAIN usage.
* doc/as.texi: Document 'R' flag to .section directive.
* testsuite/gas/elf/elf.exp: Run new tests.
* testsuite/gas/elf/section10.d: Unset SHF_GNU_RETAIN bit.
* testsuite/gas/elf/section10.s: Likewise.
* testsuite/gas/elf/section22.d: New test.
* testsuite/gas/elf/section22.s: New test.
* testsuite/gas/elf/section23.s: New test.
* testsuite/gas/elf/section23a.d: New test.
* testsuite/gas/elf/section23b.d: New test.
* testsuite/gas/elf/section23b.err: New test.
* testsuite/gas/elf/section24.l: New test.
* testsuite/gas/elf/section24.s: New test.
* testsuite/gas/elf/section24a.d: New test.
* testsuite/gas/elf/section24b.d: New test.
include/ChangeLog:
* elf/common.h (SHF_GNU_RETAIN): Define.
ld/ChangeLog:
* NEWS: Announce support for SHF_GNU_RETAIN.
* ld.texi (garbage collection): Document SHF_GNU_RETAIN.
(Output Section Discarding): Likewise.
* testsuite/ld-elf/elf.exp: Run new tests.
* testsuite/ld-elf/retain1.s: New test.
* testsuite/ld-elf/retain1a.d: New test.
* testsuite/ld-elf/retain1b.d: New test.
* testsuite/ld-elf/retain2.d: New test.
* testsuite/ld-elf/retain2.ld: New test.
* testsuite/ld-elf/retain2.map: New test.
* testsuite/ld-elf/retain3.d: New test.
* testsuite/ld-elf/retain3.s: New test.
* testsuite/ld-elf/retain4.d: New test.
* testsuite/ld-elf/retain4.s: New test.
* testsuite/ld-elf/retain5.d: New test.
* testsuite/ld-elf/retain5.map: New test.
* testsuite/ld-elf/retain5lib.s: New test.
* testsuite/ld-elf/retain5main.s: New test.
* testsuite/ld-elf/retain6a.d: New test.
* testsuite/ld-elf/retain6b.d: New test.
* testsuite/ld-elf/retain6lib.s: New test.
* testsuite/ld-elf/retain6main.s: New test.
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 25 | ||||
-rw-r--r-- | ld/NEWS | 4 | ||||
-rw-r--r-- | ld/ld.texi | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/elf.exp | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain1.s | 104 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain1a.d | 27 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain1b.d | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain2.d | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain2.ld | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain2.map | 32 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain3.d | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain3.s | 19 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain4.d | 9 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain4.s | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain5.d | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain5.map | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain5lib.s | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain5main.s | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain6a.d | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain6b.d | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain6lib.s | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/retain6main.s | 13 |
22 files changed, 363 insertions, 0 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 7141182..0e2ddee 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,28 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + + * NEWS: Announce support for SHF_GNU_RETAIN. + * ld.texi (garbage collection): Document SHF_GNU_RETAIN. + (Output Section Discarding): Likewise. + * testsuite/ld-elf/elf.exp: Run new tests. + * testsuite/ld-elf/retain1.s: New test. + * testsuite/ld-elf/retain1a.d: New test. + * testsuite/ld-elf/retain1b.d: New test. + * testsuite/ld-elf/retain2.d: New test. + * testsuite/ld-elf/retain2.ld: New test. + * testsuite/ld-elf/retain2.map: New test. + * testsuite/ld-elf/retain3.d: New test. + * testsuite/ld-elf/retain3.s: New test. + * testsuite/ld-elf/retain4.d: New test. + * testsuite/ld-elf/retain4.s: New test. + * testsuite/ld-elf/retain5.d: New test. + * testsuite/ld-elf/retain5.map: New test. + * testsuite/ld-elf/retain5lib.s: New test. + * testsuite/ld-elf/retain5main.s: New test. + * testsuite/ld-elf/retain6a.d: New test. + * testsuite/ld-elf/retain6b.d: New test. + * testsuite/ld-elf/retain6lib.s: New test. + * testsuite/ld-elf/retain6main.s: New test. + 2020-11-17 Alan Modra <amodra@gmail.com> PR 26882 @@ -23,6 +23,10 @@ unless you are working on a project that has its own analogue of symbol tables that are not reflected in the ELF symtabs. +* Add support for the SHF_GNU_RETAIN ELF section flag. + This flag specifies that the section should not be garbage collected by the + linker. + Changes in 2.35: * X86 NaCl target support is removed. @@ -1807,6 +1807,9 @@ specified either by one of the options @samp{--entry}, @samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY} command in the linker script. +As a GNU extension, ELF input sections marked with the +@code{SHF_GNU_RETAIN} flag will not be garbage collected. + @kindex --print-gc-sections @kindex --no-print-gc-sections @cindex garbage collection @@ -5291,6 +5294,10 @@ The special output section name @samp{/DISCARD/} may be used to discard input sections. Any input sections which are assigned to an output section named @samp{/DISCARD/} are not included in the output file. +This can be used to discard input sections marked with the ELF flag +@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker +garbage collection. + Note, sections that match the @samp{/DISCARD/} output section will be discarded even if they are in an ELF section group which has other members which are not being discarded. This is deliberate. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index f2ff039..6e61c7f 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -119,6 +119,16 @@ if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } { set ASFLAGS "$ASFLAGS -mx86-used-note=no" } +# Build libraries required for SHF_GNU_RETAIN tests. +if { [check_gc_sections_available] && [supports_gnu_osabi] } { + run_ld_link_tests [list \ + [list "Build libretain5.a" "" "" "" \ + {retain5lib.s} {} "libretain5.a"] \ + [list "Build libretain6.a" "" "" "" \ + {retain6lib.s} {} "libretain6.a"] \ + ] +} + set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]] foreach t $test_list { # We need to strip the ".d", but can leave the dirname. diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s new file mode 100644 index 0000000..f7716fa --- /dev/null +++ b/ld/testsuite/ld-elf/retain1.s @@ -0,0 +1,104 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, %object +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, %object +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, %object +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, %object +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, %object +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, %object +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, %function +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"awR" + .type retain0, %object +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"awR" + .type retain1, %object +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"awR" + .type retain2, %object +retain2: + .word 1 + + .section .bss.sretain0,"awR" + .type sretain0, %object +sretain0: + .zero 2 + + .section .bss.sretain1,"awR" + .type sretain1, %object +sretain1: + .zero 2 + + .section .data.sretain2,"aRw" + .type sretain2, %object +sretain2: + .word 1 + + .section .text.fnretain1,"Rax" + .global fnretain1 + .type fnretain1, %function +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, %function +fndiscard2: + .word 0 + + .section .bss.lsretain0,"awR" + .type lsretain0.2, %object +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aRw" + .type lsretain1.1, %object +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aRw" + .type lsretain2.0, %object +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain1a.d b/ld/testsuite/ld-elf/retain1a.d new file mode 100644 index 0000000..29adb5d --- /dev/null +++ b/ld/testsuite/ld-elf/retain1a.d @@ -0,0 +1,27 @@ +#name: SHF_GNU_RETAIN 1a +#source: retain1.s +#ld: -e _start --gc-sections +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#DUMPPROG: nm + +#... +[0-9a-f]+ . fnretain1 +#... +[0-9a-f]+ . lsretain0.2 +#... +[0-9a-f]+ . lsretain1.1 +#... +[0-9a-f]+ . lsretain2.0 +#... +[0-9a-f]+ . retain0 +#... +[0-9a-f]+ . retain1 +#... +[0-9a-f]+ . retain2 +#... +[0-9a-f]+ . sretain0 +#... +[0-9a-f]+ . sretain1 +#... +[0-9a-f]+ . sretain2 +#pass diff --git a/ld/testsuite/ld-elf/retain1b.d b/ld/testsuite/ld-elf/retain1b.d new file mode 100644 index 0000000..b1cafc9 --- /dev/null +++ b/ld/testsuite/ld-elf/retain1b.d @@ -0,0 +1,10 @@ +#name: SHF_GNU_RETAIN 1b +#source: retain1.s +#ld: -e _start --gc-sections +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#nm: -n + +#failif +#... +[0-9a-f]+ . .*discard.* +#... diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d new file mode 100644 index 0000000..1a63f51 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.d @@ -0,0 +1,5 @@ +#name: SHF_GNU_RETAIN 2 (remove SHF_GNU_RETAIN sections by placing in /DISCARD/) +#source: retain1.s +#ld: -e _start -Map=retain2.map --gc-sections --script=retain2.ld +#map: retain2.map +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] diff --git a/ld/testsuite/ld-elf/retain2.ld b/ld/testsuite/ld-elf/retain2.ld new file mode 100644 index 0000000..8ef9827 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + /DISCARD/ : + { + *(.text.fnretain1) + } +} diff --git a/ld/testsuite/ld-elf/retain2.map b/ld/testsuite/ld-elf/retain2.map new file mode 100644 index 0000000..4028aa1 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.map @@ -0,0 +1,32 @@ +# Test that .text.fnretain1, which has the SHF_GNU_RETAIN flag, can still be +# explicitly discarded from the output file. + +#... +Discarded input sections + + .text.* +#... + .data.* +#... + .bss.* +#... + .bss.discard0.* +#... + .bss.discard1.* +#... + .data.discard2.* +#... + .bss.sdiscard0.* +#... + .bss.sdiscard1.* +#... + .data.sdiscard2.* +#... + .text.fndiscard0.* +#... + .text.fnretain1.* +#... + .text.fndiscard2.* +#... +Memory Configuration +#pass diff --git a/ld/testsuite/ld-elf/retain3.d b/ld/testsuite/ld-elf/retain3.d new file mode 100644 index 0000000..3c81a88 --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.d @@ -0,0 +1,11 @@ +#name: SHF_GNU_RETAIN 3 (keep sections referenced by retained sections) +#source: retain3.s +#ld: -e _start --gc-sections +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#DUMPPROG: nm + +#... +[0-9a-f]+ . bar +#... +[0-9a-f]+ . foo +#pass diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s new file mode 100644 index 0000000..ce315cb --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.s @@ -0,0 +1,19 @@ +/* The retention of bar should also prevent foo from being gc'ed, since bar + references foo. */ + .section .text.foo,"ax" + .global foo + .type foo, %function +foo: + .word 0 + + .section .text.bar,"axR" + .global bar + .type bar, %function +bar: + .long foo + + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain4.d b/ld/testsuite/ld-elf/retain4.d new file mode 100644 index 0000000..b423fb9 --- /dev/null +++ b/ld/testsuite/ld-elf/retain4.d @@ -0,0 +1,9 @@ +#name: SHF_GNU_RETAIN 4 (keep orphaned sections when not discarding) +#source: retain4.s +#ld: -e _start --gc-sections --orphan-handling=place +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#DUMPPROG: nm + +#... +[0-9a-f]+ . orphaned_fn +#pass diff --git a/ld/testsuite/ld-elf/retain4.s b/ld/testsuite/ld-elf/retain4.s new file mode 100644 index 0000000..f30f121 --- /dev/null +++ b/ld/testsuite/ld-elf/retain4.s @@ -0,0 +1,13 @@ +/* A section that doesn't match any linker script input section rules but + has SHF_GNU_RETAIN applied should not be garbage collected. */ + .section .orphaned_section,"axR" + .global orphaned_fn + .type orphaned_fn, %function +orphaned_fn: + .word 0 + + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain5.d b/ld/testsuite/ld-elf/retain5.d new file mode 100644 index 0000000..86e85f8 --- /dev/null +++ b/ld/testsuite/ld-elf/retain5.d @@ -0,0 +1,11 @@ +#name: SHF_GNU_RETAIN 5 (don't pull SHF_GNU_RETAIN section out of lib) +#source: retain5main.s +#ld: --gc-sections -e _start --print-gc-sections -Ltmpdir -lretain5 -Map=retain5.map +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#map: retain5.map +#DUMPPROG: nm + +#failif +#... +[0-9a-f]+ . foo +#... diff --git a/ld/testsuite/ld-elf/retain5.map b/ld/testsuite/ld-elf/retain5.map new file mode 100644 index 0000000..6b97c2a --- /dev/null +++ b/ld/testsuite/ld-elf/retain5.map @@ -0,0 +1,5 @@ +# Check that the library was actually loaded to catch any false PASS. + +#... +LOAD tmpdir/libretain5.a +#pass diff --git a/ld/testsuite/ld-elf/retain5lib.s b/ld/testsuite/ld-elf/retain5lib.s new file mode 100644 index 0000000..4e83731 --- /dev/null +++ b/ld/testsuite/ld-elf/retain5lib.s @@ -0,0 +1,6 @@ +/* The link will fail if foo is included because undefined_sym is not defined. */ + .section .text.foo,"axR" + .global foo + .type foo, %function +foo: + .long undefined_sym diff --git a/ld/testsuite/ld-elf/retain5main.s b/ld/testsuite/ld-elf/retain5main.s new file mode 100644 index 0000000..89a7784 --- /dev/null +++ b/ld/testsuite/ld-elf/retain5main.s @@ -0,0 +1,5 @@ + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain6a.d b/ld/testsuite/ld-elf/retain6a.d new file mode 100644 index 0000000..aa93117 --- /dev/null +++ b/ld/testsuite/ld-elf/retain6a.d @@ -0,0 +1,13 @@ +#name: SHF_GNU_RETAIN 6a (pull section out of lib required by SHF_GNU_RETAIN section) +#source: retain6main.s +#ld: --gc-sections -e _start -u bar -Ltmpdir -lretain6 +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#DUMPPROG: nm + +#... +[0-9a-f]+ . bar +#... +[0-9a-f]+ . retain_from_lib +#... +[0-9a-f]+ . retained_fn +#pass diff --git a/ld/testsuite/ld-elf/retain6b.d b/ld/testsuite/ld-elf/retain6b.d new file mode 100644 index 0000000..f29ba71 --- /dev/null +++ b/ld/testsuite/ld-elf/retain6b.d @@ -0,0 +1,10 @@ +#name: SHF_GNU_RETAIN 6b (pull section out of lib required by SHF_GNU_RETAIN section) +#source: retain6main.s +#ld: --gc-sections -e _start -u bar -Ltmpdir -lretain6 +#notarget: ![supports_gnu_osabi] ![check_gc_sections_available] +#DUMPPROG: nm + +#failif +#... +[0-9a-f]+ . .*discard.* +#... diff --git a/ld/testsuite/ld-elf/retain6lib.s b/ld/testsuite/ld-elf/retain6lib.s new file mode 100644 index 0000000..a393dba --- /dev/null +++ b/ld/testsuite/ld-elf/retain6lib.s @@ -0,0 +1,17 @@ + .section .text.bar,"ax" + .global bar + .type bar, %function +bar: + .word 0 + + .section .text.retain_from_lib,"axR" + .global retain_from_lib + .type retain_from_lib, %function +retain_from_lib: + .word 0 + + .section .text.discard_from_lib,"ax" + .global discard_from_lib + .type discard_from_lib, %function +discard_from_lib: + .word 0 diff --git a/ld/testsuite/ld-elf/retain6main.s b/ld/testsuite/ld-elf/retain6main.s new file mode 100644 index 0000000..a66c5b3 --- /dev/null +++ b/ld/testsuite/ld-elf/retain6main.s @@ -0,0 +1,13 @@ +/* Undefined symbol reference in retained section .text.retained_fn requires + symbol definition to be pulled out of library. */ + .section .text.retained_fn,"axR" + .global retained_fn + .type retained_fn, %function +retained_fn: + .long bar + + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 |