`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.
The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is present, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.
When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.
This commit adds the necessary update.
In the corner case when DT_MIPS_RLD_MAP_REL is present, but
.rld_map section is not, the dynamic loader writes the debug
pointer to some arbitrary bytes in memory. To avoid crushes
on otherwise "working" binaries, we set offset to zero
so that the dynamic loader would just overwrite the dynamic
section.
Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.
Refs: #82
Signed-off-by: Ivan A. Melnikov <iv@altlinux.org>
Add a testcase for the following reported alignment issue with contiguous note
sections (#275):
"""
If a binary has multiple SHT_NOTE sections and corresponding PT_NOTE
headers, we can see the error:
patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
if the SHT_NOTE sections aren't sized to end on aligned boundaries. An example
would be a binary with:
[ 2] .note.ABI-tag NOTE 00000000000002f4 000002f4
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.propert NOTE 0000000000000318 00000318
0000000000000030 0000000000000000 A 0 0 8
[ 4] .note.gnu.build-i NOTE 0000000000000348 00000348
0000000000000024 0000000000000000 A 0 0 4
NOTE 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x0000000000000030 0x0000000000000030 R 0x8
NOTE 0x00000000000002f4 0x00000000000002f4 0x00000000000002f4
0x0000000000000078 0x0000000000000074 R 0x4
since the PT_NOTE section at 2f4 covers [2] and [3] but the code
calclates curr_off should be 314, not the 318 in the binary. This
is an alignment issue.
"""
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Add a testcase for the following reported alignment issue with contiguous note
sections (#275):
"""
If a binary has multiple SHT_NOTE sections and corresponding PT_NOTE
headers, we can see the error:
patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
if the SHT_NOTE sections aren't sized to end on aligned boundaries. An example
would be a binary with:
[ 2] .note.ABI-tag NOTE 00000000000002f4 000002f4
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.propert NOTE 0000000000000318 00000318
0000000000000030 0000000000000000 A 0 0 8
[ 4] .note.gnu.build-i NOTE 0000000000000348 00000348
0000000000000024 0000000000000000 A 0 0 4
NOTE 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x0000000000000030 0x0000000000000030 R 0x8
NOTE 0x00000000000002f4 0x00000000000002f4 0x00000000000002f4
0x0000000000000078 0x0000000000000074 R 0x4
since the PT_NOTE section at 2f4 covers [2] and [3] but the code
calclates curr_off should be 314, not the 318 in the binary. This
is an alignment issue.
"""
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Parsing this file results in patchelf segfaulting at:
Program received signal SIGSEGV, Segmentation fault.
std::vector<Elf32_Phdr, std::allocator<Elf32_Phdr> >::_M_realloc_insert<Elf32_Phdr const&> (this=0x7fffffff80a8, __position=..., __args=...)
at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/vector.tcc:449
449 _Alloc_traits::construct(this->_M_impl,
(gdb) bt
at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/vector.tcc:449
at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/stl_vector.h:1195
this=0x7fffffff8088, fileContents=...) at patchelf.cc:421
Parsing this file results in patchelf segfaulting at:
at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/char_traits.h:335
at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/basic_string.h:527
this=0x7fffffff8028, fileContents=...) at patchelf.cc:449
The comment in the code below the patched line
clearly suggests that it should go on in this case.
This condition occurs on Alpine Linux (musl-libc-based):
http://patchwork.alpinelinux.org/patch/2206/
Fixes#97. In essence, the problem is that some packages in Nixpkgs have
RPATHs pointing to both $NIX_BUILD_TOP and $out, e.g.:
/tmp/nix-build-openldap-2.4.44.drv-0/openldap-2.4.44/libraries/libldap_r/.libs
/tmp/nix-build-openldap-2.4.44.drv-0/openldap-2.4.44/libraries/liblber/.libs
/nix/store/bfkmdxmv3a3f0g3d2q8jkdz2wam93c5z-openldap-2.4.44/lib
/nix/store/bfkmdxmv3a3f0g3d2q8jkdz2wam93c5z-openldap-2.4.44/lib64
Currently, running `patchelf --shrink-rpath` does the wrong thing by
keeping the /tmp/ paths and deleting the /nix/store ones. Now we can fix
the problem by using
patchelf --shrink-rpath --allowed-rpath-prefixes $NIX_STORE_DIR
in the Nixpkgs fixupPhase instead.
This leads to numerous build failures:
http://hydra.nixos.org/eval/1136585
because ELF interpreter names are not unique (e.g. ld-linux.so.2 is
used on systems other than i686-linux).
* compile locally this test in the no-rpath test
* add tests for prebuilt no-rpath binaries on various ELF platforms
=> ia64 does not work, probably a bug in patchelf. Marking it as XFAIL for now
- add options in AM_INIT_AUTOMAKE to be more strict
and to enable more advanced features (color-tests and parallel-tests)
- rewrite tests/Makefile.am to use automake rules for building program and libraries
=> we can now do:
./bootstrap.sh && mkdir build && cd build && ../configure && make -j distcheck
- use Makefile variables $< (and $@) so that sources are found correctly
- use ${srcdir} in test scripts to find the sources
This allows "make distcheck" to successfully pass