summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-04-21 23:29:16 -0400
committerRusty Wagner <rusty@vector35.com>2017-04-21 23:29:16 -0400
commit87990dd2043a6234003620b6a408e5ae17c4eade (patch)
treea77daf0d96f27aa037e76ea2ba868ce968271638
parent93020159006b68c5e0e5b1eafeef11d1df72da1a (diff)
parent66c7accacdbc73ed4edb7e9bada54085a3272426 (diff)
Merge branch 'mlil' into dev
-rw-r--r--binaryninjaapi.h187
-rw-r--r--binaryninjacore.h441
-rw-r--r--function.cpp238
-rw-r--r--lowlevelil.cpp260
-rw-r--r--mediumlevelil.cpp494
-rw-r--r--python/__init__.py1
-rw-r--r--python/function.py292
-rw-r--r--python/lowlevelil.py308
-rw-r--r--python/mediumlevelil.py735
9 files changed, 2732 insertions, 224 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index bab26345..ab84afc4 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1811,11 +1811,27 @@ namespace BinaryNinja
static bool IsBackEdge(BasicBlock* source, BasicBlock* target);
};
- struct StackVariable
+ struct Variable: public BNVariable
{
+ Variable();
+ Variable(BNVariableSourceType type, uint32_t index, uint64_t storage);
+ Variable(const BNVariable& var);
+
+ Variable& operator=(const Variable& var);
+
+ bool operator==(const Variable& var) const;
+ bool operator!=(const Variable& var) const;
+ bool operator<(const Variable& var) const;
+
+ uint64_t ToIdentifier() const;
+ static Variable FromIdentifier(uint64_t id);
+ };
+
+ struct VariableNameAndType
+ {
+ Variable var;
Ref<Type> type;
std::string name;
- int64_t offset;
bool autoDefined;
};
@@ -1824,7 +1840,7 @@ namespace BinaryNinja
uint32_t sourceOperand;
Ref<Type> type;
std::string name;
- int64_t startingOffset;
+ Variable var;
int64_t referencedOffset;
};
@@ -1855,13 +1871,24 @@ namespace BinaryNinja
struct RegisterValue
{
BNRegisterValueType state;
- uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register
- int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue
- uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive
+ int64_t value;
+
+ static RegisterValue FromAPIObject(BNRegisterValue& value);
+ };
+
+ struct PossibleValueSet
+ {
+ BNRegisterValueType state;
+ int64_t value;
+ std::vector<BNValueRange> ranges;
+ std::set<int64_t> valueSet;
std::vector<LookupTableEntry> table;
+
+ static PossibleValueSet FromAPIObject(BNPossibleValueSet& value);
};
class FunctionGraph;
+ class MediumLevelILFunction;
class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction>
{
@@ -1893,12 +1920,8 @@ namespace BinaryNinja
std::vector<size_t> GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr);
RegisterValue GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg);
RegisterValue GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg);
- RegisterValue GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg);
- RegisterValue GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg);
RegisterValue GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size);
RegisterValue GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size);
- RegisterValue GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size);
- RegisterValue GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size);
RegisterValue GetParameterValueAtInstruction(Architecture* arch, uint64_t addr, Type* functionType, size_t i);
RegisterValue GetParameterValueAtLowLevelILInstruction(size_t instr, Type* functionType, size_t i);
std::vector<uint32_t> GetRegistersReadByInstruction(Architecture* arch, uint64_t addr);
@@ -1913,6 +1936,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);
@@ -1921,12 +1946,22 @@ namespace BinaryNinja
Ref<FunctionGraph> CreateFunctionGraph();
- std::map<int64_t, StackVariable> GetStackLayout();
+ std::map<int64_t, std::vector<VariableNameAndType>> GetStackLayout();
void CreateAutoStackVariable(int64_t offset, Ref<Type> type, const std::string& name);
void CreateUserStackVariable(int64_t offset, Ref<Type> type, const std::string& name);
void DeleteAutoStackVariable(int64_t offset);
void DeleteUserStackVariable(int64_t offset);
- bool GetStackVariableAtFrameOffset(int64_t offset, StackVariable& var);
+ bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var);
+
+ std::map<Variable, VariableNameAndType> GetVariables();
+ void CreateAutoVariable(const Variable& var, Ref<Type> type, const std::string& name,
+ bool ignoreDisjointUses = false);
+ void CreateUserVariable(const Variable& var, Ref<Type> type, const std::string& name,
+ bool ignoreDisjointUses = false);
+ void DeleteAutoVariable(const Variable& var);
+ void DeleteUserVariable(const Variable& var);
+ Ref<Type> GetVariableType(const Variable& var);
+ std::string GetVariableName(const Variable& var);
void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches);
void SetUserIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches);
@@ -2058,7 +2093,8 @@ namespace BinaryNinja
LowLevelILFunction(BNLowLevelILFunction* func);
uint64_t GetCurrentAddress() const;
- void SetCurrentAddress(uint64_t addr);
+ void SetCurrentAddress(Architecture* arch, uint64_t addr);
+ size_t GetInstructionStart(Architecture* arch, uint64_t addr);
void ClearIndirectBranches();
void SetIndirectBranches(const std::vector<ArchAndAddr>& branches);
@@ -2145,6 +2181,7 @@ namespace BinaryNinja
BNLowLevelILInstruction operator[](size_t i) const;
size_t GetIndexForInstruction(size_t i) const;
size_t GetInstructionCount() const;
+ size_t GetExprCount() const;
void AddLabelForAddress(Architecture* arch, ExprId addr);
BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr);
@@ -2159,6 +2196,130 @@ namespace BinaryNinja
uint32_t GetTemporaryFlagCount();
std::vector<Ref<BasicBlock>> GetBasicBlocks() const;
+
+ Ref<LowLevelILFunction> GetSSAForm() const;
+ Ref<LowLevelILFunction> 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 GetSSARegisterDefinition(uint32_t reg, size_t idx) const;
+ size_t GetSSAFlagDefinition(uint32_t flag, size_t idx) const;
+ size_t GetSSAMemoryDefinition(size_t idx) const;
+ std::set<size_t> GetSSARegisterUses(uint32_t reg, size_t idx) const;
+ std::set<size_t> GetSSAFlagUses(uint32_t flag, size_t idx) const;
+ std::set<size_t> GetSSAMemoryUses(size_t idx) const;
+
+ RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx);
+ RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx);
+
+ RegisterValue GetExprValue(size_t expr);
+ PossibleValueSet GetPossibleExprValues(size_t expr);
+
+ RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr);
+ RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr);
+ PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr);
+ PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr);
+ RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr);
+ RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr);
+ PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr);
+ PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr);
+ RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr);
+ RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr);
+ PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr);
+ PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr);
+
+ Ref<MediumLevelILFunction> GetMediumLevelIL() const;
+ Ref<MediumLevelILFunction> GetMappedMediumLevelIL() const;
+ size_t GetMappedMediumLevelILInstructionIndex(size_t instr) const;
+ size_t GetMappedMediumLevelILExprIndex(size_t expr) const;
+ };
+
+ 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 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);
+
+ BNMediumLevelILInstruction operator[](size_t i) const;
+ size_t GetIndexForInstruction(size_t i) const;
+ size_t GetInstructionForExpr(size_t expr) const;
+ size_t GetInstructionCount() const;
+ size_t GetExprCount() 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 Variable& var, size_t idx) const;
+ size_t GetSSAMemoryDefinition(size_t idx) const;
+ std::set<size_t> GetSSAVarUses(const Variable& var, size_t idx) const;
+ std::set<size_t> GetSSAMemoryUses(size_t idx) const;
+
+ RegisterValue GetSSAVarValue(const Variable& var, size_t idx);
+ RegisterValue GetExprValue(size_t expr);
+ PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr);
+ PossibleValueSet GetPossibleExprValues(size_t expr);
+
+ size_t GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const;
+ size_t GetSSAMemoryIndexAtInstruction(size_t instr) const;
+ Variable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const;
+ Variable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const;
+ Variable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const;
+
+ RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr);
+ RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr);
+ PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr);
+ PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr);
+ RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr);
+ RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr);
+ PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr);
+ PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr);
+ RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr);
+ RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr);
+ PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr);
+ PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr);
+
+ BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const;
+ std::map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const;
+
+ Ref<LowLevelILFunction> GetLowLevelIL() const;
+ size_t GetLowLevelILInstructionIndex(size_t instr) const;
+ size_t GetLowLevelILExprIndex(size_t expr) const;
};
class FunctionRecognizer
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 0b2375ef..7e9a034f 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -66,6 +66,8 @@
#define BN_INVALID_OPERAND 0xffffffff
+#define BN_INVALID_EXPR ((size_t)-1)
+
#define BN_DEFAULT_MIN_STRING_LENGTH 4
#define BN_MAX_STRING_LENGTH 128
@@ -87,6 +89,9 @@
#define LLVM_SVCS_RM_PIC 1
#define LLVM_SVCS_RM_DYNAMIC_NO_PIC 2
+#define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL
+#define BN_MAX_VARIABLE_INDEX 0xfffff
+
#ifdef __cplusplus
extern "C"
{
@@ -116,6 +121,7 @@ extern "C"
struct BNSymbol;
struct BNTemporaryFile;
struct BNLowLevelILFunction;
+ struct BNMediumLevelILFunction;
struct BNType;
struct BNStructure;
struct BNNamedTypeReference;
@@ -211,7 +217,7 @@ extern "C"
// not be used directly by the architecture plugins
CodeSymbolToken = 64,
DataSymbolToken = 65,
- StackVariableToken = 66,
+ LocalVariableToken = 66,
ImportToken = 67,
AddressDisplayToken = 68
};
@@ -219,7 +225,7 @@ extern "C"
enum BNInstructionTextTokenContext
{
NoTokenContext = 0,
- StackVariableTokenContext = 1,
+ LocalVariableTokenContext = 1,
DataVariableTokenContext = 2,
FunctionReturnTokenContext = 3,
ArgumentTokenContext = 4
@@ -235,8 +241,8 @@ extern "C"
FunctionHeaderStartLineType,
FunctionHeaderEndLineType,
FunctionContinuationLineType,
- StackVariableLineType,
- StackVariableListEndLineType,
+ LocalVariableLineType,
+ LocalVariableListEndLineType,
FunctionEndLineType,
NoteStartLineType,
NoteLineType,
@@ -267,17 +273,17 @@ extern "C"
enum BNLowLevelILOperation
{
LLIL_NOP,
- LLIL_SET_REG,
- LLIL_SET_REG_SPLIT,
- LLIL_SET_FLAG,
- LLIL_LOAD,
- LLIL_STORE,
- LLIL_PUSH,
- LLIL_POP,
- LLIL_REG,
+ LLIL_SET_REG, // Not valid in SSA form (see LLIL_SET_REG_SSA)
+ LLIL_SET_REG_SPLIT, // Not valid in SSA form (see LLIL_SET_REG_SPLIT_SSA)
+ LLIL_SET_FLAG, // Not valid in SSA form (see LLIL_SET_FLAG_SSA)
+ LLIL_LOAD, // Not valid in SSA form (see LLIL_LOAD_SSA)
+ LLIL_STORE, // Not valid in SSA form (see LLIL_STORE_SSA)
+ LLIL_PUSH, // Not valid in SSA form (expanded)
+ LLIL_POP, // Not valid in SSA form (expanded)
+ LLIL_REG, // Not valid in SSA form (see LLIL_REG_SSA)
LLIL_CONST,
- LLIL_FLAG,
- LLIL_FLAG_BIT,
+ LLIL_FLAG, // Not valid in SSA form (see LLIL_FLAG_SSA)
+ LLIL_FLAG_BIT, // Not valid in SSA form (see LLIL_FLAG_BIT_SSA)
LLIL_ADD,
LLIL_ADC,
LLIL_SUB,
@@ -314,7 +320,7 @@ extern "C"
LLIL_NORET,
LLIL_IF,
LLIL_GOTO,
- LLIL_FLAG_COND,
+ LLIL_FLAG_COND, // Valid only in Lifted IL
LLIL_CMP_E,
LLIL_CMP_NE,
LLIL_CMP_SLT,
@@ -332,7 +338,28 @@ extern "C"
LLIL_TRAP,
LLIL_UNDEF,
LLIL_UNIMPL,
- LLIL_UNIMPL_MEM
+ LLIL_UNIMPL_MEM,
+
+ // The following instructions are only used in SSA form
+ LLIL_SET_REG_SSA,
+ LLIL_SET_REG_SSA_PARTIAL,
+ LLIL_SET_REG_SPLIT_SSA,
+ LLIL_REG_SPLIT_DEST_SSA, // Only valid within an LLIL_SET_REG_SPLIT_SSA instruction
+ LLIL_REG_SSA,
+ LLIL_REG_SSA_PARTIAL,
+ LLIL_SET_FLAG_SSA,
+ LLIL_FLAG_SSA,
+ LLIL_FLAG_BIT_SSA,
+ LLIL_CALL_SSA,
+ LLIL_SYSCALL_SSA,
+ LLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ LLIL_CALL_STACK_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ LLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions
+ LLIL_LOAD_SSA,
+ LLIL_STORE_SSA,
+ LLIL_REG_PHI,
+ LLIL_FLAG_PHI,
+ LLIL_MEM_PHI
};
enum BNLowLevelILFlagCondition
@@ -370,7 +397,12 @@ extern "C"
{
NormalFunctionGraph = 0,
LowLevelILFunctionGraph = 1,
- LiftedILFunctionGraph = 2
+ LiftedILFunctionGraph = 2,
+ LowLevelILSSAFormFunctionGraph = 3,
+ MediumLevelILFunctionGraph = 4,
+ MediumLevelILSSAFormFunctionGraph = 5,
+ MappedMediumLevelILFunctionGraph = 6,
+ MappedMediumLevelILSSAFormFunctionGraph = 7
};
enum BNDisassemblyOption
@@ -383,8 +415,7 @@ extern "C"
GroupLinearDisassemblyFunctions = 64,
// Debugging options
- ShowBasicBlockRegisterState = 128,
- ShowFlagUsage = 129
+ ShowFlagUsage = 128
};
enum BNTypeClass
@@ -601,16 +632,18 @@ extern "C"
enum BNRegisterValueType
{
+ UndeterminedValue,
EntryValue,
- OffsetFromEntryValue,
ConstantValue,
StackFrameOffset,
- UndeterminedValue,
- OffsetFromUndeterminedValue,
+ ReturnAddressValue,
+
+ // The following are only valid in BNPossibleValueSet
SignedRangeValue,
UnsignedRangeValue,
LookupTableValue,
- ComparisonResultValue
+ InSetOfValues,
+ NotInSetOfValues
};
enum BNPluginOrigin
@@ -644,10 +677,22 @@ extern "C"
struct BNRegisterValue
{
BNRegisterValueType state;
- uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register
- int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue
- uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive
- BNLookupTableEntry* table; // Number of entries in rangeEnd
+ int64_t value;
+ };
+
+ struct BNValueRange
+ {
+ uint64_t start, end, step;
+ };
+
+ struct BNPossibleValueSet
+ {
+ BNRegisterValueType state;
+ int64_t value;
+ BNValueRange* ranges;
+ int64_t* valueSet;
+ BNLookupTableEntry* table;
+ size_t count;
};
struct BNRegisterOrConstant
@@ -664,6 +709,129 @@ 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_SET_VAR_SPLIT, // Not valid in SSA form (see MLIL_SET_VAR_SPLIT_SSA)
+ 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_ADDRESS_OF,
+ MLIL_ADDRESS_OF_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, // Not valid in SSA form (see MLIL_CALL_SSA)
+ MLIL_CALL_UNTYPED, // Not valid in SSA form (see MLIL_CALL_UNTYPED_SSA)
+ MLIL_CALL_OUTPUT, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions
+ MLIL_CALL_PARAM, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions
+ MLIL_RET, // Not valid in SSA form (see MLIL_RET_SSA)
+ 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, // Not valid in SSA form (see MLIL_SYSCALL_SSA)
+ MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA)
+ 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_SET_VAR_SPLIT_SSA,
+ MLIL_SET_VAR_ALIASED,
+ MLIL_SET_VAR_ALIASED_FIELD,
+ MLIL_VAR_SSA,
+ MLIL_VAR_SSA_FIELD,
+ MLIL_VAR_ALIASED,
+ MLIL_VAR_ALIASED_FIELD,
+ MLIL_CALL_SSA,
+ MLIL_CALL_UNTYPED_SSA,
+ MLIL_SYSCALL_SSA,
+ MLIL_SYSCALL_UNTYPED_SSA,
+ MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA family instructions
+ MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA family 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 BNVariableSourceType
+ {
+ StackVariableSourceType,
+ RegisterVariableSourceType,
+ FlagVariableSourceType
+ };
+
+ struct BNVariable
+ {
+ BNVariableSourceType type;
+ uint32_t index;
+ int64_t storage;
+ };
+
// Callbacks
struct BNLogListener
{
@@ -1013,11 +1181,11 @@ extern "C"
uint32_t (*getFloatReturnValueRegister)(void* ctxt);
};
- struct BNStackVariable
+ struct BNVariableNameAndType
{
+ BNVariable var;
BNType* type;
char* name;
- int64_t offset;
bool autoDefined;
};
@@ -1026,7 +1194,7 @@ extern "C"
uint32_t sourceOperand;
BNType* type;
char* name;
- int64_t startingOffset;
+ uint64_t varIdentifier;
int64_t referencedOffset;
};
@@ -1275,6 +1443,19 @@ extern "C"
BNType* type;
};
+ enum BNILBranchDependence
+ {
+ NotBranchDependent,
+ TrueBranchDependent,
+ FalseBranchDependent
+ };
+
+ struct BNILBranchInstructionAndDependence
+ {
+ size_t branch;
+ BNILBranchDependence dependence;
+ };
+
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
BINARYNINJACOREAPI void BNFreeString(char* str);
BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count);
@@ -1731,26 +1912,21 @@ 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,
uint64_t addr, uint32_t reg);
- BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg);
- BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg);
BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtInstruction(BNFunction* func, BNArchitecture* arch,
uint64_t addr, int64_t offset, size_t size);
BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterInstruction(BNFunction* func, BNArchitecture* arch,
uint64_t addr, int64_t offset, size_t size);
- BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtLowLevelILInstruction(BNFunction* func, size_t i,
- int64_t offset, size_t size);
- BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterLowLevelILInstruction(BNFunction* func, size_t i,
- int64_t offset, size_t size);
BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtInstruction(BNFunction* func, BNArchitecture* arch,
uint64_t addr, BNType* functionType, size_t i);
BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtLowLevelILInstruction(BNFunction* func, size_t instr,
BNType* functionType, size_t i);
- BINARYNINJACOREAPI void BNFreeRegisterValue(BNRegisterValue* value);
+ BINARYNINJACOREAPI void BNFreePossibleValueSet(BNPossibleValueSet* value);
BINARYNINJACOREAPI uint32_t* BNGetRegistersReadByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr,
size_t* count);
BINARYNINJACOREAPI uint32_t* BNGetRegistersWrittenByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr,
@@ -1811,14 +1987,27 @@ extern "C"
uint64_t len, size_t* count);
BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings);
- BINARYNINJACOREAPI BNStackVariable* BNGetStackLayout(BNFunction* func, size_t* count);
- BINARYNINJACOREAPI void BNFreeStackLayout(BNStackVariable* vars, size_t count);
+ BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count);
BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name);
BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name);
BINARYNINJACOREAPI void BNDeleteAutoStackVariable(BNFunction* func, int64_t offset);
BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset);
- BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, int64_t offset, BNStackVariable* var);
- BINARYNINJACOREAPI void BNFreeStackVariable(BNStackVariable* var);
+ BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, BNArchitecture* arch, uint64_t addr,
+ int64_t offset, BNVariableNameAndType* var);
+ BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var);
+
+ BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type,
+ const char* name, bool ignoreDisjointUses);
+ BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type,
+ const char* name, bool ignoreDisjointUses);
+ BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var);
+ BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var);
+ BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var);
+ BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var);
+ BINARYNINJACOREAPI uint64_t BNToVariableIdentifier(const BNVariable* var);
+ BINARYNINJACOREAPI BNVariable BNFromVariableIdentifier(uint64_t id);
BINARYNINJACOREAPI void BNSetAutoIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source,
BNArchitectureAndAddress* branches, size_t count);
@@ -2010,7 +2199,10 @@ extern "C"
BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func);
BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func);
BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func);
- BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, uint64_t addr);
+ BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func,
+ BNArchitecture* arch, uint64_t addr);
+ BINARYNINJACOREAPI size_t BNLowLevelILGetInstructionStart(BNLowLevelILFunction* func,
+ BNArchitecture* arch, uint64_t addr);
BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func);
BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches,
size_t count);
@@ -2033,6 +2225,7 @@ extern "C"
BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i);
BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i);
BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func);
BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr);
BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func,
@@ -2048,6 +2241,168 @@ extern "C"
BINARYNINJACOREAPI BNBasicBlock** BNGetLowLevelILBasicBlockList(BNLowLevelILFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILSSAForm(BNLowLevelILFunction* func);
+ BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILNonSSAForm(BNLowLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILSSAExprIndex(BNLowLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAExprIndex(BNLowLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILSSAMemoryDefinition(BNLowLevelILFunction* func, size_t idx);
+ BINARYNINJACOREAPI size_t* BNGetLowLevelILSSARegisterUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx,
+ size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAFlagUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx,
+ size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t idx, size_t* count);
+
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSARegisterValue(BNLowLevelILFunction* func,
+ uint32_t reg, size_t idx);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAFlagValue(BNLowLevelILFunction* func,
+ uint32_t flag, size_t idx);
+
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAtInstruction(BNLowLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAfterInstruction(BNLowLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAtInstruction(BNLowLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAfterInstruction(BNLowLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAtInstruction(BNLowLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAfterInstruction(BNLowLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAtInstruction(BNLowLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAfterInstruction(BNLowLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAtInstruction(BNLowLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAfterInstruction(BNLowLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAtInstruction(BNLowLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAfterInstruction(BNLowLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func);
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMappedMediumLevelIL(BNLowLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILInstructionIndex(BNLowLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILExprIndex(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 BNGetMediumLevelILInstructionForExpr(BNMediumLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(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 BNVariable* var, size_t idx);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx);
+ BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNVariable* 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 BNVariable* var, size_t idx);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func,
+ const BNVariable* var, size_t idx, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func,
+ const BNVariable* var, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func,
+ size_t instr);
+ BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForFlagAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(BNMediumLevelILFunction* func,
+ int64_t offset, size_t instr);
+
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAfterInstruction(BNMediumLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(BNMediumLevelILFunction* func,
+ uint32_t reg, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAfterInstruction(BNMediumLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAtInstruction(BNMediumLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAfterInstruction(BNMediumLevelILFunction* func,
+ uint32_t flag, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAtInstruction(BNMediumLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAfterInstruction(BNMediumLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAtInstruction(BNMediumLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+ BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAfterInstruction(BNMediumLevelILFunction* func,
+ int64_t offset, size_t len, size_t instr);
+
+ BINARYNINJACOREAPI BNILBranchDependence BNGetMediumLevelILBranchDependence(BNMediumLevelILFunction* func,
+ size_t curInstr, size_t branchInstr);
+ BINARYNINJACOREAPI BNILBranchInstructionAndDependence* BNGetAllMediumLevelILBranchDependence(
+ BNMediumLevelILFunction* func, size_t instr, size_t* count);
+ BINARYNINJACOREAPI void BNFreeILBranchDependenceList(BNILBranchInstructionAndDependence* branches);
+
+ BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr);
+ BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr);
+
// Types
BINARYNINJACOREAPI BNType* BNCreateVoidType(void);
BINARYNINJACOREAPI BNType* BNCreateBoolType(void);
diff --git a/function.cpp b/function.cpp
index b1d008ee..d4f91db1 100644
--- a/function.cpp
+++ b/function.cpp
@@ -24,6 +24,73 @@ using namespace BinaryNinja;
using namespace std;
+Variable::Variable()
+{
+ type = RegisterVariableSourceType;
+ index = 0;
+ storage = 0;
+}
+
+
+Variable::Variable(BNVariableSourceType t, uint32_t i, uint64_t s)
+{
+ type = t;
+ index = i;
+ storage = s;
+}
+
+
+Variable::Variable(const BNVariable& var)
+{
+ type = var.type;
+ index = var.index;
+ storage = var.storage;
+}
+
+
+Variable& Variable::operator=(const Variable& var)
+{
+ type = var.type;
+ index = var.index;
+ storage = var.storage;
+ return *this;
+}
+
+
+bool Variable::operator==(const Variable& var) const
+{
+ if (type != var.type)
+ return false;
+ if (index != var.index)
+ return false;
+ return storage == var.storage;
+}
+
+
+bool Variable::operator!=(const Variable& var) const
+{
+ return !((*this) == var);
+}
+
+
+bool Variable::operator<(const Variable& var) const
+{
+ return ToIdentifier() < var.ToIdentifier();
+}
+
+
+uint64_t Variable::ToIdentifier() const
+{
+ return BNToVariableIdentifier(this);
+}
+
+
+Variable Variable::FromIdentifier(uint64_t id)
+{
+ return BNFromVariableIdentifier(id);
+}
+
+
Function::Function(BNFunction* func)
{
m_object = func;
@@ -161,23 +228,28 @@ 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;
}
-static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value)
+RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value)
{
RegisterValue result;
result.state = value.state;
- result.reg = value.reg;
result.value = value.value;
- result.rangeStart = value.rangeStart;
- result.rangeEnd = value.rangeEnd;
- result.rangeStep = value.rangeStep;
+ return result;
+}
+
+
+PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value)
+{
+ PossibleValueSet result;
+ result.state = value.state;
+ result.value = value.value;
if (value.state == LookupTableValue)
{
- for (size_t i = 0; i < (size_t)value.rangeEnd; i++)
+ for (size_t i = 0; i < value.count; i++)
{
LookupTableEntry entry;
entry.fromValues.insert(entry.fromValues.end(), &value.table[i].fromValues[0],
@@ -186,7 +258,17 @@ static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value)
result.table.push_back(entry);
}
}
- BNFreeRegisterValue(&value);
+ else if ((value.state == SignedRangeValue) || (value.state == UnsignedRangeValue))
+ {
+ for (size_t i = 0; i < value.count; i++)
+ result.ranges.push_back(value.ranges[i]);
+ }
+ else if ((value.state == InSetOfValues) || (value.state == NotInSetOfValues))
+ {
+ for (size_t i = 0; i < value.count; i++)
+ result.valueSet.insert(value.valueSet[i]);
+ }
+ BNFreePossibleValueSet(&value);
return result;
}
@@ -194,56 +276,28 @@ static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value)
RegisterValue Function::GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg)
{
BNRegisterValue value = BNGetRegisterValueAtInstruction(m_object, arch->GetObject(), addr, reg);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
RegisterValue Function::GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg)
{
BNRegisterValue value = BNGetRegisterValueAfterInstruction(m_object, arch->GetObject(), addr, reg);
- return GetRegisterValueFromAPIObject(value);
-}
-
-
-RegisterValue Function::GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg)
-{
- BNRegisterValue value = BNGetRegisterValueAtLowLevelILInstruction(m_object, i, reg);
- return GetRegisterValueFromAPIObject(value);
-}
-
-
-RegisterValue Function::GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg)
-{
- BNRegisterValue value = BNGetRegisterValueAfterLowLevelILInstruction(m_object, i, reg);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
RegisterValue Function::GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size)
{
BNRegisterValue value = BNGetStackContentsAtInstruction(m_object, arch->GetObject(), addr, offset, size);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
RegisterValue Function::GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size)
{
BNRegisterValue value = BNGetStackContentsAfterInstruction(m_object, arch->GetObject(), addr, offset, size);
- return GetRegisterValueFromAPIObject(value);
-}
-
-
-RegisterValue Function::GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size)
-{
- BNRegisterValue value = BNGetStackContentsAtLowLevelILInstruction(m_object, i, offset, size);
- return GetRegisterValueFromAPIObject(value);
-}
-
-
-RegisterValue Function::GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size)
-{
- BNRegisterValue value = BNGetStackContentsAfterLowLevelILInstruction(m_object, i, offset, size);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
@@ -251,7 +305,7 @@ RegisterValue Function::GetParameterValueAtInstruction(Architecture* arch, uint6
{
BNRegisterValue value = BNGetParameterValueAtInstruction(m_object, arch->GetObject(), addr,
functionType ? functionType->GetObject() : nullptr, i);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
@@ -259,7 +313,7 @@ RegisterValue Function::GetParameterValueAtLowLevelILInstruction(size_t instr, T
{
BNRegisterValue value = BNGetParameterValueAtLowLevelILInstruction(m_object, instr,
functionType ? functionType->GetObject() : nullptr, i);
- return GetRegisterValueFromAPIObject(value);
+ return RegisterValue::FromAPIObject(value);
}
@@ -301,7 +355,7 @@ vector<StackVariableReference> Function::GetStackVariablesReferencedByInstructio
ref.sourceOperand = refs[i].sourceOperand;
ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr;
ref.name = refs[i].name;
- ref.startingOffset = refs[i].startingOffset;
+ ref.var = Variable::FromIdentifier(refs[i].varIdentifier);
ref.referencedOffset = refs[i].referencedOffset;
result.push_back(ref);
}
@@ -343,7 +397,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 +409,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 +438,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));
@@ -421,23 +481,23 @@ Ref<FunctionGraph> Function::CreateFunctionGraph()
}
-map<int64_t, StackVariable> Function::GetStackLayout()
+map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout()
{
size_t count;
- BNStackVariable* vars = BNGetStackLayout(m_object, &count);
+ BNVariableNameAndType* vars = BNGetStackLayout(m_object, &count);
- map<int64_t, StackVariable> result;
+ map<int64_t, vector<VariableNameAndType>> result;
for (size_t i = 0; i < count; i++)
{
- StackVariable var;
+ VariableNameAndType var;
var.name = vars[i].name;
var.type = new Type(BNNewTypeReference(vars[i].type));
- var.offset = vars[i].offset;
+ var.var = vars[i].var;
var.autoDefined = vars[i].autoDefined;
- result[vars[i].offset] = var;
+ result[vars[i].var.storage].push_back(var);
}
- BNFreeStackLayout(vars, count);
+ BNFreeVariableList(vars, count);
return result;
}
@@ -466,22 +526,86 @@ void Function::DeleteUserStackVariable(int64_t offset)
}
-bool Function::GetStackVariableAtFrameOffset(int64_t offset, StackVariable& result)
+bool Function::GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr,
+ int64_t offset, VariableNameAndType& result)
{
- BNStackVariable var;
- if (!BNGetStackVariableAtFrameOffset(m_object, offset, &var))
+ BNVariableNameAndType var;
+ if (!BNGetStackVariableAtFrameOffset(m_object, arch->GetObject(), addr, offset, &var))
return false;
result.type = new Type(BNNewTypeReference(var.type));
result.name = var.name;
- result.offset = var.offset;
+ result.var = var.var;
result.autoDefined = var.autoDefined;
- BNFreeStackVariable(&var);
+ BNFreeVariableNameAndType(&var);
return true;
}
+map<Variable, VariableNameAndType> Function::GetVariables()
+{
+ size_t count;
+ BNVariableNameAndType* vars = BNGetFunctionVariables(m_object, &count);
+
+ map<Variable, VariableNameAndType> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ VariableNameAndType var;
+ var.name = vars[i].name;
+ var.type = new Type(BNNewTypeReference(vars[i].type));
+ var.var = vars[i].var;
+ var.autoDefined = vars[i].autoDefined;
+ result[vars[i].var] = var;
+ }
+
+ BNFreeVariableList(vars, count);
+ return result;
+}
+
+
+void Function::CreateAutoVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses)
+{
+ BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses);
+}
+
+
+void Function::CreateUserVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses)
+{
+ BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses);
+}
+
+
+void Function::DeleteAutoVariable(const Variable& var)
+{
+ BNDeleteAutoVariable(m_object, &var);
+}
+
+
+void Function::DeleteUserVariable(const Variable& var)
+{
+ BNDeleteUserVariable(m_object, &var);
+}
+
+
+Ref<Type> Function::GetVariableType(const Variable& var)
+{
+ BNType* type = BNGetVariableType(m_object, &var);
+ if (!type)
+ return nullptr;
+ return new Type(type);
+}
+
+
+string Function::GetVariableName(const Variable& var)
+{
+ char* name = BNGetVariableName(m_object, &var);
+ string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
void Function::SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches)
{
BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()];
diff --git a/lowlevelil.cpp b/lowlevelil.cpp
index bf3b980e..9764445e 100644
--- a/lowlevelil.cpp
+++ b/lowlevelil.cpp
@@ -48,9 +48,15 @@ uint64_t LowLevelILFunction::GetCurrentAddress() const
}
-void LowLevelILFunction::SetCurrentAddress(uint64_t addr)
+void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr)
{
- BNLowLevelILSetCurrentAddress(m_object, addr);
+ BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr);
+}
+
+
+size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr)
+{
+ return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr);
}
@@ -547,6 +553,12 @@ size_t LowLevelILFunction::GetInstructionCount() const
}
+size_t LowLevelILFunction::GetExprCount() const
+{
+ return BNGetLowLevelILExprCount(m_object);
+}
+
+
void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr)
{
BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr);
@@ -643,3 +655,247 @@ vector<Ref<BasicBlock>> LowLevelILFunction::GetBasicBlocks() const
BNFreeBasicBlockList(blocks, count);
return result;
}
+
+
+Ref<LowLevelILFunction> LowLevelILFunction::GetSSAForm() const
+{
+ BNLowLevelILFunction* func = BNGetLowLevelILSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new LowLevelILFunction(func);
+}
+
+
+Ref<LowLevelILFunction> LowLevelILFunction::GetNonSSAForm() const
+{
+ BNLowLevelILFunction* func = BNGetLowLevelILNonSSAForm(m_object);
+ if (!func)
+ return nullptr;
+ return new LowLevelILFunction(func);
+}
+
+
+size_t LowLevelILFunction::GetSSAInstructionIndex(size_t instr) const
+{
+ return BNGetLowLevelILSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t LowLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const
+{
+ return BNGetLowLevelILNonSSAInstructionIndex(m_object, instr);
+}
+
+
+size_t LowLevelILFunction::GetSSAExprIndex(size_t expr) const
+{
+ return BNGetLowLevelILSSAExprIndex(m_object, expr);
+}
+
+
+size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const
+{
+ return BNGetLowLevelILNonSSAExprIndex(m_object, expr);
+}
+
+
+size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t idx) const
+{
+ return BNGetLowLevelILSSARegisterDefinition(m_object, reg, idx);
+}
+
+
+size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t idx) const
+{
+ return BNGetLowLevelILSSAFlagDefinition(m_object, flag, idx);
+}
+
+
+size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t idx) const
+{
+ return BNGetLowLevelILSSAMemoryDefinition(m_object, idx);
+}
+
+
+set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) const
+{
+ size_t count;
+ size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, 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> LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const
+{
+ size_t count;
+ size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, 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> LowLevelILFunction::GetSSAMemoryUses(size_t idx) const
+{
+ size_t count;
+ size_t* instrs = BNGetLowLevelILSSAMemoryUses(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 LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t idx)
+{
+ BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, idx);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t idx)
+{
+ BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, idx);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetExprValue(size_t expr)
+{
+ BNRegisterValue value = BNGetLowLevelILExprValue(m_object, expr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILRegisterValueAfterInstruction(m_object, reg, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILFlagValueAtInstruction(m_object, flag, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILFlagValueAfterInstruction(m_object, flag, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILStackContentsAtInstruction(m_object, offset, len, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue LowLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNRegisterValue value = BNGetLowLevelILStackContentsAfterInstruction(m_object, offset, len, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+Ref<MediumLevelILFunction> LowLevelILFunction::GetMediumLevelIL() const
+{
+ BNMediumLevelILFunction* func = BNGetMediumLevelILForLowLevelIL(m_object);
+ if (!func)
+ return nullptr;
+ return new MediumLevelILFunction(func);
+}
+
+
+Ref<MediumLevelILFunction> LowLevelILFunction::GetMappedMediumLevelIL() const
+{
+ BNMediumLevelILFunction* func = BNGetMappedMediumLevelIL(m_object);
+ if (!func)
+ return nullptr;
+ return new MediumLevelILFunction(func);
+}
+
+
+size_t LowLevelILFunction::GetMappedMediumLevelILInstructionIndex(size_t instr) const
+{
+ return BNGetMappedMediumLevelILInstructionIndex(m_object, instr);
+}
+
+
+size_t LowLevelILFunction::GetMappedMediumLevelILExprIndex(size_t expr) const
+{
+ return BNGetMappedMediumLevelILExprIndex(m_object, expr);
+}
diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp
new file mode 100644
index 00000000..868f3f75
--- /dev/null
+++ b/mediumlevelil.cpp
@@ -0,0 +1,494 @@
+// 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::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;
+}
+
+
+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::GetInstructionForExpr(size_t expr) const
+{
+ return BNGetMediumLevelILInstructionForExpr(m_object, expr);
+}
+
+
+size_t MediumLevelILFunction::GetInstructionCount() const
+{
+ return BNGetMediumLevelILInstructionCount(m_object);
+}
+
+
+size_t MediumLevelILFunction::GetExprCount() const
+{
+ return BNGetMediumLevelILExprCount(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 Variable& 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 Variable& 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 Variable& 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);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleExprValues(m_object, expr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const
+{
+ return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr);
+}
+
+
+size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const
+{
+ return BNGetMediumLevelILSSAMemoryIndexAtILInstruction(m_object, instr);
+}
+
+
+Variable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const
+{
+ return BNGetMediumLevelILVariableForRegisterAtInstruction(m_object, reg, instr);
+}
+
+
+Variable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const
+{
+ return BNGetMediumLevelILVariableForFlagAtInstruction(m_object, flag, instr);
+}
+
+
+Variable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const
+{
+ return BNGetMediumLevelILVariableForStackLocationAtInstruction(m_object, offset, instr);
+}
+
+
+RegisterValue MediumLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILRegisterValueAtInstruction(m_object, reg, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILRegisterValueAfterInstruction(m_object, reg, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILFlagValueAtInstruction(m_object, flag, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILFlagValueAfterInstruction(m_object, flag, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILStackContentsAtInstruction(m_object, offset, len, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+RegisterValue MediumLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNRegisterValue value = BNGetMediumLevelILStackContentsAfterInstruction(m_object, offset, len, instr);
+ return RegisterValue::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr)
+{
+ BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr);
+ return PossibleValueSet::FromAPIObject(value);
+}
+
+
+BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const
+{
+ return BNGetMediumLevelILBranchDependence(m_object, curInstr, branchInstr);
+}
+
+
+map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const
+{
+ size_t count;
+ BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count);
+
+ map<size_t, BNILBranchDependence> result;
+ for (size_t i = 0; i < count; i++)
+ result[deps[i].branch] = deps[i].dependence;
+
+ BNFreeILBranchDependenceList(deps);
+ return result;
+}
+
+
+Ref<LowLevelILFunction> MediumLevelILFunction::GetLowLevelIL() const
+{
+ BNLowLevelILFunction* func = BNGetLowLevelILForMediumLevelIL(m_object);
+ if (!func)
+ return nullptr;
+ return new LowLevelILFunction(func);
+}
+
+
+size_t MediumLevelILFunction::GetLowLevelILInstructionIndex(size_t instr) const
+{
+ return BNGetLowLevelILInstructionIndex(m_object, instr);
+}
+
+
+size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const
+{
+ return BNGetLowLevelILExprIndex(m_object, expr);
+}
diff --git a/python/__init__.py b/python/__init__.py
index f028bc5b..c7c5f768 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 9e58c47d..18856ff2 100644
--- a/python/function.py
+++ b/python/function.py
@@ -26,13 +26,14 @@ import ctypes
import _binaryninjacore as core
from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType,
HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend,
- DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext)
+ DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType)
import architecture
import highlight
import associateddatastore
import types
import basicblock
import lowlevelil
+import mediumlevelil
import binaryview
import log
@@ -50,93 +51,158 @@ class RegisterValue(object):
def __init__(self, arch, value):
self.type = RegisterValueType(value.state)
if value.state == RegisterValueType.EntryValue:
- self.reg = arch.get_reg_name(value.reg)
- elif value.state == RegisterValueType.OffsetFromEntryValue:
- self.reg = arch.get_reg_name(value.reg)
+ self.reg = arch.get_reg_name(value.value)
+ elif value.state == RegisterValueType.ConstantValue:
+ self.value = value.value
+ elif value.state == RegisterValueType.StackFrameOffset:
self.offset = value.value
+
+ def __repr__(self):
+ if self.type == RegisterValueType.EntryValue:
+ return "<entry %s>" % self.reg
+ if self.type == RegisterValueType.ConstantValue:
+ return "<const %#x>" % self.value
+ if self.type == RegisterValueType.StackFrameOffset:
+ return "<stack frame offset %#x>" % self.offset
+ if self.type == RegisterValueType.ReturnAddressValue:
+ return "<return address>"
+ return "<undetermined>"
+
+
+class ValueRange(object):
+ def __init__(self, start, end, step):
+ self.start = start
+ self.end = end
+ self.step = step
+
+ def __repr__(self):
+ if self.step == 1:
+ return "<range: %#x to %#x>" % (self.start, self.end)
+ return "<range: %#x to %#x, step %#x>" % (self.start, self.end, self.step)
+
+
+class PossibleValueSet(object):
+ def __init__(self, arch, value):
+ self.type = RegisterValueType(value.state)
+ if value.state == RegisterValueType.EntryValue:
+ self.reg = arch.get_reg_name(value.value)
elif value.state == RegisterValueType.ConstantValue:
self.value = value.value
elif value.state == RegisterValueType.StackFrameOffset:
self.offset = value.value
elif value.state == RegisterValueType.SignedRangeValue:
self.offset = value.value
- self.start = value.rangeStart
- self.end = value.rangeEnd
- self.step = value.rangeStep
- if self.start & (1 << 63):
- self.start |= ~((1 << 63) - 1)
- if self.end & (1 << 63):
- self.end |= ~((1 << 63) - 1)
+ self.ranges = []
+ for i in xrange(0, value.count):
+ start = value.ranges[i].start
+ end = value.ranges[i].end
+ step = value.ranges[i].step
+ if start & (1 << 63):
+ start |= ~((1 << 63) - 1)
+ if end & (1 << 63):
+ end |= ~((1 << 63) - 1)
+ self.ranges.append(ValueRange(start, end, step))
elif value.state == RegisterValueType.UnsignedRangeValue:
self.offset = value.value
- self.start = value.rangeStart
- self.end = value.rangeEnd
- self.step = value.rangeStep
+ self.ranges = []
+ for i in xrange(0, value.count):
+ start = value.ranges[i].start
+ end = value.ranges[i].end
+ step = value.ranges[i].step
+ self.ranges.append(ValueRange(start, end, step))
elif value.state == RegisterValueType.LookupTableValue:
self.table = []
self.mapping = {}
- for i in xrange(0, value.rangeEnd):
+ for i in xrange(0, value.count):
from_list = []
for j in xrange(0, value.table[i].fromCount):
from_list.append(value.table[i].fromValues[j])
self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue
self.table.append(LookupTableEntry(from_list, value.table[i].toValue))
- elif value.state == RegisterValueType.OffsetFromUndeterminedValue:
- self.offset = value.value
+ elif (value.state == RegisterValueType.InSetOfValues) or (value.state == RegisterValueType.NotInSetOfValues):
+ self.values = set()
+ for i in xrange(0, value.count):
+ self.values.add(value.valueSet[i])
def __repr__(self):
if self.type == RegisterValueType.EntryValue:
return "<entry %s>" % self.reg
- if self.type == RegisterValueType.OffsetFromEntryValue:
- return "<entry %s + %#x>" % (self.reg, self.offset)
if self.type == RegisterValueType.ConstantValue:
return "<const %#x>" % self.value
if self.type == RegisterValueType.StackFrameOffset:
return "<stack frame offset %#x>" % self.offset
- if (self.type == RegisterValueType.SignedRangeValue) or (self.type == RegisterValueType.UnsignedRangeValue):
- if self.step == 1:
- return "<range: %#x to %#x>" % (self.start, self.end)
- return "<range: %#x to %#x, step %#x>" % (self.start, self.end, self.step)
+ if self.type == RegisterValueType.SignedRangeValue:
+ return "<signed ranges: %s>" % repr(self.ranges)
+ if self.type == RegisterValueType.UnsignedRangeValue:
+ return "<unsigned ranges: %s>" % repr(self.ranges)
if self.type == RegisterValueType.LookupTableValue:
return "<table: %s>" % ', '.join([repr(i) for i in self.table])
- if self.type == RegisterValueType.OffsetFromUndeterminedValue:
- return "<undetermined with offset %#x>" % self.offset
+ if self.type == RegisterValueType.InSetOfValues:
+ return "<in %s>" % repr(self.values)
+ if self.type == RegisterValueType.NotInSetOfValues:
+ return "<not in %s>" % repr(self.values)
+ if self.type == RegisterValueType.ReturnAddressValue:
+ return "<return address>"
return "<undetermined>"
-class StackVariable(object):
- def __init__(self, ofs, name, t):
- self.offset = ofs
- self.name = name
- self.type = t
-
- def __repr__(self):
- return "<var@%x: %s %s>" % (self.offset, self.type, self.name)
-
- def __str__(self):
- return self.name
-
-
class StackVariableReference(object):
- def __init__(self, src_operand, t, name, start_ofs, ref_ofs):
+ def __init__(self, src_operand, t, name, var, ref_ofs):
self.source_operand = src_operand
self.type = t
self.name = name
- self.starting_offset = start_ofs
+ self.var = var
self.referenced_offset = ref_ofs
if self.source_operand == 0xffffffff:
self.source_operand = None
def __repr__(self):
if self.source_operand is None:
- if self.referenced_offset != self.starting_offset:
- return "<ref to %s%+#x>" % (self.name, self.referenced_offset - self.starting_offset)
+ if self.referenced_offset != self.var.storage:
+ return "<ref to %s%+#x>" % (self.name, self.referenced_offset - self.var.storage)
return "<ref to %s>" % self.name
- if self.referenced_offset != self.starting_offset:
- return "<operand %d ref to %s%+#x>" % (self.source_operand, self.name, self.referenced_offset)
+ if self.referenced_offset != self.var.storage:
+ return "<operand %d ref to %s%+#x>" % (self.source_operand, self.name, self.var.storage)
return "<operand %d ref to %s>" % (self.source_operand, self.name)
+class Variable(object):
+ def __init__(self, func, source_type, index, storage, name = None, var_type = None):
+ self.function = func
+ self.source_type = VariableSourceType(source_type)
+ self.index = index
+ self.storage = storage
+
+ var = core.BNVariable()
+ var.type = source_type
+ var.index = index
+ var.storage = storage
+ self.identifier = core.BNToVariableIdentifier(var)
+
+ if name is None:
+ name = core.BNGetVariableName(func.handle, var)
+ if var_type is None:
+ var_type = core.BNGetVariableType(func.handle, var)
+ if var_type:
+ var_type = types.Type(var_type)
+
+ self.name = name
+ self.type = var_type
+
+ @classmethod
+ def from_identifier(self, func, identifier, name = None, var_type = None):
+ var = core.BNFromVariableIdentifier(identifier)
+ return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type)
+
+ def __repr__(self):
+ if self.type is None:
+ return "<var %s>" % self.name
+ return "<var %s %s%s>" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name())
+
+ def __str__(self):
+ return self.name
+
+
class ConstantReference(object):
def __init__(self, val, size):
self.value = val
@@ -298,6 +364,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))
@@ -308,14 +379,28 @@ class Function(object):
@property
def stack_layout(self):
- """List of function stack (read-only)"""
+ """List of function stack variables (read-only)"""
count = ctypes.c_ulonglong()
v = core.BNGetStackLayout(self.handle, count)
result = []
for i in xrange(0, count.value):
- result.append(StackVariable(v[i].offset, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type))))
- result.sort(key = lambda x: x.offset)
- core.BNFreeStackLayout(v, count.value)
+ result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
+ types.Type(handle = core.BNNewTypeReference(v[i].type))))
+ result.sort(key = lambda x: x.identifier)
+ core.BNFreeVariableList(v, count.value)
+ return result
+
+ @property
+ def vars(self):
+ """List of function variables (read-only)"""
+ count = ctypes.c_ulonglong()
+ v = core.BNGetFunctionVariables(self.handle, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
+ types.Type(handle = core.BNNewTypeReference(v[i].type))))
+ result.sort(key = lambda x: x.identifier)
+ core.BNFreeVariableList(v, count.value)
return result
@property
@@ -396,7 +481,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):
@@ -418,7 +503,6 @@ class Function(object):
reg = arch.regs[reg].index
value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg)
result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_reg_value_after(self, addr, reg, arch=None):
@@ -440,37 +524,6 @@ class Function(object):
reg = arch.regs[reg].index
value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg)
result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
- return result
-
- def get_reg_value_at_low_level_il_instruction(self, i, reg, arch=None):
- """
- ``get_reg_value_at_low_level_il_instruction`` returns the value of the specified register ``reg`` at the il address
- i
-
- :param int i: il address of instruction to query
- :param Architecture arch: (optional) Architecture for the given function
- :rtype: function.RegisterValue
- :Example:
-
- >>> func.get_reg_value_at_low_level_il_instruction(15, 'rdi')
- <const 0x2>
- """
- if arch is None:
- arch = self.arch
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
- value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg)
- result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
- return result
-
- def get_reg_value_after_low_level_il_instruction(self, i, reg):
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
- value = core.BNGetRegisterValueAfterLowLevelILInstruction(self.handle, i, reg)
- result = RegisterValue(self.arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_stack_contents_at(self, addr, offset, size, arch=None):
@@ -496,7 +549,6 @@ class Function(object):
arch = self.arch
value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size)
result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_stack_contents_after(self, addr, offset, size, arch=None):
@@ -504,19 +556,6 @@ class Function(object):
arch = self.arch
value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size)
result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
- return result
-
- def get_stack_contents_at_low_level_il_instruction(self, i, offset, size):
- value = core.BNGetStackContentsAtLowLevelILInstruction(self.handle, i, offset, size)
- result = RegisterValue(self.arch, value)
- core.BNFreeRegisterValue(value)
- return result
-
- def get_stack_contents_after_low_level_il_instruction(self, i, offset, size):
- value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size)
- result = RegisterValue(self.arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_parameter_at(self, addr, func_type, i, arch=None):
@@ -526,7 +565,6 @@ class Function(object):
func_type = func_type.handle
value = core.BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i)
result = RegisterValue(arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_parameter_at_low_level_il_instruction(self, instr, func_type, i):
@@ -534,7 +572,6 @@ class Function(object):
func_type = func_type.handle
value = core.BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type, i)
result = RegisterValue(self.arch, value)
- core.BNFreeRegisterValue(value)
return result
def get_regs_read_by(self, addr, arch=None):
@@ -566,8 +603,10 @@ class Function(object):
refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count)
result = []
for i in xrange(0, count.value):
- result.append(StackVariableReference(refs[i].sourceOperand, types.Type(core.BNNewTypeReference(refs[i].type)),
- refs[i].name, refs[i].startingOffset, refs[i].referencedOffset))
+ var_type = types.Type(core.BNNewTypeReference(refs[i].type))
+ result.append(StackVariableReference(refs[i].sourceOperand, var_type,
+ refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type),
+ refs[i].referencedOffset))
core.BNFreeStackVariableReferenceList(refs, count.value)
return result
@@ -595,7 +634,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):
@@ -606,7 +645,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):
@@ -802,6 +841,57 @@ class Function(object):
color = highlight.HighlightColor(color)
core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct())
+ def create_auto_stack_var(self, offset, var_type, name):
+ core.BNCreateAutoStackVariable(self.handle, offset, var_type.handle, name)
+
+ def create_user_stack_var(self, offset, var_type, name):
+ core.BNCreateUserStackVariable(self.handle, offset, var_type.handle, name)
+
+ def delete_auto_stack_var(self, offset):
+ core.BNDeleteAutoStackVariable(self.handle, offset)
+
+ def delete_user_stack_var(self, offset):
+ core.BNDeleteUserStackVariable(self.handle, offset)
+
+ def create_auto_var(self, var, var_type, name, ignore_disjoint_uses = False):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ core.BNCreateAutoVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses)
+
+ def create_user_var(self, var, var_type, name, ignore_disjoint_uses = False):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ core.BNCreateUserVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses)
+
+ def delete_auto_var(self, var):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ core.BNDeleteAutoVariable(self.handle, var_data)
+
+ def delete_user_var(self, var):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ core.BNDeleteUserVariable(self.handle, var_data)
+
+ def get_stack_var_at_frame_offset(self, offset, addr, arch=None):
+ if arch is None:
+ arch = self.arch
+ found_var = core.BNVariableNameAndType()
+ if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var):
+ return None
+ result = Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage,
+ found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type)))
+ core.BNFreeVariableNameAndType(found_var)
+ return result
+
class AdvancedFunctionAnalysisDataRequestor(object):
def __init__(self, func = None):
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index c80fcd0d..a737d95e 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -25,6 +25,7 @@ import _binaryninjacore as core
from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType
import function
import basicblock
+import mediumlevelil
class LowLevelILLabel(object):
@@ -53,7 +54,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_PUSH: [("src", "expr")],
LowLevelILOperation.LLIL_POP: [],
LowLevelILOperation.LLIL_REG: [("src", "reg")],
- LowLevelILOperation.LLIL_CONST: [("value", "int")],
+ LowLevelILOperation.LLIL_CONST: [("constant", "int")],
LowLevelILOperation.LLIL_FLAG: [("src", "flag")],
LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")],
LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")],
@@ -107,10 +108,29 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")],
LowLevelILOperation.LLIL_SYSCALL: [],
LowLevelILOperation.LLIL_BP: [],
- LowLevelILOperation.LLIL_TRAP: [("value", "int")],
+ LowLevelILOperation.LLIL_TRAP: [("vector", "int")],
LowLevelILOperation.LLIL_UNDEF: [],
LowLevelILOperation.LLIL_UNIMPL: [],
- LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")]
+ LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")],
+ LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")],
+ LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")],
+ LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")],
+ LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")],
+ LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")],
+ LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")],
+ 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: [("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")],
+ LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")],
+ LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
}
def __init__(self, func, expr_index, instr_index=None):
@@ -142,16 +162,41 @@ class LowLevelILInstruction(object):
else:
value = func.arch.get_reg_name(instr.operands[i])
elif operand_type == "flag":
- value = func.arch.get_flag_name(instr.operands[i])
+ if (instr.operands[i] & 0x80000000) != 0:
+ value = instr.operands[i]
+ else:
+ value = func.arch.get_flag_name(instr.operands[i])
elif operand_type == "cond":
value = LowLevelILFlagCondition(instr.operands[i])
elif operand_type == "int_list":
count = ctypes.c_ulonglong()
- operands = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
value = []
for i in xrange(count.value):
- value.append(operands[i])
- core.BNLowLevelILFreeOperandList(operands)
+ value.append(operand_list[i])
+ core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ value = []
+ for i in xrange(count.value / 2):
+ reg = operand_list[i * 2]
+ reg_index = operand_list[(i * 2) + 1]
+ if (reg & 0x80000000) == 0:
+ reg = func.arch.get_reg_name(reg)
+ value.append((reg, reg_index))
+ core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "flag_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ value = []
+ for i in xrange(count.value / 2):
+ flag = operand_list[i * 2]
+ flag_index = operand_list[(i * 2) + 1]
+ if (flag & 0x80000000) == 0:
+ flag = func.arch.get_flag_name(flag)
+ value.append((flag, flag_index))
+ core.BNLowLevelILFreeOperandList(operand_list)
self.operands.append(value)
self.__dict__[name] = value
@@ -193,6 +238,123 @@ class LowLevelILInstruction(object):
core.BNFreeInstructionText(tokens, count.value)
return result
+ @property
+ def ssa_form(self):
+ """SSA form of expression (read-only)"""
+ return LowLevelILInstruction(self.function.ssa_form,
+ core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index))
+
+ @property
+ def non_ssa_form(self):
+ """Non-SSA form of expression (read-only)"""
+ return LowLevelILInstruction(self.function.non_ssa_form,
+ core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index))
+
+ @property
+ def mapped_medium_level_il(self):
+ """Gets the medium level IL expression corresponding to this expression"""
+ expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index)
+ if expr is None:
+ return None
+ return mediumlevelil.MediumLevelILInstruction(self.function.mapped_medium_level_il, expr)
+
+ @property
+ def value(self):
+ """Value of expression if constant or a known value (read-only)"""
+ value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ @property
+ def possible_values(self):
+ """Possible values of expression using path-sensitive static data flow analysis (read-only)"""
+ value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_reg_value(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_reg_value_after(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_reg_values(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_reg_values_after(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_flag_value(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_flag_value_after(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_flag_values(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_flag_values_after(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_stack_contents(self, offset, size):
+ value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_stack_contents_after(self, offset, size):
+ value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_stack_contents(self, offset, size):
+ value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_stack_contents_after(self, offset, size):
+ value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value)
@@ -270,7 +432,12 @@ class LowLevelILFunction(object):
@current_address.setter
def current_address(self, value):
- core.BNLowLevelILSetCurrentAddress(self.handle, value)
+ core.BNLowLevelILSetCurrentAddress(self.handle, self.arch.handle, value)
+
+ def set_current_address(self, value, arch = None):
+ if arch is None:
+ arch = self.arch
+ core.BNLowLevelILSetCurrentAddress(self.handle, arch.handle, value)
@property
def temp_reg_count(self):
@@ -296,6 +463,40 @@ class LowLevelILFunction(object):
core.BNFreeBasicBlockList(blocks, count.value)
return result
+ @property
+ def ssa_form(self):
+ """Low level IL in SSA form (read-only)"""
+ result = core.BNGetLowLevelILSSAForm(self.handle)
+ if not result:
+ return None
+ return LowLevelILFunction(self.arch, result, self.source_function)
+
+ @property
+ def non_ssa_form(self):
+ """Low level IL in non-SSA (default) form (read-only)"""
+ result = core.BNGetLowLevelILNonSSAForm(self.handle)
+ if not result:
+ return None
+ return LowLevelILFunction(self.arch, result, self.source_function)
+
+ @property
+ def medium_level_il(self):
+ """Medium level IL for this low level IL."""
+ result = core.BNGetMediumLevelILForLowLevelIL(self.handle)
+ if not result:
+ return None
+ return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function)
+
+ @property
+ def mapped_medium_level_il(self):
+ """Medium level IL with mappings between low level IL and medium level IL. Unused stores are not removed.
+ Typically, this should only be used to answer queries on assembly or low level IL where the query is
+ easier to perform on medium level IL."""
+ result = core.BNGetMappedMediumLevelIL(self.handle)
+ if not result:
+ return None
+ return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function)
+
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value)
@@ -329,6 +530,14 @@ class LowLevelILFunction(object):
finally:
core.BNFreeBasicBlockList(blocks, count.value)
+ def get_instruction_start(self, addr, arch = None):
+ if arch is None:
+ arch = self.arch
+ result = core.BNLowLevelILGetInstructionStart(self.handle, arch.handle, addr)
+ if result >= core.BNGetLowLevelILInstructionCount(self.handle):
+ return None
+ return result
+
def clear_indirect_branches(self):
core.BNLowLevelILClearIndirectBranches(self.handle)
@@ -1262,6 +1471,89 @@ class LowLevelILFunction(object):
return None
return LowLevelILLabel(label)
+ def get_ssa_instruction_index(self, instr):
+ return core.BNGetLowLevelILSSAInstructionIndex(self.handle, instr)
+
+ def get_non_ssa_instruction_index(self, instr):
+ return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr)
+
+ def get_ssa_reg_definition(self, reg, index):
+ result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index)
+ if result >= core.BNGetLowLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def get_ssa_flag_definition(self, flag, index):
+ result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index)
+ if result >= core.BNGetLowLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def get_ssa_memory_definition(self, index):
+ result = core.BNGetLowLevelILSSAMemoryDefinition(self.handle, index)
+ if result >= core.BNGetLowLevelILInstructionCount(self.handle):
+ return None
+ return result
+
+ def get_ssa_reg_uses(self, reg, index):
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_ssa_flag_uses(self, flag, index):
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, 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.BNGetLowLevelILSSAMemoryUses(self.handle, index, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeILInstructionList(instrs)
+ return result
+
+ def get_ssa_reg_value(self, reg, index):
+ if isinstance(reg, str):
+ reg = self.arch.regs[reg].index
+ value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index)
+ result = function.RegisterValue(self.arch, value)
+ return result
+
+ def get_ssa_flag_value(self, flag, index):
+ if isinstance(flag, str):
+ flag = self.arch.get_flag_by_name(flag)
+ value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index)
+ result = function.RegisterValue(self.arch, value)
+ return result
+
+ def get_mapped_medium_level_il_instruction_index(self, instr):
+ med_il = self.mapped_medium_level_il
+ if med_il is None:
+ return None
+ result = core.BNGetMappedMediumLevelILInstructionIndex(self.handle, instr)
+ if result >= core.BNGetMediumLevelILInstructionCount(med_il.handle):
+ return None
+ return result
+
+ def get_mapped_medium_level_il_expr_index(self, expr):
+ med_il = self.mapped_medium_level_il
+ if med_il is None:
+ return None
+ result = core.BNGetMappedMediumLevelILExprIndex(self.handle, expr)
+ if result >= core.BNGetMediumLevelILExprCount(med_il.handle):
+ return None
+ return result
+
class LowLevelILBasicBlock(basicblock.BasicBlock):
def __init__(self, view, handle, owner):
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
new file mode 100644
index 00000000..bc7a5c89
--- /dev/null
+++ b/python/mediumlevelil.py
@@ -0,0 +1,735 @@
+# 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, ILBranchDependence
+import function
+import basicblock
+import lowlevelil
+
+
+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_SET_VAR_SPLIT: [("high", "var"), ("low", "var"), ("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_ADDRESS_OF: [("src", "var")],
+ MediumLevelILOperation.MLIL_ADDRESS_OF_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: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")],
+ MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")],
+ MediumLevelILOperation.MLIL_CALL_PARAM: [("src", "var_list")],
+ MediumLevelILOperation.MLIL_RET: [("src", "expr_list")],
+ 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: [("output", "var_list"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")],
+ 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"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")],
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")],
+ MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")],
+ MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")],
+ MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")],
+ MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")],
+ MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")],
+ MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("params", "expr"), ("stack", "expr")],
+ MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("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
+ if instr_index is None:
+ self.instr_index = core.BNGetMediumLevelILInstructionForExpr(func.handle, expr_index)
+ else:
+ 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
+ for operand in operands:
+ name, operand_type = operand
+ if operand_type == "int":
+ value = instr.operands[i]
+ elif operand_type == "expr":
+ value = MediumLevelILInstruction(func, instr.operands[i])
+ elif operand_type == "var":
+ value = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
+ elif operand_type == "int_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ value = []
+ for j in xrange(count.value):
+ value.append(operand_list[j])
+ core.BNMediumLevelILFreeOperandList(operand_list)
+ elif operand_type == "var_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):
+ value.append(function.Variable.from_identifier(self.function.source_function, operand_list[j]))
+ 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 / 2):
+ var_id = operand_list[j * 2]
+ var_index = operand_list[(j * 2) + 2]
+ value.append((function.Variable.from_identifier(self.function.source_function,
+ var_id), var_index))
+ core.BNMediumLevelILFreeOperandList(operand_list)
+ elif operand_type == "expr_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):
+ value.append(MediumLevelILInstruction(func, operand_list[j]))
+ core.BNMediumLevelILFreeOperandList(operand_list)
+ self.operands.append(value)
+ self.__dict__[name] = value
+ i += 1
+
+ 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) and
+ (self.expr_index == core.BNGetMediumLevelILIndexForInstruction(self.function.handle, self.instr_index))):
+ 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 if constant or a known value (read-only)"""
+ value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ @property
+ def possible_values(self):
+ """Possible values of expression using path-sensitive static data flow analysis (read-only)"""
+ value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ @property
+ def branch_dependence(self):
+ """Set of branching instructions that must take the true or false path to reach this instruction"""
+ count = ctypes.c_ulonglong()
+ deps = core.BNGetAllMediumLevelILBranchDependence(self.function.handle, self.instr_index, count)
+ result = {}
+ for i in xrange(0, count.value):
+ result[deps[i].branch] = ILBranchDependence(deps[i].dependence)
+ core.BNFreeILBranchDependenceList(deps)
+ return result
+
+ @property
+ def low_level_il(self):
+ """Low level IL form of this expression"""
+ expr = self.function.get_low_level_il_expr_index(self.expr_index)
+ if expr is None:
+ return None
+ return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr)
+
+ @property
+ def ssa_memory_index(self):
+ """Index of active memory contents in SSA form for this instruction"""
+ return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index)
+
+ def get_ssa_var_possible_values(self, var, index):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_ssa_var_index(self, var):
+ var_data = core.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index)
+
+ def get_var_for_reg(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index)
+ return function.Variable(self.function.source_function, result.type, result.index, result.storage)
+
+ def get_var_for_flag(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.regs[flag].index
+ result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index)
+ return function.Variable(self.function.source_function, result.type, result.index, result.storage)
+
+ def get_var_for_stack_location(self, offset):
+ result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index)
+ return function.Variable(self.function.source_function, result.type, result.index, result.storage)
+
+ def get_reg_value(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_reg_value_after(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_reg_values(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_reg_values_after(self, reg):
+ if isinstance(reg, str):
+ reg = self.function.arch.regs[reg].index
+ value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_flag_value(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_flag_value_after(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_flag_values(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_flag_values_after(self, flag):
+ if isinstance(flag, str):
+ flag = self.function.arch.flags[flag].index
+ value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_stack_contents(self, offset, size):
+ value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_stack_contents_after(self, offset, size):
+ value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.RegisterValue(self.function.arch, value)
+ return result
+
+ def get_possible_stack_contents(self, offset, size):
+ value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_possible_stack_contents_after(self, offset, size):
+ value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index)
+ result = function.PossibleValueSet(self.function.arch, value)
+ core.BNFreePossibleValueSet(value)
+ return result
+
+ def get_branch_dependence(self, branch_instr):
+ return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.function.handle, self.instr_index, branch_instr))
+
+ 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)
+
+ @property
+ def low_level_il(self):
+ """Low level IL for this function"""
+ result = core.BNGetLowLevelILForMediumLevelIL(self.handle)
+ if not result:
+ return None
+ return lowlevelil.LowLevelILFunction(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.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ 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.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ 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.BNVariable()
+ var_data.type = var.source_type
+ var_data.index = var.index
+ var_data.storage = var.storage
+ value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index)
+ result = function.RegisterValue(self.arch, value)
+ return result
+
+ def get_low_level_il_instruction_index(self, instr):
+ low_il = self.low_level_il
+ if low_il is None:
+ return None
+ low_il = low_il.ssa_form
+ if low_il is None:
+ return None
+ result = core.BNGetLowLevelILInstructionIndex(self.handle, instr)
+ if result >= core.BNGetLowLevelILInstructionCount(low_il.handle):
+ return None
+ return result
+
+ def get_low_level_il_expr_index(self, expr):
+ low_il = self.low_level_il
+ if low_il is None:
+ return None
+ low_il = low_il.ssa_form
+ if low_il is None:
+ return None
+ result = core.BNGetLowLevelILExprIndex(self.handle, expr)
+ if result >= core.BNGetLowLevelILExprCount(low_il.handle):
+ return None
+ 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]