This commit modifies the way fields are written in the dynamic
section in order to account the architecture of the target ELF
file. Instead of copying the raw data, use the helper functions
to convert endianness.
Signed-off-by: Bryce Ferguson <bryce.ferguson@rockwellcollins.com>
SHT_NOTE sections can be mapped in memory by PT_NOTE segments. When
rewriting an SHT_NOTE, attempt to also rewrite a matching segment if it
exists.
Note that an ELF can contain multiple SHT_NOTE sections, and a given
PT_NOTE segment can theoretically map multiple contiguous sections.
There are multiple ways this could be handled, the one picked here is to
pre-normalize PT_NOTE segments so that a multi-section segment gets
broken up into multiple separate segments instead.
Also fix (or more like hack around) alignment issues with note sections.
Keeping the original alignment value when possible is important because
it determines how the data within the section needs to be parsed.
Currently patchelf uses the host system's page size (determined at build
time) as the default section load memory alignment. This causes multiple
issues
- Cross-compilation: when using patchelf on ELFs targetting a different
architecture from the host, the host page size is still used by
default.
- Variable page size architectures: ARMv8 systems can be configured in
either 4K, 16K, or 64K page size mode depending on kernel
configuration. An ARMv8 patchelf built on a 4K page size system will
end up creating ELFs that cannot be used on a 64K page size system.
- Reproducibility: the page size of the machine that built patchelf
"leaks" into the binary.
The build time --with-page-size as well as the run time --page-size
options can be used to work around some of these issues. But it's much
better to have patchelf do the right thing without explicit
configuration.
This commit adds support for inferring page size from the ELF header's
"machine" field. The default values are extracted from GNU gold's source
code. Note that both --with-page-size as well as --page-size continue to
work and take precedence on the default value.
When running patchelf on some existing patchelf'd binaries to change to longer
RPATHS, ldd would report the binaries as invalid. The output of objdump -x on
those libraryies should show the top of the .dynamic section is getting trashed,
something like:
0x600000001 0x0000000000429000
0x335000 0x0000000000335000
0xc740 0x000000000000c740
0x1000 0x0000000000009098
SONAME libglib-2.0.so.0
(which should be RPATH and DT_NEEDED entries)
This was tracked down to the code which injects the PT_LOAD section.
The issue is that if the program headers were previously relocated to the end
of the file which was how patchelf operated previously, the relocation code
wouldn't work properly on a second run as it now assumes they're located after
the elf header. This change forces them back to immediately follow the elf
header which is where the code has made space for them.
Should fix https://github.com/NixOS/patchelf/issues/170
and https://github.com/NixOS/patchelf/issues/192
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>