How Tech - Systems Programming

How Tech - Systems Programming

Analyzing Binary Dependencies and Symbols: What nm and objdump Actually Tell You

Feb 13, 2026
∙ Paid

Understanding how programs find and connect to their dependencies at runtime is one of those skills that separates someone who can write code from someone who can debug production systems. When your program crashes with “symbol not found” or mysteriously behaves differently in production than it did on your laptop, you need to understand what’s happening at the binary level.

This guide will walk you through the tools and techniques that professional systems engineers use to debug these issues. We’ll start with the theory, then get our hands dirty with real code.


Why Your Binary Crashes at Runtime (Not Compile Time)

Dynamic linking defers symbol resolution to runtime. Your code compiles perfectly because the linker only checks that symbols exist in the shared libraries you link against. But at runtime, ld.so has to actually find and bind those symbols. That’s where things fall apart.

I once deployed a service that worked everywhere except one production cluster. Turns out we had two libraries both providing weak definitions of operator new. Load order differed between environments - staging loaded libA first, production loaded libB first. Runtime picked different implementations. Five hours of debugging later, nm -C showed both libraries exporting W operator new (weak binding). The fix? Make our override strong (remove __attribute__((weak))).

User's avatar

Continue reading this post for free, courtesy of Systems.

Or purchase a paid subscription.
© 2026 Sumedh S · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture