LLTFI (Low-Level Tensor Fault Injector) is an LLVM-based fault injection framework supporting C/C++ and ML applications (TensorFlow, PyTorch). It injects faults into LLVM IR. It is built on top of LLFI and is fully backward compatible with it.
| Variable | Path |
|---|---|
| Source tree | /home/karthik/Programs/LLTFI |
| Build root | /home/karthik/Programs/LLTFI-build |
| LLVM DST root | /usr/lib/llvm-20 (apt install) |
| LLVM SRC root | /home/karthik/Programs/llvm-project |
| LLVM version | 20.1 |
To rebuild from source:
./setup -LLFI_BUILD_ROOT /home/karthik/Programs/LLTFI-build \
-LLVM_SRC_ROOT /home/karthik/Programs/llvm-project \
-LLVM_DST_ROOT /usr/lib/llvm-20 \
-LLVM_GXX_BIN_DIR /usr/lib/llvm-20/binThe build root must not already exist. Delete it first if rebuilding from scratch.
To rebuild after code changes (faster):
cd /home/karthik/Programs/LLTFI-build && makeFrom the build directory:
cd /home/karthik/Programs/LLTFI-build/test_suite
python3 SCRIPTS/llfi_test --all_cpp # all 21 tests
python3 SCRIPTS/llfi_test --all_hardware_faults # 8 tests
python3 SCRIPTS/llfi_test --all_trace_tools_tests # 3 tests
python3 SCRIPTS/llfi_test --all_makefile_generation # 2 tests
python3 SCRIPTS/llfi_test --all_ml # ML/ONNX toolsExpected: 21/21 PASS for --all. Some error messages during fault injection runs are normal.
--all_ml runs additional tests not included in --all:
| Test group | Tests | Requirements |
|---|---|---|
CompareLayerOutputs |
2 | pip install onnx pygraphviz |
ExtendONNXModel |
1 | pip install onnx |
outputONNXGraph |
1 | pip install onnx pydot |
| TensorFlow → ONNX | 3 | pip install tensorflow tf2onnx onnx |
| PyTorch → ONNX | 2 | pip install torch onnx |
| ONNX → LLVM IR | 2 | onnx-mlir + mlir-translate on PATH or $ONNX_MLIR_BUILD set |
| Fault injection (ML) | 3 | LLTFI build + model.ll in sample_programs/.../mnist/ (run compile.sh first) |
Tests with missing deps are reported as SKIP (not FAIL) and excluded from the pass/fail count.
The ONNX→IR and fault injection tests use the pre-built model.onnx from
sample_programs/ml_sample_programs/vision_models/mnist/. The fault injection
test also requires model.ll which is produced by that directory's compile.sh.
llvm_passes/ LLVM pass plugins (compiled to llfi-passes.so)
core/ Fault injection, profiling, tracing passes
hardware_failures/ Built-in hardware fault selectors (bitflip, funcname, etc.)
runtime_lib/ Runtime library (libllfi-rt.so) linked into instrumented binaries
bin/ Python driver scripts: instrument.py, profile.py, injectfault.py
docs/ input_masterlist.yaml, input_masterlist_ml.yaml — reference schemas
for the input.yaml files that control instrumentation and injection
input_yaml_guide.md — prose guide to writing input.yaml (user-facing)
tools/ Trace analysis tools (tracediff.py, traceontograph.py, traceunion.py,
tracetodot.py), GenerateMakefile/
test_suite/ Regression tests
PROGRAMS/ Source programs used by tests
HardwareFaults/ Hardware fault injection test cases
Traces/ Pre-committed trace reference files for trace tool tests
MakefileGeneration/ Makefile generation test cases
The codebase targets LLVM 19. Key API changes to keep in mind:
#include "llvm/IR/CFG.h"(notllvm/Support/CFG.h— removed in LLVM 15)CI->arg_size()(notCI->getNumArgOperands()— removed in LLVM 15)func->getName().str()returnsStringRef; call.str()before assigning tostd::stringopt -load-pass-plugin(notopt -load— legacy PM removed in LLVM 17)--passes=passname(not-passname— old opt syntax removed in LLVM 17)InsertPositionrequires aBasicBlock::iterator, not a rawInstruction*— call.getIterator()on the insertion pointgetFirstNonPHIOrDbgOrLifetime()now returnsBasicBlock::iterator(notInstruction*)getFirstNonPHI()→getFirstNonPHIIt()(returns iterator)M.getGlobalList()is private — usenew GlobalVariable(M, type, ...)to insert directlyitaniumDemangle(str)takes a singlestring_viewargument (old 4-arg form removed)- All passes use the new pass manager (
PassInfoMixin,llvmGetPassPluginInfo);InstructionDuplicationexposes both a legacy PM class and a new PM wrapper (NewInstructionDuplicationPass) registered as"InstructionDuplicationPass"inSEDPasses.so
The following files appear as untracked after running tests and should not be staged:
test_suite/HardwareFaults/*/inp.in,graph_input.dat— deployed bydeploy_prog.pyfromPROGRAMS/test_suite/HardwareFaults/*/llfi.test.log.*— test run artifactstest_suite/Traces/*/llfi/llfi_stat_output/*.report.txt— generated by trace analysis
Run from the source tree root:
bash lint.sh # check only
bash lint.sh --fix # auto-fix clang-format issues in-place
bash lint.sh --cpp # C++ checks only
bash lint.sh --python # Python checks onlyRequirements:
- C++:
clang-format-20andclang-tidy-20(apt install clang-format-20 clang-tidy-20) - C++ static analysis also needs
compile_commands.jsonin the build root:cd /home/karthik/Programs/LLTFI-build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
- Python:
flake8andflake8-bugbear(pip install flake8 flake8-bugbear)
clang-tidy config (.clang-tidy): Checks include modernize-use-override, readability-container-size-empty, cppcoreguidelines-init-variables, bugprone-*, clang-analyzer-core.*, performance-*, and others. The following are intentionally disabled because they fire on legitimate LLVM patterns or system-header code:
| Disabled check | Reason |
|---|---|
cppcoreguidelines-slicing |
cl::opt<string> to string is idiomatic LLVM (use .getValue() instead) |
clang-analyzer-optin.* |
Fires on standard LLVM pass framework patterns |
clang-analyzer-cplusplus.NewDelete |
False positives from LLVM's internal memory management |
clang-diagnostic-macro-redefined |
Suppress DEBUG_TYPE conflicts with LLVM headers |
bugprone-assignment-in-if-condition |
while ((pos = s.find(x)) != npos) is idiomatic C++ |
See CODING_GUIDELINES.md for the full style guide. Key points:
C++:
- Use
nullptr, notNULL - Every header needs
#ifndefinclude guards - Missing
returninbool runOnModule(...)is UB — always returnfalseunless IR was modified - Derived-class overrides: use
override, omitvirtual; abstract base classes needvirtual ~Base() = default; - Use
cast<>(asserts) when type is guaranteed;dyn_cast<>(returns null) when it may not match - Use
except Exception:in Python; in C++ useerrs()for pass diagnostics
Python:
- Python 3 only (
#!/usr/bin/env python3) - Use
with open(...) as f:always — no bareopen()without context manager except Exception:minimum; use specific types (OSError,KeyError) where knownsys.exit(), notexit()- No
subprocess(..., shell=True)— use list args andstdout=open(file, 'w')for redirection yaml.safe_load()always — neveryaml.load()without Loader
- Wiki Page 4: says
input_masterlist.yamlis inbin/— actually indocs/ - Wiki Page 5: uses
llvm-gcc(replaced by clang) and oldopt -loadsyntax - Wiki Page 9: references
gui/config/files that no longer exist (Java GUI removed)