Join our Newsletter — 33% off our NHI Course
Home› FAQ› Cyber Security› What are the signs that lazy linking is…
Cyber Security

What are the signs that lazy linking is being used to delay resolution of external functions?

← Back to all FAQ
By NHI Mgmt Group Editorial Team Updated September 25, 2026 Domain: Cyber Security

A common sign is that external functions are not resolved at load time but only when the program first calls them. In practice, that means the Procedure Linkage Table and Global Offset Table carry the initial indirection, and the dynamic linker resolves the symbol on demand. Analysts may see the first call incur extra resolution activity before subsequent calls execute directly.

How lazy linking reveals deferred symbol resolution

Lazy linking is usually visible through timing and execution order rather than a special error message. The first call into a shared library symbol pays the resolution cost, while later calls bypass that work. In a debugger or trace, that creates a distinct first-hit pattern: control flow enters the resolver path once, then settles into the normal target address on subsequent invocations.

The mechanism is consistent with how the runtime uses the Procedure Linkage Table and Global Offset Table as the indirection layer. Before resolution, the call site routes through that trampoline; after resolution, the table entry is updated so the program can call the function directly. That transition is the practical sign that binding was deferred until runtime.

Because the symbol is resolved on demand, you may also see extra memory writes or loader activity at the moment of the first call. On instrumented systems, this can look like a brief jump into the dynamic linker, followed by a return to the caller and then a normal branch to the resolved address. The behaviour is most obvious when comparing the first invocation with repeated calls to the same imported function.

What the first-call behaviour tells an analyst

Lazy linking is not just an implementation detail, it changes what evidence is available during analysis. If a function is only resolved after execution begins, static inspection of import tables alone may not fully show the eventual runtime target, especially when symbol interposition, preload hooks, or patched loaders are involved. That means runtime observation often matters more than the binary layout by itself.

The main diagnostic clue is asymmetry. One call path incurs resolution overhead, and later calls do not. If you are watching disassembly, you may also see the PLT stub used as the stable entry point, with the GOT slot rewritten after the symbol lookup completes. That makes lazy binding easier to distinguish from eager binding, where the addresses are settled before the program reaches the relevant code path.

This pattern can also affect reproducibility in analysis. A trace captured before the first call may show different control flow from a trace captured after resolution has already happened. When you compare runs, make sure you know whether the function was already bound, because the first-use resolution event can disappear from later samples.

Operational indicators that confirm delayed resolution

Analysts usually confirm lazy linking by correlating several signals rather than relying on a single one. The strongest indicators are a PLT stub in the call path, a GOT entry that changes after first use, and resolver activity that occurs exactly once per symbol in the current process image. If those three line up, delayed resolution is the likely explanation.

You can also validate the behaviour by calling the same imported function twice under observation. The first call should show resolver involvement, while the second should be materially quieter and shorter. If the path still resolves repeatedly, that points to a different problem, such as a non-standard loader, an unresolved relocation issue, or instrumentation that prevents the resolved address from being cached.

For deeper inspection, tools that reveal dynamic relocations and symbol binding order are more useful than plain string extraction or import listing. The practical question is not whether a function exists in the dependency graph, but whether execution is still paying the indirection cost at call time. That is the operational signature lazy linking leaves behind.

Risk and Threat Considerations

Lazy binding creates a brief window where the process depends on runtime symbol resolution, which can complicate both debugging and trust assumptions about what code actually executes first. In hostile or heavily instrumented environments, that indirection can become a point where loader behaviour, preloading, or interception changes the effective target of a call.

Failure mechanism: The program enters a resolver path on first use, allowing the PLT and GOT indirection to be influenced before the final address is fixed for subsequent calls.

Impact: Analysts may misread early execution traces, miss loader-mediated behaviour, or underestimate how much the first invocation differs from steady-state execution.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

MITRE ATT&CK addresses the attack and risk surface, while NIST CSF 2.0 sets the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
MITRE ATT&CKT1202 — Indirect Command ExecutionLazy linking uses an indirection path before the final function is reached.
Recommendation — Trace indirect call paths to understand when execution is routed through a resolver stub.
NIST CSF 2.0DE.CM-01 — Monitoring for Unauthorized Personnel, Connections, Devices, and SoftwareRuntime observation is needed to detect first-call resolution behaviour in execution traces.
Recommendation — Monitor execution traces to distinguish first-use resolution from steady-state calls.

Practitioner Guidance

What to verify: Confirm whether the symbol is resolved only once per process and whether the GOT entry changes after the first call. That is the fastest way to separate lazy binding from ordinary direct calls or repeated loader activity.

Common mistake: Treating the import list as proof of runtime call behaviour. For this question, the import tells you what may be called, but the call trace tells you when and how the target was actually bound.

Practitioner takeaway: The key judgement is to separate static linkage structure from runtime binding behaviour, because lazy linking is identified by the first-call transition, not by the mere presence of an imported function.

Deepen Your Knowledge

Sign up to our weekly newsletter — get 33% off our NHI Foundation Level Course

    NHIMG Editorial Note
    Reviewed and updated by the NHIMG editorial team on September 25, 2026.
    NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org