Skip to content

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:

  • switch case values
  • getelementptr indices
  • intrinsic and inline-asm immediate operands (immarg / "i"/"n" constraints)
  • phi incoming 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.