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.
This commit is contained in:
Jan Beulich
2025-10-10 16:02:50 +02:00
parent 6b7bbb6942
commit 8c41c5e09d
9 changed files with 164 additions and 5 deletions

View File

@@ -920,7 +920,7 @@ _bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
unsigned int unsigned int
_bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out, _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; struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
SCNHDR *scnhdr_ext = (SCNHDR *) out; 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 sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
(this is especially important when dealing with the .idata section since (this is especially important when dealing with the .idata section since
the addresses for routines from .dlls must be overwritten). If .reloc the addresses for routines from .dlls must be overwritten). If .reloc
section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE section data is ever generated, we generally need to add
(0x02000000). Also, the resource data should also be read and IMAGE_SCN_MEM_DISCARDABLE (0x02000000). */
writable. */
/* FIXME: Alignment is also encoded in this field, at least on /* FIXME: Alignment is also encoded in this field, at least on
ARM-WINCE. Although - how do we get the original alignment field 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++) p++)
if (memcmp (scnhdr_int->s_name, p->section_name, SCNNMLEN) == 0) 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") if (memcmp (scnhdr_int->s_name, ".text", sizeof ".text")
|| (bfd_get_file_flags (abfd) & WP_TEXT)) || (bfd_get_file_flags (abfd) & WP_TEXT))
scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE; 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; break;
} }

View File

@@ -38,6 +38,8 @@ run_dump_test "section-exclude"
run_dump_test "set" run_dump_test "set"
run_dump_test "reloc"
if { [istarget "aarch64-*-*"] || [istarget "arm*-*-*"] || [istarget "i*86-*-*"] if { [istarget "aarch64-*-*"] || [istarget "arm*-*-*"] || [istarget "i*86-*-*"]
|| [istarget "x86_64-*-*"] } then { || [istarget "x86_64-*-*"] } then {
run_dump_test "cv_comp" run_dump_test "cv_comp"

View File

@@ -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

View File

@@ -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)

View File

@@ -137,6 +137,9 @@ run_dump_test "orphan"
run_dump_test "orphan_nu" run_dump_test "orphan_nu"
run_dump_test "reloc" run_dump_test "reloc"
run_dump_test "reloc2a"
run_dump_test "reloc2b"
run_dump_test "reloc2c"
run_dump_test "weakdef-1" run_dump_test "weakdef-1"

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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