3

I have tried to do this:

patchelf --set-interpreter ../lib/ld-linux-x86-64.so.2 "${APPDIR}/usr/bin/myapp"

so I have this:

readelf -l AppDir/usr/bin/myapp
...
[Requesting program interpreter: ../lib/ld-linux-x86-64.so.2]

But it looks like it does not like the relative path as I get the error:

$  AppDir/usr/bin/myapp 
bash: AppDir/usr/bin/myapp: No such file or directory

I have found this question, as I tried to solve this by using $ORIGIN: Using $ORIGIN to specify the interpreter in ELF binaries isn't working, but it does not answer my question.

Is there a simple way to patch an executable with your certain linker, if you could not know beforehand its absolute path on a machine (e.g. if it's an appimage case)? The only workaround I know is to use path/to/my/ld.so --library-path <path/to/my/libs> path/to/my/exe. But I am just curious, if there is a way to actually patch an executable, so that I could launch it directly?

JenyaKh
  • 2,040
  • 17
  • 25
  • 1
    Just out of curiosity, what is the reason you need a custom loader? The need to change the default is so rare, that I doubt there is a way to do it. A workaround could be to use a shell script with an embedded binary like discussed [here](https://stackoverflow.com/q/18410785/17862371). – Jakob Stark May 25 '22 at 11:05
  • Thank you, @JakobStark! Now I just know that such an approach (as by the link) exists -- very interesting. However, I was hoping for a "static" solution, as an extracted appimage is read-only. I need to put the linker to the appimage, as I put libc.so and other runtime into it. Appimag-ed libc.so is complaining about the system linker not having some symbols, if e.g. you make the appimage at 35 Fedora and then move it to 33 Fedora. I know that carrying libc.so is discouraged, but in my case I have to. – JenyaKh May 25 '22 at 11:17
  • Ok actually I tried it and on my system (Open Suse Leap) it works like charm. Are you sure the paths are correct? – Jakob Stark May 25 '22 at 11:18
  • I meant that you need to create the appimage on a newer system and move it to an older one. Then you, probably, will encounter the problem that you use the 35's libc.so but it will need some symbols from your system linker (33's in my example) and will not find them. – JenyaKh May 25 '22 at 11:21
  • 1
    Ah I think I got it. If you run the application as `AppDir/usr/bin/myapp`, the path is not relative to the location of the binary but to your current working directory. So you should either `cd` into `AppDir/usr/bin` first or specify `./AppDir/usr/lib/ld-linux-x86-64.so.2` as the loader. – Jakob Stark May 25 '22 at 11:22

1 Answers1

3

You need to specify the path relative to the current working directory (the one you use to execute the program) and not relative to the directory that contains the binary file.

echo 'int main() { return 0; }' > main.c
gcc -Wl,--dynamic-linker=./lib/ld-linux-x86-64.so.2 -o main main.c

mkdir bin
mkdir lib
cp /lib64/ld-linux-x86-64.so.2 lib/
cp main bin/

bin/main          # this should run without problems
cd bin; ./main    # this throws a "No such file or directory" error

Jakob Stark
  • 3,346
  • 6
  • 22
  • Yes, I have just checked, and it worked! Thank you! I kinda expected it to be relative the location of the executable, but it looks like it is the current directory. – JenyaKh May 25 '22 at 11:39
  • if there is '$ORIGIN/..' then it is located relative to the location of the executable -- after symlinks resolved (I presume all but cannot be sure), and appararently if relative then relative to the current directory. I had a case where i tried '$ORIGIN/../lib' for a "bin/file" that was symlink to another file elsewhere in filesystem (and not in "sibling" directory). in ths case the '$ORIGIN/../lib' did not work as I expected... – tomi Feb 24 '23 at 10:39