patchelf icon indicating copy to clipboard operation
patchelf copied to clipboard

Align startOffset with p_align instead of pagesize for compatibility

Open yuta-hayama opened this issue 2 years ago • 0 comments

According to the ELF specification, the alignment of loadable process segments should satisfy (p_vaddr mod pagesize) == (p_offset mod pagesize).

By 9f1c0af97b947687d3f916e10baa405b11d57584, p_align of the LOAD segment newly added by patchelf is no longer a fixed value pagesize. Then patchelf calculates p_offset to satisfy (p_vaddr mod pagesize) == (p_offset mod pagesize) according to the ELF specification. (p_offset is rounded up by pagesize.)

However, glibc earlier than 2.35 incorrectly requires that the LOAD segment be (p_vaddr mod p_align) == (p_offset mod p_align). Since patchelf rounds up p_vaddr by p_align, (p_vaddr mod p_align) == 0, but if p_align is not equal to pagesize, (p_offset mod p_align) == 0 may not be true. glibc will output the following error message if the LOAD segment does not satisfy the alignment requirement.

ELF load command address/offset not properly aligned

This is the commit when the issue is fixed in glibc. https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=163f625cf9becbb82dfec63a29e566324129c0cd

Now, this is a regression caused by an older glibc, and the output of patchelf is correct in terms of the ELF specification. However, there are many systems that use glibc earlier than 2.35 (such as Ubuntu 20.04). For compatibility, it is preferable to calculate p_offset according to glibc requirements.

Note that patchelf always places the section to be rewritten at the end of the file, as described in the comment at the top of rewriteSectionsLibrary(). This can be a problem when p_align is large (For example, gcc on Ubuntu 18.04 seems to output a binary with p_align=0x200000) because the output file size expands per unit of p_align each time rewriteSectionsLibrary() is called.

Although, considering the restrictions of glibc, I think the code intended by 9f1c0af97b947687d3f916e10baa405b11d57584 would be like this. To solve the problem of file size growth, it will be necessary to change the concept of "for dynamic libraries, we just place the replacement sections at the end of the file". For example, if a section rewrite results in a LOAD segment where no section is placed, then the section to be rewritten could be placed over it.

This may resolve issue #492.

yuta-hayama avatar Jul 31 '23 05:07 yuta-hayama