When you compile multiple C files into one program, each file might define its own helper functions. Binding determines which symbols the linker can see across file boundaries — and which are kept private.
Misunderstanding binding causes common linker errors like "multiple definition of symbol" or unexpected symbol collisions.
Think of binding as the visibility scope of a symbol:
The binding is stored in the high 4 bits of <code>st_info</code> in the <code>Elf64_Sym</code> structure:
| Binding | Constant | Value | Behavior |
|---|---|---|---|
| Local | STB_LOCAL | 0 | Not visible outside the object file. Multiple files can have same name. |
| Global | STB_GLOBAL | 1 | Visible to all object files in the link. Must be unique across entire program. |
| Weak | STB_WEAK | 2 | Like global, but overridden by any strong global definition. |
C functions are global by default. Static functions (<code>static void foo()</code>) are local. GCC attributes <code>__attribute__((weak))</code> make symbols weak.
Resolution order during linking:
Two source files defining overlapping symbols:
a.c: helper (STB_GLOBAL), priv (STB_LOCAL via static), weak_fn (STB_WEAK)
b.c: helper (STB_GLOBAL), weak_fn (STB_WEAK, overrides a.c), only_weak (STB_WEAK)
What <code>nm</code> shows:
$ nm a.o 0000000000000000 W weak_fn 0000000000000000 T helper 0000000000000000 t priv $ nm b.o 0000000000000000 W weak_fn 0000000000000000 W only_weak 0000000000000000 T helper
Notice: <code>priv</code> is lowercase 't' (local), while <code>helper</code> is uppercase 'T' (global).
# Create a local symbol with 'static' echo 'static int x = 5;' | tee a.c echo 'int x = 10;' | tee b.c gcc -c a.c b.c nm a.o | grep ' x' # shows lowercase 'd' (local data) nm b.o | grep ' x' # shows uppercase 'D' (global data) # Try linking -- succeeds because a.o's x is local gcc a.o b.o -o test nm test | grep ' x' # shows uppercase 'D' (b.o's x wins)
What happens if two object files both define a strong (GLOBAL) symbol with the same name?
Why would you use a WEAK symbol instead of a GLOBAL one?
Binding controls which definition the linker picks. But visibility controls whether the dynamic linker can see a symbol at all — that's the next concept.