macosclang++abidebug-symbolsobject-files

Why are there symbols in my object file with `[abi:de180100]` appended?


I am compiling an application on macOS 15.4 with Xcode 16.1. Upon examining the object files the compiler produces, some of the symbols have [abi:de180100] appended to them. This suffix is not in the C++ code. It would seem this suffix is being appended to a handful of other symbols and projects as well.

I would like to know more about the suffix, why it is necessary, and what its implications are for the symbol it qualifies. However, I cannot seem to find any documentation about it anywhere. Can someone point me in the right direction?


Solution

  • The [abi:de180100] appendage is a libc++ ABI (Application Binary Interface) tag. libc++ is the LLVM/clang implementation of the Standard C++ library, corresponding to GNU/GCC libstdc++

    The tag de180100 is the concatenation of three values defined by preprocessor macros in the libc++ configuration header file (e.g /usr/lib/llvm-18/include/c++/v1/__config):

    _LIBCPP_HARDENING_SIG encodes the hardening mode of the library. A hardening mode is a level of enforcement of the library's preconditions, implemented via assertions. Hardening modes are explained here

    _LIBCPP_EXCEPTIONS_SIG encodes whether library functions may (e) or may not (n) signal failure by throwing an exception.

    So you are using libc++ version 180100, configured with hardening mode d ( = Debug mode) and with exception-throwing enabled.

    The ABI tag so concatenated is called the _LIBCPP_ODR_SIGNATURE of the library configuration. The comments in the __config header explain this macro:

    The symbol is given an ABI tag that encodes the ODR-relevant properties of the library. This ensures that no ODR violation can arise from mixing two TUs compiled with different versions or configurations of libc++ (such as exceptions vs no-exceptions). Indeed, if the program contains two definitions of a function, the ODR requires them to be token-by-token equivalent, and the linker is allowed to pick either definition and discard the other

    The representation [abi::de180100] is the demangled representation. In the mangled linker symbol, it appears as the suffix B8de180100m

    The compiler will apply such a tag to a symbol when the symbol is declared in the source code with __attribute__((__abi_tag__(_LIBCPP_ODR_SIGNATURE))). (You will not find this string by grepping your libc++ header files, because it is generated from the expansion of other preprocessor macros.)

    You, as a user of the library, will not normally deploy such an ABI-tag in the code you write (though nothing stops you). The source code in question will be template code that you have included from one of clang's Standard C++ header files. A symbol that you see ABI-tagged with _LIBCPP_ODR_SIGNATURE will define an inlined instantiation of some C++ library template (member-)function and will have weakly global linkage, meaning that the linker will ingest multiple definitions of the symbol without failure and pick one arbitrarily. The symbol is ABI-tagged because such weakly global inlined definitions are just the ones for which the hazard to ODR integrity arises.

    If you wonder why inlined instantiations of template functions are compiled with weakly global linkage (whether by clang or GCC) in the first place you can consult my answer to How does the linker handle identical template instantiations across translation units?, where I deliberately violate the ODR to demonstrate the answer.

    And for a deeper dive into the use of ABI tags in policing C++ standard library ABI compatibility, you can see C++ standard library ABI compatibility, one of the Maskray blogs.


    Incidentally, you don't have to have this guardrail if you don't want it. If you compile TUs with -D_LIBCPP_NO_ABI_TAG then clang will take the hint.