Case 177: long double ABI Changed¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux |
| Flags | ABI break |
Detected ChangeKinds |
long_double_abi_changed |
| Source files | examples/case177_long_double_abi_changed/ |
Category: Floating-Point ABI | Verdict: ๐ด BREAKING
Verdict and consumer impact¶
compute's name and purpose are unchanged โ "double the input" โ but v2's
library was rebuilt to use IEEE 754 quad precision (__float128, from
libquadmath) instead of the platform's native 80-bit x87 long double.
Itanium mangles long double as e and __float128 as g, so the
exported symbol name changes even though the C++ declaration still reads
"compute": _Z7computee โ _Z7computeg. Any binary linked against v1
resolves _Z7computee at link time; that symbol no longer exists in v2, so
the dynamic linker refuses to load the app. Recompilation against v2 is
mandatory.
Old/new diff¶
| v1.hpp | v2.hpp |
|---|---|
long double compute(long double x); |
__float128 compute(__float128 x); |
abicheck command¶
g++ -shared -fPIC -g v1.cpp -o libfoo_v1.so
g++ -shared -fPIC -g v2.cpp -o libfoo_v2.so -lquadmath
abicheck compare libfoo_v1.so libfoo_v2.so
Expected abicheck finding¶
Verdict: BREAKING (exit 4)
- func_removed: Public function removed: compute
> Old binaries call a symbol that no longer exists; dynamic linker
will refuse to load or crash at call site.
- long_double_abi_changed: long double ABI changed:
compute(long double) -> compute(__float128) โ floating-point
representation differs
> The source signature is unchanged, but the floating-point format
differs, so old binaries pass/return the value in the wrong size and
bit layout.
Additions:
- func_added: New public function: compute(__float128)
Minimum evidence¶
min_evidence: L0 โ the exported-symbol table alone is enough: abicheck
re-pairs the removed _Z7computee and added _Z7computeg symbols by their
demangled signature, detecting the long-double-family type flip directly
from the Itanium mangling token (e vs g). No debug info or headers
needed; -g above is only there so the Runtime failure demonstration
below can build a matching app.
Why abicheck catches it¶
A plain symbol diff would see this as an unrelated remove-and-add
(_Z7computee gone, _Z7computeg new). abicheck's long_double_abi_changed
detector instead re-pairs a removed/added symbol pair by demangled
signature when they differ only in a long-double-family type, producing one
finding that names the real transition โ a representation change, not a
rename โ rather than two unrelated-looking symbol events.
Runtime failure demonstration¶
Severity: BREAKING / undefined symbol at load time
Scenario: compile app against v1, swap in v2 .so without recompile.
# Build old library + app
g++ -shared -fPIC -g v1.cpp -o libfoo.so
g++ -g app.cpp -I. -L. -lfoo -Wl,-rpath,. -o app
./app
# โ compute(21.0) = 42.000000 (expected 42.0)
# Swap in new library (no recompile)
g++ -shared -fPIC -g v2.cpp -o libfoo.so -lquadmath
./app
# โ ./app: symbol lookup error: ./app: undefined symbol: _Z7computee
Why BREAKING: the old app was linked against _Z7computee. v2's
library exports _Z7computeg instead โ a different symbol, not a modified
one โ so the dynamic linker refuses to resolve the reference at load time.
Safe redesign¶
Treat a long double-family representation change as a full ABI break,
even when no C++ signature in the header text visibly changed spelling.
Bump the library's SONAME when changing the underlying floating-point
representation for any exported symbol. If both representations must be
supported (e.g. during a ppc64 IEEE128 migration), ship both under distinct
symbol versions rather than silently replacing one.
Real-world example: ppc64 toolchains moving long double from IBM
double-double to IEEE binary128 hit exactly this transition โ every
exported symbol taking or returning long double gets a new mangled name,
forcing a full rebuild of dependents even though no C/C++ source changed
spelling.
Cross-tool comparison¶
abidiff/abidw are not installed in this environment, so no output is
reproduced here.
References¶
Source files¶
CMakeLists.txtapp.cppv1.cppv1.hppv2.cppv2.hpp
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.