[PATCH RFC] bfd/ELF: offset-adjust also the LOAD segment containing the PHDRs
Jan Beulich
jbeulich@suse.com
Tue Dec 24 08:16:02 GMT 2024
On 23.12.2024 02:08, Alan Modra wrote:
> On Fri, Dec 20, 2024 at 02:20:49PM +0100, Jan Beulich wrote:
>> PR binutils/32324
>>
>> Such segments have their file offsets set early. Include the subsequent
>> offset adjustment also there, to maintain proper alignment (as mandated
>> by the input binary).
>> ---
>> RFC: I can't really explain the m->p_align_valid part of the
>> conditional, other than it (or something with the same overall
>> effect) being needed to make the ld-elf/size-2 check pass. Without
>> that extra check the program headers there move by 0x18 bytes. The
>> resulting binary still looks legitimate, just a little odd in
>> having an 24-byte gap _before_ the PHDRs rather than after.
>
> I think it's fine to adjust the testcase. And putting the gap before
> PHDRS makes for a smaller LOAD segment.
>
>> Overall the change still feels like a gross hack, yet considering
>> how convoluted the entire function is, that's surely not the first
>> one there. I'm in trouble here conceptually anyway: When objcopy-
>> ing a fully linked binary, it feels wrong to see VAs be calculated
>> from scratch. VAs may not change in this process, after all (and
>> that they did in the reported case appears to support my view).
>
> Yes, vma changes are suspect. However, rewriting file offsets may
> be required if we allow objcopy/strip to repack the file.
>
>> RFC: Having a testcase for this situation would be nice, but ld won't
>> permit creating an ELF binary with the problematic properties: It
>> demands that if the PHDRs are part of any LOAD segment, they also
>> be part of any earlier ones.
>>
>> --- a/bfd/elf.c
>> +++ b/bfd/elf.c
>> @@ -6057,6 +6057,9 @@ assign_file_positions_for_load_sections
>> == ((off + off_adjust) & -maxpagesize)))
>> off_adjust += maxpagesize;
>> off += off_adjust;
>> + if (m == phdr_load_seg && !m->includes_filehdr && m->p_align_valid)
>> + p->p_offset += off_adjust;
>> +
>> if (no_contents)
>> {
>> /* We shouldn't need to align the segment on disk since
>
> I prefer the following fix, which is equivalent to yours without the
> p_align_valid test. The improvement is keeping all the p_offset
> assignments together.
Ah yes, that looks neater indeed. Thanks for looking into this.
Jan
> commit 49c701d4c667c9bd60c6a707db9fd5f44d2d239e
> Author: Alan Modra <amodra@gmail.com>
> Date: Mon Dec 23 10:26:02 2024 +1030
>
> PR 32324, Stripping BOLT'ed binaries leads to unwanted behaviour
>
> This patch corrects layout for a PT_LOAD header that doesn't include
> the ELF file header but does contain PHDRs and sections requiring
> alignment. The required alignment (which was missing) is placed
> before the PHDRs.
>
> diff --git a/bfd/elf.c b/bfd/elf.c
> index 78394319bf0..9f5ac6384f3 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -5978,11 +5978,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
> p->p_align = 1 << bed->s->log_file_align;
>
> if (m == phdr_load_seg)
> - {
> - if (!m->includes_filehdr)
> - p->p_offset = off;
> - off += actual * bed->s->sizeof_phdr;
> - }
> + off += actual * bed->s->sizeof_phdr;
>
> no_contents = false;
> off_adjust = 0;
> @@ -6131,6 +6127,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
> {
> if (p->p_type == PT_LOAD)
> {
> + p->p_offset = off - actual * bed->s->sizeof_phdr;
> elf_elfheader (abfd)->e_phoff = p->p_offset;
> if (m->count > 0)
> {
> @@ -6141,6 +6138,9 @@ assign_file_positions_for_load_sections (bfd *abfd,
> }
> else if (phdr_load_seg != NULL)
> {
> + /* Also set PT_PHDR to match phdr_load_seg. We've
> + sorted segments so that phdr_load_seg will
> + already be set by the code immediately above. */
> Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx;
> bfd_vma phdr_off = 0; /* Octets. */
> if (phdr_load_seg->includes_filehdr)
> diff --git a/ld/testsuite/ld-elf/size-2.d b/ld/testsuite/ld-elf/size-2.d
> index 9f1a9cf48fa..e3e28cf7a93 100644
> --- a/ld/testsuite/ld-elf/size-2.d
> +++ b/ld/testsuite/ld-elf/size-2.d
> @@ -13,8 +13,8 @@
> .* \.tbss +NOBITS +0+130 [0-9a-f]+ 0+30 00 WAT .*
> .* \.map +PROGBITS +0+130 [0-9a-f]+ 0+c 00 +A .*
> #...
> - +PHDR +(0x0+40 0x0+40 0x0+40 0x0+a8 0x0+a8|0x0+34 0x0+34 0x0+34 0x0+60 0x0+60|0x0+34 0x0+a0 0x0+a0 0x0+60 0x0+60) R .*
> - +LOAD +(0x0+40 0x0+40 0x0+40 0x0+fc 0x0+fc|0x0+34 0x0+34 0x0+34 0x0+1(08|10) 0x0+1(08|10)|0x0+34 0x0+a0 0x0+a0 0x0+9c 0x0+9c) R E .*
> + +PHDR +(0x0+58 0x0+58 0x0+58 0x0+a8 0x0+a8|0x0+(a0|34) 0x0+a0 0x0+a0 0x0+60 0x0+60) R .*
> + +LOAD +(0x0+58 0x0+58 0x0+58 0x0+e4 0x0+e4|0x0+(a0|34) 0x0+a0 0x0+a0 0x0+(9c|a0) 0x0+(9c|a0)) R E .*
> +TLS +0x0+(110|a4) 0x0+110 0x0+110 0x0+20 0x0+50 R .*
> #...
> .* \.text \.tdata \.map
>
More information about the Binutils
mailing list