Overview
Theinliner.cpp example shows how to:
- Create custom workflow activities
- Clone and modify existing workflows
- Integrate activities into the analysis pipeline
- Use LLIL manipulation for code transformation
- Register plugin commands that interact with workflows
Complete Source Code
Key Concepts Explained
void FunctionInliner(Ref<AnalysisContext> analysisContext)
{
Ref<Function> function = analysisContext->GetFunction();
Ref<LowLevelILFunction> llilFunc = analysisContext->GetLowLevelILFunction();
// Perform custom analysis or transformations
// ...
}
AnalysisContext parameterRef<Workflow> inlinerWorkflow = Workflow::Get("core.function.baseAnalysis")->Clone("InlinerWorkflow");
Workflow::Get(name) - Retrieve existing workflow->Clone(newName) - Create a customizable copy"core.function.baseAnalysis" - Standard function analysis"core.module.defaultAnalysis" - Binary-level analysis"extension.*") for custom activitiesInsert(beforeActivity, newActivity) - Run before specified activity"core.function.translateTailCalls" - After basic LLIL construction"core.function.generateSSA" - When SSA form is availableWorkflow::RegisterWorkflow(inlinerWorkflow,
R"#({
"title" : "Function Inliner (Example)",
"description" : "This analysis demonstrates Binary Ninja's extensible analysis APIs.",
"targetType" : "function"
})#");
targetType can be "function" or "module"// Replace call instruction with goto
instr.Replace(llilFunc->Goto(inlineStartLabel));
// Copy IL from another function
llilFunc->PrepareToCopyFunction(targetLlil);
for (auto& block : targetLlil->GetBasicBlocks())
{
llilFunc->PrepareToCopyBlock(block);
for (size_t i = block->GetStart(); i < block->GetEnd(); i++)
{
LowLevelILInstruction tinstr = targetLlil->GetInstruction(i);
llilFunc->AddInstruction(tinstr.CopyTo(llilFunc));
}
}
llilFunc->Finalize();
PrepareToCopyFunction() - Initialize for copying from another functionPrepareToCopyBlock() - Prepare to copy a blockAddInstruction() - Add copied or new instructionsFinalize() - Complete IL constructionGenerateSSAForm() - Regenerate SSA if neededauto inlinerIsValid = [](BinaryView* view, Function* func) {
if (auto workflow = func->GetWorkflow(); workflow)
return workflow->Contains("extension.functionInliner");
return false;
};
PluginCommand::RegisterForFunction(
"Optimizer\\Inline Function at Current Call Site",
"Inline function call at current call site.",
[](BinaryView* view, Function* func) {
// Mark function for inlining
func->Reanalyze();
},
inlinerIsValid // Only show command for functions using this workflow
);
Workflow Architecture
Activity Lifecycle
Common Activity Patterns
Data Collection Activity
IL Transformation Activity
Type Inference Activity
Building Workflow Plugins
CMake Configuration
Building
Using Custom Workflows
Select Workflow When Opening Binary
- Open binary in Binary Ninja
- In analysis options, select “InlinerWorkflow”
- Analysis runs with custom activity included
Apply to Existing Function
Set as Default Workflow
Expected Output
When using the inliner workflow:- Open binary with “InlinerWorkflow” selected
- Plugin command “Optimizer > Inline Function at Current Call Site” appears
- Position cursor at a function call
- Run the command
- Function re-analyzes with call site inlined
- Decompilation shows inlined code instead of call
Advanced Workflow Concepts
Activity Configuration
Conditional Activity Execution
Use Cases
- Custom Optimizations - Implement compiler-style optimizations
- Deobfuscation - Remove obfuscation during analysis
- Pattern Recognition - Identify code patterns automatically
- Type Recovery - Advanced type inference
- Security Analysis - Detect vulnerabilities during analysis
- Code Metrics - Collect complexity metrics
Related Examples
- IL Parsing - Understanding IL manipulation
- Custom IL Visitor - IL traversal patterns
- Headless Automation - Automated analysis