Safety rails & budgeting¶
Obfuscation multiplies IR. Left unchecked, a heavy annotation on a large function can blow up compile time and binary size. xollvm gates every transform on size thresholds and an IR-growth budget, so obfuscation degrades gracefully instead of exploding.
Function-size gates¶
Skip functions that are too big or too deeply nested before any pass touches them:
| Flag | Default | Meaning |
|---|---|---|
-obf-max-function-insts=<N> |
0 (off) | Skip functions with more than N instructions. |
-obf-max-function-blocks=<N> |
0 (off) | Skip functions with more than N basic blocks. |
-obf-max-loop-depth=<N> |
0 (off) | Skip functions whose loop nesting exceeds N. |
0 disables a gate. These are global — they apply to every annotated function.
The IR-growth budget¶
Each function has a budget: a ceiling on how much its instruction count may grow across all passes. When a pass would exceed it, sites are throttled or skipped rather than emitted.
| Flag | Default | Meaning |
|---|---|---|
-obf-ir-budget-multiplier=<N> |
50 | Budget = insts_before × N (clamped by the max below). 0 = unlimited. |
-obf-ir-budget-max=<N> |
0 (off) | Absolute per-function instruction ceiling. 0 = no hard cap. |
So by default a function may grow up to 50× its original size, with no absolute cap. Tighten both for size-sensitive targets:
opt -passes=obfuscation app.ll -S -o app.obf.ll \
-obf-ir-budget-multiplier=20 -obf-ir-budget-max=8000
Budgets are global, not per-annotation
Budget knobs cannot currently be expressed as annotation tokens — set them on the command line.
Per-pass caps like maxSites / maxBlocks are per-annotation and stack on top of the budget.
Reading budget pressure¶
When the report shows many "skipped due to budget" entries, the function hit its ceiling. Two ways to respond:
- Want more obfuscation: raise
-obf-ir-budget-multiplier/-obf-ir-budget-max. - Want smaller output: lower per-pass
prob,maxDepth,loop,maxSites, or annotate fewer functions.
# see what was skipped and why
opt -passes=obfuscation app.ll -S -o app.obf.ll -obf-report-dir=obf_report -obf-verbose
The report JSON records budget utilisation per function; -obf-verbose prints skip reasons live.
See Reports & CFG visualization.
Correctness rails¶
Beyond size, two flags guard correctness and debuggability:
| Flag | Default | Meaning |
|---|---|---|
-obf-verify |
off | Run IR verification before/after each stage — catches an invalid transform close to its source. |
-obf-debug-synthetic |
on | Give inserted instructions synthetic line-0 debug locations so source steppers don't jump erratically. |
Keep -obf-verify on while developing an annotation set; it turns a mysterious downstream crash
into a precise "this pass produced invalid IR" error.