From c3992c8f10a89a0133be0d0c0ca896b04d4f72fd Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Wed, 9 Sep 2020 22:00:16 +0100 Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag --- bfd/elflink.c | 3 +- binutils/readelf.c | 4 + gas/config/obj-elf.c | 57 +++++++++++++ gas/doc/as.texi | 17 ++++ gas/testsuite/gas/elf/elf.exp | 5 ++ gas/testsuite/gas/elf/retain1.d | 24 ++++++ gas/testsuite/gas/elf/retain1.s | 131 +++++++++++++++++++++++++++++ gas/testsuite/gas/elf/retain2.d | 2 + gas/testsuite/gas/elf/retain2.l | 3 + gas/testsuite/gas/elf/retain2.s | 7 ++ gas/testsuite/gas/elf/retain3.d | 24 ++++++ gas/testsuite/gas/elf/retain3.s | 121 +++++++++++++++++++++++++++ gas/testsuite/gas/elf/section10.d | 4 +- include/elf/common.h | 1 + ld/testsuite/ld-elf/elf.exp | 14 ++++ ld/testsuite/ld-elf/retain1.msg | 8 ++ ld/testsuite/ld-elf/retain1.s | 134 ++++++++++++++++++++++++++++++ ld/testsuite/ld-elf/retain2.d | 5 ++ ld/testsuite/ld-elf/retain2.ld | 7 ++ ld/testsuite/ld-elf/retain2.map | 18 ++++ ld/testsuite/ld-elf/retain3.msg | 8 ++ ld/testsuite/ld-elf/retain3.s | 124 +++++++++++++++++++++++++++ 22 files changed, 718 insertions(+), 3 deletions(-) create mode 100644 gas/testsuite/gas/elf/retain1.d create mode 100644 gas/testsuite/gas/elf/retain1.s create mode 100644 gas/testsuite/gas/elf/retain2.d create mode 100644 gas/testsuite/gas/elf/retain2.l create mode 100644 gas/testsuite/gas/elf/retain2.s create mode 100644 gas/testsuite/gas/elf/retain3.d create mode 100644 gas/testsuite/gas/elf/retain3.s create mode 100644 ld/testsuite/ld-elf/retain1.msg create mode 100644 ld/testsuite/ld-elf/retain1.s create mode 100644 ld/testsuite/ld-elf/retain2.d create mode 100644 ld/testsuite/ld-elf/retain2.ld create mode 100644 ld/testsuite/ld-elf/retain2.map create mode 100644 ld/testsuite/ld-elf/retain3.msg create mode 100644 ld/testsuite/ld-elf/retain3.s diff --git a/bfd/elflink.c b/bfd/elflink.c index 0e339f3c1e..6d1a1c5105 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -13977,7 +13977,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) || (elf_section_data (o)->this_hdr.sh_type == SHT_FINI_ARRAY))) || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE - && elf_next_in_group (o) == NULL ))) + && elf_next_in_group (o) == NULL) + || (elf_section_flags (o) & SHF_GNU_RETAIN))) { if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) return FALSE; diff --git a/binutils/readelf.c b/binutils/readelf.c index cb4208f7b9..00502f7058 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -5977,6 +5977,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") }, /* VLE specific. */ /* 25 */ { STRING_COMMA_LEN ("VLE") }, + /* GNU specific. */ + /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") }, }; if (do_section_details) @@ -6010,6 +6012,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) case SHF_EXCLUDE: sindex = 18; break; case SHF_COMPRESSED: sindex = 20; break; case SHF_GNU_MBIND: sindex = 24; break; + case SHF_GNU_RETAIN: sindex = 26; break; default: sindex = -1; @@ -6108,6 +6111,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) case SHF_EXCLUDE: *p = 'E'; break; case SHF_COMPRESSED: *p = 'C'; break; case SHF_GNU_MBIND: *p = 'D'; break; + case SHF_GNU_RETAIN: *p = 'R'; break; default: if ((filedata->file_header.e_machine == EM_X86_64 diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 9e39707801..0e8f3aa642 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -78,6 +78,7 @@ static void obj_elf_gnu_attribute (int); static void obj_elf_tls_common (int); static void obj_elf_lcomm (int); static void obj_elf_struct (int); +static void obj_elf_retain (int); static const pseudo_typeS elf_pseudo_table[] = { @@ -119,6 +120,9 @@ static const pseudo_typeS elf_pseudo_table[] = /* A GNU extension for object attributes. */ {"gnu_attribute", obj_elf_gnu_attribute, 0}, + /* A GNU extension for preventing linker garbage collection of sections. */ + {"retain", obj_elf_retain, 0}, + /* These are used for dwarf. */ {"2byte", cons, 2}, {"4byte", cons, 4}, @@ -857,6 +861,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; @@ -1986,6 +1993,56 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED) obj_elf_vendor_attribute (OBJ_ATTR_GNU); } +/* Parse a .retain ["sectionname"] directive. + The SHF_GNU_RETAIN flag should be applied to "section name". + If section name is omitted, then the SHF_GNU_RETAIN flag should be + applied to the current section being assembled. */ +static void +obj_elf_retain (int ignored ATTRIBUTE_UNUSED) +{ + const char *name; + symbolS *secsym; + asection *bfdsec; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + { + name = now_seg->name; + if (name == NULL) + { + as_bad (_("\".retain\" directive not within a section")); + ignore_rest_of_line (); + return; + } + } + else + { + name = obj_elf_section_name (); + secsym = symbol_find (name); + if (secsym == NULL) + { + as_bad (_("section '%s' has not been declared"), name); + ignore_rest_of_line (); + return; + } + else if (secsym != NULL + && !symbol_section_p (secsym)) + { + as_bad (_("'%s' is not a section name, expected " + "\".retain [section name]\""), name); + ignore_rest_of_line (); + return; + } + } + demand_empty_rest_of_line (); + + bfdsec = bfd_get_section_by_name (stdoutput, name); + if (bfdsec != NULL) + elf_section_flags (bfdsec) |= SHF_GNU_RETAIN; + else + as_bad (_("Couldn't find BFD section for %s\n"), name); +} + void elf_obj_read_begin_hook (void) { diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 112eaf810c..3ecbf88023 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -4468,6 +4468,7 @@ Some machine configurations provide additional directives. * Quad:: @code{.quad @var{bignums}} * Reloc:: @code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]} * Rept:: @code{.rept @var{count}} +* Retain:: @code{.retain ["@var{sectionname}"]} * Sbttl:: @code{.sbttl "@var{subheading}"} @ifset COFF * Scl:: @code{.scl @var{class}} @@ -6468,6 +6469,22 @@ is equivalent to assembling A count of zero is allowed, but nothing is generated. Negative counts are not allowed and if encountered will be treated as if they were zero. +@ifset ELF +@node Retain +@section @code{.retain ["@var{sectionname}"]} + +@cindex @code{retain} directive +@cindex SHF_GNU_RETAIN + +Apply the @var{SHF_GNU_RETAIN} flag to the section named @var{sectionname}, or +the current section the directive resides in, if this argument is +omitted. + +The SHF_GNU_RETAIN section flag indicates that the given section should not be +garbage collected by the linker, even if it appears unused. + +@end ifset + @node Sbttl @section @code{.sbttl "@var{subheading}"} diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 8520421ba3..3a4879e348 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -307,6 +307,11 @@ if { [is_elf_format] } then { run_dump_test "strtab" + # Tests for the .retain directive/SHF_GNU_RETAIN. + run_dump_test "retain1" + run_dump_test "retain2" + run_dump_test "retain3" + run_dump_test "bignums" run_dump_test "section-symbol-redef" diff --git a/gas/testsuite/gas/elf/retain1.d b/gas/testsuite/gas/elf/retain1.d new file mode 100644 index 0000000000..48c57f1241 --- /dev/null +++ b/gas/testsuite/gas/elf/retain1.d @@ -0,0 +1,24 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 1 + +#... + \[..\] .bss.a0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.b0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.c0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sa0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sb0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.sc0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .text.foo0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* + \[..\] .bss.a1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.b1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.c1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sa1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sb1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.sc1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .text.foo1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* + \[..\] .text.foo2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* +#... + \[..\] .bss.lsa[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.lsb[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.lsc[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#pass diff --git a/gas/testsuite/gas/elf/retain1.s b/gas/testsuite/gas/elf/retain1.s new file mode 100644 index 0000000000..2ea652ea35 --- /dev/null +++ b/gas/testsuite/gas/elf/retain1.s @@ -0,0 +1,131 @@ +.text + .global a0 + .section .bss.a0,"aw" + .balign 2 + .type a0, STT_OBJECT + .size a0, 2 +a0: + .zero 2 + .global b0 + .section .bss.b0,"aw" + .balign 2 + .type b0, STT_OBJECT + .size b0, 2 +b0: + .zero 2 + .global c0 + .section .data.c0,"aw" + .balign 2 + .type c0, STT_OBJECT + .size c0, 2 +c0: + .short 1 + .section .bss.sa0,"aw" + .balign 2 + .type sa0, STT_OBJECT + .size sa0, 2 +sa0: + .zero 2 + .section .bss.sb0,"aw" + .balign 2 + .type sb0, STT_OBJECT + .size sb0, 2 +sb0: + .zero 2 + .section .data.sc0,"aw" + .balign 2 + .type sc0, STT_OBJECT + .size sc0, 2 +sc0: + .short 1 + .section .text.foo0,"ax" + .balign 2 + .global foo0 + .type foo0, STT_FUNC +foo0: + .size foo0, .-foo0 + .global a1 + .section .bss.a1,"aw" + .balign 2 + .type a1, STT_OBJECT + .retain .bss.a1 + .size a1, 2 +a1: + .zero 2 + .global b1 + .section .bss.b1,"aw" + .balign 2 + .type b1, STT_OBJECT + .retain .bss.b1 + .size b1, 2 +b1: + .zero 2 + .global c1 + .section .data.c1,"aw" + .balign 2 + .type c1, STT_OBJECT + .retain .data.c1 + .size c1, 2 +c1: + .short 1 + .section .bss.sa1,"aw" + .balign 2 + .type sa1, STT_OBJECT + .retain .bss.sa1 + .size sa1, 2 +sa1: + .zero 2 + .section .bss.sb1,"aw" + .balign 2 + .type sb1, STT_OBJECT + .retain .bss.sb1 + .size sb1, 2 +sb1: + .zero 2 + .section .data.sc1,"aw" + .balign 2 + .type sc1, STT_OBJECT + .retain .data.sc1 + .size sc1, 2 +sc1: + .short 1 + .section .text.foo1,"ax" + .balign 2 + .global foo1 + .type foo1, STT_FUNC + .retain .text.foo1 +foo1: + .size foo1, .-foo1 + .section .text.foo2,"ax" + .balign 2 + .global foo2 + .type foo2, STT_FUNC +foo2: + .size foo2, .-foo2 + .section .bss.lsa,"aw" + .balign 2 + .type lsa.2, STT_OBJECT + .retain .bss.lsa + .size lsa.2, 2 +lsa.2: + .zero 2 + .section .bss.lsb,"aw" + .balign 2 + .type lsb.1, STT_OBJECT + .retain .bss.lsb + .size lsb.1, 2 +lsb.1: + .zero 2 + .section .data.lsc,"aw" + .balign 2 + .type lsc.0, STT_OBJECT + .retain .data.lsc + .size lsc.0, 2 +lsc.0: + .short 1 +.text + .balign 2 + .global main + .type main, STT_FUNC +main: + .size main, .-main diff --git a/gas/testsuite/gas/elf/retain2.d b/gas/testsuite/gas/elf/retain2.d new file mode 100644 index 0000000000..55bcb87ab3 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.d @@ -0,0 +1,2 @@ +#name: SHF_GNU_RETAIN 2 +#error_output: retain2.l diff --git a/gas/testsuite/gas/elf/retain2.l b/gas/testsuite/gas/elf/retain2.l new file mode 100644 index 0000000000..3cf31b3e25 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.l @@ -0,0 +1,3 @@ +[^:]*: Assembler messages: +[^:]*:1: Error: section '.data.foo' has not been declared +[^:]*:7: Error: 'myvar' is not a section name, expected ".retain \[section name\]" diff --git a/gas/testsuite/gas/elf/retain2.s b/gas/testsuite/gas/elf/retain2.s new file mode 100644 index 0000000000..3522546886 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.s @@ -0,0 +1,7 @@ +.retain ".data.foo" +.data +.global myvar +.type myvar, STT_OBJECT +myvar: + .byte 2 +.retain "myvar" diff --git a/gas/testsuite/gas/elf/retain3.d b/gas/testsuite/gas/elf/retain3.d new file mode 100644 index 0000000000..78a7c26c47 --- /dev/null +++ b/gas/testsuite/gas/elf/retain3.d @@ -0,0 +1,24 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 3 (use flags set on .section directive) + +#... + \[..\] .bss.a0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.b0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.c0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sa0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sb0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.sc0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .text.foo0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* + \[..\] .bss.a1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.b1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.c1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sa1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sb1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.sc1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .text.foo1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* + \[..\] .text.foo2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* +#... + \[..\] .bss.lsa[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.lsb[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.lsc[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#pass diff --git a/gas/testsuite/gas/elf/retain3.s b/gas/testsuite/gas/elf/retain3.s new file mode 100644 index 0000000000..a7f050a8f5 --- /dev/null +++ b/gas/testsuite/gas/elf/retain3.s @@ -0,0 +1,121 @@ +.text + .global a0 + .section .bss.a0,"aw" + .balign 2 + .type a0, STT_OBJECT + .size a0, 2 +a0: + .zero 2 + .global b0 + .section .bss.b0,"aw" + .balign 2 + .type b0, STT_OBJECT + .size b0, 2 +b0: + .zero 2 + .global c0 + .section .data.c0,"aw" + .balign 2 + .type c0, STT_OBJECT + .size c0, 2 +c0: + .short 1 + .section .bss.sa0,"aw" + .balign 2 + .type sa0, STT_OBJECT + .size sa0, 2 +sa0: + .zero 2 + .section .bss.sb0,"aw" + .balign 2 + .type sb0, STT_OBJECT + .size sb0, 2 +sb0: + .zero 2 + .section .data.sc0,"aw" + .balign 2 + .type sc0, STT_OBJECT + .size sc0, 2 +sc0: + .short 1 + .section .text.foo0,"ax" + .balign 2 + .global foo0 + .type foo0, STT_FUNC +foo0: + .size foo0, .-foo0 + .global a1 + .section .bss.a1,"awR" + .balign 2 + .type a1, STT_OBJECT + .size a1, 2 +a1: + .zero 2 + .global b1 + .section .bss.b1,"awR" + .balign 2 + .type b1, STT_OBJECT + .size b1, 2 +b1: + .zero 2 + .global c1 + .section .data.c1,"awR" + .balign 2 + .type c1, STT_OBJECT + .size c1, 2 +c1: + .short 1 + .section .bss.sa1,"awR" + .balign 2 + .type sa1, STT_OBJECT + .size sa1, 2 +sa1: + .zero 2 + .section .bss.sb1,"awR" + .balign 2 + .type sb1, STT_OBJECT + .size sb1, 2 +sb1: + .zero 2 + .section .data.sc1,"awR" + .balign 2 + .type sc1, STT_OBJECT + .size sc1, 2 +sc1: + .short 1 + .section .text.foo1,"axR" + .balign 2 + .global foo1 + .type foo1, STT_FUNC +foo1: + .size foo1, .-foo1 + .section .text.foo2,"ax" + .balign 2 + .global foo2 + .type foo2, STT_FUNC +foo2: + .size foo2, .-foo2 + .section .bss.lsa,"awR" + .balign 2 + .type lsa.2, STT_OBJECT + .size lsa.2, 2 +lsa.2: + .zero 2 + .section .bss.lsb,"awR" + .balign 2 + .type lsb.1, STT_OBJECT + .size lsb.1, 2 +lsb.1: + .zero 2 + .section .data.lsc,"awR" + .balign 2 + .type lsc.0, STT_OBJECT + .size lsc.0, 2 +lsc.0: + .short 1 +.text + .balign 2 + .global main + .type main, STT_FUNC +main: + .size main, .-main diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d index 554a791f1d..ef91d7d086 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\) +[ ]*\[.*fefff030\]: 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\) +[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) [ ]*\[.*\][ ]+.data.foo [ ]*LOUSER\+0x7f000000[ ].* [ ]*\[0+003\]: WRITE, ALLOC diff --git a/include/elf/common.h b/include/elf/common.h index 805058146a..364c58a7de 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -554,6 +554,7 @@ /* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */ #define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ #define SHF_GNU_BUILD_NOTE (1 << 20) /* Section contains GNU BUILD ATTRIBUTE notes. */ +#define SHF_GNU_RETAIN (1 << 21) /* Section should not be garbage collected by the linker. */ #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ /* This used to be implemented as a processor specific section flag. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index c0d67d80d2..04027fcbed 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -225,6 +225,20 @@ if [check_gc_sections_available] { {pr25490-6.s} \ [list [list "readelf" {-SW} $pr25490_6_exp]] \ "pr25490-6.exe"] \ + [list "SHF_GNU_RETAIN 1" \ + "--gc-sections -e main --print-gc-sections" \ + "" \ + "" \ + {retain1.s} \ + {{ ld retain1.msg }} \ + "retain1.exe"] \ + [list "SHF_GNU_RETAIN 3 (use flags set on .section directive)" \ + "--gc-sections -e main --print-gc-sections" \ + "" \ + "" \ + {retain3.s} \ + {{ ld retain3.msg }} \ + "retain3.exe"] \ ] } diff --git a/ld/testsuite/ld-elf/retain1.msg b/ld/testsuite/ld-elf/retain1.msg new file mode 100644 index 0000000000..0e0f24ff10 --- /dev/null +++ b/ld/testsuite/ld-elf/retain1.msg @@ -0,0 +1,8 @@ +.*: removing unused section '.bss.a0' in file.* +.*: removing unused section '.bss.b0' in file.* +.*: removing unused section '.data.c0' in file.* +.*: removing unused section '.bss.sa0' in file.* +.*: removing unused section '.bss.sb0' in file.* +.*: removing unused section '.data.sc0' in file.* +.*: removing unused section '.text.foo0' in file.* +.*: removing unused section '.text.foo2' in file.* diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s new file mode 100644 index 0000000000..05b739ba64 --- /dev/null +++ b/ld/testsuite/ld-elf/retain1.s @@ -0,0 +1,134 @@ +.text + .global a0 + .section .bss.a0,"aw" + .balign 2 + .type a0, STT_OBJECT + .size a0, 2 +a0: + .zero 2 + .global b0 + .section .bss.b0,"aw" + .balign 2 + .type b0, STT_OBJECT + .size b0, 2 +b0: + .zero 2 + .global c0 + .section .data.c0,"aw" + .balign 2 + .type c0, STT_OBJECT + .size c0, 2 +c0: + .short 1 + .section .bss.sa0,"aw" + .balign 2 + .type sa0, STT_OBJECT + .size sa0, 2 +sa0: + .zero 2 + .section .bss.sb0,"aw" + .balign 2 + .type sb0, STT_OBJECT + .size sb0, 2 +sb0: + .zero 2 + .section .data.sc0,"aw" + .balign 2 + .type sc0, STT_OBJECT + .size sc0, 2 +sc0: + .short 1 + .section .text.foo0,"ax" + .balign 2 + .global foo0 + .type foo0, STT_FUNC +foo0: + .word 0 + .size foo0, .-foo0 + .global a1 + .section .bss.a1,"aw" + .balign 2 + .type a1, STT_OBJECT + .retain .bss.a1 + .size a1, 2 +a1: + .zero 2 + .global b1 + .section .bss.b1,"aw" + .balign 2 + .type b1, STT_OBJECT + .retain .bss.b1 + .size b1, 2 +b1: + .zero 2 + .global c1 + .section .data.c1,"aw" + .balign 2 + .type c1, STT_OBJECT + .retain .data.c1 + .size c1, 2 +c1: + .short 1 + .section .bss.sa1,"aw" + .balign 2 + .type sa1, STT_OBJECT + .retain .bss.sa1 + .size sa1, 2 +sa1: + .zero 2 + .section .bss.sb1,"aw" + .balign 2 + .type sb1, STT_OBJECT + .retain .bss.sb1 + .size sb1, 2 +sb1: + .zero 2 + .section .data.sc1,"aw" + .balign 2 + .type sc1, STT_OBJECT + .retain .data.sc1 + .size sc1, 2 +sc1: + .short 1 + .section .text.foo1,"ax" + .balign 2 + .global foo1 + .type foo1, STT_FUNC + .retain .text.foo1 +foo1: + .word 0 + .size foo1, .-foo1 + .section .text.foo2,"ax" + .balign 2 + .global foo2 + .type foo2, STT_FUNC +foo2: + .word 0 + .size foo2, .-foo2 + .section .bss.lsa,"aw" + .balign 2 + .type lsa.2, STT_OBJECT + .retain .bss.lsa + .size lsa.2, 2 +lsa.2: + .zero 2 + .section .bss.lsb,"aw" + .balign 2 + .type lsb.1, STT_OBJECT + .retain .bss.lsb + .size lsb.1, 2 +lsb.1: + .zero 2 + .section .data.lsc,"aw" + .balign 2 + .type lsc.0, STT_OBJECT + .retain .data.lsc + .size lsc.0, 2 +lsc.0: + .short 1 +.text + .balign 2 + .global main + .type main, STT_FUNC +main: + .size main, .-main diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d new file mode 100644 index 0000000000..207227928e --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.d @@ -0,0 +1,5 @@ +# source: retain1.s +# ld: -e main -Map=retain2.map --gc-sections --script=retain2.ld +# map: retain2.map + +#pass diff --git a/ld/testsuite/ld-elf/retain2.ld b/ld/testsuite/ld-elf/retain2.ld new file mode 100644 index 0000000000..b8c9e6dfd1 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + /DISCARD/ : + { + *(".text.foo1") + } +} diff --git a/ld/testsuite/ld-elf/retain2.map b/ld/testsuite/ld-elf/retain2.map new file mode 100644 index 0000000000..65b61f7488 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.map @@ -0,0 +1,18 @@ +# Test that .text.foo1, which has the SHF_GNU_RETAIN flag, can still be +# explicitly discarded from the output file. + +#... +Discarded input sections + + .data.* + .bss.* + .bss.a0.* + .bss.b0.* + .data.c0.* + .bss.sa0.* + .bss.sb0.* + .data.sc0.* + .text.foo0.* + .text.foo1.* + .text.foo2.* +#pass diff --git a/ld/testsuite/ld-elf/retain3.msg b/ld/testsuite/ld-elf/retain3.msg new file mode 100644 index 0000000000..0e0f24ff10 --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.msg @@ -0,0 +1,8 @@ +.*: removing unused section '.bss.a0' in file.* +.*: removing unused section '.bss.b0' in file.* +.*: removing unused section '.data.c0' in file.* +.*: removing unused section '.bss.sa0' in file.* +.*: removing unused section '.bss.sb0' in file.* +.*: removing unused section '.data.sc0' in file.* +.*: removing unused section '.text.foo0' in file.* +.*: removing unused section '.text.foo2' in file.* diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s new file mode 100644 index 0000000000..f1ade91c87 --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.s @@ -0,0 +1,124 @@ +.text + .global a0 + .section .bss.a0,"aw" + .balign 2 + .type a0, STT_OBJECT + .size a0, 2 +a0: + .zero 2 + .global b0 + .section .bss.b0,"aw" + .balign 2 + .type b0, STT_OBJECT + .size b0, 2 +b0: + .zero 2 + .global c0 + .section .data.c0,"aw" + .balign 2 + .type c0, STT_OBJECT + .size c0, 2 +c0: + .short 1 + .section .bss.sa0,"aw" + .balign 2 + .type sa0, STT_OBJECT + .size sa0, 2 +sa0: + .zero 2 + .section .bss.sb0,"aw" + .balign 2 + .type sb0, STT_OBJECT + .size sb0, 2 +sb0: + .zero 2 + .section .data.sc0,"aw" + .balign 2 + .type sc0, STT_OBJECT + .size sc0, 2 +sc0: + .short 1 + .section .text.foo0,"ax" + .balign 2 + .global foo0 + .type foo0, STT_FUNC +foo0: + .word 0 + .size foo0, .-foo0 + .global a1 + .section .bss.a1,"awR" + .balign 2 + .type a1, STT_OBJECT + .size a1, 2 +a1: + .zero 2 + .global b1 + .section .bss.b1,"awR" + .balign 2 + .type b1, STT_OBJECT + .size b1, 2 +b1: + .zero 2 + .global c1 + .section .data.c1,"awR" + .balign 2 + .type c1, STT_OBJECT + .size c1, 2 +c1: + .short 1 + .section .bss.sa1,"awR" + .balign 2 + .type sa1, STT_OBJECT + .size sa1, 2 +sa1: + .zero 2 + .section .bss.sb1,"awR" + .balign 2 + .type sb1, STT_OBJECT + .size sb1, 2 +sb1: + .zero 2 + .section .data.sc1,"awR" + .balign 2 + .type sc1, STT_OBJECT + .size sc1, 2 +sc1: + .short 1 + .section .text.foo1,"axR" + .balign 2 + .global foo1 + .type foo1, STT_FUNC +foo1: + .word 0 + .size foo1, .-foo1 + .section .text.foo2,"ax" + .balign 2 + .global foo2 + .type foo2, STT_FUNC +foo2: + .word 0 + .size foo2, .-foo2 + .section .bss.lsa,"awR" + .balign 2 + .type lsa.2, STT_OBJECT + .size lsa.2, 2 +lsa.2: + .zero 2 + .section .bss.lsb,"awR" + .balign 2 + .type lsb.1, STT_OBJECT + .size lsb.1, 2 +lsb.1: + .zero 2 + .section .data.lsc,"awR" + .balign 2 + .type lsc.0, STT_OBJECT + .size lsc.0, 2 +lsc.0: + .short 1 +.text + .balign 2 + .global main + .type main, STT_FUNC +main: + .size main, .-main -- 2.28.0