Using $Origin to Specify the Interpreter in Elf Binaries Isn't Working

Using $ORIGIN to specify the interpreter in ELF binaries isn't working

If I specify an absolute path instead of using $ORIGIN then it seems to work fine.

This is working as intended.

It is the dynamic linker that interprets (expands) $ORIGIN and other special tokens.

The Linux kernel doesn't.

And it is the kernel that reads PT_INTERP segment of the main executable and (if present) loads and invokes the interpreter (the dynamic linker). When you set interpreter to non-existant path (such as $ORIGIN/lib/ld-linux-x86-64.so.2), you get ENOENT from the kernel execve system call.

There is no way to make interpreter itself be anything other than valid path.

Depending on what you are actually trying to achieve, rtldi may be the answer.

patchelf set interpreter to a path relative to executable

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

ELF, Build-ID, is there a utility to recompute it?

So, I've got an answer from Mark. Since it is an up to date info, I post it here. But basically you guys are right. Indeed there is no tool for computing Build-ID, and the intentions of Build-ID are not (1) identification of the file contents, and not even (2) identification of the executable (code) part of it, but it is for (3) capturing "semantic meaning" of a build, which is the hard bit for formalization. (Numbers are for self-reference.)

Quote from the email:

-- "Is there a user tool recomputing the build-id from the file itself, to
check if it's not corrupted/compromised somehow etc?"
If you have time, maybe you could post an answer there?


Sorry, I don't have a stackoverflow account.
But the answer is: No, there is no such tool because the precise way a
build-id is calculated isn't specified. It just has to be universally
unique. Even the precise length of the build-id isn't specified. There
are various ways using different hashing algorithms a build-id could be
calculated to get a universally unique value. And not all data might
(still be) in the ELF file to recalculate it even if you knew how it was
created originally.

Apparently, the intentions of Build-ID changed
since the Fedora Feature page was written about
it.
And people's opinions diverge on what it is now.
Maybe in your answer you could include status of Build-ID and what it is
now as well?


I think things weren't very precisely formulated. If a tool changes the
build that creates the ELF file so that it isn't a "semantically
identical" binary anymore then it should get a new (recalculated)
build-id. But if a tool changes something about the file that still
results in a "semantically identical" binary then the build-id stays the
same.

What isn't precisely defined is what "semantically identical binary"
means. The intention is that it captures everything that a build was
made from. So if the source files used to generate a binary are
different then you expect different build-ids, even if the binary code
produced might happen to be the same.

This is why when calculating the build-id of a file through a hash
algorithm you use not just the (allocated) code sections, but also the
debuginfo sections (which will contain references to the source file
names).

But if you then for example strip the debuginfo out (and put it into a
separate file) then that doesn't change the build-id (the file was still
created from the same build).

This is also why, even if you knew the precise hashing algorithm used to
calculate the build-id, you might not be able to recalculate the
build-id. Because you might be missing some of the original data used in
the hashing algorithm to calculate the build-id.

Feel free to share this answer with others.

Cheers,

Mark

Also, for people interested in debuginfo (linux performance & tracing, anyone?), he mentioned a couple projects for managing them on Fedora:

  • https://fedoraproject.org/wiki/Changes/ParallelInstallableDebuginfo
  • https://fedoraproject.org/wiki/Changes/SubpackageAndSourceDebuginfo

GNU C Cross-compiler: Cannot execute binary file

This really looks like a kernel that is configured for pure 64-bit userspace, no i386 support.

This would be CONFIG_IA32_EMULATION in the kernel config. Check /proc/config.gz to confirm.

Multiple glibc libraries on a single host

It is very possible to have multiple versions of glibc on the same system (we do that every day).

However, you need to know that glibc consists of many pieces (200+ shared libraries) which all must match. One of the pieces is ld-linux.so.2, and it must match libc.so.6, or you'll see the errors you are seeing.

The absolute path to ld-linux.so.2 is hard-coded into the executable at link time, and can not be easily changed after the link is done (Update: can be done with patchelf; see this answer below).

To build an executable that will work with the new glibc, do this:

g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

The -rpath linker option will make the runtime loader search for libraries in /path/to/newglibc (so you wouldn't have to set LD_LIBRARY_PATH before running it), and the -dynamic-linker option will "bake" path to correct ld-linux.so.2 into the application.

If you can't relink the myapp application (e.g. because it is a third-party binary), not all is lost, but it gets trickier. One solution is to set a proper chroot environment for it. Another possibility is to use rtldi and a binary editor. Update: or you can use patchelf.

Would there ever be a reason to write code in pure binary?

Historical reason: You are running a machine that requires its boot code to be toggled in on the front panel. (And yes, this was done. Regularly in the first couple of generation of machines.)

Not-what-you-were-looking-for modern reason: When you are writing an assembler you have to figure out the process.



Related Topics



Leave a reply



Submit