nixos / patchelf Goto Github PK
View Code? Open in Web Editor NEWA small utility to modify the dynamic linker and RPATH of ELF executables
License: GNU General Public License v3.0
A small utility to modify the dynamic linker and RPATH of ELF executables
License: GNU General Public License v3.0
patchelf --set-rpath /opt/lib /opt/lib/libQtCore.so.4.8.7
warning: working around a Linux kernel bug by creating a hole of 2088960 bytes in ‘/opt/lib//libQtCore.so.4.8.7’
I am using patchelf 0.9
I saw a related bug here: #47 and its fix f6886c2
But that didn't solved my issue.
size of libQtCore.so.4.8.7 is only 3.1 M
We were using patchelf 0.8. but we hit a bug about "working around a Linux kernel bug by creating a hole of".
It was already fixed here f6886c2
For that, we tried to use latest 0.9 downloaded from github.com/releases and having some issues with configure.
Running bootstrap.sh says
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force
autoreconf: configure.ac: tracing
autoreconf: configure.ac: creating directory build-aux
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force --warnings=all
autoreconf: configure.ac: not using Autoheader
autoreconf: running: automake --add-missing --copy --force-missing --warnings=all
configure.ac:4: option `color-tests' not recognized
autoreconf: automake failed with exit status: 1
I am wondering if we could make patchelf binaries simply with a gcc patchelf.cc -o patchelf -lc
#47
My patchelf build using gcc 4.8.3 is failing because gcc -V is no longer an option. I found here that this option was removed around gcc 4.6. Using gcc 4.3.4 worked fine. My config.log file is attached.
E.g. patchelf --removed-needed libnvram.so libfoo.so
would remove libfoo's dependency on libnvram.so.
Thanks!
AFAIK, I can only replace the whole path with --set-rpath
. However, I would like to append / prepend entries to the rpath. I can do print-rpath
but that returns an $ORIGIN
var which is empty when echo
'd (NixOS).
A feature to create a new DT_SONAME would be nice. That could be useful when working with some closed-source libs like FMOD. I'm currently trying but can't get it to work.
Maybe I should try to copy the RPATH void and rework its code so that it modifies soname entries.
That file's 5 years old. I would recommend you to either just delete it, since most unices should have a copy of it anyway, or you download a current copy from GNU libc:
https://www.gnu.org/software/libc/
Fedora Linux distribution started to build all executables as position-independent code.
patchelf fails selftest on such executables (see the 'maximum file size exceeded'):
$ ../src/patchelf --set-interpreter /oops scratch/set-interpreter-short/simple
warning: working around a Linux kernel bug by creating a hole of 18870272 bytes in ‘scratch/set-interpreter-short/simple’
maximum file size exceeded
The reproducer is to call configure as:
$ ./configure CFLAGS='-O0 -fPIE' LDFLAGS='-specs=/usr/lib/rpm/redhat/redhat-hardened-ld' CXXFLAGS='-O0 -fPIE'
The /usr/lib/rpm/redhat/redhat-hardened-ld contains:
*self_spec:
+ %{!shared:%{!r:-pie}}
*link:
+ -z now
Alternatively you can replace LDFLAGS with '-z now' and add '-pie' to LDFLAGS_local variable in tests/Makefile.am (and run autoreconf before ./configure).
Complete test suite results are:
PASS: plain-fail.sh
PASS: plain-run.sh
PASS: shrink-rpath.sh
FAIL: set-interpreter-short.sh
FAIL: set-interpreter-long.sh
FAIL: set-rpath.sh
PASS: no-rpath.sh
FAIL: big-dynstr.sh
FAIL: set-rpath-library.sh
PASS: soname.sh
PASS: no-rpath-amd64.sh
PASS: no-rpath-armel.sh
PASS: no-rpath-armhf.sh
PASS: no-rpath-hurd-i386.sh
PASS: no-rpath-i386.sh
XFAIL: no-rpath-ia64.sh
PASS: no-rpath-kfreebsd-amd64.sh
PASS: no-rpath-kfreebsd-i386.sh
PASS: no-rpath-mips.sh
PASS: no-rpath-mipsel.sh
PASS: no-rpath-powerpc.sh
PASS: no-rpath-s390.sh
PASS: no-rpath-sh4.sh
PASS: no-rpath-sparc.sh
Instead of
patchelf --remove-needed libfoo1.so --remove-needed libfoo2.so bar
I would prefer something like
patchelf --remove-needed libfoo1.so:libfoo2.so bar
And please update the manpage ("--remove-needed" and "--interpreter" aren't mentioned there) and add "-h" as an alternative to "--help", as it has been requested before. "-v" as an alternative to "--version" would be nice too.
edit:
I've seen that vdanjean contributed changes that were added without mentioning him. But you should mention him and other contributors too, no matter if you merged their pull requests or if you manually applied those changes.
I would find useful a --add-needed
option that adds a DT_NEEDED
command. Thanks!
Namely on the dynamically linked qemu-user (non-static) binaries. I'm not sure how Ubuntu compiles them
With the newest version of patchelf compiled:
I try
./patchelf --set-interpreter /path/to/ld-linux.so.2 /path/to/qemu-arm
and get
warning: working around a Linux kernel bug by creating a hole of 33796096 bytes in ‘/path/to/qemu-arm’
maximum file size exceeded
I get the same error with --set-rpath as well on the same binary
patchelf.cc has hard-coded values for pageSize.
I believe it would be more portable if PageSize were
discovered using the getpagesize() function.
Also, when I do code that involves size of any kind,
including page size, I use type, size_t. But, in this
case no one would care. Besides, getpagesize()
returns an int, but that is only because it is old.
Patchelf fails to run its self tests correctly on Fedora Rawhide with ARMV7HL.
http://koji.fedoraproject.org/koji/taskinfo?taskID=5731866
https://bugzilla.redhat.com/show_bug.cgi?id=992432
This is presumably similar to the failure to run self tests on PPC:
https://bugzilla.redhat.com/show_bug.cgi?id=627370
During a --set-rpath operation on a vmware binary (vmware-vmx-debug) I get a "maximum file size exceeded" error. After looking at the code I have seen that the maxSize is calculated adding 32MB to the file size. Is there any reason for this limit?
I'm attempting to create a package for the XCTU application which is distributed only as a Linux binary. Unfortunately, patchelf
seems to barf on it:
patchelf: patchelf.cc:292: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::parse() [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `shstrtabIndex < shdrs.size()' failed.
file
says:
ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped
readelf -a
says:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x46f9f0
Start of program headers: 64 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000300000 0x0000000000300000
0x0000000000170b4e 0x0000000000170b4e R E 100000
LOAD 0x000000000014e508 0x000000000064e508 0x000000000064e508
0x0000000000000000 0x0000000000000000 RW 100000
PAX_FLAGS 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 4
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
No version information found in this file.
This file will generate a segfault / invalid memory read with patchelf:
https://crashes.fuzzing-project.org/patchelf-0.8-invalid-memory-read-Elf64_Phdr
The error messages I get from debugging tools aren't really clear, it seems it is causing some read to some wrong memory that is neither part of the stack or the heap.
Here's the address sanitizer stack trace:
==5570==ERROR: AddressSanitizer: unknown-crash on address 0x8030afdac1201830 at pc 0x00000049ed24 bp 0x7fff61a59e10 sp 0x7fff61a595c0
READ of size 56 at 0x8030afdac1201830 thread T0
#0 0x49ed23 in __asan_memcpy (/tmp/patchelf-0.8/src/patchelf+0x49ed23)
#1 0x521b7b in __gnu_cxx::new_allocator<Elf64_Phdr>::construct(Elf64_Phdr*, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/ext/new_allocator.h:130:28
#2 0x521b7b in void __gnu_cxx::__alloc_traits<std::allocator<Elf64_Phdr> >::construct<Elf64_Phdr>(std::allocator<Elf64_Phdr>&, Elf64_Phdr*, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/ext/alloc_traits.h:189
#3 0x521b7b in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_insert_aux(__gnu_cxx::__normal_iterator<Elf64_Phdr*, std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> > >, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/bits/vector.tcc:361
#4 0x517d8f in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::push_back(Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/bits/stl_vector.h:925:4
#5 0x517d8f in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym>::parse() /tmp/patchelf-0.8/src/patchelf.cc:281
#6 0x4e5ab9 in void patchElf2<ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym> >(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym>&, unsigned int) /tmp/patchelf-0.8/src/patchelf.cc:1105:5
#7 0x4e5ab9 in patchElf() /tmp/patchelf-0.8/src/patchelf.cc:1156
#8 0x4e5ab9 in main /tmp/patchelf-0.8/src/patchelf.cc:1245
#9 0x7faa93de77af in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.21-r1/work/glibc-2.21/csu/libc-start.c:289
#10 0x4190f8 in _start (/tmp/patchelf-0.8/src/patchelf+0x4190f8)
==5570==AddressSanitizer CHECK failed: /var/tmp/portage/sys-devel/llvm-3.7.0/work/llvm-3.7.0.src/projects/compiler-rt/lib/asan/asan_report.cc:347 "((0 && "Address is not in memory and not in shadow?")) != (0)" (0x0, 0x0)
#0 0x4bbf2d in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/tmp/patchelf-0.8/src/patchelf+0x4bbf2d)
#1 0x4c29c3 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/tmp/patchelf-0.8/src/patchelf+0x4c29c3)
#2 0x4b7f66 in __asan::DescribeAddressIfShadow(unsigned long, __asan::AddressDescription*, bool) (/tmp/patchelf-0.8/src/patchelf+0x4b7f66)
#3 0x4b9306 in __asan::DescribeAddress(unsigned long, unsigned long, char const*) (/tmp/patchelf-0.8/src/patchelf+0x4b9306)
#4 0x4bb0eb in __asan_report_error (/tmp/patchelf-0.8/src/patchelf+0x4bb0eb)
#5 0x49ed44 in __asan_memcpy (/tmp/patchelf-0.8/src/patchelf+0x49ed44)
#6 0x521b7b in __gnu_cxx::new_allocator<Elf64_Phdr>::construct(Elf64_Phdr*, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/ext/new_allocator.h:130:28
#7 0x521b7b in void __gnu_cxx::__alloc_traits<std::allocator<Elf64_Phdr> >::construct<Elf64_Phdr>(std::allocator<Elf64_Phdr>&, Elf64_Phdr*, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/ext/alloc_traits.h:189
#8 0x521b7b in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::_M_insert_aux(__gnu_cxx::__normal_iterator<Elf64_Phdr*, std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> > >, Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/bits/vector.tcc:361
#9 0x517d8f in std::vector<Elf64_Phdr, std::allocator<Elf64_Phdr> >::push_back(Elf64_Phdr const&) /usr/lib/gcc/x86_64-pc-linux-gnu/5.2.0/include/g++-v5/bits/stl_vector.h:925:4
#10 0x517d8f in ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym>::parse() /tmp/patchelf-0.8/src/patchelf.cc:281
#11 0x4e5ab9 in void patchElf2<ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym> >(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, unsigned long, unsigned long, Elf64_Dyn, Elf64_Sym>&, unsigned int) /tmp/patchelf-0.8/src/patchelf.cc:1105:5
#12 0x4e5ab9 in patchElf() /tmp/patchelf-0.8/src/patchelf.cc:1156
#13 0x4e5ab9 in main /tmp/patchelf-0.8/src/patchelf.cc:1245
#14 0x7faa93de77af in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.21-r1/work/glibc-2.21/csu/libc-start.c:289
#15 0x4190f8 in _start (/tmp/patchelf-0.8/src/patchelf+0x4190f8)
Hi,
Here is what i do :
patchelf --set-interpreter libs_myexe/ld-linux-x86-64.so.2 ./myexe
After it i check with :
ldd myexe | grep ld-linux
libs_myexe/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f2b025b4000)
It doesn't use the right on when i start the program, because the new path should be the contrary?
ie : /lib64/ld-linux-x86-64.so.2 => libs_myexe/ld-linux-x86-64.so.2
I do something wrong?
Thanks
Hard links are used extensively by gcc and git. See the example below.
$ cc hello.c -o hello
$ ln hello hello2
$ ls -il hello hello2
10099869 -rwxr-xr-x 2 sjackman assembly 7130 Aug 22 13:54 hello
10099869 -rwxr-xr-x 2 sjackman assembly 7130 Aug 22 13:54 hello2
$ patchelf --set-rpath /foo hello
$ ls -il hello hello2
10099870 -rwxr-xr-x 1 sjackman assembly 11226 Aug 22 13:55 hello
10099869 -rwxr-xr-x 1 sjackman assembly 7130 Aug 22 13:54 hello2
$ ls -il hello hello2
10099869 -rwxr-xr-x 2 sjackman assembly 11226 Aug 22 13:55 hello
10099869 -rwxr-xr-x 2 sjackman assembly 11226 Aug 22 13:55 hello2
I'm having trouble setting the RPATH
on a binary when it already has a RUNPATH
, even when the --force-rpath
option is employed. Test case:
cp `which ls` .
readelf -d ./ls | egrep -i "runpath|rpath"
Displays nothing, as ls by default appears to have no rpath or runpath.
patchelf --set-rpath ~/libs ./ls
readelf -d ./ls | egrep -i "runpath|rpath"
Now it displays 0x000000000000001d (RUNPATH) Library runpath: [/home/mpn/libs]
. OK, fine!
Next do:
patchelf --force-rpath --set-rpath ~/libs ./ls
readelf -d ./ls | egrep -i "runpath|rpath"
Expected result: It will display an RPATH for the binary
Actual result: It still displays only a RUNPATH for the binary
My current workaround has been to delete the existing RUNPATH using chrpath -d
(using --set-rpath "" with patchelf doesn't appear to do it, as that looks rather to set RUNPATH to an empty string instead), and then to use --force-rpath
with patchelf. Force-rpath does appear to work when there is no RUNPATH present.
The following command fails on an executable I am trying to patch to run on NixOS:
$ patchelf --set-interpreter /nix/store/ywxpkmy9kagcsvbjjhi46pr4xwpd6sfm-glibc-2.19/lib/ld-linux-x86-64.so.2 --debug server
patching ELF file `server'
replacing section `.interp' with size 80
this is an executable
using replaced section `.interp'
last replaced is 1
looking at section `.interp'
first reserved offset/addr is 0xc00/0x400c00
first page is 0x400000
patchelf: patchelf.cc:693: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
I think the assertion is here.
Here are the headers:
$ readelf -e server
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x41c9f6
Start of program headers: 64 (bytes into file)
Start of section headers: 456 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 7
Size of section headers: 64 (bytes)
Number of section headers: 22
Section header string table index: 13
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400be4 00000be4
000000000000001c 0000000000000000 A 0 0 1
[ 2] .got PROGBITS 0000000000707000 00307000
0000000000000008 0000000000000008 WA 0 0 8
[ 3] .got.plt PROGBITS 0000000000707008 00307008
0000000000000098 0000000000000008 WA 0 0 8
[ 4] .dynsym DYNSYM 0000000000705f50 00305f50
00000000000001f8 0000000000000018 A 5 0 8
[ 5] .dynstr STRTAB 0000000000705c90 00305c90
0000000000000140 0000000000000000 A 0 0 1
[ 6] .gnu.version VERSYM 00000000007059d8 003059d8
000000000000002a 0000000000000002 A 4 0 2
[ 7] .gnu.version_r VERNEED 0000000000705a08 00305a08
0000000000000040 0000000000000000 A 5 2 8
[ 8] .rela.plt RELA 0000000000705dd0 00305dd0
0000000000000180 0000000000000018 A 4 9 8
[ 9] .plt PROGBITS 0000000000705b80 00305b80
0000000000000110 0000000000000010 AX 0 0 4
[10] .hash HASH 0000000000705a48 00305a48
0000000000000074 0000000000000004 A 4 0 8
[11] .rela RELA 00000000007059c0 003059c0
0000000000000018 0000000000000018 A 4 0 8
[12] .dynamic DYNAMIC 00000000007070a0 003070a0
0000000000000130 0000000000000010 WA 5 0 8
[13] .shstrtab STRTAB 0000000000000000 00305ac0
00000000000000bd 0000000000000000 0 0 1
[14] .text PROGBITS 0000000000400c00 00000c00
0000000000189780 0000000000000000 AX 0 0 8
[15] .rodata PROGBITS 000000000058a380 0018a380
000000000017b640 0000000000000000 A 0 0 8
[16] .gosymtab PROGBITS 00000000007059c0 003059c0
0000000000000000 0000000000000000 A 0 0 8
[17] .gopclntab PROGBITS 00000000007059c0 003059c0
0000000000000000 0000000000000000 A 0 0 8
[18] .noptrdata PROGBITS 00000000007071d0 003071d0
000000000000fd38 0000000000000000 WA 0 0 8
[19] .data PROGBITS 0000000000716f08 00316f08
0000000000007888 0000000000000000 WA 0 0 8
[20] .bss NOBITS 000000000071e790 0031e790
0000000000012bb0 0000000000000000 WA 0 0 8
[21] .noptrbss NOBITS 0000000000731340 00331340
0000000002009e00 0000000000000000 WA 0 0 8
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x0000000000000188 0x0000000000000188 R E 1000
INTERP 0x0000000000000be4 0x0000000000400be4 0x0000000000400be4
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x0000000000306108 0x0000000000306108 R E 1000
LOAD 0x0000000000307000 0x0000000000707000 0x0000000000707000
0x0000000000017790 0x0000000002034140 RW 1000
DYNAMIC 0x00000000003070a0 0x00000000007070a0 0x00000000007070a0
0x0000000000000130 0x0000000000000130 RW 8
TLS 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000010 R 8
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .dynsym .dynstr .gnu.version .gnu.version_r .rela.plt .plt .hash .rela .shstrtab .text .rodata .gosymtab .gopclntab
03 .got .got.plt .dynamic .noptrdata .data .bss .noptrbss
04 .dynamic
05
06
Has anyone encountered this before? Is there a workaround? Please let me know if there's anything else I need to do to debug the issue.
At the current master branch branch, the bootstrap is not producing working configure script in Mac OS X 10.9.5.
A pull request has been open to treat this issue at #51 written by Felix Fietkau for the OpenWrt project. It would be great to have this patch upstream so everyone can benefit from it.
Log of errors:
$ ./bootstrap.sh
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: /opt/local/bin/aclocal --force --warnings=all
configure.ac:1: warning: AC_INIT: not a literal: -n 0.8
autoreconf: configure.ac: tracing
configure.ac:1: warning: AC_INIT: not a literal: -n 0.8
autoreconf: configure.ac: creating directory build-aux
autoreconf: configure.ac: not using Libtool
autoreconf: running: /opt/local/bin/autoconf --force --warnings=all
configure.ac:1: warning: AC_INIT: not a literal: -n 0.8
autoreconf: configure.ac: not using Autoheader
autoreconf: running: /opt/local/bin/automake --add-missing --copy --force-missing --warnings=all
configure.ac:1: warning: AC_INIT: not a literal: -n 0.8
configure.ac:6: installing 'build-aux/compile'
configure.ac:4: installing 'build-aux/install-sh'
configure.ac:4: installing 'build-aux/missing'
src/Makefile.am: installing 'build-aux/depcomp'
parallel-tests: installing 'build-aux/test-driver'
autoreconf: Leaving directory `.'
$ ./configure
./configure: line 4: .: filename argument required
.: usage: . filename [arguments]
ldconfig puts a warning on files that were modified with patchelf:
djcj patchelf-master $ sudo src/patchelf --set-rpath /usr/lib /usr/lib/x86_64-linux-gnu/libx264.so.142
djcj patchelf-master $ LANG=C sudo ldconfig
/sbin/ldconfig.real: file /usr/lib/x86_64-linux-gnu/libx264.so.142 is truncated
djcj patchelf-master $
After NixOS/nixpkgs@140e1de:
strings lib/ipsec/libstrongswan.so.0.0.0 | grep XX
XXt&
Before:
$ strings lib/ipsec/libstrongswan.so.0.0.0 | grep XX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
See NixOS/nixpkgs#5045, this causes an undefined symbol error.
404 Not Found
Release patchelf-0.8 doesn't exist.
When ledger 2.6.3 is built with dontPatchELF = true
, it works just fine. If patchelf is run, however, it breaks the rpath of libamounts.so.0
and libledger-2.6.3.so
. Run
ldd $out/bin/ledger
to see the broken paths.
Sorry if this question is off-topic, but I figure anyone working on this project would know the answer (and anyone using this project probably could benefit from the answer).
I'm trying to run Otto on NixOS and I'm blocked by issues #38 and/or #66. So I'm wondering what are the alternatives to PatchELF in cases where it doesn't work?
The only workaround I've come up with so far is to symlink ld-linux-x86-64.so.2
from /nix/store/...
to /lib64/
, which is pretty ugly.
I'll let @abbradar explain the issue since he's tracked it down but the main symptom is this:
$ nix-shell -p linuxPackages.virtualbox --pure --command VBoxManage
VBoxManage: error while loading shared libraries: libstdc++.so.6: wrong ELF class: ELFCLASS32
I was trying to make a function that determined if a program had already the correct runpath set (don't ask...) This should be possible by inspecting the _DYNAMIC
symbol as show here and just looking at my own d_tag == DT_RUNPATH
entry:
http://stackoverflow.com/a/2846736
However, after running a binary through patchelf, it seems like the _DYNAMIC
symbol points to garbage? I haven't investigated more, but I suspect that it just isn't updating that symbol after replacing that ELF header section... if that's the case than probably some other programs that are trying to be clever with _DYNAMIC
-introspection
When I run patchelf --set-rpath '$ORIGIN' libgomp.so.1
(Git master) on this particular shared library:
http://newton.cx/~peter/files/libgomp.so.1 (86 K)
it does not report an error, but it apparently breaks the file. For instance, ldd libgomp.so.1
then reports "not a dynamic executable", and in one case loading the library yields an error of "failed to map segment from shared object".
There's probably something about this particular file where modifying the RPATH entry is not feasible, but in that case patchelf should exit with an error rather than breaking the file.
Modified program header is stored at the end of elf files. But, linker of Android4.1 read program header at the first PAGE in elf.
code of linker~~~~~~~~:
static soinfo *
load_library(const char *name)
{
...
if ((cnt = read(fd, &__header[0], PAGE_SIZE)) < 0) {
DL_ERR("read() failed!");
goto fail;
}
...
if (load_segments(fd, &__header[0], si) < 0) {
goto fail;
}
...
}
static int
load_segments(int fd, void *header, soinfo *si)
{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header;
Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff);
...
}
Please add support for convenient recursive --set-rpath. thank you.
Hello,
I've a dynamically linked binary (it has rpath, it has interpeter), on linux x86_64, that lacks rela.dyn. Patchelf complains as if it couldn't do anything with the binary because it lacks rela.dyn.
The binary comes prebuilt from a software distributor, and I don't have access to its source or its build recipes.
Could patchelf be made to work without rela.dyn section?
Tests failed on mipsel on debian:
FAIL: set-rpath.sh
==================
Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath/main'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 404
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x65e/0x40065e
first page is 0x400000
needed space is 1748
needed space is 1780
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17578 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 290) to offset 0x2dc (size 404)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x470 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5e0 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x688 (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x698 (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6b8 (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6dc (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./main: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL set-rpath.sh (exit status: 1)
FAIL: no-rpath.sh
=================
Kernel page size is 16384 bytes
Kernel page size is 16384 bytes
patching ELF file `scratch/no-rpath/no-rpath'
Kernel page size is 16384 bytes
new rpath is `/foo:/bar:/xxxxxxxxxxxxxxx'
rpath is too long, resizing...
DT_NULL index is 26
replacing section `.dynamic' with size 264
replacing section `.dynstr' with size 234
replacing section `.interp' with size 13
this is an executable
using replaced section `.interp'
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x518/0x400518
first page is 0x400000
needed space is 1336
needed space is 1368
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17252 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 256) to offset 0x1cc (size 264)
rewriting section `.dynstr' from offset 0x4448 (size 207) to offset 0x2d4 (size 234)
rewriting section `.dynsym' from offset 0x4368 (size 224) to offset 0x3c0 (size 224)
rewriting section `.hash' from offset 0x431c (size 76) to offset 0x4a0 (size 76)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x4ec (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x4fc (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x51c (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x540 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
Kernel page size is 16384 bytes
./no-rpath: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
FAIL no-rpath.sh (exit status: 127)
FAIL: big-dynstr.sh
===================
Kernel page size is 16384 bytes
patching ELF file `scratch/big-dynstr/big-dynstr'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/big-dynstr/libsA:/home/fsateler/patchelf/tests/scratch/big-dynstr/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 406
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x65e/0x40065e
first page is 0x400000
needed space is 1752
needed space is 1784
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17578 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 290) to offset 0x2dc (size 406)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x474 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5e4 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x68c (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x69c (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6bc (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6e0 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./big-dynstr: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL big-dynstr.sh (exit status: 1)
FAIL: set-rpath-library.sh
==========================
Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath-library/main-scoped'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 427
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x666/0x400666
first page is 0x400000
needed space is 1772
needed space is 1804
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17586 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 297) to offset 0x2dc (size 427)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x488 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5f8 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x6a0 (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x6b0 (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6d0 (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6f4 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./main-scoped: error while loading shared libraries: libfoo-scoped.so: cannot open shared object file: No such file or directory
Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath-library/libsA/libfoo-scoped.so'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 324
this is a dynamic library
last page is 0x14000
needed space is 948
warning: working around a Linux kernel bug by creating a hole of 65536 bytes in ‘scratch/set-rpath-library/libsA/libfoo-scoped.so’
rewriting section `.dynamic' from offset 0x1cc (size 264) to offset 0x14160 (size 272)
rewriting section `.dynstr' from offset 0x4b0 (size 256) to offset 0x14270 (size 324)
rewriting symbol table section 5
rewriting symbol table section 34
./main-scoped: error while loading shared libraries: libfoo-scoped.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL set-rpath-library.sh (exit status: 1)
Further debug shows that the library is found, it just can't be loaded because there is an invalid MIPS.abiflags:
% LD_DEBUG=all ./scratch/set-rpath-library/main-scoped
27384:
27384: file=libfoo-scoped.so [0]; needed by ./scratch/set-rpath-library/main-scoped [0]
27384: find library=libfoo-scoped.so [0]; searching
27384: search path=/oops/tls/loongson3a:/oops/tls:/oops/loongson3a:/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB (RUNPATH from file ./scratch/set-rpath-library/main-scoped)
27384: trying file=/oops/tls/loongson3a/libfoo-scoped.so
27384: trying file=/oops/tls/libfoo-scoped.so
27384: trying file=/oops/loongson3a/libfoo-scoped.so
27384: trying file=/oops/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/loongson3a/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/loongson3a/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/libfoo-scoped.so
27384: : unknown MIPS.abiflags flags2: 1482184792
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/loongson3a/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/loongson3a/libfoo-scoped.so
27384: trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/libfoo-scoped.so
Further testing shows that this problem happens even when libfoo-scoped has not been touched. The problem appears to be when touching the main-scoped binary. So, I dug up the mentioned header, and indeed it is different in the touched binary:
% readelf -x .MIPS.abiflags ./scratch/set-rpath-library/main-scoped ; readelf -x .MIPS.abiflags main-scoped
Hex dump of section '.MIPS.abiflags':
0x003fc1b4 00000200 01010001 00000000 00000000 ................
0x003fc1c4 00000000 00000000 ........
Hex dump of section '.MIPS.abiflags':
0x004001c8 00000200 01010001 00000000 00000000 ................
0x004001d8 00000000 00000000 ........
Why would patchelf modify a section it is not supposed to?
It seems that edolstra isn't really interrested in working on this tool together with the community. The last official commit was the version bump to 0.8. I forked the master branch and added a lot of changes that had been offered but he didn't commit. All the authors are now mentioned.
If nothing happens here in a while and more people are offering pull requests, I will rename the program to something like "hackelf" or "elfpatch" and bump the version number. Unfortunately I can't program but maybe someone is interrested in helping me?
edit: I already did that. I'm not creative so I called the fork "patchelfmod".
There appears to be a problem with patchelf in hardened Gentoo. The problem is due to the "hole" put in some files, which is done in as described in this comment:
"As a workaround, make sure that the virtual address of our new
PT_LOAD segment relative to the first PT_LOAD segment is equal
to its offset"
In most cases this hole is getting very large (~18MB) and exceeds the maxSize, causing growFile to error out. It's not clear to me what specific feature is causing this. (ASLR is a common cause of bugs.)
for i in {0..100}; do
echo $i
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 --set-rpath /home/linuxbrew/.linuxbrew/lib git
./git --version || break
done
…
62
git version 2.8.0
63
git version 2.8.0
64
bash: ./git: cannot execute binary file: Exec format error
Is it possible for you to change GPL to LGPL? It would help me using your software.
The patchelf "make check" tests fail to execute on linux powerpc64.
PASS: set-interpreter-short.sh
FAIL: set-interpreter-long.sh
FAIL: set-rpath.sh
FAIL: no-rpath.sh
FAIL: big-dynstr.sh
FAIL: set-rpath-library.sh
PASS: soname.sh
This is a blocking issue for the usage of Nix/NixOS on the power architecture.
vks01# cp which git
/tmp
vks01# ./patchelf --set-rpath /Software/Git /tmp/git
vks01# ldd /tmp/git
/tmp/git:
libz.so.1 => not found (0)
libiconv.so.3 => not found (0)
libcrypto.so.1.0.0 => not found (0)
libthr.so.3 => /lib/libthr.so.3 (0x800948000)
libc.so.7 => /lib/libc.so.7 (0x800b6b000)
vks01# ./patchelf --set-rpath /Software/Git/lib /tmp/git
vks01# ldd /tmp/git
/tmp/git:
ldd: /tmp/git: Exec format error
/tmp/git: exit status 1
Please don't stop tagging the project so we downstream packagers can track the updates as usual.
Thanks.
#54 causes problems when patchelf is applied to a binary from other architecture, because the pagesize of the currently running kernel need not be the same for the binary in question. On ppc64el, the following tests fail (as of commit 63296c4):
FAIL: no-rpath-armel.sh
FAIL: no-rpath-armhf.sh
FAIL: no-rpath-hurd-i386.sh
FAIL: no-rpath-i386.sh
FAIL: no-rpath-kfreebsd-i386.sh
All of those fail with the same assertion:
patchelf: patchelf.cc:695: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() [with Elf_Ehdr = Elf32_Ehdr; Elf_Phdr = Elf32_Phdr; Elf_Shdr = Elf32_Shdr; Elf_Addr = unsigned int; Elf_Off = unsigned int; Elf_Dyn = Elf32_Dyn; Elf_Sym = Elf32_Sym]: Assertion `startAddr % getPageSize() == startOffset % getPageSize()' failed.
I'm not sure if the bug is introduced by #54 or just makes it more likely to happen due to sometimes pagesize being larger than 4096, or c4220ea should never really be expected to work, and the correct fix is to somehow get the pagesize from the binary currently being operated on.
It seems to me that patchelf expects the current binaries it operates on to match the current ABI, and that expectation is voided when run over foreign binaries.
Thanks
Hello,
It would be great to add --print-soname
and --set-soname
options to manipulate DT_SONAME
section contents. I will shortly submit a contribution on this issue,
Regards,
Chingis
If I have an ELF binary that is linked to a DSO that uses symbol versioning, then the DSO's SONAME appears in two different places: once as a DT_NEEDED entry, and once in the .gnu.version_r
version requirements section. If I use patchelf --replace-needed
, then it updates the DT_NEEDED entry, but doesn't update the .gnu.version_r
table. The resulting binary is completely broken -- trying to load it triggers an assertion failure inside the dynamic loader, as it tries to check the version of a library that was never loaded:
Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
For example, here's readelf output for a library that's had patchelf --replace-needed libgfortran.so.3 libgfortran-ed201abd.so.3.0.0
run on it:
$ readelf -a lib/python2.7/site-packages/numpy/.libs/libopenblasp-r0-4830d766.2.17.so
[...]
Dynamic section at offset 0x2318100 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgfortran-ed201abd.so.3.0.0]
[...]
Version needs section '.gnu.version_r' contains 4 entries:
Addr: 0x00000000000aff18 Offset: 0x0aff18 Link: 28 (.dynstr)
000000: Version: 1 File: libgfortran.so.3 Cnt: 1
0x0010: Name: GFORTRAN_1.0 Flags: none Version: 7
Notice that the DT_NEEDED entry is correct, but the .gnu.version_r
entry still refers to the original libgfortran.so.3
.
The fix is simple, at least conceptually :-). patchelf --replace-needed
should check for any references to the replaced SONAME inside the .gnu.version_r
section and update it if necessary.
This bug is a show-stopper for a major effort to enable binary distribution of Python packages as a standard feature on Linux -- we need patchelf --replace-needed
to work around this glibc bug or misfeature in the presence of vendored libraries. So FYI, if there's anything we can do to help fix this then we're extremely motivated to do that -- if you don't have time to work on it but can provide hints on where to look then that'd be very much appreciated, or we could probably find some $$ to fund work if that would make a difference...
(Original issue/diagnosis is in pypa/auditwheel#25)
make check
Making check in src
make[1]: Entering directory `/home/admin/nix-boot/patchelf-0.8/src'
make[1]: Nothing to be done for `check'.
make[1]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/src'
Making check in tests
make[1]: Entering directory `/home/admin/nix-boot/patchelf-0.8/tests'
make simple main main-scoped big-dynstr libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so
make[2]: Entering directory `/home/admin/nix-boot/patchelf-0.8/tests'
make[2]: `simple' is up to date.
make[2]: `main' is up to date.
make[2]: `main-scoped' is up to date.
make[2]: `big-dynstr' is up to date.
make[2]: `libfoo.so' is up to date.
make[2]: `libfoo-scoped.so' is up to date.
make[2]: `libbar.so' is up to date.
make[2]: `libbar-scoped.so' is up to date.
make[2]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/tests'
make check-TESTS
make[2]: Entering directory `/home/admin/nix-boot/patchelf-0.8/tests'
make[3]: Entering directory `/home/admin/nix-boot/patchelf-0.8/tests'
PASS: plain-fail.sh
PASS: plain-run.sh
PASS: shrink-rpath.sh
PASS: set-interpreter-short.sh
FAIL: set-interpreter-long.sh
PASS: no-rpath.sh
FAIL: set-rpath.sh
FAIL: big-dynstr.sh
FAIL: set-rpath-library.sh
make[4]: Entering directory `/home/admin/nix-boot/patchelf-0.8/tests'
make[4]: Nothing to be done for `all'.
make[4]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/tests'
============================================================================
Testsuite summary for patchelf 0.8
============================================================================
# TOTAL: 9
# PASS: 5
# SKIP: 0
# XFAIL: 0
# FAIL: 4
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
============================================================================
make[3]: *** [test-suite.log] Error 1
make[3]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/tests'
make[2]: *** [check-TESTS] Error 2
make[2]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/tests'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/home/admin/nix-boot/patchelf-0.8/tests'
make: *** [check-recursive] Error 1
Running patchelf
to enlarge my RUNPATH entry causes my section headers to change from this:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000000064 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400300 00000300
00000000000011b8 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004014b8 000014b8
0000000000000868 0000000000000000 A 0 0 1
...
To this:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .dynsym DYNSYM 00000000003ffb00 001ffb00
00000000000011b8 0000000000000018 A 2 1 8
[ 2] .dynstr STRTAB 00000000003ff270 00000270
0000000000000890 0000000000000000 A 0 0 8
[ 3] .gnu.hash GNU_HASH 0000000000400cb8 00001cb8
0000000000000064 0000000000000000 A 1 0 8
[ 4] .interp PROGBITS 0000000000400d20 00001d20
000000000000001c 0000000000000000 A 0 0 8
[ 5] .note.ABI-tag NOTE 0000000000400d40 00001d40
0000000000000020 0000000000000000 A 0 0 8
[ 6] .note.gnu.build-i NOTE 0000000000400d60 00001d60
0000000000000024 0000000000000000 A 0 0 8
...
This confuses tools such as strip
because they use a header offset of 0 as an error code; here's the relevant function assign_file_positions_for_non_load_sections
in elf.c from binutils. Running e.g. gdb --args strip -g my_binary
, and setting a breakpoint at that position shows that we get a valid section, but since its filepos
is equal to zero, binutils ignores it and continues on, getting confused. Note that even readelf
gets a little confused by this, as it doesn't even list the .dynsym
segment:
$ readelf -l my_binary
...
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .data.rel.ro .dynamic .got
$ readelf my_patched_binary
...
Section to Segment mapping:
Segment Sections...
00
01
02 .dynstr
03 .gnu.hash .interp .note.ABI-tag .note.gnu.build-id .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
04
05 .interp
06 .eh_frame_hdr
07 .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
08 .init_array .fini_array .jcr .data.rel.ro .dynamic .got
09 .dynamic
I theorize that if we keep the .interp
section at the beginning of the file, we might be able to still use tools such as strip
, but I don't actually know. Is there an easy way to permute the order of headers that patchelf
outputs? If you can just point me in the direction of how to do this, I can submit a PR.
I have a binary compiled with the Go 1.4 compiler from nixpkgs
, and I'd like to run it outside of a nix environment, so I'm trying to patch the interpreter.
patchelf 0.8 gives the following error:
$ patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 prog
patchelf: patchelf.cc:693: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
Aborted
Which I think was fixed in pull 39.
I built a patchelf from master @ 63296c4, and I now get a different error:
./result/bin/patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 --debug prog
patching ELF file `prog'
Kernel page size is 4096 bytes
replacing section `.interp' with size 28
this is an executable
using replaced section `.interp'
last replaced is 2
looking at section `'
replacing section `' which is in the way
looking at section `.interp'
first reserved offset/addr is 0xc00/0x400c00
first page is 0x400000
needed space is 600
clearing first 2504 bytes
cannot find section
headers:
$ readelf -e prog
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x43dee0
Start of program headers: 64 (bytes into file)
Start of section headers: 568 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 11
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000400c00 00000c00
000000000029d3fb 0000000000000000 AX 0 0 16
[ 2] .plt PROGBITS 000000000069e000 0029e000
0000000000000170 0000000000000010 AX 0 0 4
[ 3] .rodata PROGBITS 000000000069f000 0029f000
00000000001cd6c0 0000000000000000 A 0 0 32
[ 4] .typelink PROGBITS 000000000086c6c0 0046c6c0
0000000000001308 0000000000000000 A 0 0 8
[ 5] .gosymtab PROGBITS 000000000086d9c8 0046d9c8
0000000000000000 0000000000000000 A 0 0 1
[ 6] .gopclntab PROGBITS 000000000086d9e0 0046d9e0
00000000000f879d 0000000000000000 A 0 0 32
[ 7] .rela RELA 0000000000966180 00566180
0000000000000018 0000000000000018 A 14 0 8
[ 8] .gnu.version VERSYM 00000000009661a0 005661a0
0000000000000038 0000000000000002 A 14 0 2
[ 9] .gnu.version_r VERNEED 00000000009661e0 005661e0
0000000000000040 0000000000000000 A 12 2 8
[10] .hash HASH 0000000000966220 00566220
0000000000000090 0000000000000004 A 14 0 8
[11] .shstrtab STRTAB 0000000000000000 005662c0
0000000000000185 0000000000000000 0 0 1
[12] .dynstr STRTAB 0000000000966460 00566460
0000000000000189 0000000000000000 A 0 0 1
[13] .rela.plt RELA 0000000000966600 00566600
0000000000000210 0000000000000018 A 14 2 8
[14] .dynsym DYNSYM 0000000000966820 00566820
00000000000002a0 0000000000000018 A 12 0 8
[15] .got PROGBITS 0000000000967000 00567000
0000000000000008 0000000000000008 WA 0 0 8
[16] .got.plt PROGBITS 0000000000967020 00567020
00000000000000c8 0000000000000008 WA 0 0 8
[17] .dynamic DYNAMIC 0000000000967100 00567100
0000000000000130 0000000000000010 WA 12 0 8
[18] .noptrdata PROGBITS 0000000000967240 00567240
0000000000015eac 0000000000000000 WA 0 0 32
[19] .data PROGBITS 000000000097d100 0057d100
0000000000006f90 0000000000000000 WA 0 0 32
[20] .bss NOBITS 00000000009840a0 005840a0
0000000000009520 0000000000000000 WA 0 0 32
[21] .noptrbss NOBITS 000000000098d5c0 0058d5c0
0000000000013448 0000000000000000 WA 0 0 32
[22] .interp PROGBITS 0000000000400bb0 00000bb0
0000000000000050 0000000000000000 A 0 0 1
[23] .symtab SYMTAB 0000000000000000 00585000
00000000000340f8 0000000000000018 24 195 8
[24] .strtab STRTAB 0000000000000000 005b90f8
0000000000044f9a 0000000000000000 0 0 1
[25] .tbss NOBITS 0000000000000000 00000000
0000000000000010 0000000000000000 WAT 0 0 8
[26] .debug_abbrev PROGBITS 0000000000000000 005fe092
00000000000000fd 0000000000000000 0 0 1
[27] .debug_line PROGBITS 0000000000000000 005fe18f
00000000000386b7 0000000000000000 0 0 1
[28] .debug_frame PROGBITS 0000000000000000 00636846
00000000000409a4 0000000000000000 0 0 1
[29] .debug_info PROGBITS 0000000000000000 006771ea
000000000010c120 0000000000000000 0 0 1
[30] .debug_pubnames PROGBITS 0000000000000000 0078330a
000000000004cf2d 0000000000000000 0 0 1
[31] .debug_pubtypes PROGBITS 0000000000000000 007d0237
000000000001d88b 0000000000000000 0 0 1
[32] .debug_aranges PROGBITS 0000000000000000 007edac2
0000000000000030 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R 1000
INTERP 0x0000000000000bb0 0x0000000000400bb0 0x0000000000400bb0
0x0000000000000050 0x0000000000000050 R 1
[Requesting program interpreter: /nix/store/q0m70q5wg21hxrixkp1xk4x95sfs2fln-glibc-2.21/lib/ld-linux-x86-64.so.2]
LOAD 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x000000000029e130 0x000000000029e130 R E 1000
LOAD 0x000000000029f000 0x000000000069f000 0x000000000069f000
0x00000000002c7ac0 0x00000000002c7ac0 R 1000
LOAD 0x0000000000567000 0x0000000000967000 0x0000000000967000
0x000000000001d0a0 0x0000000000039a08 RW 1000
DYNAMIC 0x0000000000567100 0x0000000000967100 0x0000000000967100
0x0000000000000130 0x0000000000000130 RW 8
TLS 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000010 R 8
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 8
LOOS+5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 8
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .text .plt .interp
03 .rodata .typelink .gosymtab .gopclntab .rela .gnu.version .gnu.version_r .hash .shstrtab .dynstr .rela.plt .dynsym
04 .got .got.plt .dynamic .noptrdata .data .bss .noptrbss
05 .dynamic
06 .tbss
07
08
The last version tag is for 0.6, but it looks like 0.8 is the most recent release. Could you please add the tags for 0.7 and 0.8?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.