Skip to content

ABI/API failure taxonomy

This is Phase 1 of ABI/API knowledge and corpus: a top-down enumeration of the domain of known ways a compiled or source-level compatibility contract can break, organized the way the field itself is organized — not the way catalog/ happens to be organized, and not the way abicheck's own ChangeKind registry (abicheck/model/ change_catalog/) names things.

This taxonomy is deliberately independent of abicheck. It names mechanisms a reader with no abicheck installed would recognize from reading the Itanium C++ ABI, the System V / Windows x64 / AArch64 calling-convention specifications, ld.so(8), CPython's stable-ABI documentation, or the Linux kernel's module-versioning scheme — not abicheck's detectors. That independence is the point: mapping each leaf mechanism to which docs/learn/ page explains it, which catalog/ case demonstrates it, and which ChangeKind/detector claims to observe it is the next plan phase (Phase 2 — "map existing knowledge and corpus onto the taxonomy"), not this one. A leaf mechanism existing here is not a claim that abicheck detects it, documents it, or has a corpus case for it; several are known to be undetectable by any static tool (see Phase 3's KNOWN_UNDETECTABLE status in the plan). This document changes no code path, detector, or default.

Scope and stability of ids

Every leaf mechanism carries a stable id of the form <branch-slug>.<leaf-slug>, a one- or two-sentence description, and the platforms and/or languages it applies to. An id, once published, is never renumbered or reused for a different mechanism — later phases (and any future revision of this document) may add a leaf, split one leaf into two when a real distinction is found, or mark one superseded-by: <new-id>, but never silently repoint an existing id at different content. This mirrors the stability contract AGENTS.md already states for ChangeKind values (additive, never renumbered) applied to a taxonomy that has no equivalent mechanical enforcement (no changekind-partition-style gate exists for this document — see the plan's own "Risk" section on why this taxonomy cannot be checked against an external authority the way the ChangeKind registry can).

"Platforms" below uses the same vocabulary as docs/reference/platforms.md (ELF, PE/COFF, Mach-O); "Languages" names the source language(s) the mechanism is intrinsic to, not merely "any language abicheck happens to support."

1. Symbol identity (symbol-identity)

How a compiled artifact names an exported entity, and the ways that naming can shift without necessarily changing what the entity does.

id Mechanism Description Platforms / languages
symbol-identity.removal Symbol removal An exported symbol present in the old artifact is absent from the new one. ELF, PE/COFF, Mach-O · C, C++
symbol-identity.rename Symbol rename The source-level name of an exported entity changes, changing the exported symbol name with it. ELF, PE/COFF, Mach-O · C, C++
symbol-identity.mangling-scheme-change Mangling-scheme change The compiler's C++ name-mangling scheme itself changes (a mangling-ABI revision), changing every affected exported symbol's spelling without any source edit. ELF (Itanium), PE/COFF (MSVC) · C++
symbol-identity.mangling-signature-change Mangling-signature change A detail folded into the mangled name (parameter type, template argument, cv-qualifier, ref-qualifier) changes, producing a different exported symbol even though the declaration reads as "the same function" at a glance. ELF, PE/COFF, Mach-O · C++
symbol-identity.linkage-change Linkage change A symbol's linkage changes between external and internal (static, an anonymous namespace, adding/removing extern "C"), changing whether — and how — it is exported. ELF, PE/COFF, Mach-O · C, C++
symbol-identity.visibility-change Visibility attribute change An explicit visibility annotation changes (__attribute__((visibility(...))), -fvisibility, __declspec(dllexport/dllimport)), changing whether a symbol is exported at all. ELF, PE/COFF, Mach-O · C, C++
symbol-identity.version-node-change Symbol-version-node change A symbol moves to a different version node in a linker version script, or a version node is renamed or removed. ELF
symbol-identity.weak-strong-binding-change Weak/strong binding change A symbol's binding changes between weak and strong (STB_WEAK/STB_GLOBAL), altering override and interposition behavior at load time. ELF, Mach-O · C, C++
symbol-identity.alias-change Symbol alias change A symbol alias (__attribute__((alias(...))), a .symver directive) is added, removed, or repointed at a different definition. ELF
symbol-identity.ifunc-resolver-change Indirect-function resolver change A GNU indirect function (ifunc) resolver's selection logic changes, altering which concrete implementation binds to an unchanged exported name at load time. ELF (glibc) · C, C++

2. Function calling contract (calling-contract)

The machine-level agreement between caller and callee for one function: what arguments look like, where they go, and how control and exceptions flow across the call.

id Mechanism Description Platforms / languages
calling-contract.parameter-type-change Parameter type change A parameter's type changes in a way that changes its representation, size, or classification. ELF, PE/COFF, Mach-O · C, C++
calling-contract.parameter-count-change Parameter count (arity) change The number of parameters changes. ELF, PE/COFF, Mach-O · C, C++
calling-contract.parameter-order-change Parameter order change Parameters are reordered without changing the set of types, shifting which argument each register/stack slot carries. ELF, PE/COFF, Mach-O · C, C++
calling-contract.return-type-change Return type change The return type changes, including a change between register-returned and memory-returned (via hidden pointer) classification. ELF, PE/COFF, Mach-O · C, C++
calling-contract.calling-convention-change Calling-convention change The calling convention changes (cdecl/stdcall/fastcall/thiscall/vectorcall, or a register-passing ABI variant), changing how arguments and the return value move between caller and callee. PE/COFF (MSVC conventions), ELF (SysV/ARM register-passing variants) · C, C++
calling-contract.exception-specification-abi-change Exception-specification ABI change An exception specification changes in a way that affects generated unwind tables or call-site codegen — noexcept addition/removal, or (pre-C++17) a dynamic throw() specification's removal. ELF, PE/COFF, Mach-O · C++
calling-contract.variadic-change Variadic/fixed-arity change A function changes between fixed arity and variadic (...), changing argument-passing convention for any additional arguments. ELF, PE/COFF, Mach-O · C, C++
calling-contract.implicit-this-change Implicit this change A member function becomes static or vice versa, adding or removing the hidden receiver parameter. ELF, PE/COFF, Mach-O · C++
calling-contract.aggregate-classification-change Aggregate-classification change A struct/class passed or returned by value changes which of its fields determine its ABI classification (e.g. Itanium/SysV register-class assignment), changing how it is passed even though its declared signature type is unchanged. ELF (SysV/AAPCS classification), PE/COFF · C, C++
calling-contract.pass-by-value-threshold-change Pass-by-value size-threshold crossing A by-value aggregate parameter or return type grows or shrinks across the platform's register-vs-memory (invisible-reference) threshold. ELF, PE/COFF, Mach-O · C, C++

3. Data layout (data-layout)

How the bytes of a type are arranged in memory — the layer every other object-model and calling-convention rule ultimately rests on.

id Mechanism Description Platforms / languages
data-layout.size-change Type size change A type's overall size changes. ELF, PE/COFF, Mach-O · C, C++
data-layout.alignment-change Alignment change A type's required alignment changes (alignas, #pragma pack, or a field-type change that alters natural alignment). ELF, PE/COFF, Mach-O · C, C++
data-layout.field-offset-change Field offset change A field's byte offset within its containing type changes. ELF, PE/COFF, Mach-O · C, C++
data-layout.field-reorder Field reorder Fields are reordered without changing the set of field types, shifting offsets. ELF, PE/COFF, Mach-O · C, C++
data-layout.padding-change Packing/padding change Compiler packing directives change (#pragma pack, __attribute__((packed))), changing inter-field padding without a field-list change. ELF, PE/COFF, Mach-O · C, C++
data-layout.bitfield-allocation-change Bitfield allocation change A bitfield's declared width, allocation order, or storage-unit boundary changes, shifting which bits carry which field. ELF, PE/COFF, Mach-O · C, C++
data-layout.enum-underlying-type-change Enum underlying-type change An enum's underlying integer type changes, changing its size and/or signedness. ELF, PE/COFF, Mach-O · C, C++
data-layout.union-active-member-change Union member change A union's member set changes (add/remove/reorder/retype), changing the union's size and/or alignment. ELF, PE/COFF, Mach-O · C, C++
data-layout.embedded-array-dimension-change Embedded fixed-array dimension change A fixed-size array field's declared dimension changes, changing the size of every type that embeds it by value. ELF, PE/COFF, Mach-O · C, C++
data-layout.flexible-array-member-change Flexible array member change A C99 flexible array member is added, removed, or retyped, changing the struct's own fixed size and its trailing-allocation contract. ELF, PE/COFF, Mach-O · C
data-layout.tail-padding-reuse-change Tail-padding reuse change Whether a type's trailing padding may be reused by a derived class or subsequent member changes — C++ empty-base optimization or [[no_unique_address]] adoption/removal. ELF, PE/COFF, Mach-O · C++

4. C++ object model (cpp-object-model)

Mechanisms specific to C++ classes with virtual dispatch and inheritance — layered on top of data-layout, but with their own failure modes.

id Mechanism Description Platforms / languages
cpp-object-model.base-class-addition-removal Base class addition/removal A base class is added or removed, changing the derived class's layout and/or subobject set. ELF, PE/COFF, Mach-O · C++
cpp-object-model.virtual-function-insertion-reorder Virtual function insertion/reorder A new virtual function is inserted before an existing one, or existing virtual functions are reordered, shifting every subsequent function's vtable slot index. ELF, PE/COFF, Mach-O · C++
cpp-object-model.virtual-function-removal Virtual function removal A virtual function is removed from the class, removing (and potentially collapsing) its vtable slot. ELF, PE/COFF, Mach-O · C++
cpp-object-model.pure-virtual-transition Pure/non-pure virtual transition A virtual function changes between pure (= 0) and providing a definition, or vice versa. ELF, PE/COFF, Mach-O · C++
cpp-object-model.multiple-inheritance-thunk-change Multiple-inheritance thunk/vtable change Restructuring multiple or virtual inheritance changes the thunk layout or the number/order of vtables a class carries. ELF, PE/COFF, Mach-O · C++
cpp-object-model.rtti-representation-change RTTI representation change The type_info layout or its mangled type-name changes, affecting dynamic_cast/typeid behavior across compiled units. ELF (Itanium RTTI), PE/COFF (MSVC RTTI) · C++
cpp-object-model.virtual-base-layout-change Virtual base layout change A virtual base's offset or the virtual-base table (vbtable/vbase table) layout changes. ELF, PE/COFF, Mach-O · C++
cpp-object-model.covariant-return-type-change Covariant return-type change An overriding virtual function's covariant return type changes in a way that affects the thunk needed to adjust the returned pointer. ELF, PE/COFF, Mach-O · C++
cpp-object-model.vptr-presence-change Vptr presence change A class gains or loses its first virtual function, adding or removing the implicit vtable pointer and shifting every subsequent member's offset. ELF, PE/COFF, Mach-O · C++

5. Inline/template/source ABI (source-abi)

Mechanisms where the "ABI" is determined by what got compiled into each consuming translation unit, not by one fixed compiled artifact.

id Mechanism Description Platforms / languages
source-abi.inline-function-body-change Inline function body change An inline (or header-defined) function's body differs across translation units that each compile their own copy, an ODR-relevant divergence rather than a single symbol change. ELF, PE/COFF, Mach-O · C, C++
source-abi.template-instantiation-set-change Template instantiation-set change The set of template specializations actually emitted (implicitly or via explicit instantiation) changes, changing which mangled symbols exist to satisfy a consumer's use. ELF, PE/COFF, Mach-O · C++
source-abi.odr-violation One Definition Rule violation The same entity is defined differently in different translation units or shared objects linked into one program, an undefined-behavior condition rather than a single localized change. ELF, PE/COFF, Mach-O · C, C++
source-abi.constexpr-evaluation-change constexpr evaluation change A constexpr value baked into consumers at their own compile time changes, so consumers compiled against the old value silently disagree with a new binary — without themselves being recompiled. C++
source-abi.macro-driven-layout-change Macro-driven layout/signature change A feature-flag macro alters a struct's layout or a function's signature depending on the including translation unit's own macro state at compile time. C, C++
source-abi.default-template-argument-change Default template-argument change A template's default argument changes, changing which specialization (and mangled name) an unqualified use resolves to. C++

6. Export/public-surface contract (export-surface)

Whether what a header declares, what a binary actually exports, and what consumers actually use agree with each other.

id Mechanism Description Platforms / languages
export-surface.header-export-divergence Header/export divergence A symbol is declared in a public header but not actually present in the binary's export table, or vice versa (exported but undeclared). ELF, PE/COFF, Mach-O · C, C++
export-surface.visibility-demotion-without-header-change Visibility demotion without header change A symbol's exported status changes purely through build flags or a version-script edit, with no corresponding header change to signal it. ELF, PE/COFF, Mach-O · C, C++
export-surface.accidental-export Accidental export An internal/private symbol is unintentionally exported (e.g. missing static, an omitted version-script entry) and becomes a de facto contract once consumers start using it. ELF, PE/COFF, Mach-O · C, C++
export-surface.version-script-map-change Version-script/export-map change A linker version script or module-definition (.def) file changes which symbols are exported, independent of the source code. ELF (version scripts), PE/COFF (.def files) · C, C++
export-surface.documented-contract-drift Documented-contract drift The project's documented/declared public contract and its actual observable surface diverge over time, e.g. through accretion of unreviewed exports. ELF, PE/COFF, Mach-O · C, C++

7. Dynamic linker contract (dynamic-linker)

Mechanisms specific to how a dynamic loader resolves and binds a shared library at load or call time, independent of any one symbol's own contract.

id Mechanism Description Platforms / languages
dynamic-linker.soname-change SONAME change A shared library's SONAME (or Mach-O install name) changes, changing the dependency string consumers must resolve against. ELF (DT_SONAME), Mach-O (install name)
dynamic-linker.symbol-versioning-scheme-change Symbol-versioning scheme change The overall structure of version nodes across a release changes (nodes added, removed, or restructured), rather than one symbol moving between existing nodes. ELF
dynamic-linker.dt-needed-change DT_NEEDED/dependency-list change A dependency is added, removed, or reordered in the binary's needed-library list. ELF (DT_NEEDED), PE/COFF (import table), Mach-O (load commands)
dynamic-linker.rpath-runpath-change RPATH/RUNPATH change The library search path embedded in the binary changes, changing which on-disk library actually satisfies a dependency at load time. ELF
dynamic-linker.binding-mode-change Binding-mode change The binding mode changes between lazy (PLT-resolved on first call) and eager (BIND_NOW/full RELRO), changing when a missing symbol is discovered. ELF
dynamic-linker.plt-got-representation-change PLT/GOT representation change The PLT/GOT structure or relocation kind changes (e.g. IRELATIVE relocations introduced by ifunc adoption), changing load-time behavior without changing any symbol's name. ELF

8. Dependency ABI (dependency-abi)

How a break in a library the artifact under test links against propagates to that artifact's own consumers.

id Mechanism Description Platforms / languages
dependency-abi.transitive-break Transitive dependency break A linked dependency itself breaks ABI, propagating the incompatibility to every consumer of the artifact under test without that artifact's own source changing at all. ELF, PE/COFF, Mach-O · C, C++
dependency-abi.version-range-widening Dependency version-range widening A dependency version constraint is loosened enough to admit a version that is not, in fact, ABI-compatible with the versions previously admitted. ELF, PE/COFF, Mach-O · C, C++
dependency-abi.incompatible-substitution ABI-incompatible dependency substitution A build substitutes a different, ABI-incompatible provider of nominally the same dependency (e.g. a different C library, allocator, or vendored fork). ELF, PE/COFF, Mach-O · C, C++
dependency-abi.linking-mode-change Dependency linking-mode change A dependency switches between static and dynamic linking, changing symbol visibility, duplication, or ODR exposure for that dependency's own symbols. ELF, PE/COFF, Mach-O · C, C++

9. Toolchain/platform ABI (toolchain-platform)

Mechanisms where the same source code produces a different ABI purely because of the compiler, target, or platform runtime it is built against.

id Mechanism Description Platforms / languages
toolchain-platform.compiler-abi-epoch-change Compiler ABI-epoch change The compiler's own ABI for a language feature changes across a version boundary (e.g. the GCC 5 libstdc++ dual-ABI switch, an MSVC ABI-breaking release), affecting every binary built with the new compiler regardless of source changes. ELF (libstdc++ dual ABI), PE/COFF (MSVC ABI versions) · C++
toolchain-platform.target-triple-change Target-triple change The build target (architecture/vendor/OS/environment) changes, changing calling convention, type sizes, or the object format itself. ELF, PE/COFF, Mach-O · C, C++
toolchain-platform.abi-relevant-flag-change ABI-relevant compiler-flag change A compiler flag that affects generated ABI changes between builds (-fshort-enums, -mabi=, -fpack-struct, /vd, -fno-exceptions, etc.), independent of any source edit. ELF, PE/COFF, Mach-O · C, C++
toolchain-platform.libc-runtime-abi-change libc/runtime ABI change The C runtime's own ABI changes (glibc, musl, MSVCRT/UCRT version), affecting every binary linked against it. ELF, PE/COFF · C, C++
toolchain-platform.endianness-change Endianness change The target's byte order changes, changing the in-memory representation of every multi-byte value. ELF, PE/COFF, Mach-O · C, C++
toolchain-platform.word-size-change Word-size (32-bit/64-bit) change The target's pointer/word size changes, changing pointer size, long size on some platforms, and struct layout throughout. ELF, PE/COFF, Mach-O · C, C++
toolchain-platform.hardening-flag-change Hardening/mitigation flag change A security-hardening feature changes (stack protector variant, Control-Flow Integrity, ARM Pointer Authentication/BTI), which can alter calling-convention-adjacent codegen (e.g. extra hidden parameters, prologue/epilogue shape) even when it does not change the declared signature. ELF, PE/COFF, Mach-O · C, C++

10. Multi-library/product ABI (product-abi)

Contracts that exist only between components of one product or release, not within any single library's own compiled interface.

id Mechanism Description Platforms / languages
product-abi.cross-component-contract-break Cross-component contract break Two components shipped in one release disagree about a shared struct/interface version, each individually "unchanged" from its own last release. ELF, PE/COFF, Mach-O · C, C++
product-abi.version-skew-within-release Version skew within a release Components in one release carry mismatched, individually-plausible-looking versions that are jointly incompatible when combined. ELF, PE/COFF, Mach-O · C, C++
product-abi.plugin-interface-break Plugin interface break A host/plugin ABI boundary changes, breaking third-party plugins that are not part of the release being analyzed and cannot be recompiled by that release's own process. ELF, PE/COFF, Mach-O · C, C++

11. Source-level API compatibility (source-api)

Mechanisms that break recompilation of consumer source code without necessarily changing a prebuilt binary's runtime compatibility.

id Mechanism Description Platforms / languages
source-api.signature-change-source-only Source-only signature change A signature-level change breaks recompilation (e.g. adding an overload that changes overload resolution, a parameter-type change that is a source break but not a runtime one for existing compiled callers) without changing the already-compiled interface. C, C++
source-api.header-macro-removal Public macro removal A public macro consumer code relies on is removed or renamed, breaking compilation with no corresponding symbol-level change. C, C++
source-api.deprecation-attribute-addition Deprecation-attribute addition [[deprecated]]/__attribute__((deprecated)) is added to a previously plain declaration, turning previously-silent consumer usage into a warning (and, under -Werror, an error) with no change to the compiled interface. C, C++
source-api.default-argument-value-change Default-argument value change A default argument's value changes, silently altering the behavior of call sites that omit it, without any compile error to signal the change. C++
source-api.overload-resolution-change Overload-resolution change Adding a new overload changes which existing function a pre-existing call site now binds to, without that call site's own text changing. C++

12. Header-only compatibility (header-only)

Mechanisms specific to libraries that ship no compiled artifact at all — where "the ABI" is whatever each consumer's own compiler produced.

id Mechanism Description Platforms / languages
header-only.multiple-version-odr Multiple-version ODR violation Two different versions of the same header-only library are included by different translation units linked into one binary, violating the One Definition Rule across the whole program. C, C++
header-only.include-guard-macro-collision Include-guard/macro collision A header-only library's include guard or configuration macro collides with another library's identically-named macro, silently suppressing one definition. C, C++
header-only.inline-namespace-version-stamp-change Inline-namespace version-stamp change An inline-namespace-based ABI version stamp changes as intended by the library author, but breaks any consumer code that named the versioned namespace explicitly rather than through the inline alias. C++
header-only.template-heavy-recompilation-drift Per-TU recompilation drift A header-only, template-heavy library's observed behavior differs per translation unit depending on which version of the header each TU happened to compile against, since there is no single compiled artifact whose ABI could be checked. C++

13. Language/ecosystem-specific mechanisms (ecosystem-specific)

Mechanisms intrinsic to one language or runtime ecosystem that do not generalize to the branches above.

id Mechanism Description Platforms / languages
ecosystem-specific.c-restrict-qualifier-change restrict qualifier change A pointer parameter gains or loses restrict, changing optimizer aliasing assumptions — an API contract change with no change to the function's signature or ABI. C
ecosystem-specific.cpp-stdlib-abi-variant C++ standard-library ABI variant mismatch Consumers are built against a different C++ standard-library ABI implementation or configuration than the library (libstdc++ vs. libc++, or a dual-ABI mode mismatch within libstdc++ itself). ELF, Mach-O · C++
ecosystem-specific.cpython-limited-api-tag-change CPython limited-API/stable-ABI tag change A CPython extension module's Py_LIMITED_API/stable-ABI tag changes, or code built against the limited API accesses a struct field the stable ABI does not guarantee. ELF, PE/COFF, Mach-O · C (CPython extension modules)
ecosystem-specific.cpython-object-layout-change CPython object layout change CPython's own PyObject/type-object layout changes across interpreter builds or versions (including a free-threaded/no-GIL build), affecting any extension that reads that layout directly. ELF, PE/COFF, Mach-O · C (CPython extension modules)
ecosystem-specific.sycl-kernel-abi-change SYCL kernel ABI change A SYCL kernel's device-side ABI, or the host/device integration-header contract generated for it, changes. ELF, PE/COFF · SYCL/C++
ecosystem-specific.sycl-device-binary-format-change SYCL device-binary format change The packaged device-binary format or target list changes, breaking runtime device dispatch even though the host-visible symbol is unchanged. ELF, PE/COFF · SYCL/C++
ecosystem-specific.kernel-symbol-versioning-crc-change Kernel MODVERSIONS CRC change A Linux kernel symbol's MODVERSIONS CRC changes because an ABI-relevant struct or prototype reachable from that symbol changed, independent of the symbol's own name. ELF (Linux kernel modules) · C
ecosystem-specific.kernel-btf-type-id-change Kernel BTF type-ID/graph change BTF type IDs or the type graph shift when kernel struct layouts change, affecting BPF CO-RE (Compile Once – Run Everywhere) relocations that reference those types. ELF (Linux kernel, BTF) · C

Next steps

Phase 2 of the plan resolves, for every leaf above, which docs/learn/ page(s) explain it, which catalog/ case(s) demonstrate it, and which ChangeKind/detector (if any) claims to observe it. Phase 3 then classifies each leaf's coverage status (NOT_APPLICABLE, KNOWN_UNDETECTABLE, NOT_IMPLEMENTED, MISSING_CASE, PARTIALLY_COVERED, or COVERED), and Phase 4 closes MISSING_CASE gaps with paired positive/negative control cases. None of that mapping work is done by this document — see ABI/API knowledge and corpus for the full plan.