Glossary of Terms

Understanding API and ABI in Linux OS and Applications

By the Domain India teamPublished 10 min read
Knowledge base article
Contents (9 sections)

"API" and "ABI" sound alike, but they break in different ways. An API change stops your code from compiling; an ABI change lets it compile and then crashes it, or stops a program you downloaded from starting at all. This guide explains both in the Linux context, shows how to inspect them on a real binary, and explains the error messages you will meet when an ABI does not match.

Key takeaways

An API (application programming interface) is the source-code contract: the functions, types and headers you write code against. An ABI (application binary interface) is the machine-level contract that compiled code relies on: calling conventions, data sizes, the ELF file format, system call numbers and versioned library symbols. Keep the API stable and your users can recompile; keep the ABI stable and they don't need to. On Linux the kernel keeps its user-space ABI stable, glibc stays backward compatible through symbol versioning, and most "GLIBC not found" or "cannot open shared object file" errors are ABI mismatches.

1. What an API is

An API is the set of functions, data types and constants that one piece of software offers another, described at the source level. In C on Linux, it is what the header files declare:

  • the C standard library and POSIX functions, such as printf, open, read and fork;
  • library APIs, such as OpenSSL's or libcurl's functions;
  • the system call interface, which user programs normally reach through glibc wrappers rather than directly.

An API tells a programmer what to call and what arguments to pass. It says nothing about which CPU register an argument travels in.

2. What an ABI is

An ABI is the contract between pieces of compiled code. Two binaries share an ABI when they agree on:

Calling convention
How arguments and return values are passed. On x86-64 Linux (the System V ABI), the first six integer or pointer arguments go in registers rdi, rsi, rdx, rcx, r8 and r9.
Data layout
The size and alignment of types and the layout of structs. 64-bit Linux uses LP64: int is 4 bytes, long and pointers are 8.
Binary format
Executables and shared libraries use ELF, with a header stating the CPU architecture.
System calls
Each system call has a number and a register convention; on x86-64 the number goes in rax and the syscall instruction enters the kernel.
Symbols and versions
Function names in the binary, C++ name mangling, and version tags such as GLIBC_2.34 on library symbols.
Libraries needed
The shared libraries a program asks for by soname, such as libc.so.6 or libssl.so.3.

3. API and ABI side by side

QuestionAPIABI
LevelSource codeCompiled machine code
Defined byHeaders and documentationArchitecture, compiler, C library and linker conventions
A breaking change meansCode no longer compilesOld binaries crash or refuse to load
Fix for the userChange the code, recompileRecompile, or install the matching library version
Example changeA function gains a parameterA struct gains a field, changing its size

An API change can keep the ABI intact (adding a new function), and an ABI change can keep the API intact (adding a field to a struct that callers allocate themselves). That second case is the dangerous one: the code still compiles, so nobody notices until an old binary misreads memory.

4. A worked example

Take the classic program:

c
#include <stdio.h>

int main(void) {
    printf("Hello, Linux!\n");
    return 0;
}

printf and stdio.h are the API. Compile it and inspect the ABI facts the compiler recorded:

bash
gcc hello.c -o hello
file hello                  # ELF 64-bit LSB pie executable, x86-64, dynamically linked
readelf -d hello | grep NEEDED    # Shared library: [libc.so.6]
objdump -T hello | grep GLIBC     # e.g. puts with version GLIBC_2.2.5
ldd hello                   # where each needed library is found on this system

Two things stand out. The compiler replaced printf with puts, because the string has no format specifiers: the API you wrote is not always the symbol that ends up in the binary. And the symbol carries a version tag. The binary will run on any system whose glibc provides at least that version of every symbol it uses. Build it on a system with glibc 2.34 or newer and you will also see __libc_start_main tagged GLIBC_2.34, so even this hello-world will not start on an older system.

5. How Linux keeps ABIs stable

  • The kernel's user-space ABI is stable. System call numbers and behaviour are not changed in ways that break existing programs, which is why a binary built years ago can still run on a current kernel.
  • The kernel's internal API and ABI are not stable. Kernel modules must be rebuilt for each kernel version; tools such as DKMS automate this for drivers.
  • glibc is backward compatible through symbol versioning. When a function's behaviour changes, glibc keeps the old version alongside the new one. Programs built against an older glibc run on newer systems, but not the other way round.
  • Shared libraries signal ABI breaks with the soname. libssl.so.3 and libssl.so.1.1 are different ABIs; a program built for one cannot load the other.
  • C++ adds its own ABI questions: name mangling, the layout of standard library types, and exceptions. GCC's libstdc++ has used a newer ABI for std::string and std::list since GCC 5, while keeping the old one available.

6. ABI errors you will actually see

