summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-03-01 03:45:51 -0500
committerRusty Wagner <rusty@vector35.com>2017-03-01 03:45:51 -0500
commit94b38cee51eff16f1e79945806088c7ae60016d7 (patch)
tree4857d8240334f2ec40aa7a46f7fcea6a2e9ed899
parentdc0f16fa9bbac0388bb844af8d9f6c3b72ec31e8 (diff)
Adding framework for medium level IL
-rw-r--r--binaryninjaapi.h70
-rw-r--r--binaryninjacore.h174
-rw-r--r--function.cpp12
-rw-r--r--lowlevelil.cpp6
-rw-r--r--mediumlevelil.cpp378
-rw-r--r--python/__init__.py1
-rw-r--r--python/function.py20
-rw-r--r--python/lowlevelil.py8
-rw-r--r--python/mediumlevelil.py525
9 files changed, 1179 insertions, 15 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 58ea890e..1367e7c1 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1862,6 +1862,7 @@ namespace BinaryNinja
};
class FunctionGraph;
+ class MediumLevelILFunction;
class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction>
{
@@ -1913,6 +1914,8 @@ namespace BinaryNinja
std::set<uint32_t> GetFlagsReadByLiftedILInstruction(size_t i);
std::set<uint32_t> GetFlagsWrittenByLiftedILInstruction(size_t i);
+ Ref<MediumLevelILFunction> GetMediumLevelIL() const;
+
Ref<Type> GetType() const;
void SetAutoType(Type* type);
void SetUserType(Type* type);
@@ -2182,6 +2185,73 @@ namespace BinaryNinja
RegisterValue GetExprValue(size_t expr);
};
+ struct MediumLevelILLabel: public BNMediumLevelILLabel
+ {
+ MediumLevelILLabel();
+ };
+
+ class MediumLevelILFunction: public CoreRefCountObject<BNMediumLevelILFunction,
+ BNNewMediumLevelILFunctionReference, BNFreeMediumLevelILFunction>
+ {
+ public:
+ MediumLevelILFunction(Architecture* arch, Function* func = nullptr);
+ MediumLevelILFunction(BNMediumLevelILFunction* func);
+
+ uint64_t GetCurrentAddress() const;
+ void SetCurrentAddress(Architecture* arch, uint64_t addr);
+ size_t GetInstructionStart(Architecture* arch, uint64_t addr);
+
+ ExprId AddExpr(BNMediumLevelILOperation operation, size_t size,
+ ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0);
+ ExprId AddInstruction(ExprId expr);
+
+ ExprId SetVar(size_t size, const BNILVariable& var, ExprId src);
+ ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src);
+ ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src);
+ ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex, ExprId src);
+ ExprId Var(size_t size, const BNILVariable& var);
+ ExprId VarField(size_t size, const BNILVariable& var, int64_t offset);
+ ExprId VarSSA(size_t size, const BNILVariable& var, size_t index);
+ ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex);
+
+ ExprId Goto(BNMediumLevelILLabel& label);
+ ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f);
+ void MarkLabel(BNMediumLevelILLabel& label);
+
+ std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand);
+ ExprId AddLabelList(const std::vector<BNMediumLevelILLabel*>& labels);
+ ExprId AddOperandList(const std::vector<ExprId> operands);
+
+ BNILVariable GetVariable(ExprId i, size_t varOperand);
+
+ BNMediumLevelILInstruction operator[](size_t i) const;
+ size_t GetIndexForInstruction(size_t i) const;
+ size_t GetInstructionCount() const;
+
+ void Finalize();
+
+ bool GetExprText(Architecture* arch, ExprId expr, std::vector<InstructionTextToken>& tokens);
+ bool GetInstructionText(Function* func, Architecture* arch, size_t i,
+ std::vector<InstructionTextToken>& tokens);
+
+ std::vector<Ref<BasicBlock>> GetBasicBlocks() const;
+
+ Ref<MediumLevelILFunction> GetSSAForm() const;
+ Ref<MediumLevelILFunction> GetNonSSAForm() const;
+ size_t GetSSAInstructionIndex(size_t instr) const;
+ size_t GetNonSSAInstructionIndex(size_t instr) const;
+ size_t GetSSAExprIndex(size_t instr) const;
+ size_t GetNonSSAExprIndex(size_t instr) const;
+
+ size_t GetSSAVarDefinition(const BNILVariable& var, size_t idx) const;
+ size_t GetSSAMemoryDefinition(size_t idx) const;
+ std::set<size_t> GetSSAVarUses(const BNILVariable& var, size_t idx) const;
+ std::set<size_t> GetSSAMemoryUses(size_t idx) const;
+
+ RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx);
+ RegisterValue GetExprValue(size_t expr);
+ };
+
class FunctionRecognizer
{
static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 89302c64..aa9bb49b 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -92,6 +92,7 @@ extern "C"
struct BNSymbol;
struct BNTemporaryFile;
struct BNLowLevelILFunction;
+ struct BNMediumLevelILFunction;
struct BNType;
struct BNStructure;
struct BNNamedTypeReference;
@@ -363,7 +364,9 @@ extern "C"
NormalFunctionGraph = 0,
LowLevelILFunctionGraph = 1,
LiftedILFunctionGraph = 2,
- LowLevelILSSAFormFunctionGraph = 3
+ LowLevelILSSAFormFunctionGraph = 3,
+ MediumLevelILFunctionGraph = 4,
+ MediumLevelILSSAFormFunctionGraph = 5
};
enum BNDisassemblyOption
@@ -637,6 +640,115 @@ extern "C"
bool autoDiscovered;
};
+ enum BNMediumLevelILOperation
+ {
+ MLIL_NOP,
+ MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA)
+ MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD)
+ MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA)
+ MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA)
+ MLIL_VAR, // Not valid in SSA form (see MLIL_VAR_SSA)
+ MLIL_VAR_FIELD, // Not valid in SSA form (see MLIL_VAR_SSA_FIELD)
+ MLIL_CONST,
+ MLIL_ADD,
+ MLIL_ADC,
+ MLIL_SUB,
+ MLIL_SBB,
+ MLIL_AND,
+ MLIL_OR,
+ MLIL_XOR,
+ MLIL_LSL,
+ MLIL_LSR,
+ MLIL_ASR,
+ MLIL_ROL,
+ MLIL_RLC,
+ MLIL_ROR,
+ MLIL_RRC,
+ MLIL_MUL,
+ MLIL_MULU_DP,
+ MLIL_MULS_DP,
+ MLIL_DIVU,
+ MLIL_DIVU_DP,
+ MLIL_DIVS,
+ MLIL_DIVS_DP,
+ MLIL_MODU,
+ MLIL_MODU_DP,
+ MLIL_MODS,
+ MLIL_MODS_DP,
+ MLIL_NEG,
+ MLIL_NOT,
+ MLIL_SX,
+ MLIL_ZX,
+ MLIL_JUMP,
+ MLIL_JUMP_TO,
+ MLIL_CALL,
+ MLIL_RET,
+ MLIL_NORET,
+ MLIL_IF,
+ MLIL_GOTO,
+ MLIL_CMP_E,
+ MLIL_CMP_NE,
+ MLIL_CMP_SLT,
+ MLIL_CMP_ULT,
+ MLIL_CMP_SLE,
+ MLIL_CMP_ULE,
+ MLIL_CMP_SGE,
+ MLIL_CMP_UGE,
+ MLIL_CMP_SGT,
+ MLIL_CMP_UGT,
+ MLIL_TEST_BIT,
+ MLIL_BOOL_TO_INT,
+ MLIL_SYSCALL,
+ MLIL_BP,
+ MLIL_TRAP,
+ MLIL_UNDEF,
+ MLIL_UNIMPL,
+ MLIL_UNIMPL_MEM,
+
+ // The following instructions are only used in SSA form
+ MLIL_SET_VAR_SSA,
+ MLIL_SET_VAR_SSA_FIELD,
+ MLIL_VAR_SSA,
+ MLIL_VAR_SSA_FIELD,
+ MLIL_CALL_SSA,
+ MLIL_SYSCALL_SSA,
+ MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ MLIL_LOAD_SSA,
+ MLIL_STORE_SSA,
+ MLIL_VAR_PHI,
+ MLIL_MEM_PHI
+ };
+
+ struct BNMediumLevelILInstruction
+ {
+ BNMediumLevelILOperation operation;
+ size_t size;
+ uint64_t operands[5];
+ uint64_t address;
+ };
+
+ struct BNMediumLevelILLabel
+ {
+ bool resolved;
+ size_t ref;
+ size_t operand;
+ };
+
+ enum BNILVariableSourceType
+ {
+ RegisterVariableSourceType,
+ FlagVariableSourceType,
+ StackVariableSourceType
+ };
+
+ struct BNILVariable
+ {
+ BNILVariableSourceType type;
+ uint32_t index;
+ int64_t identifier;
+ };
+
// Callbacks
struct BNLogListener
{
@@ -1698,7 +1810,8 @@ extern "C"
BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr);
BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr,
size_t* count);
- BINARYNINJACOREAPI void BNFreeLowLevelILInstructionList(size_t* list);
+ BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list);
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func);
BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch,
uint64_t addr, uint32_t reg);
BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch,
@@ -2043,6 +2156,63 @@ extern "C"
BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr);
+ // Medium-level IL
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func);
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func,
+ BNArchitecture* arch, uint64_t addr);
+ BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func,
+ BNArchitecture* arch, uint64_t addr);
+ BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation,
+ size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e);
+ BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label);
+ BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op,
+ BNMediumLevelILLabel* t, BNMediumLevelILLabel* f);
+ BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label);
+ BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label);
+ BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func);
+
+ BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func,
+ BNMediumLevelILLabel** labels, size_t count);
+ BINARYNINJACOREAPI size_t BNMediumLevelILAddOperandList(BNMediumLevelILFunction* func,
+ uint64_t* operands, size_t count);
+ BINARYNINJACOREAPI uint64_t* BNMediumLevelILGetOperandList(BNMediumLevelILFunction* func, size_t expr,
+ size_t operand, size_t* count);
+ BINARYNINJACOREAPI void BNMediumLevelILFreeOperandList(uint64_t* operands);
+
+ BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func);
+
+ BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i,
+ BNInstructionTextToken** tokens, size_t* count);
+ BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func,
+ BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count);
+
+ BINARYNINJACOREAPI BNBasicBlock** BNGetMediumLevelILBasicBlockList(BNMediumLevelILFunction* func, size_t* count);
+
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILSSAForm(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILNonSSAForm(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAExprIndex(BNMediumLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func,
+ const BNILVariable* var, size_t idx);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx);
+ BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNILVariable* var,
+ size_t idx, size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func,
+ size_t idx, size_t* count);
+
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func,
+ const BNILVariable* var, size_t idx);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr);
+
// Types
BINARYNINJACOREAPI BNType* BNCreateVoidType(void);
BINARYNINJACOREAPI BNType* BNCreateBoolType(void);
diff --git a/function.cpp b/function.cpp
index fe119c9d..9faf68fa 100644
--- a/function.cpp
+++ b/function.cpp
@@ -161,7 +161,7 @@ vector<size_t> Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui
vector<size_t> result;
result.insert(result.end(), exits, &exits[count]);
- BNFreeLowLevelILInstructionList(exits);
+ BNFreeILInstructionList(exits);
return result;
}
@@ -343,7 +343,7 @@ set<size_t> Function::GetLiftedILFlagUsesForDefinition(size_t i, uint32_t flag)
set<size_t> result;
result.insert(&instrs[0], &instrs[count]);
- BNFreeLowLevelILInstructionList(instrs);
+ BNFreeILInstructionList(instrs);
return result;
}
@@ -355,7 +355,7 @@ set<size_t> Function::GetLiftedILFlagDefinitionsForUse(size_t i, uint32_t flag)
set<size_t> result;
result.insert(&instrs[0], &instrs[count]);
- BNFreeLowLevelILInstructionList(instrs);
+ BNFreeILInstructionList(instrs);
return result;
}
@@ -384,6 +384,12 @@ set<uint32_t> Function::GetFlagsWrittenByLiftedILInstruction(size_t i)
}
+Ref<MediumLevelILFunction> Function::GetMediumLevelIL() const
+{
+ return new MediumLevelILFunction(BNGetFunctionMediumLevelIL(m_object));
+}
+
+
Ref<Type> Function::GetType() const
{
return new Type(BNGetFunctionType(m_object));
diff --git a/lowlevelil.cpp b/lowlevelil.cpp
index fecde9c8..5a789981 100644
--- a/lowlevelil.cpp
+++ b/lowlevelil.cpp
@@ -720,7 +720,7 @@ set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) con
for (size_t i = 0; i < count; i++)
result.insert(instrs[i]);
- BNFreeLowLevelILInstructionList(instrs);
+ BNFreeILInstructionList(instrs);
return result;
}
@@ -734,7 +734,7 @@ set<size_t> LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const
for (size_t i = 0; i < count; i++)
result.insert(instrs[i]);
- BNFreeLowLevelILInstructionList(instrs);
+ BNFreeILInstructionList(instrs);
return result;
}
@@ -748,7 +748,7 @@ set<size_t> LowLevelILFunction::GetSSAMemoryUses(size_t idx) const
for (size_t i = 0; i < count; i++)
result.insert(instrs[i]);
- BNFreeLowLevelILInstructionList(instrs);
+ BNFreeILInstructionList(instrs);
return result;
}
diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp
new file mode 100644
index 00000000..f6ad5bfd
--- /dev/null
+++ b/mediumlevelil.cpp
@@ -0,0 +1,378 @@
+// Copyright (c) 2017 Vector 35 LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+MediumLevelILLabel::MediumLevelILLabel()
+{
+ BNMediumLevelILInitLabel(this);
+}
+
+
+MediumLevelILFunction::MediumLevelILFunction(Architecture* arch, Function* func)
+{
+ m_object = BNCreateMediumLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr);
+}
+
+
+MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func)
+{
+ m_object = func;
+}
+
+
+uint64_t MediumLevelILFunction::GetCurrentAddress() const
+{
+ return BNMediumLevelILGetCurrentAddress(m_object);
+}
+
+
+void MediumLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr)
+{
+ BNMediumLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr);
+}
+
+
+size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr)
+{
+ return BNMediumLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr);
+}
+
+
+ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size,
+ ExprId a, ExprId b, ExprId c, ExprId d, ExprId e)
+{
+ return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e);
+}
+
+
+ExprId MediumLevelILFunction::AddInstruction(size_t expr)
+{
+ return BNMediumLevelILAddInstruction(m_object, expr);
+}
+
+
+ExprId MediumLevelILFunction::SetVar(size_t size, const BNILVariable& var, ExprId src)
+{
+ return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, src);
+}
+
+
+ExprId MediumLevelILFunction::SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src)
+{
+ return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier,
+ offset, src);
+}
+
+
+ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, size_t varIndex, ExprId src)
+{
+ return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier,
+ varIndex, src);
+}
+
+
+ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset,
+ size_t varIndex, ExprId src)
+{
+ return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier,
+ offset, varIndex, src);
+}
+
+
+ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var)
+{
+ return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier);
+}
+
+
+ExprId MediumLevelILFunction::VarField(size_t size, const BNILVariable& var, int64_t offset)
+{
+ return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset);
+}
+
+
+ExprId MediumLevelILFunction::VarSSA(size_t size, const BNILVariable& var, size_t varIndex)
+{
+ return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex);
+}
+
+
+ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset,
+ size_t varIndex)
+{
+ return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier,
+ offset, varIndex);
+}
+
+
+ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label)
+{
+ return BNMediumLevelILGoto(m_object, &label);
+}
+
+
+ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f)
+{
+ return BNMediumLevelILIf(m_object, operand, &t, &f);
+}
+
+
+void MediumLevelILFunction::MarkLabel(BNMediumLevelILLabel& label)
+{
+ BNMediumLevelILMarkLabel(m_object, &label);
+}
+
+
+vector<uint64_t> MediumLevelILFunction::GetOperandList(ExprId expr, size_t listOperand)
+{
+ size_t count;
+ uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count);
+ vector<uint64_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(operands[i]);
+ BNMediumLevelILFreeOperandList(operands);
+ return result;
+}
+
+
+ExprId MediumLevelILFunction::AddLabelList(const vector<BNMediumLevelILLabel*>& labels)
+{
+ BNMediumLevelILLabel** labelList = new BNMediumLevelILLabel*[labels.size()];
+ for (size_t i = 0; i < labels.size(); i++)
+ labelList[i] = labels[i];
+ ExprId result = (ExprId)BNMediumLevelILAddLabelList(m_object, labelList, labels.size());
+ delete[] labelList;
+ return result;
+}
+
+
+ExprId MediumLevelILFunction::AddOperandList(const vector<ExprId> operands)
+{
+ uint64_t* operandList = new uint64_t[operands.size()];
+ for (size_t i = 0; i < operands.size(); i++)
+ operandList[i] = operands[i];
+ ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, operands.size());
+ delete[] operandList;
+ return result;
+}
+
+
+BNILVariable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand)
+{
+ BNMediumLevelILInstruction instr = (*this)[i];
+ BNILVariable result;
+ result.type = (BNILVariableSourceType)(instr.operands[varOperand] >> 32);
+ result.index = (uint32_t)instr.operands[varOperand];
+ result.identifier = instr.operands[varOperand + 1];
+ return result;
+}
+
+
+BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const
+{
+ return BNGetMediumLevelILByIndex(m_object, i);
+}
+
+
+size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const
+{
+ return BNGetMediumLevelILIndexForInstruction(m_object, i);
+}
+
+
+size_t MediumLevelILFunction::GetInstructionCount() const
+{
+ return BNGetMediumLevelILInstructionCount(m_object);
+}
+
+
+void MediumLevelILFunction::Finalize()
+{
+ BNFinalizeMediumLevelILFunction(m_object);
+}
+
+
+bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<InstructionTextToken>& tokens)
+{
+ size_t count;
+ BNInstructionTextToken* list;
+ if (!BNGetMediumLevelILExprText(m_object, arch->GetObject(), expr, &list, &count))
+ return false;
+
+ tokens.clear();
+ for (size_t i = 0; i < count; i++)
+ {
+ InstructionTextToken token;
+ token.type = list[i].type;
+ token.text = list[i].text;
+ token.value = list[i].value;
+ token.size = list[i].size;
+ token.operand = list[i].operand;
+ token.context = list[i].context;
+ token.address = list[i].address;
+ tokens.push_back(token);
+ }
+
+ BNFreeInstructionText(list, count);
+ return true;
+}
+
+
+bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arch, size_t instr,
+ vector<InstructionTextToken>& tokens)
+{
+ size_t count;
+ BNInstructionTextToken* list;
+ if (!BNGetMediumLevelILInstructionText(m_object, func ? func->GetObject() : nullptr, arch->GetObject(),
+ instr, &list, &count))
+ return false;
+
+ tokens.clear();
+ for (size_t i = 0; i < count; i++)
+ {
+ InstructionTextToken token;
+ token.type = list[i].type;
+ token.text = list[i].text;
+ token.value = list[i].value;
+ token.size = list[i].size;
+ token.operand = list[i].operand;
+ token.context = list[i].context;
+ token.address = list[i].address;
+ tokens.push_back(token);
+ }
+
+ BNFreeInstructionText(list, count);
+ return true;
+}
+
+
+vector<Ref<BasicBlock>> MediumLevelILFunction::GetBasicBlocks() const
+{
+ size_t count;
+ BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count);
+
+ vector<Ref<BasicBlock>> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i])));
+
+ BNFreeBasicBlockList(blocks, count);
+ return result;
+}
+
+
+Ref<MediumLevelILFunction> MediumLevelILFunction::GetSSAForm() const
+{
+ BNMediumLevelILFunction* func = BNGetMediumLevelILSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new MediumLevelILFunction(func);
+}
+
+
+Ref<MediumLevelILFunction> MediumLevelILFunction::GetNonSSAForm() const
+{
+ BNMediumLevelILFunction* func = BNGetMediumLevelILNonSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new MediumLevelILFunction(func);
+}
+
+
+size_t MediumLevelILFunction::GetSSAInstructionIndex(size_t instr) const
+{
+ return BNGetMediumLevelILSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t MediumLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const
+{
+ return BNGetMediumLevelILNonSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t MediumLevelILFunction::GetSSAExprIndex(size_t expr) const
+{
+ return BNGetMediumLevelILSSAExprIndex(m_object, expr);
+}
+
+
+size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const
+{
+ return BNGetMediumLevelILNonSSAExprIndex(m_object, expr);
+}
+
+
+size_t MediumLevelILFunction::GetSSAVarDefinition(const BNILVariable& var, size_t idx) const
+{
+ return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx);
+}
+
+
+size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const
+{
+ return BNGetMediumLevelILSSAMemoryDefinition(m_object, idx);
+}
+
+
+set<size_t> MediumLevelILFunction::GetSSAVarUses(const BNILVariable& var, size_t idx) const
+{
+ size_t count;
+ size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+set<size_t> MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const
+{
+ size_t count;
+ size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, idx, &count);
+
+ set<size_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.insert(instrs[i]);
+
+ BNFreeILInstructionList(instrs);
+ return result;
+}
+
+
+RegisterValue MediumLevelILFunction::GetSSAVarValue(const BNILVariable& var, size_t idx)
+{
+ BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetExprValue(size_t expr)
+{
+ BNRegisterValue value = BNGetMediumLevelILExprValue(m_object, expr);
+ return RegisterValue::FromAPIObject(value);
+}
diff --git a/python/__init__.py b/python/__init__.py
index b1f5cd08..7502d205 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -32,6 +32,7 @@ from .basicblock import *
from .function import *
from .log import *
from .lowlevelil import *
+from .mediumlevelil import *
from .types import *
from .functionrecognizer import *
from .update import *
diff --git a/python/function.py b/python/function.py
index 07187080..ed2a537c 100644
--- a/python/function.py
+++ b/python/function.py
@@ -33,6 +33,7 @@ import associateddatastore
import types
import basicblock
import lowlevelil
+import mediumlevelil
import binaryview
import log
@@ -139,6 +140,14 @@ class StackVariableReference(object):
return "<operand %d ref to %s>" % (self.source_operand, self.name)
+class ILVariable(object):
+ def __init__(self, func, var_type, index, identifier):
+ self.function = func
+ self.type = var_type
+ self.index = index
+ self.identifier = identifier
+
+
class ConstantReference(object):
def __init__(self, val, size):
self.value = val
@@ -300,6 +309,11 @@ class Function(object):
return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self)
@property
+ def medium_level_il(self):
+ """Function medium level IL (read-only)"""
+ return mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self)
+
+ @property
def function_type(self):
"""Function type object"""
return types.Type(core.BNGetFunctionType(self.handle))
@@ -398,7 +412,7 @@ class Function(object):
result = []
for i in xrange(0, count.value):
result.append(exits[i])
- core.BNFreeLowLevelILInstructionList(exits)
+ core.BNFreeILInstructionList(exits)
return result
def get_reg_value_at(self, addr, reg, arch=None):
@@ -597,7 +611,7 @@ class Function(object):
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
- core.BNFreeLowLevelILInstructionList(instrs)
+ core.BNFreeILInstructionList(instrs)
return result
def get_lifted_il_flag_definitions_for_use(self, i, flag):
@@ -608,7 +622,7 @@ class Function(object):
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
- core.BNFreeLowLevelILInstructionList(instrs)
+ core.BNFreeILInstructionList(instrs)
return result
def get_flags_read_by_lifted_il_instruction(self, i):
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 6ed179c2..ed1cedd4 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -124,7 +124,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")],
LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")],
LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")],
- LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("dest", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")],
LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg"), ("index", "int"), ("src", "reg_ssa_list")],
@@ -1385,7 +1385,7 @@ class LowLevelILFunction(object):
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
- core.BNFreeLowLevelILInstructionList(instrs)
+ core.BNFreeILInstructionList(instrs)
return result
def get_ssa_flag_uses(self, flag, index):
@@ -1394,7 +1394,7 @@ class LowLevelILFunction(object):
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
- core.BNFreeLowLevelILInstructionList(instrs)
+ core.BNFreeILInstructionList(instrs)
return result
def get_ssa_memory_uses(self, index):
@@ -1403,7 +1403,7 @@ class LowLevelILFunction(object):
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
- core.BNFreeLowLevelILInstructionList(instrs)
+ core.BNFreeILInstructionList(instrs)
return result
def get_ssa_reg_value(self, reg, index):
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
new file mode 100644
index 00000000..c4c4aa23
--- /dev/null
+++ b/python/mediumlevelil.py
@@ -0,0 +1,525 @@
+# Copyright (c) 2017 Vector 35 LLC
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import ctypes
+
+# Binary Ninja components
+import _binaryninjacore as core
+from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType
+import function
+import basicblock
+
+
+class MediumLevelILLabel(object):
+ def __init__(self, handle = None):
+ if handle is None:
+ self.handle = (core.BNMediumLevelILLabel * 1)()
+ core.BNMediumLevelILInitLabel(self.handle)
+ else:
+ self.handle = handle
+
+
+class MediumLevelILInstruction(object):
+ """
+ ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based
+ instructions. Tree-based instructions use infix notation with the left hand operand being the destination operand.
+ Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. MLIL ``eax = 0``).
+ """
+
+ ILOperations = {
+ MediumLevelILOperation.MLIL_NOP: [],
+ MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_LOAD: [("src", "expr")],
+ MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_VAR: [("src", "var")],
+ MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_CONST: [("constant", "int")],
+ MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_LSL: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVU: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_NEG: [("src", "expr")],
+ MediumLevelILOperation.MLIL_NOT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_SX: [("src", "expr")],
+ MediumLevelILOperation.MLIL_ZX: [("src", "expr")],
+ MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")],
+ MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")],
+ MediumLevelILOperation.MLIL_CALL: [("dest", "expr")],
+ MediumLevelILOperation.MLIL_RET: [],
+ MediumLevelILOperation.MLIL_NORET: [],
+ MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")],
+ MediumLevelILOperation.MLIL_GOTO: [("dest", "int")],
+ MediumLevelILOperation.MLIL_CMP_E: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_NE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_SLT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_ULT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_SLE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_ULE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_SGE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_UGE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_SGT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_SYSCALL: [],
+ MediumLevelILOperation.MLIL_BP: [],
+ MediumLevelILOperation.MLIL_TRAP: [("vector", "int")],
+ MediumLevelILOperation.MLIL_UNDEF: [],
+ MediumLevelILOperation.MLIL_UNIMPL: [],
+ MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")],
+ MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")],
+ MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")],
+ MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
+ MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
+ }
+
+ def __init__(self, func, expr_index, instr_index=None):
+ instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index)
+ self.function = func
+ self.expr_index = expr_index
+ self.instr_index = instr_index
+ self.operation = MediumLevelILOperation(instr.operation)
+ self.size = instr.size
+ self.address = instr.address
+ operands = MediumLevelILInstruction.ILOperations[instr.operation]
+ self.operands = []
+ i = 0
+ while i < len(operands):
+ name, operand_type = operands[i]
+ if operand_type == "int":
+ value = instr.operands[i]
+ elif operand_type == "expr":
+ value = MediumLevelILInstruction(func, instr.operands[i])
+ elif operand_type == "var":
+ var_type = ILVariableSourceType(instr.operands[i] >> 32)
+ index = instr.operands[i] & 0xffffffff
+ identifier = instr.operands[i + 1]
+ i += 1
+ value = function.ILVariable(self.function, var_type, index, identifier)
+ elif operand_type == "int_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ value = []
+ for i in xrange(count.value):
+ value.append(operand_list[i])
+ core.BNMediumLevelILFreeOperandList(operand_list)
+ elif operand_type == "var_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for j in xrange(count.value / 3):
+ var_type = ILVariableSourceType(operand_list[j * 3] >> 32)
+ index = operand_list[j * 3] & 0xffffffff
+ identifier = operand_list[(j * 3) + 1]
+ var_index = operand_list[(j * 3) + 2]
+ value.append((function.ILVariable(self.function, var_type, index, identifier), var_index))
+ core.BNMediumLevelILFreeOperandList(operand_list)
+ self.operands.append(value)
+ self.__dict__[name] = value
+
+ def __str__(self):
+ tokens = self.tokens
+ if tokens is None:
+ return "invalid"
+ result = ""
+ for token in tokens:
+ result += token.text
+ return result
+
+ def __repr__(self):
+ return "<il: %s>" % str(self)
+
+ @property
+ def tokens(self):
+ """MLIL tokens (read-only)"""
+ count = ctypes.c_ulonglong()
+ tokens = ctypes.POINTER(core.BNInstructionTextToken)()
+ if (self.instr_index is not None) and (self.function.source_function is not None):
+ if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle,
+ self.function.arch.handle, self.instr_index, tokens, count):
+ return None
+ else:
+ if not core.BNGetMediumLevelILExprText(self.function.handle, self.function.arch.handle,
+ self.expr_index, tokens, count):
+ return None
+ result = []
+ for i in xrange(0, count.value):
+ token_type = InstructionTextTokenType(tokens[i].type)
+ text = tokens[i].text
+ value = tokens[i].value
+ size = tokens[i].size
+ operand = tokens[i].operand
+ context = tokens[i].context
+ address = tokens[i].address
+ result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address))
+ core.BNFreeInstructionText(tokens, count.value)
+ return result
+
+ @property
+ def ssa_form(self):
+ """SSA form of expression (read-only)"""
+ return MediumLevelILInstruction(self.function.ssa_form,
+ core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index))
+
+ @property
+ def non_ssa_form(self):
+ """Non-SSA form of expression (read-only)"""
+ return MediumLevelILInstruction(self.function.non_ssa_form,
+ core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index))
+
+ @property
+ def value(self):
+ """Value of expression using static data flow analysis (read-only)"""
+ value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ core.BNFreeRegisterValue(value)
+ return result
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+
+class MediumLevelILExpr(object):
+ """
+ ``class MediumLevelILExpr`` hold the index of IL Expressions.
+
+ .. note:: This class shouldn't be instantiated directly. Rather the helper members of MediumLevelILFunction should be \
+ used instead.
+ """
+ def __init__(self, index):
+ self.index = index
+
+
+class MediumLevelILFunction(object):
+ """
+ ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a function. MediumLevelILExpr
+ objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class
+ methods which return MediumLevelILExpr objects.
+ """
+ def __init__(self, arch, handle = None, source_func = None):
+ self.arch = arch
+ self.source_function = source_func
+ if handle is not None:
+ self.handle = core.handle_of_type(handle, core.BNMediumLevelILFunction)
+ else:
+ func_handle = None
+ if self.source_function is not None:
+ func_handle = self.source_function.handle
+ self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle)
+
+ def __del__(self):
+ core.BNFreeMediumLevelILFunction(self.handle)
+
+ def __eq__(self, value):
+ if not isinstance(value, MediumLevelILFunction):
+ return False
+ return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents)
+
+ def __ne__(self, value):
+ if not isinstance(value, MediumLevelILFunction):
+ return True
+ return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents)
+
+ @property
+ def current_address(self):
+ """Current IL Address (read/write)"""
+ return core.BNMediumLevelILGetCurrentAddress(self.handle)
+
+ @current_address.setter
+ def current_address(self, value):
+ core.BNMediumLevelILSetCurrentAddress(self.handle, self.arch.handle, value)
+
+ def set_current_address(self, value, arch = None):
+ if arch is None:
+ arch = self.arch
+ core.BNMediumLevelILSetCurrentAddress(self.handle, arch.handle, value)
+
+ @property
+ def basic_blocks(self):
+ """list of MediumLevelILBasicBlock objects (read-only)"""
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count)
+ result = []
+ view = None
+ if self.source_function is not None:
+ view = self.source_function.view
+ for i in xrange(0, count.value):
+ result.append(MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self))
+ core.BNFreeBasicBlockList(blocks, count.value)
+ return result
+
+ @property
+ def ssa_form(self):
+ """Medium level IL in SSA form (read-only)"""
+ result = core.BNGetMediumLevelILSSAForm(self.handle)
+ if not result:
+ return None
+ return MediumLevelILFunction(self.arch, result, self.source_function)
+
+ @property
+ def non_ssa_form(self):
+ """Medium level IL in non-SSA (default) form (read-only)"""
+ result = core.BNGetMediumLevelILNonSSAForm(self.handle)
+ if not result:
+ return None
+ return MediumLevelILFunction(self.arch, result, self.source_function)
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+ def __len__(self):
+ return int(core.BNGetMediumLevelILInstructionCount(self.handle))
+
+ def __getitem__(self, i):
+ if isinstance(i, slice) or isinstance(i, tuple):
+ raise IndexError("expected integer instruction index")
+ if isinstance(i, MediumLevelILExpr):
+ return MediumLevelILInstruction(self, i.index)
+ if (i < 0) or (i >= len(self)):
+ raise IndexError("index out of range")
+ return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i)
+
+ def __setitem__(self, i, j):
+ raise IndexError("instruction modification not implemented")
+
+ def __iter__(self):
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count)
+ view = None
+ if self.source_function is not None:
+ view = self.source_function.view
+ try:
+ for i in xrange(0, count.value):
+ yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)
+ finally:
+ core.BNFreeBasicBlockList(blocks, count.value)
+
+ def get_instruction_start(self, addr, arch = None):
+ if arch is None:
+ arch = self.arch
+ result = core.BNMediumLevelILGetInstructionStart(self.handle, arch.handle, addr)
+ if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0):
+ if isinstance(operation, str):
+ operation = MediumLevelILOperation[operation]
+ elif isinstance(operation, MediumLevelILOperation):
+ operation = operation.value
+ return MediumLevelILExpr(core.BNMediumLevelILAddExpr(self.handle, operation, size, a, b, c, d, e))
+
+ def append(self, expr):
+ """
+ ``append`` adds the MediumLevelILExpr ``expr`` to the current MediumLevelILFunction.
+
+ :param MediumLevelILExpr expr: the MediumLevelILExpr to add to the current MediumLevelILFunction
+ :return: number of MediumLevelILExpr in the current function
+ :rtype: int
+ """
+ return core.BNMediumLevelILAddInstruction(self.handle, expr.index)
+
+ def goto(self, label):
+ """
+ ``goto`` returns a goto expression which jumps to the provided MediumLevelILLabel.
+
+ :param MediumLevelILLabel label: Label to jump to
+ :return: the MediumLevelILExpr that jumps to the provided label
+ :rtype: MediumLevelILExpr
+ """
+ return MediumLevelILExpr(core.BNMediumLevelILGoto(self.handle, label.handle))
+
+ def if_expr(self, operand, t, f):
+ """
+ ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the MediumLevelILLabel
+ ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero.
+
+ :param MediumLevelILExpr operand: comparison expression to evaluate.
+ :param MediumLevelILLabel t: Label for the true branch
+ :param MediumLevelILLabel f: Label for the false branch
+ :return: the MediumLevelILExpr for the if expression
+ :rtype: MediumLevelILExpr
+ """
+ return MediumLevelILExpr(core.BNMediumLevelILIf(self.handle, operand.index, t.handle, f.handle))
+
+ def mark_label(self, label):
+ """
+ ``mark_label`` assigns a MediumLevelILLabel to the current IL address.
+
+ :param MediumLevelILLabel label:
+ :rtype: None
+ """
+ core.BNMediumLevelILMarkLabel(self.handle, label.handle)
+
+ def add_label_list(self, labels):
+ """
+ ``add_label_list`` returns a label list expression for the given list of MediumLevelILLabel objects.
+
+ :param list(MediumLevelILLabel) lables: the list of MediumLevelILLabel to get a label list expression from
+ :return: the label list expression
+ :rtype: MediumLevelILExpr
+ """
+ label_list = (ctypes.POINTER(core.BNMediumLevelILLabel) * len(labels))()
+ for i in xrange(len(labels)):
+ label_list[i] = labels[i].handle
+ return MediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle, label_list, len(labels)))
+
+ def add_operand_list(self, operands):
+ """
+ ``add_operand_list`` returns an operand list expression for the given list of integer operands.
+
+ :param list(int) operands: list of operand numbers
+ :return: an operand list expression
+ :rtype: MediumLevelILExpr
+ """
+ operand_list = (ctypes.c_ulonglong * len(operands))()
+ for i in xrange(len(operands)):
+ operand_list[i] = operands[i]
+ return MediumLevelILExpr(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands)))
+
+ def operand(self, n, expr):
+ """
+ ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification.
+
+ :param int n:
+ :param MediumLevelILExpr expr:
+ :return: returns the expression ``expr`` unmodified
+ :rtype: MediumLevelILExpr
+ """
+ core.BNMediumLevelILSetExprSourceOperand(self.handle, expr.index, n)
+ return expr
+
+ def finalize(self):
+ """
+ ``finalize`` ends the function and computes the list of basic blocks.
+
+ :rtype: None
+ """
+ core.BNFinalizeMediumLevelILFunction(self.handle)
+
+ def get_ssa_instruction_index(self, instr):
+ return core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr)
+
+ def get_non_ssa_instruction_index(self, instr):
+ return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr)
+
+ def get_ssa_var_definition(self, var, index):
+ var_data = core.BNILVariable()
+ var_data.type = var.type
+ var_data.index = var.index
+ var_data.identifier = var.identifier
+ result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index)
+ if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def get_ssa_memory_definition(self, index):
+ result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index)
+ if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def get_ssa_var_uses(self, var, index):
+ count = ctypes.c_ulonglong()
+ var_data = core.BNILVariable()
+ var_data.type = var.type
+ var_data.index = var.index
+ var_data.identifier = var.identifier
+ instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_ssa_memory_uses(self, index):
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_ssa_var_value(self, var, index):
+ var_data = core.BNILVariable()
+ var_data.type = var.type
+ var_data.index = var.index
+ var_data.identifier = var.identifier
+ value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index)
+ result = function.RegisterValue(self.arch, value)
+ core.BNFreeRegisterValue(value)
+ return result
+
+
+class MediumLevelILBasicBlock(basicblock.BasicBlock):
+ def __init__(self, view, handle, owner):
+ super(MediumLevelILBasicBlock, self).__init__(view, handle)
+ self.il_function = owner
+
+ def __iter__(self):
+ for idx in xrange(self.start, self.end):
+ yield self.il_function[idx]
+
+ def __getitem__(self, idx):
+ size = self.end - self.start
+ if idx > size or idx < -size:
+ raise IndexError("list index is out of range")
+ if idx >= 0:
+ return self.il_function[idx + self.start]
+ else:
+ return self.il_function[self.end + idx]