summaryrefslogtreecommitdiff
path: root/examples/workflows/tailcall/tailcall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/workflows/tailcall/tailcall.cpp')
-rw-r--r--examples/workflows/tailcall/tailcall.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/examples/workflows/tailcall/tailcall.cpp b/examples/workflows/tailcall/tailcall.cpp
new file mode 100644
index 00000000..9305a51d
--- /dev/null
+++ b/examples/workflows/tailcall/tailcall.cpp
@@ -0,0 +1,129 @@
+#define _CRT_SECURE_NO_WARNINGS
+#define NOMINMAX
+
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+
+#include "binaryninjaapi.h"
+#include "lowlevelilinstruction.h"
+#include "mediumlevelilinstruction.h"
+
+
+using namespace BinaryNinja;
+using namespace std;
+
+#if defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+
+extern "C"
+{
+ BN_DECLARE_CORE_ABI_VERSION
+
+ void TailCallTranslation(Ref<AnalysisContext> analysisContext)
+ {
+ Ref<Function> function = analysisContext->GetFunction();
+ Ref<BinaryView> data = function->GetView();
+
+ bool updated = false;
+ uint8_t opcode[BN_MAX_INSTRUCTION_LENGTH];
+ InstructionInfo iInfo;
+
+ // Look for jumps to other functions
+ Ref<LowLevelILFunction> llilFunc = analysisContext->GetLowLevelILFunction();
+ for (auto& i : llilFunc->GetBasicBlocks())
+ {
+ // if (m_owner->IsAborted())
+ // return;
+
+ Ref<Architecture> arch = i->GetArchitecture();
+ size_t instrIndex = i->GetEnd() - 1;
+ LowLevelILInstruction instr = llilFunc->GetInstruction(instrIndex);
+ if (instr.operation != LLIL_JUMP)
+ continue;
+
+ uint64_t platformAddr;
+ LowLevelILInstruction destExpr = instr.GetDestExpr<LLIL_JUMP>();
+ RegisterValue target = destExpr.GetValue();
+ if (target.IsConstant())
+ platformAddr = target.value;
+ else if (target.state == ImportedAddressValue) // Call to imported function, look up type from import symbol
+ platformAddr = target.value;
+ else if (target.state == ExternalPointerValue && target.offset == 0)
+ platformAddr = target.value;
+ else
+ continue;
+
+ size_t opLen = data->Read(opcode, instr.address, arch->GetMaxInstructionLength());
+ if (!opLen || !arch->GetInstructionInfo(opcode, instr.address, opLen, iInfo))
+ continue;
+ Ref<Platform> platform = iInfo.archTransitionByTargetAddr ? function->GetPlatform()->GetAssociatedPlatformByAddress(platformAddr) : function->GetPlatform();
+ if (platform)
+ {
+ bool canReturn = true;
+ Ref<Function> targetFunc = nullptr;
+ if (target.state == ImportedAddressValue)
+ {
+ DataVariable var;
+ if (data->GetDataVariableAtAddress(target.value, var))
+ {
+ if (var.type && (var.type->GetClass() == PointerTypeClass) && (var.type->GetChildType()->GetClass() == FunctionTypeClass))
+ canReturn = var.type->GetChildType()->CanReturn().GetValue();
+ }
+ }
+ else if (target.state == ExternalPointerValue && target.offset == 0)
+ {
+ targetFunc = data->GetAnalysisFunction(platform, platformAddr);
+ if (targetFunc)
+ canReturn = targetFunc->CanReturn();
+ }
+ else
+ {
+ targetFunc = data->GetAnalysisFunction(platform, platformAddr);
+ if (targetFunc)
+ canReturn = targetFunc->CanReturn();
+ else
+ continue;
+ }
+
+ updated = true;
+ instr.Replace(llilFunc->TailCall(destExpr.exprIndex, instr));
+ analysisContext->Inform("directRefs", "insert", platformAddr, i->GetArchitecture(), instr.address);
+
+ if (!canReturn)
+ {
+ analysisContext->Inform("directNoReturnCalls", "insert", i->GetArchitecture(), instr.address);
+ i->GetSourceBlock()->SetCanExit(false);
+ i->SetCanExit(false);
+ }
+ }
+ }
+
+ if (!updated)
+ return;
+
+ // Updates found, regenerate SSA form
+ llilFunc->GenerateSSAForm();
+ }
+
+
+ BINARYNINJAPLUGIN bool CorePluginInit()
+ {
+ Ref<Workflow> customTailCallWorkflow = Workflow::Instance()->Clone("CustomTailCallWorkflow");
+ customTailCallWorkflow->RegisterActivity(new Activity("extension.translateTailCalls", &TailCallTranslation));
+ customTailCallWorkflow->Replace("core.function.translateTailCalls", "extension.translateTailCalls");
+ Workflow::RegisterWorkflow(customTailCallWorkflow,
+ R"#({
+ "title" : "Tail Call Translation (Example)",
+ "description" : "This analysis stands in as an example to demonstrate Binary Ninja's extensible analysis APIs. ***Note** this feature is under active development and subject to change without notice.",
+ "capabilities" : []
+ })#");
+
+ return true;
+ }
+}