patchelf icon indicating copy to clipboard operation
patchelf copied to clipboard

Using patchelf and llvm-strip in sequence corrupts ELF files

Open mologie opened this issue 2 years ago • 3 comments

Describe the bug

Running patchelf on any ELF file causes llvm-strip-14 to corrupt it afterwards. (One might argue that this is an llvm-strip bug, and it probably is, but patchelf might be able to produce an ELF file in a format that's still processable with LLVM.)

Affects: All patchelf versions from 0.14 to 0.18 that I tested, LLVM 14 and 15

Steps To Reproduce

tl;dr: Run patchelf --set-rpath '$ORIGIN' on any binary, then run llvm-strip with standard args on it. The output is always corrupted.

Use an Ubuntu 22.04 image and install llvm-14-tools for llvm-strip-14. (llvm-15-tools is similarly affected.)

$ wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-x86_64.tar.gz
[...]
$ tar xf patchelf-0.18.0-x86_64.tar.gz
$ export PATH=$PWD/bin:$PATH
$ echo 'int main() { return 0; }' > a.c
$ clang -Os -o a a.c
$ file a
a: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5a1afb6fe3c09ec9355fe3dfe35d4160dadb606d, for GNU/Linux 3.2.0, not stripped
$ ./a
$ llvm-strip --version
llvm-strip, compatible with GNU strip
Ubuntu LLVM version 14.0.0
  
  Optimized build.
  Default target: x86_64-pc-linux-gnu
  Host CPU: skylake
$ clang --version
Ubuntu clang version 14.0.0-1ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ patchelf --version
patchelf 0.18.0
$ llvm-strip -o a.stripped a
$ ./a.stripped
$ patchelf --set-rpath '$ORIGIN' --output a.patched a
$ ./a.patched
$ llvm-strip -o a.patched.stripped a.patched
$ ldd a.patched.stripped
	not a dynamic executable
$ file a.patched.stripped
a.patched.stripped: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5a1afb6fe3c09ec9355fe3dfe35d4160dadb606d, for GNU/Linux 3.2.0, stripped
$ ./a.patched.stripped
[1]    31807 segmentation fault  ./a.patched.stripped

The a.* binaries are attached: patchelf-strip-corruption.tar.gz

Expected behavior

I expected llvm-strip to work. Specifically, I'd have expected the ldd a.patched.stripped command to report that it's still a dynamic executable, and ./a.patched.stripped should not have segfaulted.

patchelf --version output

patchelf 0.18.0

Additional context

Files in this report are from Ubuntu 22.04 x86_64, but it appears to happen on any OS and with any LLVM distribution. Gave Arch Linux x86_64 and Ubuntu for arm64 a shot. Strip from binutils does not corrupt the ELF files.

mologie avatar Jul 14 '23 12:07 mologie

Just hit this bug. I have a script that, after building a couple of shared libraries, executes patchelf --set-rpath '$ORIGIN' then llvm-strip-16 -S, and I got that same result as @mologie:

ubuntu@ubuntu:~/Workspace/native-deps/out/lib$ ldd libpdfium.so 
	not a dynamic executable

Inverting the patchelf call with llvm-strip fixed the issue

HeavenVolkoff avatar Nov 08 '23 22:11 HeavenVolkoff