Case 59: Function Became Inline (outlined โ inline)¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux, macOS |
| Flags | ABI break |
Detected ChangeKinds |
func_removed |
| Source files | browse on GitHub |
Category: Symbol API | Verdict: BREAKING (API_BREAK)
What this case is about¶
v1 exports fast_abs and fast_max as regular outlined functions in the
shared library. v2 moves them to the header as static inline โ the symbols
disappear from .dynsym.
This is the inverse of case47 (inline_to_outlined), which is compatible. Moving a function from outlined to inline is breaking because existing binaries depend on the symbol being in the library.
What breaks at binary level¶
- Symbols removed:
fast_absandfast_maxare no longer in.dynsym. - Dynamic linker fails: Existing binaries that reference these symbols
get
undefined symbolerrors at load time. - Source compatibility preserved: New compilations with the v2 header work fine (the inline definition is available), but old binaries break.
What abicheck detects¶
FUNC_REMOVED: Both function symbols are absent from v2's export table. From the binary perspective, this is indistinguishable from deletion.
Overall verdict: BREAKING
How to reproduce¶
Linux:
gcc -shared -fPIC -g bad.c -o libbad.so
gcc -shared -fPIC -g good.c -o libgood.so
nm -D libbad.so | grep fast_ # โ T fast_abs, T fast_max
nm -D libgood.so | grep fast_ # โ (nothing โ inlined away)
# Link app against v1
gcc -g app.c -L. libbad.so -Wl,-rpath,. -o app
./app # works
# Swap to v2
cp libgood.so libbad.so
./app
# โ error: undefined symbol: fast_abs
macOS:
cc -shared -fPIC -g bad.c -o libbad.dylib
cc -shared -fPIC -g good.c -o libgood.dylib
nm libbad.dylib | grep fast_ # โ T _fast_abs, T _fast_max
nm libgood.dylib | grep fast_ # โ (nothing โ inlined away)
# Link app against v1
cc -g app.c -L. -lbad -Wl,-rpath,@loader_path -o app
./app # works
# Swap to v2
cp libgood.dylib libbad.dylib
./app
# โ dyld: Symbol not found: _fast_abs
How to fix¶
Keep an outlined fallback alongside the inline version:
/* header */
static inline int fast_abs(int x) { return x < 0 ? -x : x; }
/* .c file โ provide an exported symbol for backward compat */
int fast_abs(int x) { return x < 0 ? -x : x; }
Or use a __attribute__((weak)) symbol.
References¶
Source files¶
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.