Reports & CFG visualization¶
The report system is for debugging and understanding — what changed, where, and which pass did it. It emits a machine-readable obfuscation map plus per-pass CFG snapshots, and a Python viewer renders them as HTML.
Generate reports¶
Run opt with a report directory and a fixed seed:
opt -passes=obfuscation -S app.ll -o app.obf.ll \
-obf-seed=1 -obf-deterministic \
-obf-report-dir=obf_report
This produces:
obf_report/
├─ obf_report.json # machine-readable obfuscation map
└─ cfg/<fn>/
├─ before.dot # CFG before any pass
├─ after.dot # CFG after all passes
└─ per_pass/<passId>/
├─ after.dot # CFG after this pass
└─ diff.dot # optional diff overlay
| Flag | Effect |
|---|---|
-obf-report-dir=<dir> |
Emit CFG DOT files + JSON into this directory. |
-obf-report-json=<path> |
Write just the report JSON to a path (- = stdout). |
The HTML viewer¶
python utils/obf_report_html.py \
--json obf_report/obf_report.json \
--out obf_report/obf_report.html \
--renderer dot
Per-function views show pass-by-pass instruction-count deltas, CFG before/after, per-pass diff overlays, and a difficulty score (cyclomatic complexity, opaque-predicate count, MBA depth, …).
Renderers¶
--renderer |
Needs | Notes |
|---|---|---|
dot (recommended) |
Graphviz dot on PATH |
Renders graphs offline as inline SVG — no CDN, no WASM. |
wasm |
served over HTTP | python -m http.server 8000 --directory obf_report then open the page. |
text |
nothing | Metadata tables only, no graphs — works anywhere. |
Reading the vm entry¶
For virtualised functions the report's passes[] array holds a vm entry with status, changed,
insts_before, insts_after, delta_insts. A large delta_insts is expected (the interpreter is
much bigger than the original). status = "skipped" carries a skip_reason
(see VM eligibility), and the CFG diff shows the whole original graph
collapsed into the wrapper + engine.
Theme-safe CFG SVGs¶
utils/cfg_svg.py regenerates CFG SVGs directly from the obf-report .dot files — pure Python, no
Graphviz needed. It produces light+dark theme-safe SVGs (single and pair subcommands, with
--stack / --dense). These are the diagrams used throughout this documentation.
Debugging workflow¶
- Reproduce with a fixed seed (
-obf-seed=1 -obf-deterministic). - Add
-obf-verifyto catch invalid IR at the pass that introduced it. - Generate a report; open the HTML viewer and find the offending pass by its CFG diff.
- Bisect: start with a single pass, confirm it works, add passes one at a time.
See Diagnostics for obf-dump-config and obf-metrics.