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.
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.