Align startOffset with p_align instead of pagesize for compatibility #510
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
According to the ELF specification, the alignment of loadable process segments should satisfy
(p_vaddr mod pagesize) == (p_offset mod pagesize)
.By 9f1c0af,
p_align
of the LOAD segment newly added by patchelf is no longer a fixed value pagesize. Then patchelf calculatesp_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 upp_vaddr
byp_align
,(p_vaddr mod p_align) == 0
, but ifp_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.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 whenp_align
is large (For example, gcc on Ubuntu 18.04 seems to output a binary withp_align=0x200000
) because the output file size expands per unit ofp_align
each timerewriteSectionsLibrary()
is called.Although, considering the restrictions of glibc, I think the code intended by 9f1c0af 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.