macosdynamic-linkingdyld

What does "expected in: flat namespace" mean?


The OS X dynamic loader often gives errors like

Symbol not found: <some symbol name>
Referenced from: <lib location>
Expected in: flat namespace

If you search for the error you'll find a ton of errors that have it. I understand roughly that the problem is an incorrect linking, but none of the answers explain what "flat namespace" means here, exactly.


Solution

  • Disclaimer: This answer only applies to macOS 10.4 and higher. E.g. In previous versions of 'OSX' flat-namespaces were the default. And on Windows resolving can also work slightly different, depending on the mode though.

    Prolog

    Let's first talk about the background of namespaces. In MacOS there are two so-called namespaces available. Two-level namespace and single namespace (also known as flat-namespace).

    Flat-namespace

    Each process has a huge table which contains all symbols (functions, external variables, ..). When a library gets loaded it might depend on a symbol and therefore can look in the flat-namespace to find which other library or executable 'offers' it. After all symbols were found, the library adds his own symbols to the list. One huge disadvantage is the amount of possible collisions. A process might load two or more libraries with the same symbol names. It is up to the OS how to deal with collisions, but in most cases it's simply undefined behaviour and leads to a crash because of mixed libraries.

    Two-level namespace

    In a two-level namespace, instead of a plain table with symbol names, the symbols are saved with name and their library name (so where they come from). A library that relies on a symbol needs to know exactly from which library it wants to get the symbol XYZ resolved.

    What that means for your problem

    The lib was obviously compiled with a flat-namespace option and requires the symbol to run properly. A solution is to load the library it depends on before the lib gets loaded that causes the problem.

    Also interesting to find the solution to your problem:

    Run otool -hV on the library. If you don't see TWOLEVEL, then it was linked with -flat-namespace.