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 /gas | |
parent | 40d9d2fd796a184f04a83ca4442fd78034b5e00b (diff) | |
download | gdb-99fabbc9739a87ba3433e66792e93b773896790e.zip gdb-99fabbc9739a87ba3433e66792e93b773896790e.tar.gz 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 'gas')
-rw-r--r-- | gas/ChangeLog | 23 | ||||
-rw-r--r-- | gas/NEWS | 5 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 80 | ||||
-rw-r--r-- | gas/doc/as.texi | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/elf.exp | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section10.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section10.s | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section22.d | 19 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section22.s | 34 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section23.s | 11 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section23a.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section23b.d | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section23b.err | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section24.s | 38 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section24a.d | 17 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section24b.d | 10 |
16 files changed, 250 insertions, 22 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index cdbc1ca..fcfce70 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + H.J. Lu <hongjiu.lu@intel.com> + + * 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.s: New test. + * testsuite/gas/elf/section24a.d: New test. + * testsuite/gas/elf/section24b.d: New test. + 2020-11-13 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com> * NEWS: Update news. @@ -52,6 +52,11 @@ * Configure with --enable-x86-used-note by default for Linux/x86. +* Add support for the SHF_GNU_RETAIN flag, which can be applied to + sections using the 'R' flag in the .section directive. + SHF_GNU_RETAIN specifies that the section should not be garbage + collected by the linker. It requires the GNU or FreeBSD ELF OSABIs. + Changes in 2.35: * X86 NaCl target support is removed. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 7aed812..54d42d9 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -806,9 +806,17 @@ obj_elf_change_section (const char *name, as_bad (_("changed section attributes for %s"), name); } else - /* FIXME: Maybe we should consider removing a previously set - processor or application specific attribute as suspicious ? */ - elf_section_flags (sec) = attr; + { + /* Don't overwrite a previously set SHF_GNU_RETAIN flag for the + section. The entire section must be marked retained. */ + if ((elf_tdata (stdoutput)->has_gnu_osabi & elf_gnu_osabi_retain) + && ((elf_section_flags (old_sec) & SHF_GNU_RETAIN))) + attr |= SHF_GNU_RETAIN; + + /* FIXME: Maybe we should consider removing a previously set + processor or application specific attribute as suspicious ? */ + elf_section_flags (sec) = attr; + } if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize) as_bad (_("changed section entity size for %s"), name); @@ -861,6 +869,9 @@ obj_elf_parse_section_letters (char *str, size_t len, case 'd': *gnu_attr |= SHF_GNU_MBIND; break; + case 'R': + *gnu_attr |= SHF_GNU_RETAIN; + break; case '?': *is_clone = TRUE; break; @@ -890,8 +901,32 @@ obj_elf_parse_section_letters (char *str, size_t len, if (ISDIGIT (*str)) { char * end; + struct elf_backend_data *bed; + bfd_vma numeric_flags = strtoul (str, &end, 0); + + attr |= numeric_flags; + + bed = (struct elf_backend_data *) + get_elf_backend_data (stdoutput); + + if (bed->elf_osabi == ELFOSABI_NONE + || bed->elf_osabi == ELFOSABI_STANDALONE + || bed->elf_osabi == ELFOSABI_GNU + || bed->elf_osabi == ELFOSABI_FREEBSD) + { + /* Add flags in the SHF_MASKOS range to gnu_attr for + OSABIs that support those flags. + Also adding the flags for ELFOSABI_{NONE,STANDALONE} + allows them to be validated later in obj_elf_section. + We can't just always set these bits in gnu_attr for + all OSABIs, since Binutils does not recognize all + SHF_MASKOS bits for non-GNU OSABIs. It's therefore + possible that numeric flags are being used to set bits + in the SHF_MASKOS range for those targets, and we + don't want assembly to fail in those situations. */ + *gnu_attr |= (numeric_flags & SHF_MASKOS); + } - attr |= strtoul (str, & end, 0); /* Update str and len, allowing for the fact that we will execute str++ and len-- below. */ end --; @@ -1387,26 +1422,37 @@ obj_elf_section (int push) done: demand_empty_rest_of_line (); - obj_elf_change_section (name, type, attr, entsize, &match, linkonce, - push); - - if ((gnu_attr & SHF_GNU_MBIND) != 0) + if ((gnu_attr & (SHF_GNU_MBIND | SHF_GNU_RETAIN)) != 0) { struct elf_backend_data *bed; + bfd_boolean mbind_p = (gnu_attr & SHF_GNU_MBIND) != 0; - if ((attr & SHF_ALLOC) == 0) + if (mbind_p && (attr & SHF_ALLOC) == 0) as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name); bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput); - if (bed->elf_osabi == ELFOSABI_NONE) - bed->elf_osabi = ELFOSABI_GNU; - else if (bed->elf_osabi != ELFOSABI_GNU - && bed->elf_osabi != ELFOSABI_FREEBSD) - as_bad (_("GNU_MBIND section is supported only by GNU " - "and FreeBSD targets")); - elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind; + + if (bed->elf_osabi != ELFOSABI_GNU + && bed->elf_osabi != ELFOSABI_FREEBSD + && bed->elf_osabi != ELFOSABI_NONE) + as_bad (_("%s section is supported only by GNU and FreeBSD targets"), + mbind_p ? "GNU_MBIND" : "GNU_RETAIN"); + else + { + if (bed->elf_osabi == ELFOSABI_NONE) + bed->elf_osabi = ELFOSABI_GNU; + + if (mbind_p) + elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind; + if ((gnu_attr & SHF_GNU_RETAIN) != 0) + elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_retain; + + attr |= gnu_attr; + } } - elf_section_flags (now_seg) |= gnu_attr; + + obj_elf_change_section (name, type, attr, entsize, &match, linkonce, + push); if (linked_to_section_index != -1UL) { diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 278de41..84a7e61 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -6659,6 +6659,9 @@ section is a member of a section group section is used for thread-local-storage @item ? section is a member of the previously-current section's group, if any +@item R +retained section (apply SHF_GNU_RETAIN to prevent linker garbage +collection, GNU ELF extension) @item @code{<number>} a numeric value indicating the bits to be set in the ELF section header's flags field. Note - if one or more of the alphabetic characters described above is diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index edacf27..0ba32c7 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -261,8 +261,12 @@ if { [is_elf_format] } then { run_dump_test "section19" run_dump_test "section20" run_dump_test "section21" + run_dump_test "section22" + run_dump_test "section23a" + run_dump_test "section23b" + run_dump_test "section24a" + run_dump_test "section24b" run_dump_test "sh-link-zero" - run_dump_test "dwarf2-1" $dump_opts run_dump_test "dwarf2-2" $dump_opts run_dump_test "dwarf2-3" $dump_opts diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d index 554a791..6aa7b08 100644 --- a/gas/testsuite/gas/elf/section10.d +++ b/gas/testsuite/gas/elf/section10.d @@ -18,7 +18,7 @@ #... [ ]*\[.*\][ ]+sec3 [ ]*PROGBITS.* -[ ]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) +[ ]*\[.*fedff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) #... [ ]*\[.*\][ ]+sec4 [ ]*LOOS\+0x11[ ].* @@ -26,7 +26,7 @@ #... [ ]*\[.*\][ ]+sec5 [ ]*LOUSER\+0x9[ ].* -[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) +[ ]*\[.*fedf0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) [ ]*\[.*\][ ]+.data.foo [ ]*LOUSER\+0x7f000000[ ].* [ ]*\[0+003\]: WRITE, ALLOC diff --git a/gas/testsuite/gas/elf/section10.s b/gas/testsuite/gas/elf/section10.s index 29f1184..d52b345 100644 --- a/gas/testsuite/gas/elf/section10.s +++ b/gas/testsuite/gas/elf/section10.s @@ -7,7 +7,7 @@ .word 2 # Make sure that specifying further arguments to .sections is still supported - .section sec3, "0xfefff000MS", %progbits, 32 + .section sec3, "0xfedff000MS", %progbits, 32 .word 3 # Make sure that extra flags can be set for well known sections as well. @@ -19,7 +19,7 @@ .word 5 # Test both together, with a quoted type value. - .section sec5, "0xfeff0000", "0x80000009" + .section sec5, "0xfedf0000", "0x80000009" .word 6 # Test that declaring an extended version of a known special section works. diff --git a/gas/testsuite/gas/elf/section22.d b/gas/testsuite/gas/elf/section22.d new file mode 100644 index 0000000..8aa7fcf --- /dev/null +++ b/gas/testsuite/gas/elf/section22.d @@ -0,0 +1,19 @@ +#readelf: -h -S --wide +#name: SHF_GNU_RETAIN sections 22 +#notarget: ![supports_gnu_osabi] + +#... + +OS/ABI: +UNIX - GNU +#... + \[..\] .text.discard0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* +#... + \[..\] .data.discard1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* +#... + \[..\] .bss.discard2[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* +#... + \[..\] .bss.retain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#... + \[..\] .data.retain1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#... + \[..\] .text.retain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* +#pass diff --git a/gas/testsuite/gas/elf/section22.s b/gas/testsuite/gas/elf/section22.s new file mode 100644 index 0000000..66ed990 --- /dev/null +++ b/gas/testsuite/gas/elf/section22.s @@ -0,0 +1,34 @@ + .section .text.discard0,"ax",%progbits + .global discard0 + .type discard0, %function +discard0: + .word 0 + + .section .data.discard1,"aw" + .global discard1 + .type discard1, %object +discard1: + .word 1 + + .section .bss.discard2,"aw" + .global discard2 + .type discard2, %object +discard2: + .zero 2 + + .section .bss.retain0,"awR",%nobits + .global retain0 + .type retain0, %object +retain0: + .zero 2 + + .section .data.retain1,"awR",%progbits + .type retain1, %object +retain1: + .word 1 + + .section .text.retain2,"axR",%progbits + .global retain2 + .type retain2, %function +retain2: + .word 0 diff --git a/gas/testsuite/gas/elf/section23.s b/gas/testsuite/gas/elf/section23.s new file mode 100644 index 0000000..d671119 --- /dev/null +++ b/gas/testsuite/gas/elf/section23.s @@ -0,0 +1,11 @@ + .section .data.retain_var,"0x200003" + .global retain_var + .type retain_var, %object +retain_var: + .long 2 + + .section .text._start,"ax" + .global _start + .type _start, %function +_start: + .word 0 diff --git a/gas/testsuite/gas/elf/section23a.d b/gas/testsuite/gas/elf/section23a.d new file mode 100644 index 0000000..2e413e1 --- /dev/null +++ b/gas/testsuite/gas/elf/section23a.d @@ -0,0 +1,10 @@ +#name: SHF_GNU_RETAIN set with numeric flag value in .section +#source: section23.s +#target: [supports_gnu_osabi] +#readelf: -h -S --wide + +#... + +OS/ABI: +UNIX - GNU +#... + \[..\] .data.retain_var[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#pass diff --git a/gas/testsuite/gas/elf/section23b.d b/gas/testsuite/gas/elf/section23b.d new file mode 100644 index 0000000..c85200e --- /dev/null +++ b/gas/testsuite/gas/elf/section23b.d @@ -0,0 +1,6 @@ +#name: SHF_GNU_RETAIN set with numeric flag value in .section for non-GNU OSABI target +#source: section23.s +#error_output: section23b.err +#target: msp430-*-elf visium-*-elf + +# This test only runs for targets which set ELFOSABI_STANDALONE. diff --git a/gas/testsuite/gas/elf/section23b.err b/gas/testsuite/gas/elf/section23b.err new file mode 100644 index 0000000..83de60c --- /dev/null +++ b/gas/testsuite/gas/elf/section23b.err @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:1: Error: GNU_RETAIN section is supported only by GNU and FreeBSD targets diff --git a/gas/testsuite/gas/elf/section24.s b/gas/testsuite/gas/elf/section24.s new file mode 100644 index 0000000..adcff4a --- /dev/null +++ b/gas/testsuite/gas/elf/section24.s @@ -0,0 +1,38 @@ + .section .text,"ax",%progbits + .word 0 + .section .data,"aw" + .word 0 + .section .bss,"aw",%nobits + .word 0 + .section .rodata,"a" + .word 0 + +/* Test that we can set the 'R' flag on an existing section. */ + .section .text,"axR",%progbits + .word 0 + .section .data,"awR" + .word 0 + .section .bss,"awR",%nobits + .word 0 + .section .rodata,"aR" + .word 0 + +/* Test that the 'R' flag does not get clobbered when the section is switched + back to. */ + .section .text,"ax",%progbits + .word 0 + .section .data,"aw" + .word 0 + .section .bss,"aw",%nobits + .word 0 + .section .rodata,"a" + .word 0 + + .section .text + .word 0 + .section .data + .word 0 + .section .bss + .word 0 + .section .rodata + .word 0 diff --git a/gas/testsuite/gas/elf/section24a.d b/gas/testsuite/gas/elf/section24a.d new file mode 100644 index 0000000..8f316d3 --- /dev/null +++ b/gas/testsuite/gas/elf/section24a.d @@ -0,0 +1,17 @@ +#name: Merge SHF_GNU_RETAIN for non-unique sections +#notarget: ![supports_gnu_osabi] +#source: section24.s +#readelf: -h -S --wide + +#... + +OS/ABI: +UNIX - GNU +#... + \[..\] .text[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR .* +#... + \[..\] .data[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR .* +#... + \[..\] .bss[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR .* +#... + \[..\] .rodata[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AR .* +#pass + diff --git a/gas/testsuite/gas/elf/section24b.d b/gas/testsuite/gas/elf/section24b.d new file mode 100644 index 0000000..451ec21 --- /dev/null +++ b/gas/testsuite/gas/elf/section24b.d @@ -0,0 +1,10 @@ +#name: Merge SHF_GNU_RETAIN for non-unique sections (check no unmerged) +#notarget: ![supports_gnu_osabi] +#source: section24.s +#readelf: -S --wide + +#failif +#... + \[..\] .(text|data|bss|rodata)[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 [^R] .* +#pass + |