Reading — step 1 of 5
Read
~1 min readStatic Loading
Symbols
A symbol is a named entry: function, variable, section.
Symbol entry (64-bit):
struct Symbol {
uint32_t name; // offset into strtab
uint8_t info; // bind:4 | type:4
uint8_t other; // visibility
uint16_t shndx; // section index, or SHN_UNDEF
uint64_t value; // address (or value for absolute)
uint64_t size;
};
Bind:
- STB_LOCAL: file-scope.
- STB_GLOBAL: visible across files.
- STB_WEAK: like global but yields to STB_GLOBAL.
Type:
- STT_FUNC: function.
- STT_OBJECT: data variable.
- STT_SECTION: section symbol.
- STT_FILE: source filename.
- STT_NOTYPE: unspecified.
Visibility:
- STV_DEFAULT: visible.
- STV_HIDDEN: not visible to dynamic linker (file-local).
- STV_PROTECTED: visible but call goes through GOT (no preemption).
Symbols in .o:
- Defined: have non-zero shndx + value.
- Undefined: shndx = SHN_UNDEF, value = 0. Linker resolves.
Symbol resolution (linker):
- Each input .o contributes symbols.
- Global symbol defined in two files → MULTIPLE_DEFINITION error (unless one is weak).
- Undefined symbol not found anywhere → UNDEFINED_REFERENCE error.
Symbol versioning:
- glibc: foo@@GLIBC_2.4 vs foo@GLIBC_2.5.
- Multiple versions in one .so for ABI compat.
- Linker picks based on what was at build time.
Mangled names (C++):
_ZN3fooEv=foo().- Need
c++filtornm -Cto demangle.
nm shows symbols. T = text (function), D = data (initialized), B = bss, U = undefined.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…