Keyboard Shortcuts

Ctrl+K
Open search
Esc
Close search / dialog
↑
Back to top

Symbol Binding

15 minintermediateModule 5: SymbolsContinues from symbol-table

Why This Matters

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.

A Simple Model

Think of binding as the visibility scope of a symbol:

The Actual Detail

The binding is stored in the high 4 bits of <code>st_info</code> in the <code>Elf64_Sym</code> structure:

BindingConstantValueBehavior
LocalSTB_LOCAL0Not visible outside the object file. Multiple files can have same name.
GlobalSTB_GLOBAL1Visible to all object files in the link. Must be unique across entire program.
WeakSTB_WEAK2Like 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:

  1. Strong (GLOBAL) definitions override weak ones
  2. Multiple strong definitions = error ("multiple definition")
  3. Multiple weak definitions = pick any (usually first one found)
  4. LOCAL symbols never participate in cross-file resolution

A Real Example

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).

Try It

# 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)

Check Your Understanding

What happens if two object files both define a strong (GLOBAL) symbol with the same name?

Apply It

Why would you use a WEAK symbol instead of a GLOBAL one?

Connect

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.

← Swipe to navigate →