Case 50: SONAME Inconsistent (Wrong Major Version)¶
| Field | Value |
|---|---|
| Verdict | ๐ข COMPATIBLE |
| Category | Quality (Compatible) |
| Platforms | Linux |
| Flags | Bad practice |
Detected ChangeKinds |
โ |
| Source files | browse on GitHub |
Policy verdict: ๐ก BAD PRACTICE | ABI compatibility verdict: COMPATIBLE
What this case is about¶
Both libraries export the same symbols with identical signatures. The difference
is in the DT_SONAME metadata: v1 uses libfoo.so.0 while the project release
version is 1.x (implying the correct SONAME should be libfoo.so.1).
This is a policy-level bad practice: the SONAME is present (unlike Case 05) but does not follow the convention of matching the ABI epoch / major version.
Why SONAME inconsistency is bad practice¶
- Package managers (dpkg, rpm) use SONAME to generate dependency lists.
A wrong SONAME major means packages depend on the wrong
libfoo.so.0and will fail to findlibfoo.so.1after a correct upgrade. - Parallel installation is broken:
libfoo.so.0andlibfoo.so.1are meant to coexist, but if the library was alwayslibfoo.so.0, upgrading to the real ABI epoch1forces unnecessary coordinated rebuilds. - ldconfig creates symlinks based on SONAME. A stale SONAME means the wrong symlink tree, breaking runtime lookup for correctly-linked binaries.
What abicheck detects¶
SONAME_CHANGED: The SONAME differs between v1 and v2 (.so.0vs.so.1). This is classified as a metadata change. Because the actual symbols and types are identical, the functional ABI is compatible.
Policy verdict: ๐ก BAD PRACTICE (SONAME mismatch is a packaging/upgrade hazard). ABI compatibility verdict: COMPATIBLE (same ABI surface; symbols and types identical).
How to reproduce¶
# Build both variants
gcc -shared -fPIC -g bad.c -o libbad.so -Wl,-soname,libfoo.so.0
gcc -shared -fPIC -g good.c -o libgood.so -Wl,-soname,libfoo.so.1
# Verify SONAME
readelf -d libbad.so | grep SONAME
# โ (SONAME) Library soname: [libfoo.so.0] โ wrong major
readelf -d libgood.so | grep SONAME
# โ (SONAME) Library soname: [libfoo.so.1] โ correct
# Run abicheck
python3 -m abicheck.cli dump libbad.so -o /tmp/v1.json
python3 -m abicheck.cli dump libgood.so -o /tmp/v2.json
python3 -m abicheck.cli compare /tmp/v1.json /tmp/v2.json
# โ COMPATIBLE + SONAME_CHANGED note
How to fix¶
Set SONAME to match your project's ABI major version:
gcc -shared -fPIC lib.c -o libfoo.so.1.2.3 -Wl,-soname,libfoo.so.1
ln -sf libfoo.so.1.2.3 libfoo.so.1
ln -sf libfoo.so.1 libfoo.so
In CMake:
Real Failure Demo¶
Severity: BAD PRACTICE
Scenario: app links against library with wrong SONAME, then we inspect DT_NEEDED.
# Build with wrong SONAME
gcc -shared -fPIC -g bad.c -o libfoo.so -Wl,-soname,libfoo.so.0
ln -sf libfoo.so libfoo.so.0 # create SONAME symlink so loader finds it
gcc -g app.c -L. -lfoo -Wl,-rpath,. -o app
readelf -d app | grep NEEDED
# โ (NEEDED) Shared library: [libfoo.so.0] โ wrong major baked in
./app
# โ foo() = 42, bar(5) = 6 (works today)
# After upgrade, libfoo.so.1 exists but app still looks for libfoo.so.0
# โ runtime error: libfoo.so.0: cannot open shared object file
Why BAD PRACTICE: Runtime works today, but the wrong SONAME major gets baked into every consumer's DT_NEEDED. Future upgrades to the correct SONAME require rebuilding all consumers.
Real-world example¶
Debian's shared library policy requires SONAME to follow the
libname.so.MAJOR convention. Packages with inconsistent SONAMEs are
rejected during review because they break upgrade paths.
References¶
Source files¶
See also: Examples overview ยท All COMPATIBLE cases ยท Category: Quality (Compatible).