Skip to content

Case 139: Symbol Version Node Removed

Field Value
Verdict 🔴 BREAKING
Category Breaking
Platforms Linux
Flags ABI break
Detected ChangeKinds symbol_version_node_removed
Source files examples/case139_symbol_version_node_removed/

Category: ELF / Symbol versioning | Verdict: BREAKING

What this case is about

v1 exports two symbols bound to two version nodes defined by a linker version script:

LIBX_1.0 { global: alpha; local: *; };
LIBX_2.0 { global: beta; } LIBX_1.0;   # beta@@LIBX_2.0

A consumer that links against beta records a dependency on beta@LIBX_2.0.

v2 deletes the LIBX_2.0 node and folds beta into LIBX_1.0:

LIBX_1.0 { global: alpha; beta; local: *; };   # beta@@LIBX_1.0

The version node LIBX_2.0 no longer exists, so the verneed beta@LIBX_2.0 baked into the old consumer can no longer be satisfied. This is the classic glibc-style versioned-symbol ABI break: removing or renaming a version node breaks every binary that recorded a dependency on it, even though the symbol name is still exported.

What abicheck detects

  • SYMBOL_VERSION_NODE_REMOVED: the LIBX_2.0 version definition present in v1 is gone in v2. Classified as BREAKING.

(The compare also notes symbol_moved_version_node for beta relocating to a different node.)

Overall verdict: BREAKING.

How to reproduce

gcc -shared -fPIC -g v1.c -o libv1.so -Wl,--version-script=v1.map
gcc -shared -fPIC -g v2.c -o libv2.so -Wl,--version-script=v2.map

readelf -V libv1.so | grep 'Name: LIBX'   # LIBX_1.0, LIBX_2.0
readelf -V libv2.so | grep 'Name: LIBX'   # LIBX_1.0 only

python3 -m abicheck.cli dump libv1.so -o v1.json
python3 -m abicheck.cli dump libv2.so -o v2.json
python3 -m abicheck.cli compare v1.json v2.json
# → BREAKING + SYMBOL_VERSION_NODE_REMOVED

How to fix

Never remove or rename a published version node. Add new symbols under a new node (LIBX_3.0) while keeping all existing nodes intact, so old verneed records keep resolving.

Real Failure Demo

Severity: CRITICAL (load-time failure)

An executable built against v1 (recording beta@LIBX_2.0) fails to start when run against v2 with:

symbol beta version LIBX_2.0 not defined in file libv1.so with link time reference

Source files

  • CMakeLists.txt
  • app.c
  • v1.c
  • v1.map
  • v2.c
  • v2.map

See also: Examples overview · All BREAKING cases · Category: Breaking.