tools / compatibility-checker arch · class · endianglibc · muslsymbol versions readelf -h -V ./app

Compatibility Checker

The failures that look like "the binary is broken" are almost always one of five things: wrong architecture, wrong word size, wrong endianness, wrong libc, or a GLIBC symbol version that is newer than the host provides. This tool checks all five and tells you which one applies.

Binary vs target no upload, no execution
Drop the ELF binary here or click to choose a file

The five failure modes, in order of how often they bite

1. Architecture. e_machine is the only field the kernel checks before handing the file to the loader. A mismatch produces cannot execute binary file: Exec format error — it never reaches ld.so, so no library error will ever appear. On x86-64 hosts a 32-bit binary is a special case: the kernel accepts it if IA-32 emulation is compiled in and the 32-bit loader exists, which is why i386 binaries sometimes run and sometimes do not.

2. Word size. ELFCLASS32 and ELFCLASS64 describe the same file layout with different field widths. A 32-bit object linked into a 64-bit build fails at link time with wrong ELF class; a 32-bit executable on a host without multilib fails at run time with a missing ld-linux.so.2.

3. Endianness. Rare, except when it is not: s390x and big-endian MIPS/PPC are big-endian, everything in the amd64/arm64 world is little-endian. Cross-endian builds fail with the same Exec format error, so it is worth checking before blaming the CPU architecture.

4. Libc family. A binary linked against glibc records /lib64/ld-linux-x86-64.so.2 in PT_INTERP. That path does not exist on Alpine, which uses musl and /lib/ld-musl-x86_64.so.1. The error is no such file or directory — the most misleading message in the whole toolchain, because the binary is right there. The file that is missing is the interpreter.

5. Symbol versions. This is the subtle one. glibc records a version for each exported symbol (GLIBC_2.34, GLIBC_2.38) and a binary records which versions it needs in .gnu.version_r. Symbols are backward compatible, never forward: a binary built on Ubuntu 24.04 will demand GLIBC_2.38 and refuse to start on 22.04 even if every library name matches. The fix is not to copy libraries around; it is to build against the oldest glibc you intend to support, or link statically.

What this check cannot tell you

Static analysis reads what the file declares. It cannot know whether the target host actually has the listed libraries installed, whether ld.so.cache is stale, whether a kernel module is missing, or whether the program will fail at runtime for a functional reason. It is a fast way to rule out the mechanical causes before you start debugging the real one.