ErrorWhat it meansUsual fix
version GLIBC_2.xx not foundThe binary was built on a newer system than the one running itBuild on the oldest system you support, or run a newer OS
error while loading shared libraries: libX.so.NA library at that soname is not installedInstall the matching library version, or rebuild
Exec format errorThe binary is for a different CPU architecture, such as arm64 on x86-64Download or build for the right architecture
Crash only after a library upgradeThe library changed its ABI without changing its sonameRebuild against the new version; report it upstream
Module compiled against a different Node.js versionA native add-on was built for another Node.js ABIReinstall dependencies, or use add-ons built on Node-API

Distributions built on musl libc, such as Alpine Linux, have a different C library ABI from glibc systems, so a glibc binary will not run there unchanged. Language ecosystems handle this with tagged builds: Python wheels are labelled manylinux (glibc) or musllinux, and Node.js native add-ons built on Node-API keep working across Node.js versions.

7. Good practice for developers

  1. Version your API with semantic versioning.
    A backward-incompatible change means a new major version.
  2. Bump the soname when the ABI breaks.
    Users of the old library keep working, because both can be installed side by side.
  3. Hide struct layouts behind opaque pointers
    in public C APIs, so you can add fields without an ABI break.
  4. Build release binaries on the oldest system you support
    , usually inside a container, so they don't depend on newer glibc symbols.
  5. Check ABI changes automatically.
    Tools such as libabigail's abidiff compare two builds of a library and report incompatible changes before release.
Static linking is not a free pass

Linking everything statically avoids missing-library errors, but you then ship your own copy of every library, including their security bugs, and some glibc features still expect a matching system library. Containers are usually the cleaner way to control the whole user-space ABI.

8. Running this on Domain India

  • Shared hosting (cPanel, DirectAdmin, Webuzo): jailed SSH access is available on every shared hosting plan. It is off by default; ask support to enable it for your account, and log in with an SSH key. You cannot install system libraries, and tools available inside the jailed shell vary; ask support. The cPanel and DirectAdmin servers run CloudLinux 8 (measured September 2026), so a binary built on a much newer distribution may fail with a GLIBC error; run ldd --version over SSH to see the glibc version before you upload one. PHP's process functions are disabled on cPanel, so PHP cannot launch uploaded programs; see PHP disabled functions on shared hosting. Enabling and accessing jailed SSH covers access.
  • App Platform: you control the whole user-space ABI through your Dockerfile's base image; Node.js apps are detected automatically and other languages deploy with a Dockerfile. See App Platform: getting started.
  • VPS: a self-managed server with root access and no cPanel, where you choose the distribution, install libraries and build software yourself.
App Starter
₹100/mo + GST
  • 512 MB RAM per app
  • 1 vCPU
  • 5 GB NVMe SSD
  • PostgreSQL Database
See plan details

Frequently asked questions

What is the difference between an API and an ABI?

An API is the source-code contract: the functions, types and headers you write code against. An ABI is the binary contract: calling conventions, data sizes, the executable format and versioned symbols that compiled code depends on. An API break stops code compiling; an ABI break makes existing binaries fail.

What does "version GLIBC_2.xx not found" mean?

The program was compiled on a system with a newer glibc and uses a symbol version the running system does not have. Rebuild it on an older system or in a container that matches the target, or run it on a newer operating system.

Is the Linux kernel ABI stable?

The interface between the kernel and user programs, mainly system calls, is kept stable so old binaries keep running. The kernel's internal interfaces for modules are not stable, so modules must be rebuilt for each kernel version.

Can a binary built on Ubuntu run on another Linux distribution?

Often, if both use the same CPU architecture, the target's glibc is at least as new as the one it was built against, and the same shared library versions are installed. It will not run unchanged on musl-based distributions such as Alpine.

What is a soname?

The name a shared library advertises for its ABI, such as libssl.so.3. Programs record the soname they need, and a library changes its soname when it breaks its ABI, so old and new versions can be installed side by side.

Does static linking solve ABI problems?

It avoids missing shared libraries, but it bundles copies of every library, including their security bugs, and does not remove every dependency on the system. Building in a container that matches your target is usually a better fix.

Can I run my own compiled programs on Domain India shared hosting?

Jailed SSH is available on request on every shared plan, with key login, but you cannot install system libraries and the tools inside the jail vary, so ask support first. For full control of libraries, use the App Platform with a Dockerfile or a self-managed VPS.

Ready to run your own builds? Deploy with a Dockerfile on the App Platform, take full control on a VPS, or open a support ticket to ask about jailed SSH on your shared hosting.

Run your app with the libraries it needs

Deploy from a Dockerfile and choose your own base image, without managing a server.

See the App Platform

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app