summaryrefslogtreecommitdiff
path: root/examples/llil_parser/src
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-08-01 23:39:18 -0400
committerRusty Wagner <rusty@vector35.com>2017-08-05 20:49:14 -0400
commite47e2fb13369ff7d1c9e7728bb793ee56640afe1 (patch)
treeb6683fa3e28da3158c6559612959267a81fabbb2 /examples/llil_parser/src
parent92ef6481d84d3289ba86a9b9ffe6553bb5842c5d (diff)
Refactor IL instruction access APIs
Diffstat (limited to 'examples/llil_parser/src')
-rw-r--r--examples/llil_parser/src/LowLevel_IL_Parser.cpp442
-rw-r--r--examples/llil_parser/src/llil_parser.cpp409
2 files changed, 409 insertions, 442 deletions
diff --git a/examples/llil_parser/src/LowLevel_IL_Parser.cpp b/examples/llil_parser/src/LowLevel_IL_Parser.cpp
deleted file mode 100644
index 2f61b83a..00000000
--- a/examples/llil_parser/src/LowLevel_IL_Parser.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
-LLIL Parser - Binary Ninja C++ API Sample
- - Robert Yates - 22/JUN/17
- */
-
-#include "LowLevel_IL_Parser.h"
-#include <iostream>
-#include <sstream>
-
-int main(int argc, char* argv[])
-{
-
- try
- {
- ShowBanner();
-
-
- if (argc != 2)
- {
- printf("Usage: %s <input file>\n", argv[0]);
- exit(-1);
- }
-
- std::string inputName = argv[1];
-
- SetBundledPluginDirectory(get_plugins_directory());
- InitCorePlugins();
- InitUserPlugins();
-
- auto bd = BinaryData(new FileMetadata(), inputName.c_str());
- BinaryView *bv;
-
- for (auto type : BinaryViewType::GetViewTypes())
- {
- if (type->IsTypeValidForData(&bd) && type->GetName() != "Raw")
- {
- bv = type->Create(&bd);
- break;
- }
- }
-
- printf("[i] Starting analysis\n");
- bv->UpdateAnalysisAndWait();
-
- printf("[i] Analysis done - %zd Functions\n", bv->GetAnalysisFunctionList().size());
-
- if (bv->GetAnalysisFunctionList().size() < 1)
- throw std::runtime_error("Error no functions found\n");
-
- LlilParser myParser(bv);
- myParser.decodeWholeFunction(bv->GetAnalysisFunctionList()[0]);
-
- /*
- // Show Single LLIL in function x at index x
- myParser.decodeIndexInFunction(0x407930, 0);
-
- // Decode a whole function by address
- myParser.decodeWholeFunction(0x407930);
-
- // Decode all functions
- for (const auto& f : bv->GetAnalysisFunctionList())
- {
- // Decode a whole function by BinaryNinja::Function object
- myParser.decodeWholeFunction(f);
- }
- */
-
- }
- catch (const std::exception& e)
- {
- printf("An Exception Occured: %s\n", e.what());
- }
-
- printf("[i] Finished\n");
-}
-
-
-
-LlilParser::LlilParser(BinaryView *bv)
- : m_bv(bv)
-{
- m_currentFunction.clear();
- m_tabs = 0;
- m_currentInstructionId = 0;
-}
-
-void LlilParser::showIndent() const
-{
- for (int i = 0; i < m_tabs; i++)
- printf(" ");
-}
-
-void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn)
-{
-
- auto instructionSynatx = g_llilSyntaxMap.find(insn.operation);
- BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = m_currentFunction[0]->GetLowLevelIL();
- if (instructionSynatx == g_llilSyntaxMap.end())
- throw std::runtime_error("Error unknown LLIL\n");
-
- showIndent();
- printf("Instruction: %s\n", getLowLevelILOperationName(insn.operation).c_str());
- m_tabs += 3;
-
- int operandId = 0;
- for (const auto& operand : instructionSynatx->second)
- {
- if (operand.type == OperandType::kExpr)
- {
- // In this case the value in the operands[x] field is a new instruction & expression index value
- BNLowLevelILInstruction nextInstruction = (*llil)[insn.operands[operandId]];
-
- analysisInstruction(nextInstruction); // recursion begins :)
- }
- else if (operand.type == OperandType::kReg)
- {
- // In this case the register id is in the first operands field and we use Arch to translate
- showIndent();
- printf("Reg: %s\n", m_bv->GetDefaultArchitecture()->GetRegisterName(static_cast<uint32_t>(insn.operands[0])).c_str());
- m_tabs += 3;
- }
- else if (operand.type == OperandType::kInt)
- {
- // In this case the operand is simply a value
- showIndent();
- printf("Value: %zX\n", insn.operands[0]);
- m_tabs += 3;
- }
- else if (operand.type == OperandType::kFlag)
- {
- // In this case the operand is a flag
- printf("Flag: %s\n", m_bv->GetDefaultArchitecture()->GetFlagName(static_cast<uint32_t>(insn.operands[0])).c_str());
- m_tabs += 3;
- }
- else if (operand.type == OperandType::kIntList)
- {
- // In this case we have an array of llil targets
- std::vector<uint64_t> intList = llil->GetOperandList(llil->GetIndexForInstruction(m_currentInstructionId), operandId);
- showIndent();
- printf("Target LLIL Indices: ");
- for (const auto i : intList)
- {
- printf("%zd ", i);
- }
- printf("\n");
- }
- else
- {
- printf("[e] LLIL Parser: Not Handled -> OperandPurpose: %d OperandType: %d\n", operand.purpose, operand.type);
- }
-
-
- operandId++;
- }
-
-
-}
-
-void LlilParser::decodeIndexInFunction(uint64_t functionAddress, int indexIl)
-{
-
- m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress);
- if (m_currentFunction.size() < 1)
- throw std::runtime_error("Error no functions at requested address\n");
-
- BinaryNinja::Function *function = m_currentFunction[0];
- BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL();
-
- m_currentInstructionId = indexIl;
- BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(indexIl)];
-
-
- analysisInstruction(currentInstruction);
- m_tabs = 0;
-
-}
-
-void LlilParser::decodeWholeFunction(BinaryNinja::Function *function)
-{
- m_currentFunction.clear();
- m_currentFunction.push_back(function);
-
- BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL();
-
- for (size_t i = 0; i < llil->GetInstructionCount(); i++)
- {
-
- m_currentInstructionId = i;
- BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)];
-
- printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i);
-
- analysisInstruction(currentInstruction);
- m_tabs = 0;
- }
-
-}
-
-void LlilParser::decodeWholeFunction(uint64_t functionAddress)
-{
-
- m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress);
- if (m_currentFunction.size() < 1)
- throw std::runtime_error("Error no functions at requested address or possible invalid BundledPluginDirectory\n");
-
- BinaryNinja::Function *function = m_currentFunction[0];
- BinaryNinja::Ref<BinaryNinja::LowLevelILFunction> llil = function->GetLowLevelIL();
-
-
-
- for (size_t i = 0; i < llil->GetInstructionCount(); i++)
- {
- m_currentInstructionId = i;
- BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)];
-
- printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i);
-
- analysisInstruction(currentInstruction);
- m_tabs = 0;
- }
-
-}
-
-void ShowBanner()
-{
-
- printf (".____ .____ .___.____ __________ \n");
- printf ("| | | | | | | \\______ \\_____ _______ ______ ___________ \n");
- printf ("| | | | | | | | ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\\n");
- printf ("| |___| |___| | |___ | | / __ \\| | \\/\\___ \\\\ ___/| | \\/\n");
- printf ("|_______ \\_______ \\___|_______ \\ |____| (____ /__| /____ >\\___ >__| \n");
- printf (" \\/ \\/ \\/ \\/ \\/ \\/ \n");
- printf("====================================================================================\n\n");
-
-}
-
-#ifdef _WIN32
-std::string get_plugins_directory()
-{
- return "C:\\Program Files\\Vector35\\BinaryNinja\\plugins\\";
-}
-#elif __APPLE__
-std::string get_plugins_directory()
-{
- return "/Applications/Binary Ninja.app/Contents/MacOS/plugins/";
-}
-#else
-std::string get_plugins_directory()
-{
- return "~/binaryninja/plugins";
-}
-#endif
-
-const std::string LlilParser::getLowLevelILOperationName(BNLowLevelILOperation id) const
-{
-
- switch (id)
- {
- case LLIL_NOP:
- return "LLIL_NOP";
- case LLIL_SET_REG:
- return "LLIL_SET_REG";
- case LLIL_SET_REG_SPLIT:
- return "LLIL_SET_REG_SPLIT";
- case LLIL_SET_FLAG:
- return "LLIL_SET_FLAG";
- case LLIL_LOAD:
- return "LLIL_LOAD";
- case LLIL_STORE:
- return "LLIL_STORE";
- case LLIL_PUSH:
- return "LLIL_PUSH";
- case LLIL_POP:
- return "LLIL_POP";
- case LLIL_REG:
- return "LLIL_REG";
- case LLIL_CONST:
- return "LLIL_CONST";
- case LLIL_CONST_PTR:
- return "LLIL_CONST_PTR";
- case LLIL_FLAG:
- return "LLIL_FLAG";
- case LLIL_FLAG_BIT:
- return "LLIL_FLAG_BIT";
- case LLIL_ADD:
- return "LLIL_ADD";
- case LLIL_ADC:
- return "LLIL_ADC";
- case LLIL_SUB:
- return "LLIL_SUB";
- case LLIL_SBB:
- return "LLIL_SBB";
- case LLIL_AND:
- return "LLIL_AND";
- case LLIL_OR:
- return "LLIL_OR";
- case LLIL_XOR:
- return "LLIL_XOR";
- case LLIL_LSL:
- return "LLIL_LSL";
- case LLIL_LSR:
- return "LLIL_LSR";
- case LLIL_ASR:
- return "LLIL_ASR";
- case LLIL_ROL:
- return "LLIL_ROL";
- case LLIL_RLC:
- return "LLIL_RLC";
- case LLIL_ROR:
- return "LLIL_ROR";
- case LLIL_RRC:
- return "LLIL_RRC";
- case LLIL_MUL:
- return "LLIL_MUL";
- case LLIL_MULU_DP:
- return "LLIL_MULU_DP";
- case LLIL_MULS_DP:
- return "LLIL_MULS_DP";
- case LLIL_DIVU:
- return "LLIL_DIVU";
- case LLIL_DIVU_DP:
- return "LLIL_DIVU_DP";
- case LLIL_DIVS:
- return "LLIL_DIVS";
- case LLIL_DIVS_DP:
- return "LLIL_DIVS_DP";
- case LLIL_MODU:
- return "LLIL_MODU";
- case LLIL_MODU_DP:
- return "LLIL_MODU_DP";
- case LLIL_MODS:
- return "LLIL_MODS";
- case LLIL_MODS_DP:
- return "LLIL_MODS_DP";
- case LLIL_NEG:
- return "LLIL_NEG";
- case LLIL_NOT:
- return "LLIL_NOT";
- case LLIL_SX:
- return "LLIL_SX";
- case LLIL_ZX:
- return "LLIL_ZX";
- case LLIL_LOW_PART:
- return "LLIL_LOW_PART";
- case LLIL_JUMP:
- return "LLIL_JUMP";
- case LLIL_JUMP_TO:
- return "LLIL_JUMP_TO";
- case LLIL_CALL:
- return "LLIL_CALL";
- case LLIL_RET:
- return "LLIL_RET";
- case LLIL_NORET:
- return "LLIL_NORET";
- case LLIL_IF:
- return "LLIL_IF";
- case LLIL_GOTO:
- return "LLIL_GOTO";
- case LLIL_FLAG_COND:
- return "LLIL_FLAG_COND";
- case LLIL_CMP_E:
- return "LLIL_CMP_E";
- case LLIL_CMP_NE:
- return "LLIL_CMP_NE";
- case LLIL_CMP_SLT:
- return "LLIL_CMP_SLT";
- case LLIL_CMP_ULT:
- return "LLIL_CMP_ULT";
- case LLIL_CMP_SLE:
- return "LLIL_CMP_SLE";
- case LLIL_CMP_ULE:
- return "LLIL_CMP_ULE";
- case LLIL_CMP_SGE:
- return "LLIL_CMP_SGE";
- case LLIL_CMP_UGE:
- return "LLIL_CMP_UGE";
- case LLIL_CMP_SGT:
- return "LLIL_CMP_SGT";
- case LLIL_CMP_UGT:
- return "LLIL_CMP_UGT";
- case LLIL_TEST_BIT:
- return "LLIL_TEST_BIT";
- case LLIL_BOOL_TO_INT:
- return "LLIL_BOOL_TO_INT";
- case LLIL_ADD_OVERFLOW:
- return "LLIL_ADD_OVERFLOW";
- case LLIL_SYSCALL:
- return "LLIL_SYSCALL";
- case LLIL_BP:
- return "LLIL_BP";
- case LLIL_TRAP:
- return "LLIL_TRAP";
- case LLIL_UNDEF:
- return "LLIL_UNDEF";
- case LLIL_UNIMPL:
- return "LLIL_UNIMPL";
- case LLIL_UNIMPL_MEM:
- return "LLIL_UNIMPL_MEM";
- case LLIL_SET_REG_SSA:
- return "LLIL_SET_REG_SSA";
- case LLIL_SET_REG_SSA_PARTIAL:
- return "LLIL_SET_REG_SSA_PARTIAL";
- case LLIL_SET_REG_SPLIT_SSA:
- return "LLIL_SET_REG_SPLIT_SSA";
- case LLIL_REG_SPLIT_DEST_SSA:
- return "LLIL_REG_SPLIT_DEST_SSA";
- case LLIL_REG_SSA:
- return "LLIL_REG_SSA";
- case LLIL_REG_SSA_PARTIAL:
- return "LLIL_REG_SSA_PARTIAL";
- case LLIL_SET_FLAG_SSA:
- return "LLIL_SET_FLAG_SSA";
- case LLIL_FLAG_SSA:
- return "LLIL_FLAG_SSA";
- case LLIL_FLAG_BIT_SSA:
- return "LLIL_FLAG_BIT_SSA";
- case LLIL_CALL_SSA:
- return "LLIL_CALL_SSA";
- case LLIL_SYSCALL_SSA:
- return "LLIL_SYSCALL_SSA";
- case LLIL_CALL_PARAM_SSA:
- return "LLIL_CALL_PARAM_SSA";
- case LLIL_CALL_STACK_SSA:
- return "LLIL_CALL_STACK_SSA";
- case LLIL_CALL_OUTPUT_SSA:
- return "LLIL_CALL_OUTPUT_SSA";
- case LLIL_LOAD_SSA:
- return "LLIL_LOAD_SSA";
- case LLIL_STORE_SSA:
- return "LLIL_STORE_SSA";
- case LLIL_REG_PHI:
- return "LLIL_REG_PHI";
- case LLIL_FLAG_PHI:
- return "LLIL_FLAG_PHI";
- case LLIL_MEM_PHI:
- return "LLIL_MEM_PHI";
- }
-
- return "Unknown";
- //throw std::runtime_error("GetLowLevelILOperationName Failure");
-
-} \ No newline at end of file
diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp
new file mode 100644
index 00000000..72ac71bd
--- /dev/null
+++ b/examples/llil_parser/src/llil_parser.cpp
@@ -0,0 +1,409 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include "binaryninjacore.h"
+#include "binaryninjaapi.h"
+#include "lowlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+#ifndef __WIN32__
+#include <libgen.h>
+#include <dlfcn.h>
+static string GetPluginsDirectory()
+{
+ Dl_info info;
+ if (!dladdr((void *)BNGetBundledPluginDirectory, &info))
+ return NULL;
+
+ stringstream ss;
+ ss << dirname((char *)info.dli_fname) << "/plugins/";
+ return ss.str();
+}
+#else
+static string GetPluginsDirectory()
+{
+ return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\";
+}
+#endif
+
+
+static void PrintIndent(size_t indent)
+{
+ for (size_t i = 0; i < indent; i++)
+ printf(" ");
+}
+
+
+static void PrintOperation(BNLowLevelILOperation operation)
+{
+#define ENUM_PRINTER(op) \
+ case op: \
+ printf(#op); \
+ break;
+
+ switch (operation)
+ {
+ ENUM_PRINTER(LLIL_NOP)
+ ENUM_PRINTER(LLIL_SET_REG)
+ ENUM_PRINTER(LLIL_SET_REG_SPLIT)
+ ENUM_PRINTER(LLIL_SET_FLAG)
+ ENUM_PRINTER(LLIL_LOAD)
+ ENUM_PRINTER(LLIL_STORE)
+ ENUM_PRINTER(LLIL_PUSH)
+ ENUM_PRINTER(LLIL_POP)
+ ENUM_PRINTER(LLIL_REG)
+ ENUM_PRINTER(LLIL_CONST)
+ ENUM_PRINTER(LLIL_CONST_PTR)
+ ENUM_PRINTER(LLIL_FLAG)
+ ENUM_PRINTER(LLIL_FLAG_BIT)
+ ENUM_PRINTER(LLIL_ADD)
+ ENUM_PRINTER(LLIL_ADC)
+ ENUM_PRINTER(LLIL_SUB)
+ ENUM_PRINTER(LLIL_SBB)
+ ENUM_PRINTER(LLIL_AND)
+ ENUM_PRINTER(LLIL_OR)
+ ENUM_PRINTER(LLIL_XOR)
+ ENUM_PRINTER(LLIL_LSL)
+ ENUM_PRINTER(LLIL_LSR)
+ ENUM_PRINTER(LLIL_ASR)
+ ENUM_PRINTER(LLIL_ROL)
+ ENUM_PRINTER(LLIL_RLC)
+ ENUM_PRINTER(LLIL_ROR)
+ ENUM_PRINTER(LLIL_RRC)
+ ENUM_PRINTER(LLIL_MUL)
+ ENUM_PRINTER(LLIL_MULU_DP)
+ ENUM_PRINTER(LLIL_MULS_DP)
+ ENUM_PRINTER(LLIL_DIVU)
+ ENUM_PRINTER(LLIL_DIVU_DP)
+ ENUM_PRINTER(LLIL_DIVS)
+ ENUM_PRINTER(LLIL_DIVS_DP)
+ ENUM_PRINTER(LLIL_MODU)
+ ENUM_PRINTER(LLIL_MODU_DP)
+ ENUM_PRINTER(LLIL_MODS)
+ ENUM_PRINTER(LLIL_MODS_DP)
+ ENUM_PRINTER(LLIL_NEG)
+ ENUM_PRINTER(LLIL_NOT)
+ ENUM_PRINTER(LLIL_SX)
+ ENUM_PRINTER(LLIL_ZX)
+ ENUM_PRINTER(LLIL_LOW_PART)
+ ENUM_PRINTER(LLIL_JUMP)
+ ENUM_PRINTER(LLIL_JUMP_TO)
+ ENUM_PRINTER(LLIL_CALL)
+ ENUM_PRINTER(LLIL_RET)
+ ENUM_PRINTER(LLIL_NORET)
+ ENUM_PRINTER(LLIL_IF)
+ ENUM_PRINTER(LLIL_GOTO)
+ ENUM_PRINTER(LLIL_FLAG_COND)
+ ENUM_PRINTER(LLIL_CMP_E)
+ ENUM_PRINTER(LLIL_CMP_NE)
+ ENUM_PRINTER(LLIL_CMP_SLT)
+ ENUM_PRINTER(LLIL_CMP_ULT)
+ ENUM_PRINTER(LLIL_CMP_SLE)
+ ENUM_PRINTER(LLIL_CMP_ULE)
+ ENUM_PRINTER(LLIL_CMP_SGE)
+ ENUM_PRINTER(LLIL_CMP_UGE)
+ ENUM_PRINTER(LLIL_CMP_SGT)
+ ENUM_PRINTER(LLIL_CMP_UGT)
+ ENUM_PRINTER(LLIL_TEST_BIT)
+ ENUM_PRINTER(LLIL_BOOL_TO_INT)
+ ENUM_PRINTER(LLIL_ADD_OVERFLOW)
+ ENUM_PRINTER(LLIL_SYSCALL)
+ ENUM_PRINTER(LLIL_BP)
+ ENUM_PRINTER(LLIL_TRAP)
+ ENUM_PRINTER(LLIL_UNDEF)
+ ENUM_PRINTER(LLIL_UNIMPL)
+ ENUM_PRINTER(LLIL_UNIMPL_MEM)
+ ENUM_PRINTER(LLIL_SET_REG_SSA)
+ ENUM_PRINTER(LLIL_SET_REG_SSA_PARTIAL)
+ ENUM_PRINTER(LLIL_SET_REG_SPLIT_SSA)
+ ENUM_PRINTER(LLIL_REG_SPLIT_DEST_SSA)
+ ENUM_PRINTER(LLIL_REG_SSA)
+ ENUM_PRINTER(LLIL_REG_SSA_PARTIAL)
+ ENUM_PRINTER(LLIL_SET_FLAG_SSA)
+ ENUM_PRINTER(LLIL_FLAG_SSA)
+ ENUM_PRINTER(LLIL_FLAG_BIT_SSA)
+ ENUM_PRINTER(LLIL_CALL_SSA)
+ ENUM_PRINTER(LLIL_SYSCALL_SSA)
+ ENUM_PRINTER(LLIL_CALL_PARAM_SSA)
+ ENUM_PRINTER(LLIL_CALL_STACK_SSA)
+ ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA)
+ ENUM_PRINTER(LLIL_LOAD_SSA)
+ ENUM_PRINTER(LLIL_STORE_SSA)
+ ENUM_PRINTER(LLIL_REG_PHI)
+ ENUM_PRINTER(LLIL_FLAG_PHI)
+ ENUM_PRINTER(LLIL_MEM_PHI)
+ default:
+ printf("<invalid operation %" PRId32 ">", operation);
+ break;
+ }
+}
+
+
+static void PrintFlagCondition(BNLowLevelILFlagCondition cond)
+{
+ switch (cond)
+ {
+ ENUM_PRINTER(LLFC_E)
+ ENUM_PRINTER(LLFC_NE)
+ ENUM_PRINTER(LLFC_SLT)
+ ENUM_PRINTER(LLFC_ULT)
+ ENUM_PRINTER(LLFC_SLE)
+ ENUM_PRINTER(LLFC_ULE)
+ ENUM_PRINTER(LLFC_SGE)
+ ENUM_PRINTER(LLFC_UGE)
+ ENUM_PRINTER(LLFC_SGT)
+ ENUM_PRINTER(LLFC_UGT)
+ ENUM_PRINTER(LLFC_NEG)
+ ENUM_PRINTER(LLFC_POS)
+ ENUM_PRINTER(LLFC_O)
+ ENUM_PRINTER(LLFC_NO)
+ default:
+ printf("<invalid condition>");
+ break;
+ }
+}
+
+
+static void PrintRegister(LowLevelILFunction* func, uint32_t reg)
+{
+ if (LLIL_REG_IS_TEMP(reg))
+ printf("temp%d", LLIL_GET_TEMP_REG_INDEX(reg));
+ else
+ {
+ string name = func->GetArchitecture()->GetRegisterName(reg);
+ if (name.size() == 0)
+ printf("<no name>");
+ else
+ printf("%s", name.c_str());
+ }
+}
+
+
+static void PrintFlag(LowLevelILFunction* func, uint32_t flag)
+{
+ if (LLIL_REG_IS_TEMP(flag))
+ printf("cond:%d", LLIL_GET_TEMP_REG_INDEX(flag));
+ else
+ {
+ string name = func->GetArchitecture()->GetFlagName(flag);
+ if (name.size() == 0)
+ printf("<no name>");
+ else
+ printf("%s", name.c_str());
+ }
+}
+
+
+static void PrintILExpr(const LowLevelILInstruction& instr, size_t indent)
+{
+ PrintIndent(indent);
+ PrintOperation(instr.operation);
+ printf("\n");
+
+ indent++;
+
+ for (auto& operand : instr.GetOperands())
+ {
+ switch (operand.GetType())
+ {
+ case IntegerLowLevelOperand:
+ PrintIndent(indent);
+ printf("int 0x%" PRIx64 "\n", operand.GetInteger());
+ break;
+
+ case IndexLowLevelOperand:
+ PrintIndent(indent);
+ printf("index %" PRIdPTR "\n", operand.GetIndex());
+ break;
+
+ case ExprLowLevelOperand:
+ PrintILExpr(operand.GetExpr(), indent);
+ break;
+
+ case RegisterLowLevelOperand:
+ PrintIndent(indent);
+ printf("reg ");
+ PrintRegister(instr.function, operand.GetRegister());
+ printf("\n");
+ break;
+
+ case FlagLowLevelOperand:
+ PrintIndent(indent);
+ printf("flag ");
+ PrintFlag(instr.function, operand.GetFlag());
+ printf("\n");
+ break;
+
+ case FlagConditionLowLevelOperand:
+ PrintIndent(indent);
+ printf("flag condition ");
+ PrintFlagCondition(operand.GetFlagCondition());
+ printf("\n");
+ break;
+
+ case SSARegisterLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg ");
+ PrintRegister(instr.function, operand.GetSSARegister().reg);
+ printf("#%" PRIdPTR "\n", operand.GetSSARegister().version);
+ break;
+
+ case SSAFlagLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa flag ");
+ PrintFlag(instr.function, operand.GetSSAFlag().flag);
+ printf("#%" PRIdPTR "\n", operand.GetSSAFlag().version);
+ break;
+
+ case IndexListLowLevelOperand:
+ PrintIndent(indent);
+ printf("index list ");
+ for (auto i : operand.GetIndexList())
+ printf("%" PRIdPTR " ", i);
+ printf("\n");
+ break;
+
+ case SSARegisterListLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg list ");
+ for (auto& i : operand.GetSSARegisterList())
+ {
+ PrintRegister(instr.function, i.reg);
+ printf("#%" PRIdPTR " ", i.version);
+ }
+ printf("\n");
+ break;
+
+ case SSAFlagListLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg list ");
+ for (auto& i : operand.GetSSAFlagList())
+ {
+ PrintFlag(instr.function, i.flag);
+ printf("#%" PRIdPTR " ", i.version);
+ }
+ printf("\n");
+ break;
+
+ default:
+ PrintIndent(indent);
+ printf("<invalid operand>\n");
+ break;
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ fprintf(stderr, "Expected input filename\n");
+ return 1;
+ }
+
+ // In order to initiate the bundled plugins properly, the location
+ // of where bundled plugins directory is must be set. Since
+ // libbinaryninjacore is in the path get the path to it and use it to
+ // determine the plugins directory
+ SetBundledPluginDirectory(GetPluginsDirectory());
+ InitCorePlugins();
+ InitUserPlugins();
+
+ Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]);
+ Ref<BinaryView> bv;
+ for (auto type : BinaryViewType::GetViewTypes())
+ {
+ if (type->IsTypeValidForData(bd) && type->GetName() != "Raw")
+ {
+ bv = type->Create(bd);
+ break;
+ }
+ }
+
+ if (!bv || bv->GetTypeName() == "Raw")
+ {
+ fprintf(stderr, "Input file does not appear to be an exectuable\n");
+ return -1;
+ }
+
+ bv->UpdateAnalysisAndWait();
+
+ // Go through all functions in the binary
+ for (auto& func : bv->GetAnalysisFunctionList())
+ {
+ // Get the name of the function and display it
+ Ref<Symbol> sym = func->GetSymbol();
+ if (sym)
+ printf("Function %s:\n", sym->GetFullName().c_str());
+ else
+ printf("Function at 0x%" PRIx64 ":\n", func->GetStart());
+
+ // Fetch the low level IL for the function
+ Ref<LowLevelILFunction> il = func->GetLowLevelIL();
+ if (!il)
+ {
+ printf(" Does not have LLIL\n\n");
+ continue;
+ }
+
+ // Loop through all blocks in the function
+ for (auto& block : il->GetBasicBlocks())
+ {
+ // Loop though each instruction in the block
+ for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++)
+ {
+ // Fetch IL instruction
+ LowLevelILInstruction instr = (*il)[instrIndex];
+
+ // Display core's intrepretation of the IL instruction
+ vector<InstructionTextToken> tokens;
+ il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens);
+ printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address);
+ for (auto& token: tokens)
+ printf("%s", token.text.c_str());
+ printf("\n");
+
+ // Generically parse the IL tree and display the parts
+ PrintILExpr(instr, 2);
+
+ // Example of using visitors to find all constants in the instruction
+ instr.VisitExprs([&](const LowLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case LLIL_CONST:
+ case LLIL_CONST_PTR:
+ printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant());
+ return false; // Done parsing this
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+
+ // Example of using the templated accessors for efficiently parsing load instructions
+ instr.VisitExprs([&](const LowLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case LLIL_LOAD:
+ if (expr.GetSourceExpr<LLIL_LOAD>().operation == LLIL_CONST_PTR)
+ {
+ printf(" Loading from address 0x%" PRIx64 "\n",
+ expr.GetSourceExpr<LLIL_LOAD>().GetConstant<LLIL_CONST_PTR>());
+ return false; // Done parsing this
+ }
+ break;
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+ }
+ }
+
+ printf("\n");
+ }
+ return 0;
+}