Case 131: RTTI Mode Flip (-fno-rtti)¶
| Field | Value |
|---|---|
| Verdict | ๐ก COMPATIBLE_WITH_RISK |
| Category | Risk |
| Platforms | Linux |
| Flags | โ |
Detected ChangeKinds |
rtti_mode_changed |
| Source files | examples/case131_rtti_mode_flip/ |
Category: Build Mode | Verdict: ๐ก COMPATIBLE_WITH_RISK
Verdict and consumer impact¶
Same source, same exported symbols in both versions โ the only difference
is the build mode: v1 is built with RTTI enabled (-frtti), v2 with
-fno-rtti. -fno-rtti omits type_info for polymorphic types, so
dynamic_cast/typeid and cross-DSO exception matching that relies on RTTI
identity can fail to link, or silently misbehave, when one side has RTTI and
the other does not. A symbol-only or DWARF-only check sees nothing โ the
signal lives entirely in the captured build flags, which keeps this a RISK
finding rather than a proven binary break in this trivial fixture (which
uses no polymorphic types at all).
Old/new diff¶
| v1.cpp | v2.cpp |
|---|---|
int compute(int x) { return x + 1; } (built -frtti) |
identical source (built -fno-rtti) |
abicheck command¶
cmake -S examples -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build --target case131_rtti_mode_flip_v1 case131_rtti_mode_flip_v2
# Scope the build-info to each side's own compile entry (see case130's
# README for why an unscoped compile_commands.json finds no difference).
jq '[.[] | select(.file | endswith("case131_rtti_mode_flip/v1.cpp"))]' \
build/compile_commands.json > v1_cc.json
jq '[.[] | select(.file | endswith("case131_rtti_mode_flip/v2.cpp"))]' \
build/compile_commands.json > v2_cc.json
abicheck dump build/case131_rtti_mode_flip/libv1.so --build-info v1_cc.json -o v1.abi.json
abicheck dump build/case131_rtti_mode_flip/libv2.so --build-info v2_cc.json -o v2.abi.json
abicheck compare v1.abi.json v2.abi.json
Expected abicheck finding¶
Verdict: COMPATIBLE_WITH_RISK (exit 0)
Deployment Risk Changes:
- rtti_mode_changed: Runtime-model option 'rtti:CXX' changed: 'on' -> 'off'.
May not be link- or runtime-compatible across consumers; the artifact
diff confirms any concrete break.
Minimum evidence¶
min_evidence: L3 โ the RTTI mode is not recorded in the ELF symbol table
or DWARF for this fixture; it is only visible in the per-side compile flags
captured from a compile_commands.json (or an equivalent build-system
compile database). No artifact-level (L0/L1/L2) evidence carries this fact,
which is why the verdict tops out at RISK rather than BREAKING (ADR-028 D3).
Why abicheck catches it¶
abicheck dump --build-info normalizes each side's captured compiler flags
into build options; the -frtti/-fno-rtti pair is recognized as the
canonical rtti runtime-model option. compare then diffs the two sides'
option sets and reports the flip as rtti_mode_changed when they disagree.
Runtime failure demonstration¶
No crash in this minimal fixture. compute() uses no polymorphic types,
so there's no dynamic_cast/typeid for the mode mismatch to break here โ
that's the point of RISK rather than BREAKING.
g++ -std=gnu++17 -fPIC -shared -g -frtti v1.cpp -o libcompute.so
g++ -g app.cpp -L. -lcompute -Wl,-rpath,. -o app
./app
# -> exit: 0
# Swap in the -fno-rtti build (no recompile)
g++ -std=gnu++17 -fPIC -shared -g -fno-rtti v2.cpp -o libcompute.so
./app
# -> exit: 0 (this fixture exercises no dynamic_cast/typeid path)
The real hazard shows up once a public polymorphic type crosses the
boundary and one side lacks its type_info.
Safe redesign¶
Keep a single RTTI mode for the public ABI, or rebuild consumers in the
matching mode if the public API exposes polymorphic types or
dynamic_cast/typeid. Document the library's RTTI-mode contract
explicitly rather than relying on consumers matching the build flag by
convention.
Cross-tool comparison¶
abidiff/abidw operate on ELF and DWARF only โ a build-flag-only change
like this leaves no trace there, so a binary-only comparison tool reports no
change at all. This class of finding only exists at abicheck's L3
build-context layer.
Source files¶
CMakeLists.txtapp.cppv1.cppv2.cpp
See also: Examples overview ยท All COMPATIBLE_WITH_RISK cases ยท Category: Risk.