From 8c41c5e09dbfe74e71a19c57e14472ba17ccd7ef Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 10 Oct 2025 16:02:50 +0200 Subject: [PATCH] bfd/PE: respect SEC_ALLOC when deciding whether to force IMAGE_SCN_MEM_DISCARDABLE While in the common case sections like .reloc don't need to be accessed by a binary (that's the job of the loader), there are rare cases where the situation is different. Unconditionally forcing the discardable flag is therefore unhelpful. Avoid doing so when SEC_ALLOC is set, which would in particular be the case when .reloc isn't (solely) linker- generated. While adjusting the comment, drop the wrong (stale?) following sentence: .rsrc, as per its table entry, doesn't need to be writable. And commenting on it wanting to be readable would then need to be repeated for all other sections as well. --- bfd/peXXigen.c | 15 ++++++++++----- gas/testsuite/gas/pe/pe.exp | 2 ++ gas/testsuite/gas/pe/reloc.d | 13 +++++++++++++ gas/testsuite/gas/pe/reloc.s | 19 +++++++++++++++++++ ld/testsuite/ld-pe/pe.exp | 3 +++ ld/testsuite/ld-pe/reloc2.s | 19 +++++++++++++++++++ ld/testsuite/ld-pe/reloc2a.d | 35 +++++++++++++++++++++++++++++++++++ ld/testsuite/ld-pe/reloc2b.d | 32 ++++++++++++++++++++++++++++++++ ld/testsuite/ld-pe/reloc2c.d | 31 +++++++++++++++++++++++++++++++ 9 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 gas/testsuite/gas/pe/reloc.d create mode 100644 gas/testsuite/gas/pe/reloc.s create mode 100644 ld/testsuite/ld-pe/reloc2.s create mode 100644 ld/testsuite/ld-pe/reloc2a.d create mode 100644 ld/testsuite/ld-pe/reloc2b.d create mode 100644 ld/testsuite/ld-pe/reloc2c.d diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index 938a29d7e3a..ac818ee383c 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -920,7 +920,7 @@ _bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out) unsigned int _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out, - const asection *section ATTRIBUTE_UNUSED) + const asection *section) { struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in; SCNHDR *scnhdr_ext = (SCNHDR *) out; @@ -989,9 +989,8 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out, sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set (this is especially important when dealing with the .idata section since the addresses for routines from .dlls must be overwritten). If .reloc - section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE - (0x02000000). Also, the resource data should also be read and - writable. */ + section data is ever generated, we generally need to add + IMAGE_SCN_MEM_DISCARDABLE (0x02000000). */ /* FIXME: Alignment is also encoded in this field, at least on ARM-WINCE. Although - how do we get the original alignment field @@ -1037,10 +1036,16 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out, p++) if (memcmp (scnhdr_int->s_name, p->section_name, SCNNMLEN) == 0) { + unsigned long must_have = p->must_have; + if (memcmp (scnhdr_int->s_name, ".text", sizeof ".text") || (bfd_get_file_flags (abfd) & WP_TEXT)) scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE; - scnhdr_int->s_flags |= p->must_have; + /* Avoid forcing in the discardable flag if the section itself is + allocated. */ + if (section->flags & SEC_ALLOC) + must_have &= ~IMAGE_SCN_MEM_DISCARDABLE; + scnhdr_int->s_flags |= must_have; break; } diff --git a/gas/testsuite/gas/pe/pe.exp b/gas/testsuite/gas/pe/pe.exp index 8682789d209..e12723972e7 100644 --- a/gas/testsuite/gas/pe/pe.exp +++ b/gas/testsuite/gas/pe/pe.exp @@ -38,6 +38,8 @@ run_dump_test "section-exclude" run_dump_test "set" +run_dump_test "reloc" + if { [istarget "aarch64-*-*"] || [istarget "arm*-*-*"] || [istarget "i*86-*-*"] || [istarget "x86_64-*-*"] } then { run_dump_test "cv_comp" diff --git a/gas/testsuite/gas/pe/reloc.d b/gas/testsuite/gas/pe/reloc.d new file mode 100644 index 00000000000..444590c3a35 --- /dev/null +++ b/gas/testsuite/gas/pe/reloc.d @@ -0,0 +1,13 @@ +#as: --no-pad-sections +#objdump: -wPsections +#name: .reloc section attributes + +.*: .* + +Section headers.*: + # Name *paddr *vaddr *size .* Flags + 1 \.text *0*0000 0*0000 0*0(4|10) .* Align: (4|16) EXECUTE,READ,CODE + 2 \.data *0*0000 0*0000 0*0(8|10) .* Align: (4|16) READ,WRITE,INITIALIZED DATA + 3 \.bss .* + 4 \.rdata *0*0000 0*0000 0*0(8|10) .* Align: (4|16) READ,INITIALIZED DATA + 5 \.reloc *0*0000 0*0000 0*00c .* Align: 4 READ,INITIALIZED DATA diff --git a/gas/testsuite/gas/pe/reloc.s b/gas/testsuite/gas/pe/reloc.s new file mode 100644 index 00000000000..ddcfeba1d78 --- /dev/null +++ b/gas/testsuite/gas/pe/reloc.s @@ -0,0 +1,19 @@ + .text + .global _start +_start: + .nop + + .section .rdata, "r" + .dc.a _start + .dc.a . + + .data +.L1: .rva _start +.L2: .rva . + + .section .reloc, "r" + .p2align 2 + .rva .data + .long 2 * 4 + 2 * 2 + .short .L1 - .data + (3 << 12) + .short .L2 - .data + (3 << 12) diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp index 2e8cd172820..d30a5627183 100644 --- a/ld/testsuite/ld-pe/pe.exp +++ b/ld/testsuite/ld-pe/pe.exp @@ -137,6 +137,9 @@ run_dump_test "orphan" run_dump_test "orphan_nu" run_dump_test "reloc" +run_dump_test "reloc2a" +run_dump_test "reloc2b" +run_dump_test "reloc2c" run_dump_test "weakdef-1" diff --git a/ld/testsuite/ld-pe/reloc2.s b/ld/testsuite/ld-pe/reloc2.s new file mode 100644 index 00000000000..ddcfeba1d78 --- /dev/null +++ b/ld/testsuite/ld-pe/reloc2.s @@ -0,0 +1,19 @@ + .text + .global _start +_start: + .nop + + .section .rdata, "r" + .dc.a _start + .dc.a . + + .data +.L1: .rva _start +.L2: .rva . + + .section .reloc, "r" + .p2align 2 + .rva .data + .long 2 * 4 + 2 * 2 + .short .L1 - .data + (3 << 12) + .short .L2 - .data + (3 << 12) diff --git a/ld/testsuite/ld-pe/reloc2a.d b/ld/testsuite/ld-pe/reloc2a.d new file mode 100644 index 00000000000..11fe9b69e7e --- /dev/null +++ b/ld/testsuite/ld-pe/reloc2a.d @@ -0,0 +1,35 @@ +#source: reloc2.s +#as: --no-pad-sections +#name: PE .reloc section attributes (builtin+custom) +#ld: --enable-reloc-section --section-align=0x1000 -e _start +#objdump: -hpwPsections + +.*: file format .* + +#... +PE File Base Relocations.* +Virtual Address: .* Number of fixups 2 +[ ]*reloc 0 offset 0 .* HIGHLOW +[ ]*reloc 1 offset [48] .* HIGHLOW + +Virtual Address: .* Number of fixups 2 +[ ]*reloc 0 offset 0 .* (HIGHLOW|DIR64) +[ ]*reloc 1 offset [48] .* (HIGHLOW|DIR64) + +#?private flags = .* + +Section headers.*: + # Name *paddr *vaddr *size .* Flags + 1 \.text *0000.* 0.*000 0*200 .* EXECUTE,READ,CODE + 2 \.data *0000.* 0.*000 0*200 .* READ,WRITE,INITIALIZED DATA + 3 \.rdata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 4 \.idata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 5 \.reloc *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + +Sections: +Idx Name *Size *VMA *LMA *File off .* Flags + 0 \.text *0*(1?4|8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 \.data *0*(8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, DATA + 2 \.rdata *0*0000.. .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 3 \.idata *0*1(4|8) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 \.reloc *0*000018 .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA diff --git a/ld/testsuite/ld-pe/reloc2b.d b/ld/testsuite/ld-pe/reloc2b.d new file mode 100644 index 00000000000..cdd9a181be3 --- /dev/null +++ b/ld/testsuite/ld-pe/reloc2b.d @@ -0,0 +1,32 @@ +#source: reloc2.s RUN_OBJCOPY +#as: --no-pad-sections +#name: PE .reloc section attributes (builtin only) +#objcopy_objects: --rename-section .reloc=.rdata$1 +#ld: --enable-reloc-section --section-align=0x1000 -e _start +#objdump: -hpwPsections + +.*: file format .* + +#... +PE File Base Relocations.* +Virtual Address: .* Number of fixups 2 +[ ]*reloc 0 offset 0 .* (HIGHLOW|DIR64) +[ ]*reloc 1 offset [48] .* (HIGHLOW|DIR64) + +#?private flags = .* + +Section headers.*: + # Name *paddr *vaddr *size .* Flags + 1 \.text *0000.* 0.*000 0*200 .* EXECUTE,READ,CODE + 2 \.data *0000.* 0.*000 0*200 .* READ,WRITE,INITIALIZED DATA + 3 \.rdata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 4 \.idata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 5 \.reloc *0000.* 0.*000 0*200 .* DISCARDABLE,READ,INITIALIZED DATA + +Sections: +Idx Name *Size *VMA *LMA *File off .* Flags + 0 \.text *0*(1?4|8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 \.data *0*(8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, DATA + 2 \.rdata *0*0000.. .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 3 \.idata *0*1(4|8) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 \.reloc *0*00000c .*000 .*000 0*0000... .* CONTENTS, LOAD, READONLY, DATA diff --git a/ld/testsuite/ld-pe/reloc2c.d b/ld/testsuite/ld-pe/reloc2c.d new file mode 100644 index 00000000000..fbc1ab12a47 --- /dev/null +++ b/ld/testsuite/ld-pe/reloc2c.d @@ -0,0 +1,31 @@ +#source: reloc2.s +#as: --no-pad-sections +#name: PE .reloc section attributes (custom only) +#ld: --disable-reloc-section --section-align=0x1000 -e _start +#objdump: -hpwPsections + +.*: file format .* + +#... +PE File Base Relocations.* +Virtual Address: .* Number of fixups 2 +[ ]*reloc 0 offset 0 .* HIGHLOW +[ ]*reloc 1 offset [48] .* HIGHLOW + +#?private flags = .* + +Section headers.*: + # Name *paddr *vaddr *size .* Flags + 1 \.text *0000.* 0.*000 0*200 .* EXECUTE,READ,CODE + 2 \.data *0000.* 0.*000 0*200 .* READ,WRITE,INITIALIZED DATA + 3 \.rdata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 4 \.idata *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + 5 \.reloc *0000.* 0.*000 0*200 .* READ,INITIALIZED DATA + +Sections: +Idx Name *Size *VMA *LMA *File off .* Flags + 0 \.text *0*(1?4|8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 \.data *0*(8|10) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, DATA + 2 \.rdata *0*0000.. .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 3 \.idata *0*1(4|8) .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 \.reloc *0*00000c .*000 .*000 0*0000... .* CONTENTS, ALLOC, LOAD, READONLY, DATA -- 2.47.3