Given a foreign binary on a Nix system, you have to patch its dynamic linker/loader.
First you need to find out what linker/loader to use.
You can do this by going into your nix repl
and loading your desired nixpkgs
.
Then you run:
"${pkgs.glibc}/lib64/ld-linux-x86-64.so.2"
Which will return you a path that looks like this:
/nix/store/d54amiggq6bw23jw6mdsgamvs6v1g3bh-glibc-2.25-123/lib64/ld-linux-x86-64.so.2
You can then use:
patchelf --set-interpreter '/nix/store/d54amiggq6bw23jw6mdsgamvs6v1g3bh-glibc-2.25-123/lib64/ld-linux-x86-64.so.2' ./binarytobepatched
Or you can run it directly:
/nix/store/d54amiggq6bw23jw6mdsgamvs6v1g3bh-glibc-2.25-123/lib64/ld-linux-x86-64.so.2 ./binarytobepatched
Note that if you are doing this inside a Nix expression, you should be instead using:
$(cat $NIX_CC/nix-support/dynamic-linker)
Note that if you use ldd
on NixOS on an unpatched binary it will probably show:
/lib64/ld-linux-x86-64.so.2 => /nix/store/d54amiggq6bw23jw6mdsgamvs6v1g3bh-glibc-2.25-123/lib64/ld-linux-x86-64.so.2 (0x00007f04fcc29000)
That ld-linux-x86-64.so.2
path is derived from the Glibc that ldd
itself was built with.
Note after patching the interpreter, upon running the binary, you may still fail to load some shared library.
For example, the official released NodeJS (https://nodejs.org/en/download/) are partially statically compiled binaries with some additional shared libraries still required. In particular
libstdc++.so.6
.So after patching the
./bin/node
, and running it, you'll still get something like:This is also revealed by:
And by:
At this point the rpath must be set. However the interpreter and the rpath should probably be set together.