Skip to content

Case 02: Parameter Type Change

Field Value
Verdict ๐Ÿ”ด BREAKING
Category Breaking
Platforms Linux
Flags ABI break, API break
Detected ChangeKinds func_params_changed
Source files examples/case02_param_type_change/

Category: Symbol API | Verdict: ๐Ÿ”ด BREAKING

Verdict and consumer impact

Callers compiled against v1 pass int a in a 32-bit register; v2 expects double a in an FP register (x86-64 SysV ABI). The argument is misread, producing wrong results or a crash. Re-compilation against v2 is mandatory.

Old/new diff

v1.c v2.c
double process(int a, int b) double process(double a, int b)

abicheck command

gcc -shared -fPIC -g v1.c -o libfoo_v1.so
gcc -shared -fPIC -g v2.c -o libfoo_v2.so
abicheck compare libfoo_v1.so libfoo_v2.so

Expected abicheck finding

Verdict: BREAKING (exit 4)

- func_params_changed: Parameters changed: process (int, int -> double, int)
  > Callers push arguments with the old layout; callee reads wrong data
    from stack/registers.

Minimum evidence

min_evidence: L1 โ€” DWARF debug info carries each parameter's type, so -g alone (no public headers) is enough to detect the signature change.

Why abicheck catches it

DWARF's DW_TAG_formal_parameter entries record each parameter's type for both versions; abicheck diffs the two functions' parameter-type lists directly from debug info, no headers required.

Runtime failure demonstration

Severity: CRITICAL

Scenario: compile app against v1, swap in v2 .so without recompile.

# Build old library + app
gcc -shared -fPIC -g v1.c -o libfoo.so
gcc -g app.c -L. -lfoo -Wl,-rpath,. -o app
./app
# โ†’ process(3, 4) = 7.0
# โ†’ Expected: 7.0

# Swap in new library (no recompile)
gcc -shared -fPIC -g v2.c -o libfoo.so
./app
# โ†’ process(3, 4) = <garbage> (3 misread as double, wrong FP register)

Why CRITICAL: v2 expects double a in an FP register while the app passes an int in an integer register; the argument is silently misinterpreted, producing wrong output with no error or crash.

Safe redesign

Introduce a new function with the desired signature alongside the old one. Keep the old symbol with its original signature for at least one deprecation cycle.

Real-world example: common in numerical libraries (BLAS, LAPACK) when precision is upgraded โ€” float โ†’ double parameter changes require wrapper shims for backward compatibility.

Cross-tool comparison

abidw --out-file v1.xml libfoo_v1.so
abidw --out-file v2.xml libfoo_v2.so
abidiff v1.xml v2.xml
echo "exit: $?"   # โ†’ 4

Note on abidiff 2.4.0: libabigail classifies parameter type changes as "indirect sub-type changes" with exit code 4 (ABI change detected, not flagged as symbol-removal breaking). The change is still real ABI drift and should be treated as BREAKING by policy.

References


Source files

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

See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.