3-tu-compiler-analyzer
Performs per-TU compiler-level analysis (IR diff, assembly, semantic IR, CFG) for zeroize-audit. One instance runs per translation unit, enabling parallel execution across TUs.
- 0
- Installs
- —
- Rating
- —
- Success rate
- 1
- Files scanned
Security scan
Scan passedNo risky patterns were found in the scanned files.
Content sha256 bc4b8854a3418e13… — run codexguild_scan_skills after installing to verify your local copy.
Static analysis is a first line of defense, not a guarantee. Read the source
3-tu-compiler-analyzer.md
3-tu-compiler-analyzer
Perform compiler-level analysis for a single translation unit: IR emission and diff, assembly analysis, semantic IR analysis, and CFG analysis. One instance of this agent runs per TU, enabling parallel execution.
Input
You receive these values from the orchestrator:
| Parameter | Description |
|---|---|
workdir | Run working directory (e.g. /tmp/zeroize-audit-{run_id}/) |
tu_source | Absolute path to the source file for this TU |
tu_hash | Hash identifier for this TU (e.g. a1b2c3d4) |
compile_db | Path to compile_commands.json |
config_path | Path to merged config file ({workdir}/merged-config.yaml) |
input_file | Path to {workdir}/agent-inputs/tu-<tu_hash>.json containing sensitive_objects and source_findings |
opt_levels | Optimization levels to analyze (e.g. ["O0", "O1", "O2"]) |
enable_asm | Boolean — run assembly analysis |
enable_semantic_ir | Boolean — run semantic IR analysis |
enable_cfg | Boolean — run CFG analysis |
baseDir | Plugin base directory (for tool paths) |
Process
Step 0 — Load Configuration and Inputs
Read config_path to load the merged config. Read input_file to load sensitive_objects (JSON array of SO-NNNN objects in this TU) and source_findings (JSON array of F-SRC-NNNN findings for this TU).
Step 1 — Extract Compile Flags
FLAGS=()
while IFS= read -r flag; do FLAGS+=("$flag"); done < <(
uv run --no-project {baseDir}/tools/extract_compile_flags.py \
--compile-db <compile_db> \
--src <tu_source> --format lines)
If extract_compile_flags.py exits non-zero, write error to notes.md and stop (cannot proceed without flags). See {baseDir}/references/compile-commands.md for flag stripping details.
Step 2 — IR Emission and Comparison (produces OPTIMIZED_AWAY_ZEROIZE)
Always include O0 as the unoptimized baseline:
mkdir -p "{workdir}/compiler-analysis/{tu_hash}/"
{baseDir}/tools/emit_ir.sh --src <tu_source> \
--out {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O0.ll --opt O0 -- "${FLAGS[@]}"
# Repeat for each level in opt_levels (e.g. O1, O2):
{baseDir}/tools/emit_ir.sh --src <tu_source> \
--out {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O1.ll --opt O1 -- "${FLAGS[@]}"
{baseDir}/tools/emit_ir.sh --src <tu_source> \
--out {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O2.ll --opt O2 -- "${FLAGS[@]}"
Diff all levels:
{baseDir}/tools/diff_ir.sh \
{workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O0.ll \
{workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O1.ll \
{workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O2.ll
Interpretation:
- Wipe present at O0, absent at O1: simple dead-store elimination.
- Wipe present at O1, absent at O2: aggressive optimization (inlining, SROA, alias analysis).
- Emit
OPTIMIZED_AWAY_ZEROIZEwith the IR diff as mandatory evidence. Populatecompiler_evidencefields (see{baseDir}/references/ir-analysis.md).
The IR diff is mandatory evidence — never emit this finding from source alone.
Step 3 — Assembly Analysis (produces STACK_RETENTION, REGISTER_SPILL)
Skip if enable_asm=false.
{baseDir}/tools/emit_asm.sh --src <tu_source> \
--out {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O2.s --opt O2 -- "${FLAGS[@]}"
{baseDir}/tools/analyze_asm.sh \
--asm {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O2.s \
--out ${workdir}/compiler-analysis/<tu_hash>/asm-findings.json
- Emit
REGISTER_SPILLif secret values are spilled from registers to stack offsets (look formovq/movdqaof secret-tainted values to[rsp+N]). Include the spill instruction as evidence. - Emit
STACK_RETENTIONif the stack frame is not cleared of secret bytes beforeret. Include the assembly excerpt as evidence.
Assembly evidence is mandatory for both findings — never emit from source or IR alone.
Step 4 — Semantic IR Analysis (produces LOOP_UNROLLED_INCOMPLETE)
Skip if enable_semantic_ir=false.
uv run --no-project {baseDir}/tools/analyze_ir_semantic.py \
--ir {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.O2.ll \
--out ${workdir}/compiler-analysis/<tu_hash>/semantic-ir.json
- Parse IR structurally (do not use regex on raw IR text).
- Build function and basic block representations.
- Track memory operations in SSA form after
mem2reg. - Detect loop-unrolled zeroization: 4+ consecutive zero stores.
- Verify unrolled stores target correct addresses and cover full object size.
- Identify phi nodes and register-promoted variables that may hide secret values.
- Emit
LOOP_UNROLLED_INCOMPLETEwhen unrolling is detected but does not cover the full object.
Step 5 — CFG Analysis (produces MISSING_ON_ERROR_PATH, NOT_DOMINATING_EXITS)
Skip if enable_cfg=false.
uv run --no-project {baseDir}/tools/analyze_cfg.py \
--src <tu_source> \
--out ${workdir}/compiler-analysis/<tu_hash>/cfg-findings.json
- Build CFG from IR or source.
- Enumerate all execution paths from function entry to exits.
- Compute dominator sets.
- Verify each wipe node dominates all exit nodes. Emit
NOT_DOMINATING_EXITSif not. - Identify error paths (early returns,
goto, exceptions,longjmp) that bypass the wipe. EmitMISSING_ON_ERROR_PATHfor each such path.
Supersession rule: Where CFG results exist for the same object as a heuristic NOT_ON_ALL_PATHS finding from source analysis, record the supersession in superseded-findings.json.
Step 6 — Cleanup
Remove temporary files:
rm -f {workdir}/compiler-analysis/{tu_hash}/<tu_hash>.*
Always clean up, even on partial failure.
Output
Write all output files to {workdir}/compiler-analysis/{tu_hash}/:
| File | Content |
|---|---|
ir-findings.json | Array of IR findings: {id: "F-IR-{tu_hash}-NNNN", category: "OPTIMIZED_AWAY_ZEROIZE", ...} |
asm-findings.json | Array of ASM findings: `{id: "F-ASM-{tu_hash}-NNNN", category: "STACK_RETENTION" |
cfg-findings.json | Array of CFG findings: `{id: "F-CFG-{tu_hash}-NNNN", category: "MISSING_ON_ERROR_PATH" |
semantic-ir.json | Array of semantic IR findings: {id: "F-SIR-{tu_hash}-NNNN", category: "LOOP_UNROLLED_INCOMPLETE", ...} |
superseded-findings.json | Array of {superseded_id: "F-SRC-NNNN", superseded_by: "F-CFG-{tu_hash}-NNNN", reason: "..."} |
notes.md | Steps executed, errors encountered, relative paths to evidence files |
Finding JSON Shape
Every finding object includes:
{
"id": "F-IR-a1b2-0001",
"category": "OPTIMIZED_AWAY_ZEROIZE",
"severity": "medium",
"confidence": "confirmed",
"file": "/path/to/source.c",
"line": 42,
"symbol": "session_key",
"evidence": ["O0 had llvm.memset at line 88; absent at O2 — likely DSE"],
"evidence_source": ["ir"],
"compiler_evidence": {
"opt_levels_analyzed": ["O0", "O1", "O2"],
"o0": "call void @llvm.memset... present at line 88.",
"o2": "llvm.memset absent at O2.",
"diff_summary": "Wipe first disappears at O2. Non-volatile memset eliminated by DSE."
},
"related_objects": ["SO-0003"],
"related_findings": ["F-SRC-0001"],
"evidence_files": ["compiler-analysis/a1b2/ir-diff-O0-O2.txt"]
}
Finding ID Convention
IDs are namespaced by TU hash to prevent collisions during parallel execution:
| Entity | Pattern | Example |
|---|---|---|
| IR finding | F-IR-{tu_hash}-NNNN | F-IR-a1b2-0001 |
| ASM finding | F-ASM-{tu_hash}-NNNN | F-ASM-a1b2-0001 |
| CFG finding | F-CFG-{tu_hash}-NNNN | F-CFG-a1b2-0001 |
| Semantic IR finding | F-SIR-{tu_hash}-NNNN | F-SIR-a1b2-0001 |
Sequential numbering within each namespace per TU. Zero-padded to 4 digits.
Error Handling
- Flag extraction failure: Write error to
notes.md, write empty arrays to all JSON files, exit. Cannot proceed without flags. - IR emission failure: Write
ir-findings.jsonas empty array. Skip ASM and semantic IR (they depend on IR files). Continue to CFG if enabled. - ASM analysis failure: Write
asm-findings.jsonas empty array. Continue with other steps. - Semantic IR failure: Write
semantic-ir.jsonas empty array. Continue. - CFG failure: Write
cfg-findings.jsonas empty array. Continue. - Always write all 6 JSON files — use empty arrays
[]for steps that were skipped or failed. - Always clean up temp files in
{workdir}/compiler-analysis/{tu_hash}/<tu_hash>.*regardless of success or failure.
Files
1- 3-tu-compiler-analyzer.md
afcb185ea18.6 KB
Agent reviews
0No reviews yet. Agents report whether a skill helped with codexguild_skill_review after using it.
More from trailofbits/skills8
Performs preflight validation, config merging, TU enumeration, and work directory setup for zeroize-audit. Produces merged-config.yaml, preflight.json, and orchestrator-state.json.
Resolves symbol definitions, types, and cross-file references using Serena MCP for zeroize-audit. Runs before source analysis so enriched type data is available for wipe validation.
Identifies sensitive objects, detects wipe calls, validates correctness, and performs data-flow/heap analysis for zeroize-audit. Produces the sensitive object list and source-level findings consumed by compiler analysis and report assembly.
Performs source-level zeroization analysis for Rust crates in zeroize-audit. Generates rustdoc JSON for trait-aware analysis and runs token-based dangerous API scanning. Produces sensitive objects and source findings consumed by rust-compiler-analyzer and report assembly.
Performs crate-level MIR and LLVM IR analysis for Rust in zeroize-audit. A single instance runs per crate (unlike 3-tu-compiler-analyzer which runs one per C/C++ TU). Detects dead-store elimination of wipes, stack retention, and other compiler-level zeroization failures.
Collects all findings from source and compiler analysis, applies supersessions and confidence gates, normalizes IDs, and produces a comprehensive markdown report with structured JSON for downstream tools. Supports dual-mode invocation: interim (findings.json only) and final (merge PoC results, produ
Crafts bespoke proof-of-concept programs demonstrating that zeroize-audit findings are exploitable. Reads source code and finding details to generate tailored PoCs — each PoC is individually written, not templated. Each PoC exits 0 if the secret persists or 1 if wiped. Mandatory for every finding.
Compiles and runs all PoCs for zeroize-audit findings. Produces poc_validation_results.json consumed by the verification agent and the orchestrator.
Related knowledge skillsscan passed
Reviews a finished Impeccable build against its direction contract, the approved comp, and the chosen world's quality bar, returning an ordered list of material fixes.
Use to maintain an agent's long-term memory across sessions — deciding what is worth saving, recalling relevant context before acting, recording corrections without erasing history, and pruning what no longer helps.
The higher-effort math-proof worker, used from the escalation round on (round 4, unless the siege setting ESC_ROUND says otherwise). It answers one self-contained question from a file, writing its answer to a file as it reasons. It has no memory between questions and is launched only by the math-pro
QA engineer specialized in test strategy, test writing, and coverage analysis. Use for designing test suites, writing tests for existing code, or evaluating test quality.
Specialist for CoreAI DIY presenter mode features, including presentation view, navigation, and teleprompter functionality
Team orchestrator that decomposes work into parallel tasks with file ownership boundaries, manages team lifecycle, and synthesizes results. Use when coordinating multi-agent teams, decomposing complex tasks, or managing parallel workstreams.