← Concepts & Glossary
Detection & Analysis

Call Graph

A map of which functions call which — the foundation of reachability and taint analysis.

What is a call graph?

A call graph is a directed graph whose nodes are functions and whose edges represent "caller to callee" relationships. If function A invokes B, there is an edge from A to B. Chase enough of those edges and you get a complete map of how execution can flow through a program.

It sounds simple — and in the small it is — but a production call graph has to resolve dynamic dispatch, interfaces, reflection, callbacks, and cross-package edges through hundreds of dependency versions. Almost every interesting program analysis, from reachability to taint to dead-code detection, starts from this structure.

How it works

Building a useful call graph is an exercise in symbol resolution at scale:

  1. Parse and resolve. Every source file is parsed into an AST. Function definitions and call sites are extracted, then linked to the specific symbol they refer to — accounting for scope, imports, re-exports, and language-specific name resolution.
  2. Version-aware dependency edges. A call into a dependency is resolved against the exact version in the lockfile. The same package name at 1.2.0 and 1.3.5 can expose different APIs, and the graph has to reflect that.
  3. Dynamic dispatch and higher-order calls. Interfaces, virtual methods, and function values are resolved with type information where available and conservative over-approximation where not. Every edge is tagged with a confidence signal so downstream analyses can decide how to treat it.

Why it matters

Without a call graph, a security analyzer is guessing. It can tell you that a vulnerable function exists somewhere in your dependencies, but it cannot tell you whether your code actually calls it. That is the difference between "1,400 CVEs in your SBOM" and "22 CVEs reachable from your code."

Call-graph quality also sets the ceiling for every downstream technique. A taint analyzer that runs on a sloppy graph produces sloppy findings. The engineering investment in graph accuracy pays off in every report the platform generates.

What value it adds

  • Enables every serious analysis

    Reachability, taint, dead-code elimination, change-impact — all of them start by walking a call graph. Without it, the analyzer is pattern-matching.

  • Cross-package edges, not just your code

    The interesting flows go through your dependencies. A graph that stops at the package boundary misses exactly the paths that matter for supply-chain risk.

  • Version-aware resolution

    Edges are resolved against the exact dependency version in the lockfile — so the graph reflects what actually ships, not a generic snapshot of the ecosystem.

  • Confidence-tagged edges

    Reflection and dynamic dispatch get marked as uncertain rather than silently dropped. Downstream stages can choose whether to trust or quarantine those paths.

  • Feeds fast, deterministic re-analysis

    When a single file changes, the graph is updated incrementally — so reachability on a PR completes in seconds, not minutes.

How Safeguard uses it

The call graph is the substrate underneath reachability analysis, taint analysis, and exploit-path reasoning in Griffin AI. Every other concept on this page relies on it being accurate.

See your real call graph.

Point Safeguard at a repo. Watch the call graph build across your first-party code and every dependency.