Constant encryption — constenc¶
Numeric constant encryption for scalar integer and floating-point immediates.
constenc replaces selected constant operands of instructions with runtime computations that
produce the same value but are opaque to the optimizer. Each is routed through a per-function
volatile anchor, so -O2 / constant-propagation cannot fold the original constant back. It is the
complement of strenc (which hides string literals): constenc hides the magic
numbers, keys, and thresholds that would otherwise sit in the IR and binary as plain immediates.
Runs first in the pipeline, so later passes (mba, substitution, bcf, …) further bury the
materialization arithmetic.
What it skips¶
Constants that must stay literal are skipped automatically:
switchcase valuesgetelementptrindices- intrinsic and inline-asm immediate operands (
immarg/"i"/"n"constraints) phiincoming values- EH-funclet operands
Supported widths: integer 1..32 and 64, plus float and double. Trivial small-magnitude
constants (below minAbs) are left alone.
Options¶
| Key | Default | Range | Meaning |
|---|---|---|---|
prob |
60 | 0–100 | Probability (%) to encode a candidate constant site. |
maxSites |
200 | 1–100000 | Cap on encoded constants per function (also budget-throttled). |
minAbs |
2 | ≥ 0 | Skip constants whose magnitude is below this (e.g. 0/1/-1). |
encInt |
1 | 0/1 | Encode integer constants. |
encFP |
1 | 0/1 | Encode float/double constants. |
wrapMBA |
0 | 0/1 | Route materialized constants through MBA (linear inflation). |
Example¶
__attribute__((annotate("obf: constenc(prob=100,minAbs=4,encFP=0)")))
int license_check(int serial) { return serial ^ 0xC0FFEE; }
Stack it with MBA
constenc(wrapMBA=1) pipes each materialized constant through MBA. Combined with a following
mba pass, the arithmetic that reconstructs the constant becomes an MBA expression
itself — two layers over every magic number.