From 3d403cfae9d5a366f112c8a5936a371a01cfd230 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 10 Jul 2017 21:40:51 -0400 Subject: Add confidence levels to type objects --- python/mediumlevelil.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'python/mediumlevelil.py') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..275746cc 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -265,8 +265,9 @@ class MediumLevelILInstruction(object): size = tokens[i].size operand = tokens[i].operand context = tokens[i].context + confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result -- cgit v1.3.1 From 35c65d909d1ec36a4a1bad7404c9f986e259f662 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 14 Jul 2017 01:05:18 -0400 Subject: Adding API to get type of MLIL expression --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ mediumlevelil.cpp | 9 +++++++++ python/callingconvention.py | 2 +- python/function.py | 4 ++-- python/mediumlevelil.py | 9 +++++++++ python/types.py | 12 ++++++------ 7 files changed, 31 insertions(+), 9 deletions(-) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 2341e39f..f079e7c0 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2550,6 +2550,8 @@ namespace BinaryNinja Ref GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; + + Confidence> GetExprType(size_t expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index f5b89437..0414b512 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2488,6 +2488,8 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr); BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNTypeWithConfidence BNGetMediumLevelILExprType(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 8bbb2746..df78de2d 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -494,3 +494,12 @@ size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const { return BNGetLowLevelILExprIndex(m_object, expr); } + + +Confidence> MediumLevelILFunction::GetExprType(size_t expr) +{ + BNTypeWithConfidence result = BNGetMediumLevelILExprType(m_object, expr); + if (!result.type) + return nullptr; + return Confidence>(new Type(result.type), result.confidence); +} diff --git a/python/callingconvention.py b/python/callingconvention.py index e6aa323c..db473c53 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -41,7 +41,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch, handle = None, confidence = types.Type.max_confidence): + def __init__(self, arch, handle = None, confidence = types.max_confidence): if handle is None: self.arch = arch self._pending_reg_lists = {} diff --git a/python/function.py b/python/function.py index 3cd5396f..aa0d05eb 100644 --- a/python/function.py +++ b/python/function.py @@ -185,7 +185,7 @@ class Variable(object): if var_type is None: var_type_conf = core.BNGetVariableType(func.handle, var) if var_type_conf.type: - var_type = types.Type(var_type, confidence = var_type_conf.confidence) + var_type = types.Type(var_type_conf.type, confidence = var_type_conf.confidence) else: var_type = None @@ -1401,7 +1401,7 @@ class InstructionTextToken(object): """ def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, - context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.Type.max_confidence): + context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.max_confidence): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 275746cc..76a85a86 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -26,6 +26,7 @@ from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDep import function import basicblock import lowlevelil +import types class SSAVariable(object): @@ -397,6 +398,14 @@ class MediumLevelILInstruction(object): result += operand.vars_read return result + @property + def expr_type(self): + """Type of expression""" + result = core.BNGetMediumLevelILExprType(self.function.handle, self.expr_index) + if result.type: + return types.Type(result.type, confidence = result.confidence) + return None + def get_ssa_var_possible_values(self, ssa_var): var_data = core.BNVariable() var_data.type = ssa_var.var.source_type diff --git a/python/types.py b/python/types.py index c3d7156e..5933661a 100644 --- a/python/types.py +++ b/python/types.py @@ -18,6 +18,8 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +max_confidence = 255 + import ctypes # Binary Ninja components @@ -198,8 +200,6 @@ class Symbol(object): class Type(object): - max_confidence = 255 - def __init__(self, handle, confidence = max_confidence): self.handle = handle self.confidence = confidence @@ -336,8 +336,8 @@ class Type(object): return core.BNGetTypeString(self.handle) def __repr__(self): - if self.confidence < Type.max_confidence: - return "" % (str(self), (self.confidence * 100) / Type.max_confidence) + if self.confidence < max_confidence: + return "" % (str(self), (self.confidence * 100) / max_confidence) return "" % str(self) def get_string_before_name(self): @@ -560,7 +560,7 @@ class Type(object): class BoolWithConfidence(object): - def __init__(self, value, confidence = Type.max_confidence): + def __init__(self, value, confidence = max_confidence): self.value = value self.confidence = confidence @@ -578,7 +578,7 @@ class BoolWithConfidence(object): class ReferenceTypeWithConfidence(object): - def __init__(self, value, confidence = Type.max_confidence): + def __init__(self, value, confidence = max_confidence): self.value = value self.confidence = confidence -- cgit v1.3.1 From bb15b09b7888d238ab78d249fdf0e0c29999d9df Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Fri, 14 Jul 2017 13:06:36 -0400 Subject: Added __hash__ and __eq__ to Variable and SSAVariable (#725) --- python/function.py | 6 ++++++ python/mediumlevelil.py | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'python/mediumlevelil.py') diff --git a/python/function.py b/python/function.py index d06d604d..b8db6875 100644 --- a/python/function.py +++ b/python/function.py @@ -203,6 +203,12 @@ class Variable(object): def __str__(self): return self.name + def __eq__(self, other): + return self.identifier == other.identifier + + def __hash__(self): + return hash(self.identifier) + class ConstantReference(object): def __init__(self, val, size, ptr, intermediate): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1274bd9b..1fdfab4b 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -36,6 +36,15 @@ class SSAVariable(object): def __repr__(self): return "" % (repr(self.var), self.version) + def __eq__(self, other): + return ( + (self.var.identifier, self.version) == + (other.var.identifier, other.version) + ) + + def __hash__(self): + return hash(self.var.identifier, self.version) + class MediumLevelILLabel(object): def __init__(self, handle = None): -- cgit v1.3.1 From 18083837fe452a91e457f02ed8be2abf5fc66877 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 14 Jul 2017 18:49:26 -0400 Subject: Add API to get list of all definitions or uses of a variable --- binaryninjaapi.h | 3 +++ binaryninjacore.h | 5 +++++ mediumlevelil.cpp | 28 ++++++++++++++++++++++++++++ python/mediumlevelil.py | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f079e7c0..20752370 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2520,6 +2520,9 @@ namespace BinaryNinja std::set GetSSAVarUses(const Variable& var, size_t version) const; std::set GetSSAMemoryUses(size_t version) const; + std::set GetVariableDefinitions(const Variable& var) const; + std::set GetVariableUses(const Variable& var) const; + RegisterValue GetSSAVarValue(const Variable& var, size_t version); RegisterValue GetExprValue(size_t expr); PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); diff --git a/binaryninjacore.h b/binaryninjacore.h index 0414b512..e601cd1c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2435,6 +2435,11 @@ extern "C" BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, size_t version, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILVariableDefinitions(BNMediumLevelILFunction* func, + const BNVariable* var, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILVariableUses(BNMediumLevelILFunction* func, + const BNVariable* var, size_t* count); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, const BNVariable* var, size_t version); BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index df78de2d..b4abaa72 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -313,6 +313,34 @@ set MediumLevelILFunction::GetSSAMemoryUses(size_t version) const } +set MediumLevelILFunction::GetVariableDefinitions(const Variable& var) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILVariableDefinitions(m_object, &var, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set MediumLevelILFunction::GetVariableUses(const Variable& var) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILVariableUses(m_object, &var, &count); + + set 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 version) { BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 76a85a86..8a8d8d0b 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -793,6 +793,32 @@ class MediumLevelILFunction(object): core.BNFreeILInstructionList(instrs) return result + def get_var_definitions(self, var): + 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.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_var_uses(self, var): + 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.BNGetMediumLevelILVariableUses(self.handle, var_data, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + def get_ssa_var_value(self, ssa_var): var_data = core.BNVariable() var_data.type = ssa_var.var.source_type -- cgit v1.3.1 From 6857160ff18733d7a218101ab1d67ede04c1018b Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Sat, 15 Jul 2017 09:48:11 -0700 Subject: Accidentally omitted the parenthesis to create a tuple for SSAVariable.__hash__ (#737) --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/mediumlevelil.py') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 1fdfab4b..fb27c490 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -43,7 +43,7 @@ class SSAVariable(object): ) def __hash__(self): - return hash(self.var.identifier, self.version) + return hash((self.var.identifier, self.version)) class MediumLevelILLabel(object): -- cgit v1.3.1 From e89e8aa18316ae0e30845acf729436788c470083 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 15 Jul 2017 22:05:35 -0400 Subject: Fixes #700 MLIL_SET_VAR_SPLIT_SSA operands are incorrectly typed --- python/mediumlevelil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/mediumlevelil.py') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index fb27c490..5b5617aa 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -148,7 +148,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "ssa_var"), ("low", "ssa_var"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], -- cgit v1.3.1 From bf9d72bbae638a42f0b93a9053dffcb1f5e79ff3 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 18 Jul 2017 00:20:01 -0400 Subject: Add instruction for indirect structure access --- binaryninjaapi.h | 1 + binaryninjacore.h | 5 +++++ python/mediumlevelil.py | 4 ++++ python/types.py | 5 +++++ type.cpp | 6 ++++++ 5 files changed, 21 insertions(+) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 20752370..4f46cd44 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1842,6 +1842,7 @@ namespace BinaryNinja void SetTypeName(const QualifiedName& name); uint64_t GetElementCount() const; + uint64_t GetOffset() const; void SetFunctionCanReturn(const Confidence& canReturn); diff --git a/binaryninjacore.h b/binaryninjacore.h index e601cd1c..2b758a94 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -726,7 +726,9 @@ extern "C" 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_LOAD_STRUCT, // Not valid in SSA form (see MLIL_LOAD_STRUCT_SSA) MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA) + MLIL_STORE_STRUCT, // Not valid in SSA form (see MLIL_STORE_STRUCT_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, @@ -811,7 +813,9 @@ extern "C" 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_LOAD_STRUCT_SSA, MLIL_STORE_SSA, + MLIL_STORE_STRUCT_SSA, MLIL_VAR_PHI, MLIL_MEM_PHI }; @@ -2534,6 +2538,7 @@ extern "C" BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); + BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type); BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn); BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type); BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope); diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8a8d8d0b..ba83f7aa 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -71,7 +71,9 @@ class MediumLevelILInstruction(object): 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_LOAD_STRUCT: [("src", "expr"), ("offset", "int")], MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT: [("dest", "expr"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], @@ -154,7 +156,9 @@ class MediumLevelILInstruction(object): 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_LOAD_STRUCT_SSA: [("src", "expr"), ("offset", "int"), ("src_memory", "int")], MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT_SSA: [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } diff --git a/python/types.py b/python/types.py index 5933661a..ab3fb337 100644 --- a/python/types.py +++ b/python/types.py @@ -332,6 +332,11 @@ class Type(object): """Type count (read-only)""" return core.BNGetTypeElementCount(self.handle) + @property + def offset(self): + """Offset into structure (read-only)""" + return core.BNGetTypeOffset(self.handle) + def __str__(self): return core.BNGetTypeString(self.handle) diff --git a/type.cpp b/type.cpp index 837b212d..19624cdd 100644 --- a/type.cpp +++ b/type.cpp @@ -414,6 +414,12 @@ uint64_t Type::GetElementCount() const } +uint64_t Type::GetOffset() const +{ + return BNGetTypeOffset(m_object); +} + + string Type::GetString() const { char* str = BNGetTypeString(m_object); -- cgit v1.3.1 From 111add984b0a517966f133ae69c51d2084dee985 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 24 Jul 2017 20:10:18 -0400 Subject: Adding size of stack var refs, source operand in MLIL --- binaryninjaapi.h | 1 + binaryninjacore.h | 2 ++ function.cpp | 1 + python/function.py | 5 +++-- python/mediumlevelil.py | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 4f46cd44..83d12d21 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2062,6 +2062,7 @@ namespace BinaryNinja std::string name; Variable var; int64_t referencedOffset; + size_t size; }; struct IndirectBranchInfo diff --git a/binaryninjacore.h b/binaryninjacore.h index 9bca447d..01c78ff4 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -826,6 +826,7 @@ extern "C" struct BNMediumLevelILInstruction { BNMediumLevelILOperation operation; + uint32_t sourceOperand; size_t size; uint64_t operands[5]; uint64_t address; @@ -1253,6 +1254,7 @@ extern "C" char* name; uint64_t varIdentifier; int64_t referencedOffset; + size_t size; }; struct BNIndirectBranchInfo diff --git a/function.cpp b/function.cpp index 0e1fa5cf..66b2aade 100644 --- a/function.cpp +++ b/function.cpp @@ -358,6 +358,7 @@ vector Function::GetStackVariablesReferencedByInstructio ref.name = refs[i].name; ref.var = Variable::FromIdentifier(refs[i].varIdentifier); ref.referencedOffset = refs[i].referencedOffset; + ref.size = refs[i].size; result.push_back(ref); } diff --git a/python/function.py b/python/function.py index aa0d05eb..c3310b6c 100644 --- a/python/function.py +++ b/python/function.py @@ -148,12 +148,13 @@ class PossibleValueSet(object): class StackVariableReference(object): - def __init__(self, src_operand, t, name, var, ref_ofs): + def __init__(self, src_operand, t, name, var, ref_ofs, size): self.source_operand = src_operand self.type = t self.name = name self.var = var self.referenced_offset = ref_ofs + self.size = size if self.source_operand == 0xffffffff: self.source_operand = None @@ -621,7 +622,7 @@ class Function(object): var_type = types.Type(core.BNNewTypeReference(refs[i].type), confidence = refs[i].typeConfidence) 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)) + refs[i].referencedOffset, refs[i].size)) core.BNFreeStackVariableReferenceList(refs, count.value) return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index ba83f7aa..3377ab6a 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -174,6 +174,7 @@ class MediumLevelILInstruction(object): self.operation = MediumLevelILOperation(instr.operation) self.size = instr.size self.address = instr.address + self.source_operand = instr.sourceOperand operands = MediumLevelILInstruction.ILOperations[instr.operation] self.operands = [] i = 0 -- cgit v1.3.1 From e47e2fb13369ff7d1c9e7728bb793ee56640afe1 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 1 Aug 2017 23:39:18 -0400 Subject: Refactor IL instruction access APIs --- binaryninjaapi.h | 495 ++++- binaryninjacore.h | 42 +- examples/llil_parser/CMakeLists.txt | 1 - examples/llil_parser/Makefile | 51 + examples/llil_parser/Makefile.win | 9 + examples/llil_parser/README.md | 63 - examples/llil_parser/inc/LowLevel_IL_Parser.h | 171 -- examples/llil_parser/src/LowLevel_IL_Parser.cpp | 442 ---- examples/llil_parser/src/llil_parser.cpp | 409 ++++ examples/mlil_parser/CMakeLists.txt | 50 + examples/mlil_parser/Makefile | 51 + examples/mlil_parser/Makefile.win | 9 + examples/mlil_parser/src/mlil_parser.cpp | 356 ++++ lowlevelil.cpp | 563 ++--- lowlevelilinstruction.cpp | 2305 +++++++++++++++++++++ lowlevelilinstruction.h | 906 ++++++++ mediumlevelil.cpp | 221 +- mediumlevelilinstruction.cpp | 2526 +++++++++++++++++++++++ mediumlevelilinstruction.h | 982 +++++++++ python/mediumlevelil.py | 12 +- 20 files changed, 8473 insertions(+), 1191 deletions(-) create mode 100644 examples/llil_parser/Makefile create mode 100644 examples/llil_parser/Makefile.win delete mode 100644 examples/llil_parser/README.md delete mode 100644 examples/llil_parser/inc/LowLevel_IL_Parser.h delete mode 100644 examples/llil_parser/src/LowLevel_IL_Parser.cpp create mode 100644 examples/llil_parser/src/llil_parser.cpp create mode 100644 examples/mlil_parser/CMakeLists.txt create mode 100644 examples/mlil_parser/Makefile create mode 100644 examples/mlil_parser/Makefile.win create mode 100644 examples/mlil_parser/src/mlil_parser.cpp create mode 100644 lowlevelilinstruction.cpp create mode 100644 lowlevelilinstruction.h create mode 100644 mediumlevelilinstruction.cpp create mode 100644 mediumlevelilinstruction.h (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index be909b01..9a61a9cb 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2311,6 +2312,35 @@ namespace BinaryNinja LowLevelILLabel(); }; + struct ILSourceLocation + { + uint64_t address; + uint32_t sourceOperand; + bool valid; + + ILSourceLocation(): valid(false) + { + } + + ILSourceLocation(uint64_t addr, uint32_t operand): address(addr), sourceOperand(operand), valid(true) + { + } + + ILSourceLocation(const BNLowLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + + ILSourceLocation(const BNMediumLevelILInstruction& instr): + address(instr.address), sourceOperand(instr.sourceOperand), valid(true) + { + } + }; + + struct LowLevelILInstruction; + struct SSARegister; + struct SSAFlag; + class LowLevelILFunction: public CoreRefCountObject { @@ -2318,6 +2348,13 @@ namespace BinaryNinja LowLevelILFunction(Architecture* arch, Function* func = nullptr); LowLevelILFunction(BNLowLevelILFunction* func); + Ref GetFunction() const; + Ref GetArchitecture() const; + + void PrepareToCopyFunction(LowLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNLowLevelILLabel* GetLabelForSourceInstruction(size_t i); + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); @@ -2326,83 +2363,166 @@ namespace BinaryNinja void SetIndirectBranches(const std::vector& branches); ExprId AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); + ExprId AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); ExprId AddInstruction(ExprId expr); - ExprId Nop(); - ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0); - ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val); - ExprId SetFlag(uint32_t flag, ExprId val); - ExprId Load(size_t size, ExprId addr); - ExprId Store(size_t size, ExprId addr, ExprId val); - ExprId Push(size_t size, ExprId val); - ExprId Pop(size_t size); - ExprId Register(size_t size, uint32_t reg); - ExprId Const(size_t size, uint64_t val); - ExprId ConstPointer(size_t size, uint64_t val); - ExprId Flag(uint32_t reg); - ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex); - ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0); - ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0); - ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0); - ExprId Neg(size_t size, ExprId a, uint32_t flags = 0); - ExprId Not(size_t size, ExprId a, uint32_t flags = 0); - ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0); - ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0); - ExprId Jump(ExprId dest); - ExprId Call(ExprId dest); - ExprId Return(size_t dest); - ExprId NoReturn(); - ExprId FlagCondition(BNLowLevelILFlagCondition cond); - ExprId CompareEqual(size_t size, ExprId a, ExprId b); - ExprId CompareNotEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b); - ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b); - ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b); - ExprId TestBit(size_t size, ExprId a, ExprId b); - ExprId BoolToInt(size_t size, ExprId a); - ExprId SystemCall(); - ExprId Breakpoint(); - ExprId Trap(uint32_t num); - ExprId Undefined(); - ExprId Unimplemented(); - ExprId UnimplementedMemoryRef(size_t size, ExprId addr); - - ExprId Goto(BNLowLevelILLabel& label); - ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f); + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, ExprId val, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId addr, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId addr, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Push(size_t size, ExprId val, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Pop(size_t size, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Register(size_t size, uint32_t reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSA(size_t size, const SSARegister& reg, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Flag(uint32_t flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Add(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Sub(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCallSSA(const std::vector& output, const std::vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SystemCall(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterPhi(const SSARegister& dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagPhi(const SSAFlag& dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNLowLevelILLabel& label); std::vector GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); + ExprId AddIndexList(const std::vector operands); + ExprId AddSSARegisterList(const std::vector& regs); + ExprId AddSSAFlagList(const std::vector& flags); ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); @@ -2412,11 +2532,18 @@ namespace BinaryNinja ExprId Operand(uint32_t n, ExprId expr); - BNLowLevelILInstruction operator[](size_t i) const; + BNLowLevelILInstruction GetRawExpr(size_t i) const; + LowLevelILInstruction operator[](size_t i); + LowLevelILInstruction GetInstruction(size_t i); + LowLevelILInstruction GetExpr(size_t i); size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionForExpr(size_t expr) const; size_t GetInstructionCount() const; size_t GetExprCount() const; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void ReplaceExpr(size_t expr, size_t newExpr); + void AddLabelForAddress(Architecture* arch, ExprId addr); BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr); @@ -2438,18 +2565,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSARegisterDefinition(uint32_t reg, size_t version) const; - size_t GetSSAFlagDefinition(uint32_t flag, size_t version) const; + size_t GetSSARegisterDefinition(const SSARegister& reg) const; + size_t GetSSAFlagDefinition(const SSAFlag& flag) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set GetSSARegisterUses(uint32_t reg, size_t version) const; - std::set GetSSAFlagUses(uint32_t flag, size_t version) const; + std::set GetSSARegisterUses(const SSARegister& reg) const; + std::set GetSSAFlagUses(const SSAFlag& flag) const; std::set GetSSAMemoryUses(size_t version) const; - RegisterValue GetSSARegisterValue(uint32_t reg, size_t version); - RegisterValue GetSSAFlagValue(uint32_t flag, size_t version); + RegisterValue GetSSARegisterValue(const SSARegister& reg); + RegisterValue GetSSAFlagValue(const SSAFlag& flag); RegisterValue GetExprValue(size_t expr); + RegisterValue GetExprValue(const LowLevelILInstruction& expr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const LowLevelILInstruction& expr); RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); @@ -2477,6 +2606,9 @@ namespace BinaryNinja MediumLevelILLabel(); }; + struct MediumLevelILInstruction; + struct SSAVariable; + class MediumLevelILFunction: public CoreRefCountObject { @@ -2484,34 +2616,218 @@ namespace BinaryNinja MediumLevelILFunction(Architecture* arch, Function* func = nullptr); MediumLevelILFunction(BNMediumLevelILFunction* func); + Ref GetFunction() const; + Ref GetArchitecture() const; + uint64_t GetCurrentAddress() const; void SetCurrentAddress(Architecture* arch, uint64_t addr); size_t GetInstructionStart(Architecture* arch, uint64_t addr); + void PrepareToCopyFunction(MediumLevelILFunction* func); + void PrepareToCopyBlock(BasicBlock* block); + BNMediumLevelILLabel* GetLabelForSourceInstruction(size_t i); + 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); + ExprId AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, + size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddExprWithLocation(BNMediumLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + + ExprId Nop(const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSAField(size_t size, const Variable& dest, size_t newVersion, size_t prevVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliased(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SetVarAliasedField(size_t size, const Variable& dest, size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Load(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Store(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreSSA(size_t size, ExprId dest, size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarAliasedField(size_t size, const Variable& src, size_t memVersion, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddressOfField(const Variable& var, uint64_t offset, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Mult(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SignExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); + ExprId JumpTo(ExprId dest, const std::vector& targets, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Call(const std::vector& output, ExprId dest, const std::vector& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntyped(const std::vector& output, ExprId dest, const std::vector& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Syscall(const std::vector& output, const std::vector& params, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntyped(const std::vector& output, const std::vector& params, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CallUntypedSSA(const std::vector& output, ExprId dest, + const std::vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallSSA(const std::vector& output, const std::vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc = ILSourceLocation()); + ExprId SyscallUntypedSSA(const std::vector& output, + const std::vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Return(const std::vector& sources, const ILSourceLocation& loc = ILSourceLocation()); + ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Trap(int64_t vector, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); + ExprId UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId VarPhi(const SSAVariable& dest, const std::vector& sources, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId MemoryPhi(size_t destMemVersion, const std::vector& sourceMemVersions, + const ILSourceLocation& loc = ILSourceLocation()); + + ExprId Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc = ILSourceLocation()); void MarkLabel(BNMediumLevelILLabel& label); + ExprId AddInstruction(ExprId expr); + std::vector GetOperandList(ExprId i, size_t listOperand); ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); - - BNMediumLevelILInstruction operator[](size_t i) const; + ExprId AddIndexList(const std::vector& operands); + ExprId AddVariableList(const std::vector& vars); + ExprId AddSSAVariableList(const std::vector& vars); + + BNMediumLevelILInstruction GetRawExpr(size_t i) const; + MediumLevelILInstruction operator[](size_t i); + MediumLevelILInstruction GetInstruction(size_t i); + MediumLevelILInstruction GetExpr(size_t i); size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionForExpr(size_t expr) const; size_t GetInstructionCount() const; size_t GetExprCount() const; + void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value); + void MarkInstructionForRemoval(size_t i); + void ReplaceInstruction(size_t i, ExprId expr); + void ReplaceExpr(size_t expr, size_t newExpr); + void Finalize(); + void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true, + const std::set& knownAliases = std::set()); bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); bool GetInstructionText(Function* func, Architecture* arch, size_t i, std::vector& tokens); + void VisitInstructions(const std::function& func); + void VisitAllExprs(const std::function& func); + std::vector> GetBasicBlocks() const; Ref GetSSAForm() const; @@ -2521,18 +2837,20 @@ namespace BinaryNinja size_t GetSSAExprIndex(size_t instr) const; size_t GetNonSSAExprIndex(size_t instr) const; - size_t GetSSAVarDefinition(const Variable& var, size_t version) const; + size_t GetSSAVarDefinition(const SSAVariable& var) const; size_t GetSSAMemoryDefinition(size_t version) const; - std::set GetSSAVarUses(const Variable& var, size_t version) const; + std::set GetSSAVarUses(const SSAVariable& var) const; std::set GetSSAMemoryUses(size_t version) const; std::set GetVariableDefinitions(const Variable& var) const; std::set GetVariableUses(const Variable& var) const; - RegisterValue GetSSAVarValue(const Variable& var, size_t version); + RegisterValue GetSSAVarValue(const SSAVariable& var); RegisterValue GetExprValue(size_t expr); - PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr); + RegisterValue GetExprValue(const MediumLevelILInstruction& expr); + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var, size_t instr); PossibleValueSet GetPossibleExprValues(size_t expr); + PossibleValueSet GetPossibleExprValues(const MediumLevelILInstruction& expr); size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const; size_t GetSSAMemoryVersionAtInstruction(size_t instr) const; @@ -2554,13 +2872,14 @@ namespace BinaryNinja PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; - std::map GetAllBranchDependenceAtInstruction(size_t instr) const; + std::unordered_map GetAllBranchDependenceAtInstruction(size_t instr) const; Ref GetLowLevelIL() const; size_t GetLowLevelILInstructionIndex(size_t instr) const; size_t GetLowLevelILExprIndex(size_t expr) const; Confidence> GetExprType(size_t expr); + Confidence> GetExprType(const MediumLevelILInstruction& expr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index e2eb0700..22980067 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2297,6 +2297,7 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNCreateLowLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetLowLevelILOwnerFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2304,17 +2305,27 @@ extern "C" BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, - size_t count); + size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddExpr(BNLowLevelILFunction* func, BNLowLevelILOperation operation, size_t size, - uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); + BINARYNINJACOREAPI size_t BNLowLevelILAddExprWithLocation(BNLowLevelILFunction* func, uint64_t addr, uint32_t sourceOperand, + BNLowLevelILOperation operation, size_t size, uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); BINARYNINJACOREAPI void BNLowLevelILSetExprSourceOperand(BNLowLevelILFunction* func, size_t expr, uint32_t operand); BINARYNINJACOREAPI size_t BNLowLevelILAddInstruction(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNLowLevelILGoto(BNLowLevelILFunction* func, BNLowLevelILLabel* label); + BINARYNINJACOREAPI size_t BNLowLevelILGotoWithLocation(BNLowLevelILFunction* func, BNLowLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNLowLevelILIf(BNLowLevelILFunction* func, uint64_t op, BNLowLevelILLabel* t, BNLowLevelILLabel* f); + BINARYNINJACOREAPI size_t BNLowLevelILIfWithLocation(BNLowLevelILFunction* func, uint64_t op, + BNLowLevelILLabel* t, BNLowLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNLowLevelILInitLabel(BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNLowLevelILMarkLabel(BNLowLevelILFunction* func, BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILFunction(BNLowLevelILFunction* func, BNLowLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILBasicBlock(BNLowLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLabelForLowLevelILSourceInstruction(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNLowLevelILAddLabelList(BNLowLevelILFunction* func, BNLowLevelILLabel** labels, size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddOperandList(BNLowLevelILFunction* func, uint64_t* operands, size_t count); BINARYNINJACOREAPI uint64_t* BNLowLevelILGetOperandList(BNLowLevelILFunction* func, size_t expr, size_t operand, @@ -2323,9 +2334,14 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionForExpr(BNLowLevelILFunction* func, size_t expr); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateLowLevelILOperand(BNLowLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNReplaceLowLevelILExpr(BNLowLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2402,6 +2418,7 @@ extern "C" BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNFunction* BNGetMediumLevelILOwnerFunction(BNMediumLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, BNArchitecture* arch, uint64_t addr); @@ -2409,13 +2426,28 @@ extern "C" 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 BNMediumLevelILAddExprWithLocation(BNMediumLevelILFunction* func, + BNMediumLevelILOperation operation, uint64_t addr, uint32_t sourceOperand, 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 BNMediumLevelILGotoWithLocation(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label, + uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI size_t BNMediumLevelILIfWithLocation(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f, uint64_t addr, uint32_t sourceOperand); BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func, + bool analyzeConditionals, bool handleAliases, BNVariable* knownAliases, size_t knownAliasCount); + + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func, + BNMediumLevelILFunction* src); + BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILBasicBlock(BNMediumLevelILFunction* func, BNBasicBlock* block); + BINARYNINJACOREAPI BNMediumLevelILLabel* BNGetLabelForMediumLevelILSourceInstruction(BNMediumLevelILFunction* func, + size_t instr); BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, BNMediumLevelILLabel** labels, size_t count); @@ -2431,6 +2463,12 @@ extern "C" BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNUpdateMediumLevelILOperand(BNMediumLevelILFunction* func, size_t instr, + size_t operandIndex, uint64_t value); + BINARYNINJACOREAPI void BNMarkMediumLevelILInstructionForRemoval(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILInstruction(BNMediumLevelILFunction* func, size_t instr, size_t expr); + BINARYNINJACOREAPI void BNReplaceMediumLevelILExpr(BNMediumLevelILFunction* func, size_t expr, size_t newExpr); + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt index 5a0676e0..6d782109 100644 --- a/examples/llil_parser/CMakeLists.txt +++ b/examples/llil_parser/CMakeLists.txt @@ -5,7 +5,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) project(LLIL_Parser) #----------------------------------------------------------------------------- -include_directories("inc/") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) #----------------------------------------------------------------------------- file( GLOB_RECURSE SRCS *.cpp *.h) diff --git a/examples/llil_parser/Makefile b/examples/llil_parser/Makefile new file mode 100644 index 00000000..13c01e62 --- /dev/null +++ b/examples/llil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := llil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/llil_parser/Makefile.win b/examples/llil_parser/Makefile.win new file mode 100644 index 00000000..fb714c0b --- /dev/null +++ b/examples/llil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/llil_parser.cpp + if not exist bin mkdir bin + cl ./src/llil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/llil_parser/README.md b/examples/llil_parser/README.md deleted file mode 100644 index 07532c79..00000000 --- a/examples/llil_parser/README.md +++ /dev/null @@ -1,63 +0,0 @@ -LLIL Parser - Binary Ninja C++ API Sample -=== - -> Robert Yates | 22nd June 2017 - -LLIL Parser is a simple example for demonstrating how to use the BinaryNinja C++ API - -![ScreenShot](https://user-images.githubusercontent.com/1876966/27665067-58d34dd0-5c6b-11e7-9361-6efd01cfa0af.JPG) - -Example of building under windows from scratch -=== - -* https://cmake.org/ Required for this example -* We will be using Visual Studio 2017 however if want to use a different version simply run the `cmake -G` command to find the alternative name to use in the cmake commands below, be sure to use the Win64 version. - -Note: if you havent installed binary ninja into a default location then you will need to edit the cmake file and also the `std::string get_plugins_directory()` function in the `.cpp` file - -# Building the BinaryNinja API -``` -git clone https://github.com/Vector35/binaryninja-api.git -cd binaryninja -mkdir _build -cd _build -cmake .. -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -``` - -The objective here is to build the `binaryninjaapi.lib` This will be placed in the `bin` folder - -# Building the C++ Example - -``` -cd ../examples -mkdir _build -cd _build -cmake ../llil_parser -G "Visual Studio 15 2017 Win64" -cmake --build . --config Release -cd Release -copy "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.dll" . -``` - -If you get an error about `BINJA_API_LIBRARY` check the API has built properly and `binaryninjaapi.lib` is located in the `bin` folder in the root folder of the API - -If you get an error about `BINJA_CORE_LIBRARY` then the file C:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib is missing see [Create .lib file from .dll](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) on details about how to create this lib file from the dll file located in that directory - -> Building under the linux is almost exactly the same however you need not use the `-G` parameter and you build with the `make` command instead of `cmake --build` another important note is that i had to execute `cp ~/binaryninja/libbinaryninjacore.so.1 ~/binaryninja/libbinaryninjacore.so` before linking would work - -Note i do not have access to a MAC so i havent tested this. - -Using the example -=== - -Simply run the compiled executable with a target binary as a parameter and it will parse the LLIL from the first detected function in the target binary. - -The `void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn)` function is probably the most -function of interest for learning. - -This example is only intended for learning from the source code however if you wish to turn it into something more useful then you could add callbacks in the analysis function to keep track of when certain regs, values occur etc. - -# Disclaimer - -This was mostly figured out by myself and may not be the best way to achieve the intended desire, however i hope it serves as a starting point - diff --git a/examples/llil_parser/inc/LowLevel_IL_Parser.h b/examples/llil_parser/inc/LowLevel_IL_Parser.h deleted file mode 100644 index 7b3b6baa..00000000 --- a/examples/llil_parser/inc/LowLevel_IL_Parser.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef __LOWLEVEL_IL_PARSER_H_ -#define __LOWLEVEL_IL_PARSER_H_ - -#include "binaryninjacore.h" -#include "binaryninjaapi.h" -#include - -std::string get_plugins_directory(); -void ShowBanner(); - -using namespace BinaryNinja; - -enum OperandPurpose -{ - kDest, - kSrc, - kConstant, - kLeft, - kRight, - kHi, - kLow, - kTargets, - kCondition, - kVector, - kOutput, - kStack, - kParam, - kDestMemory, - kSrcMemory, - kTrue, - kFalse, - kBit, - kCarry, - kFullReg, -}; - -enum OperandType -{ - kReg, - kExpr, - kFlag, - kIntList, - kInt, - kRegSsa, - kRegSsaList, - kFlagSsa, - kCond, - kFlagSsaList, -}; - -struct BNLowLevelILOperationSyntax -{ - OperandPurpose purpose; - OperandType type; -}; - - -static std::map> g_llilSyntaxMap = { \ -{ LLIL_NOP,{} }, \ -{ LLIL_SET_REG,{ { kDest, kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT,{ { kHi, kReg },{ kLow,kReg },{ kSrc,kExpr } } } , \ -{ LLIL_SET_FLAG,{ { kDest, kFlag },{ kSrc,kExpr } } }, \ -{ LLIL_LOAD,{ { kSrc, kExpr } } }, \ -{ LLIL_STORE,{ { kDest, kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_PUSH,{ { kSrc, kExpr } } }, \ -{ LLIL_POP,{} }, \ -{ LLIL_REG,{ { kSrc, kReg } } }, \ -{ LLIL_CONST,{ { kConstant, kInt } } }, \ -{ LLIL_CONST_PTR,{ { kConstant, kInt } } }, \ -{ LLIL_FLAG,{ { kSrc, kFlag } } }, \ -{ LLIL_FLAG_BIT,{ { kSrc, kFlag },{ kBit,kInt } } }, \ -{ LLIL_ADD,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ADC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_SUB,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SBB,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_AND,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_OR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_XOR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_LSR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ASR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_ROL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RLC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_ROR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_RRC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ -{ LLIL_MUL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULU_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MULS_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_DIVS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_MODS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ -{ LLIL_NEG,{ { kSrc, kExpr } } }, \ -{ LLIL_NOT,{ { kSrc, kExpr } } }, \ -{ LLIL_SX,{ { kSrc, kExpr } } }, \ -{ LLIL_ZX,{ { kSrc, kExpr } } }, \ -{ LLIL_LOW_PART,{ { kSrc, kExpr } } }, \ -{ LLIL_JUMP,{ { kDest, kExpr } } }, \ -{ LLIL_JUMP_TO,{ { kDest, kExpr },{ kTargets,kIntList } } }, \ -{ LLIL_CALL,{ { kDest, kExpr } } }, \ -{ LLIL_RET,{ { kDest, kExpr } } }, \ -{ LLIL_NORET,{} }, \ -{ LLIL_IF,{ { kCondition, kExpr },{ kTrue,kInt },{ kFalse,kInt } } }, \ -{ LLIL_GOTO,{ { kDest, kInt } } }, \ -{ LLIL_FLAG_COND,{ { kCondition, kCond } } }, \ -{ LLIL_CMP_E,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_NE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SLE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_ULE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_SGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_CMP_UGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_TEST_BIT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_BOOL_TO_INT,{ { kSrc, kExpr } } }, \ -{ LLIL_ADD_OVERFLOW,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ -{ LLIL_SYSCALL,{} }, \ -{ LLIL_BP,{} }, \ -{ LLIL_TRAP,{ { kVector, kInt } } }, \ -{ LLIL_UNDEF,{} }, \ -{ LLIL_UNIMPL,{} }, \ -{ LLIL_UNIMPL_MEM,{ { kSrc, kExpr } } }, \ -{ LLIL_SET_REG_SSA,{ { kDest, kRegSsa },{ kSrc,kExpr } } }, \ -{ LLIL_IF,{ { kFullReg, kRegSsa },{ kDest,kReg },{ kSrc,kExpr } } }, \ -{ LLIL_SET_REG_SPLIT_SSA,{ { kHi, kExpr },{ kLow,kExpr },{ kSrc,kExpr } } }, \ -{ LLIL_REG_SPLIT_DEST_SSA,{ { kDest, kRegSsa } } }, \ -{ LLIL_REG_SSA,{ { kSrc, kRegSsa } } }, \ -{ LLIL_REG_SSA_PARTIAL,{ { kFullReg, kRegSsa },{ kSrc,kReg } } }, \ -{ LLIL_SET_FLAG_SSA,{ { kDest, kFlagSsa },{ kSrc,kExpr } } }, \ -{ LLIL_FLAG_SSA,{ { kSrc, kFlagSsa } } }, \ -{ LLIL_FLAG_BIT_SSA,{ { kSrc, kFlagSsa },{ kBit, kInt } } }, \ -{ LLIL_CALL_SSA,{ { kOutput, kExpr },{ kDest,kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_SYSCALL_SSA,{ { kOutput, kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ -{ LLIL_CALL_OUTPUT_SSA,{ { kDestMemory, kInt },{ kDest, kRegSsaList } } }, \ -{ LLIL_CALL_STACK_SSA,{ { kSrc, kRegSsa },{ kSrcMemory, kInt } } }, \ -{ LLIL_CALL_PARAM_SSA,{ { kSrc, kRegSsaList } } }, \ -{ LLIL_LOAD_SSA,{ { kSrc, kExpr },{ kSrcMemory, kInt } } }, \ -{ LLIL_STORE_SSA,{ { kDest, kExpr },{ kDestMemory,kInt },{ kSrcMemory,kInt },{ kSrc,kExpr } } }, \ -{ LLIL_REG_PHI,{ { kDest, kRegSsa },{ kSrc, kRegSsaList } } }, \ -{ LLIL_FLAG_PHI,{ { kDest, kFlagSsa },{ kSrc, kFlagSsaList } } }, \ -{ LLIL_MEM_PHI,{ { kDestMemory, kInt },{ kSrcMemory, kIntList } } }, \ -}; - - -class LlilParser -{ - -public: - LlilParser(BinaryView *bv); - const std::string getLowLevelILOperationName(const BNLowLevelILOperation id) const; - void decodeIndexInFunction(uint64_t functionAddress, int indexIl); - void decodeWholeFunction(uint64_t functionAddress); - void decodeWholeFunction(BinaryNinja::Function *function); -private: - void showIndent() const; - void analysisInstruction(const BNLowLevelILInstruction& insn); - - BinaryView *m_bv; - std::vector> m_currentFunction; - int m_tabs; - size_t m_currentInstructionId; -}; - - -#endif /* __LOWLEVEL_IL_PARSER_H_ */ \ No newline at end of file diff --git a/examples/llil_parser/src/LowLevel_IL_Parser.cpp b/examples/llil_parser/src/LowLevel_IL_Parser.cpp deleted file mode 100644 index 2f61b83a..00000000 --- a/examples/llil_parser/src/LowLevel_IL_Parser.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -LLIL Parser - Binary Ninja C++ API Sample - - Robert Yates - 22/JUN/17 - */ - -#include "LowLevel_IL_Parser.h" -#include -#include - -int main(int argc, char* argv[]) -{ - - try - { - ShowBanner(); - - - if (argc != 2) - { - printf("Usage: %s \n", argv[0]); - exit(-1); - } - - std::string inputName = argv[1]; - - SetBundledPluginDirectory(get_plugins_directory()); - InitCorePlugins(); - InitUserPlugins(); - - auto bd = BinaryData(new FileMetadata(), inputName.c_str()); - BinaryView *bv; - - for (auto type : BinaryViewType::GetViewTypes()) - { - if (type->IsTypeValidForData(&bd) && type->GetName() != "Raw") - { - bv = type->Create(&bd); - break; - } - } - - printf("[i] Starting analysis\n"); - bv->UpdateAnalysisAndWait(); - - printf("[i] Analysis done - %zd Functions\n", bv->GetAnalysisFunctionList().size()); - - if (bv->GetAnalysisFunctionList().size() < 1) - throw std::runtime_error("Error no functions found\n"); - - LlilParser myParser(bv); - myParser.decodeWholeFunction(bv->GetAnalysisFunctionList()[0]); - - /* - // Show Single LLIL in function x at index x - myParser.decodeIndexInFunction(0x407930, 0); - - // Decode a whole function by address - myParser.decodeWholeFunction(0x407930); - - // Decode all functions - for (const auto& f : bv->GetAnalysisFunctionList()) - { - // Decode a whole function by BinaryNinja::Function object - myParser.decodeWholeFunction(f); - } - */ - - } - catch (const std::exception& e) - { - printf("An Exception Occured: %s\n", e.what()); - } - - printf("[i] Finished\n"); -} - - - -LlilParser::LlilParser(BinaryView *bv) - : m_bv(bv) -{ - m_currentFunction.clear(); - m_tabs = 0; - m_currentInstructionId = 0; -} - -void LlilParser::showIndent() const -{ - for (int i = 0; i < m_tabs; i++) - printf(" "); -} - -void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn) -{ - - auto instructionSynatx = g_llilSyntaxMap.find(insn.operation); - BinaryNinja::Ref llil = m_currentFunction[0]->GetLowLevelIL(); - if (instructionSynatx == g_llilSyntaxMap.end()) - throw std::runtime_error("Error unknown LLIL\n"); - - showIndent(); - printf("Instruction: %s\n", getLowLevelILOperationName(insn.operation).c_str()); - m_tabs += 3; - - int operandId = 0; - for (const auto& operand : instructionSynatx->second) - { - if (operand.type == OperandType::kExpr) - { - // In this case the value in the operands[x] field is a new instruction & expression index value - BNLowLevelILInstruction nextInstruction = (*llil)[insn.operands[operandId]]; - - analysisInstruction(nextInstruction); // recursion begins :) - } - else if (operand.type == OperandType::kReg) - { - // In this case the register id is in the first operands field and we use Arch to translate - showIndent(); - printf("Reg: %s\n", m_bv->GetDefaultArchitecture()->GetRegisterName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kInt) - { - // In this case the operand is simply a value - showIndent(); - printf("Value: %zX\n", insn.operands[0]); - m_tabs += 3; - } - else if (operand.type == OperandType::kFlag) - { - // In this case the operand is a flag - printf("Flag: %s\n", m_bv->GetDefaultArchitecture()->GetFlagName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kIntList) - { - // In this case we have an array of llil targets - std::vector intList = llil->GetOperandList(llil->GetIndexForInstruction(m_currentInstructionId), operandId); - showIndent(); - printf("Target LLIL Indices: "); - for (const auto i : intList) - { - printf("%zd ", i); - } - printf("\n"); - } - else - { - printf("[e] LLIL Parser: Not Handled -> OperandPurpose: %d OperandType: %d\n", operand.purpose, operand.type); - } - - - operandId++; - } - - -} - -void LlilParser::decodeIndexInFunction(uint64_t functionAddress, int indexIl) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - m_currentInstructionId = indexIl; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(indexIl)]; - - - analysisInstruction(currentInstruction); - m_tabs = 0; - -} - -void LlilParser::decodeWholeFunction(BinaryNinja::Function *function) -{ - m_currentFunction.clear(); - m_currentFunction.push_back(function); - - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void LlilParser::decodeWholeFunction(uint64_t functionAddress) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address or possible invalid BundledPluginDirectory\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void ShowBanner() -{ - - printf (".____ .____ .___.____ __________ \n"); - printf ("| | | | | | | \\______ \\_____ _______ ______ ___________ \n"); - printf ("| | | | | | | | ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\\n"); - printf ("| |___| |___| | |___ | | / __ \\| | \\/\\___ \\\\ ___/| | \\/\n"); - printf ("|_______ \\_______ \\___|_______ \\ |____| (____ /__| /____ >\\___ >__| \n"); - printf (" \\/ \\/ \\/ \\/ \\/ \\/ \n"); - printf("====================================================================================\n\n"); - -} - -#ifdef _WIN32 -std::string get_plugins_directory() -{ - return "C:\\Program Files\\Vector35\\BinaryNinja\\plugins\\"; -} -#elif __APPLE__ -std::string get_plugins_directory() -{ - return "/Applications/Binary Ninja.app/Contents/MacOS/plugins/"; -} -#else -std::string get_plugins_directory() -{ - return "~/binaryninja/plugins"; -} -#endif - -const std::string LlilParser::getLowLevelILOperationName(BNLowLevelILOperation id) const -{ - - switch (id) - { - case LLIL_NOP: - return "LLIL_NOP"; - case LLIL_SET_REG: - return "LLIL_SET_REG"; - case LLIL_SET_REG_SPLIT: - return "LLIL_SET_REG_SPLIT"; - case LLIL_SET_FLAG: - return "LLIL_SET_FLAG"; - case LLIL_LOAD: - return "LLIL_LOAD"; - case LLIL_STORE: - return "LLIL_STORE"; - case LLIL_PUSH: - return "LLIL_PUSH"; - case LLIL_POP: - return "LLIL_POP"; - case LLIL_REG: - return "LLIL_REG"; - case LLIL_CONST: - return "LLIL_CONST"; - case LLIL_CONST_PTR: - return "LLIL_CONST_PTR"; - case LLIL_FLAG: - return "LLIL_FLAG"; - case LLIL_FLAG_BIT: - return "LLIL_FLAG_BIT"; - case LLIL_ADD: - return "LLIL_ADD"; - case LLIL_ADC: - return "LLIL_ADC"; - case LLIL_SUB: - return "LLIL_SUB"; - case LLIL_SBB: - return "LLIL_SBB"; - case LLIL_AND: - return "LLIL_AND"; - case LLIL_OR: - return "LLIL_OR"; - case LLIL_XOR: - return "LLIL_XOR"; - case LLIL_LSL: - return "LLIL_LSL"; - case LLIL_LSR: - return "LLIL_LSR"; - case LLIL_ASR: - return "LLIL_ASR"; - case LLIL_ROL: - return "LLIL_ROL"; - case LLIL_RLC: - return "LLIL_RLC"; - case LLIL_ROR: - return "LLIL_ROR"; - case LLIL_RRC: - return "LLIL_RRC"; - case LLIL_MUL: - return "LLIL_MUL"; - case LLIL_MULU_DP: - return "LLIL_MULU_DP"; - case LLIL_MULS_DP: - return "LLIL_MULS_DP"; - case LLIL_DIVU: - return "LLIL_DIVU"; - case LLIL_DIVU_DP: - return "LLIL_DIVU_DP"; - case LLIL_DIVS: - return "LLIL_DIVS"; - case LLIL_DIVS_DP: - return "LLIL_DIVS_DP"; - case LLIL_MODU: - return "LLIL_MODU"; - case LLIL_MODU_DP: - return "LLIL_MODU_DP"; - case LLIL_MODS: - return "LLIL_MODS"; - case LLIL_MODS_DP: - return "LLIL_MODS_DP"; - case LLIL_NEG: - return "LLIL_NEG"; - case LLIL_NOT: - return "LLIL_NOT"; - case LLIL_SX: - return "LLIL_SX"; - case LLIL_ZX: - return "LLIL_ZX"; - case LLIL_LOW_PART: - return "LLIL_LOW_PART"; - case LLIL_JUMP: - return "LLIL_JUMP"; - case LLIL_JUMP_TO: - return "LLIL_JUMP_TO"; - case LLIL_CALL: - return "LLIL_CALL"; - case LLIL_RET: - return "LLIL_RET"; - case LLIL_NORET: - return "LLIL_NORET"; - case LLIL_IF: - return "LLIL_IF"; - case LLIL_GOTO: - return "LLIL_GOTO"; - case LLIL_FLAG_COND: - return "LLIL_FLAG_COND"; - case LLIL_CMP_E: - return "LLIL_CMP_E"; - case LLIL_CMP_NE: - return "LLIL_CMP_NE"; - case LLIL_CMP_SLT: - return "LLIL_CMP_SLT"; - case LLIL_CMP_ULT: - return "LLIL_CMP_ULT"; - case LLIL_CMP_SLE: - return "LLIL_CMP_SLE"; - case LLIL_CMP_ULE: - return "LLIL_CMP_ULE"; - case LLIL_CMP_SGE: - return "LLIL_CMP_SGE"; - case LLIL_CMP_UGE: - return "LLIL_CMP_UGE"; - case LLIL_CMP_SGT: - return "LLIL_CMP_SGT"; - case LLIL_CMP_UGT: - return "LLIL_CMP_UGT"; - case LLIL_TEST_BIT: - return "LLIL_TEST_BIT"; - case LLIL_BOOL_TO_INT: - return "LLIL_BOOL_TO_INT"; - case LLIL_ADD_OVERFLOW: - return "LLIL_ADD_OVERFLOW"; - case LLIL_SYSCALL: - return "LLIL_SYSCALL"; - case LLIL_BP: - return "LLIL_BP"; - case LLIL_TRAP: - return "LLIL_TRAP"; - case LLIL_UNDEF: - return "LLIL_UNDEF"; - case LLIL_UNIMPL: - return "LLIL_UNIMPL"; - case LLIL_UNIMPL_MEM: - return "LLIL_UNIMPL_MEM"; - case LLIL_SET_REG_SSA: - return "LLIL_SET_REG_SSA"; - case LLIL_SET_REG_SSA_PARTIAL: - return "LLIL_SET_REG_SSA_PARTIAL"; - case LLIL_SET_REG_SPLIT_SSA: - return "LLIL_SET_REG_SPLIT_SSA"; - case LLIL_REG_SPLIT_DEST_SSA: - return "LLIL_REG_SPLIT_DEST_SSA"; - case LLIL_REG_SSA: - return "LLIL_REG_SSA"; - case LLIL_REG_SSA_PARTIAL: - return "LLIL_REG_SSA_PARTIAL"; - case LLIL_SET_FLAG_SSA: - return "LLIL_SET_FLAG_SSA"; - case LLIL_FLAG_SSA: - return "LLIL_FLAG_SSA"; - case LLIL_FLAG_BIT_SSA: - return "LLIL_FLAG_BIT_SSA"; - case LLIL_CALL_SSA: - return "LLIL_CALL_SSA"; - case LLIL_SYSCALL_SSA: - return "LLIL_SYSCALL_SSA"; - case LLIL_CALL_PARAM_SSA: - return "LLIL_CALL_PARAM_SSA"; - case LLIL_CALL_STACK_SSA: - return "LLIL_CALL_STACK_SSA"; - case LLIL_CALL_OUTPUT_SSA: - return "LLIL_CALL_OUTPUT_SSA"; - case LLIL_LOAD_SSA: - return "LLIL_LOAD_SSA"; - case LLIL_STORE_SSA: - return "LLIL_STORE_SSA"; - case LLIL_REG_PHI: - return "LLIL_REG_PHI"; - case LLIL_FLAG_PHI: - return "LLIL_FLAG_PHI"; - case LLIL_MEM_PHI: - return "LLIL_MEM_PHI"; - } - - return "Unknown"; - //throw std::runtime_error("GetLowLevelILOperationName Failure"); - -} \ No newline at end of file diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp new file mode 100644 index 00000000..72ac71bd --- /dev/null +++ b/examples/llil_parser/src/llil_parser.cpp @@ -0,0 +1,409 @@ +#include +#include +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include +#include +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNLowLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(LLIL_NOP) + ENUM_PRINTER(LLIL_SET_REG) + ENUM_PRINTER(LLIL_SET_REG_SPLIT) + ENUM_PRINTER(LLIL_SET_FLAG) + ENUM_PRINTER(LLIL_LOAD) + ENUM_PRINTER(LLIL_STORE) + ENUM_PRINTER(LLIL_PUSH) + ENUM_PRINTER(LLIL_POP) + ENUM_PRINTER(LLIL_REG) + ENUM_PRINTER(LLIL_CONST) + ENUM_PRINTER(LLIL_CONST_PTR) + ENUM_PRINTER(LLIL_FLAG) + ENUM_PRINTER(LLIL_FLAG_BIT) + ENUM_PRINTER(LLIL_ADD) + ENUM_PRINTER(LLIL_ADC) + ENUM_PRINTER(LLIL_SUB) + ENUM_PRINTER(LLIL_SBB) + ENUM_PRINTER(LLIL_AND) + ENUM_PRINTER(LLIL_OR) + ENUM_PRINTER(LLIL_XOR) + ENUM_PRINTER(LLIL_LSL) + ENUM_PRINTER(LLIL_LSR) + ENUM_PRINTER(LLIL_ASR) + ENUM_PRINTER(LLIL_ROL) + ENUM_PRINTER(LLIL_RLC) + ENUM_PRINTER(LLIL_ROR) + ENUM_PRINTER(LLIL_RRC) + ENUM_PRINTER(LLIL_MUL) + ENUM_PRINTER(LLIL_MULU_DP) + ENUM_PRINTER(LLIL_MULS_DP) + ENUM_PRINTER(LLIL_DIVU) + ENUM_PRINTER(LLIL_DIVU_DP) + ENUM_PRINTER(LLIL_DIVS) + ENUM_PRINTER(LLIL_DIVS_DP) + ENUM_PRINTER(LLIL_MODU) + ENUM_PRINTER(LLIL_MODU_DP) + ENUM_PRINTER(LLIL_MODS) + ENUM_PRINTER(LLIL_MODS_DP) + ENUM_PRINTER(LLIL_NEG) + ENUM_PRINTER(LLIL_NOT) + ENUM_PRINTER(LLIL_SX) + ENUM_PRINTER(LLIL_ZX) + ENUM_PRINTER(LLIL_LOW_PART) + ENUM_PRINTER(LLIL_JUMP) + ENUM_PRINTER(LLIL_JUMP_TO) + ENUM_PRINTER(LLIL_CALL) + ENUM_PRINTER(LLIL_RET) + ENUM_PRINTER(LLIL_NORET) + ENUM_PRINTER(LLIL_IF) + ENUM_PRINTER(LLIL_GOTO) + ENUM_PRINTER(LLIL_FLAG_COND) + ENUM_PRINTER(LLIL_CMP_E) + ENUM_PRINTER(LLIL_CMP_NE) + ENUM_PRINTER(LLIL_CMP_SLT) + ENUM_PRINTER(LLIL_CMP_ULT) + ENUM_PRINTER(LLIL_CMP_SLE) + ENUM_PRINTER(LLIL_CMP_ULE) + ENUM_PRINTER(LLIL_CMP_SGE) + ENUM_PRINTER(LLIL_CMP_UGE) + ENUM_PRINTER(LLIL_CMP_SGT) + ENUM_PRINTER(LLIL_CMP_UGT) + ENUM_PRINTER(LLIL_TEST_BIT) + ENUM_PRINTER(LLIL_BOOL_TO_INT) + ENUM_PRINTER(LLIL_ADD_OVERFLOW) + ENUM_PRINTER(LLIL_SYSCALL) + ENUM_PRINTER(LLIL_BP) + ENUM_PRINTER(LLIL_TRAP) + ENUM_PRINTER(LLIL_UNDEF) + ENUM_PRINTER(LLIL_UNIMPL) + ENUM_PRINTER(LLIL_UNIMPL_MEM) + ENUM_PRINTER(LLIL_SET_REG_SSA) + ENUM_PRINTER(LLIL_SET_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_REG_SPLIT_SSA) + ENUM_PRINTER(LLIL_REG_SPLIT_DEST_SSA) + ENUM_PRINTER(LLIL_REG_SSA) + ENUM_PRINTER(LLIL_REG_SSA_PARTIAL) + ENUM_PRINTER(LLIL_SET_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_SSA) + ENUM_PRINTER(LLIL_FLAG_BIT_SSA) + ENUM_PRINTER(LLIL_CALL_SSA) + ENUM_PRINTER(LLIL_SYSCALL_SSA) + ENUM_PRINTER(LLIL_CALL_PARAM_SSA) + ENUM_PRINTER(LLIL_CALL_STACK_SSA) + ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(LLIL_LOAD_SSA) + ENUM_PRINTER(LLIL_STORE_SSA) + ENUM_PRINTER(LLIL_REG_PHI) + ENUM_PRINTER(LLIL_FLAG_PHI) + ENUM_PRINTER(LLIL_MEM_PHI) + default: + printf("", operation); + break; + } +} + + +static void PrintFlagCondition(BNLowLevelILFlagCondition cond) +{ + switch (cond) + { + ENUM_PRINTER(LLFC_E) + ENUM_PRINTER(LLFC_NE) + ENUM_PRINTER(LLFC_SLT) + ENUM_PRINTER(LLFC_ULT) + ENUM_PRINTER(LLFC_SLE) + ENUM_PRINTER(LLFC_ULE) + ENUM_PRINTER(LLFC_SGE) + ENUM_PRINTER(LLFC_UGE) + ENUM_PRINTER(LLFC_SGT) + ENUM_PRINTER(LLFC_UGT) + ENUM_PRINTER(LLFC_NEG) + ENUM_PRINTER(LLFC_POS) + ENUM_PRINTER(LLFC_O) + ENUM_PRINTER(LLFC_NO) + default: + printf(""); + break; + } +} + + +static void PrintRegister(LowLevelILFunction* func, uint32_t reg) +{ + if (LLIL_REG_IS_TEMP(reg)) + printf("temp%d", LLIL_GET_TEMP_REG_INDEX(reg)); + else + { + string name = func->GetArchitecture()->GetRegisterName(reg); + if (name.size() == 0) + printf(""); + else + printf("%s", name.c_str()); + } +} + + +static void PrintFlag(LowLevelILFunction* func, uint32_t flag) +{ + if (LLIL_REG_IS_TEMP(flag)) + printf("cond:%d", LLIL_GET_TEMP_REG_INDEX(flag)); + else + { + string name = func->GetArchitecture()->GetFlagName(flag); + if (name.size() == 0) + printf(""); + else + printf("%s", name.c_str()); + } +} + + +static void PrintILExpr(const LowLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerLowLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexLowLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprLowLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case RegisterLowLevelOperand: + PrintIndent(indent); + printf("reg "); + PrintRegister(instr.function, operand.GetRegister()); + printf("\n"); + break; + + case FlagLowLevelOperand: + PrintIndent(indent); + printf("flag "); + PrintFlag(instr.function, operand.GetFlag()); + printf("\n"); + break; + + case FlagConditionLowLevelOperand: + PrintIndent(indent); + printf("flag condition "); + PrintFlagCondition(operand.GetFlagCondition()); + printf("\n"); + break; + + case SSARegisterLowLevelOperand: + PrintIndent(indent); + printf("ssa reg "); + PrintRegister(instr.function, operand.GetSSARegister().reg); + printf("#%" PRIdPTR "\n", operand.GetSSARegister().version); + break; + + case SSAFlagLowLevelOperand: + PrintIndent(indent); + printf("ssa flag "); + PrintFlag(instr.function, operand.GetSSAFlag().flag); + printf("#%" PRIdPTR "\n", operand.GetSSAFlag().version); + break; + + case IndexListLowLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case SSARegisterListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSARegisterList()) + { + PrintRegister(instr.function, i.reg); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case SSAFlagListLowLevelOperand: + PrintIndent(indent); + printf("ssa reg list "); + for (auto& i : operand.GetSSAFlagList()) + { + PrintFlag(instr.function, i.flag); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + default: + PrintIndent(indent); + printf("\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref bd = new BinaryData(new FileMetadata(), argv[1]); + Ref bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the low level IL for the function + Ref il = func->GetLowLevelIL(); + if (!il) + { + printf(" Does not have LLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + LowLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_CONST: + case LLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const LowLevelILInstruction& expr) { + switch (expr.operation) + { + case LLIL_LOAD: + if (expr.GetSourceExpr().operation == LLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr().GetConstant()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/examples/mlil_parser/CMakeLists.txt b/examples/mlil_parser/CMakeLists.txt new file mode 100644 index 00000000..1bf6e3a7 --- /dev/null +++ b/examples/mlil_parser/CMakeLists.txt @@ -0,0 +1,50 @@ +# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +project(MLIL_Parser) + +#----------------------------------------------------------------------------- +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..) +#----------------------------------------------------------------------------- +file( GLOB_RECURSE SRCS *.cpp *.h) +#----------------------------------------------------------------------------- +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +#----------------------------------------------------------------------------- +if(WIN32) + set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +elseif(APPLE) + set(BINJA_DIR "/Applications/Binary Ninja.app" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +else() + set(BINJA_DIR "$ENV{HOME}/binaryninja" + CACHE PATH "Binary Ninja installation directory") + set(BINJA_BIN_DIR "${BINJA_DIR}") + set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins" + CACHE PATH "Binary Ninja user plugins directory") +endif() +#----------------------------------------------------------------------------- +add_executable (${PROJECT_NAME} ${SRCS} ) +#----------------------------------------------------------------------------- +find_library(BINJA_API_LIBRARY binaryninjaapi + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug) +find_library(BINJA_CORE_LIBRARY binaryninjacore + HINTS ${BINJA_BIN_DIR}) +#----------------------------------------------------------------------------- +target_link_libraries(${PROJECT_NAME} + ${BINJA_API_LIBRARY} + ${BINJA_CORE_LIBRARY} + ) +#----------------------------------------------------------------------------- +install (TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION Lib + ARCHIVE DESTINATION Lib) + diff --git a/examples/mlil_parser/Makefile b/examples/mlil_parser/Makefile new file mode 100644 index 00000000..44b7b77f --- /dev/null +++ b/examples/mlil_parser/Makefile @@ -0,0 +1,51 @@ +# Path to prebuilt libbinaryninjaapi.a +BINJA_API_A := ../../bin/libbinaryninjaapi.a + +# Path to binaryninjaapi.h and json +INC := -I../../ + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + # Path to binaryninja install + BINJAPATH := $(HOME)/binaryninja/ + CC := g++ +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang++ +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := mlil_parser +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/mlil_parser/Makefile.win b/examples/mlil_parser/Makefile.win new file mode 100644 index 00000000..92718ac0 --- /dev/null +++ b/examples/mlil_parser/Makefile.win @@ -0,0 +1,9 @@ +BINJA_API_INC_PATH = ..\..\ +BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib +BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib" + +FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB) + +bininfo: ./src/mlil_parser.cpp + if not exist bin mkdir bin + cl ./src/mlil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp new file mode 100644 index 00000000..8fb762eb --- /dev/null +++ b/examples/mlil_parser/src/mlil_parser.cpp @@ -0,0 +1,356 @@ +#include +#include +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include +#include +static string GetPluginsDirectory() +{ + Dl_info info; + if (!dladdr((void *)BNGetBundledPluginDirectory, &info)) + return NULL; + + stringstream ss; + ss << dirname((char *)info.dli_fname) << "/plugins/"; + return ss.str(); +} +#else +static string GetPluginsDirectory() +{ + return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\"; +} +#endif + + +static void PrintIndent(size_t indent) +{ + for (size_t i = 0; i < indent; i++) + printf(" "); +} + + +static void PrintOperation(BNMediumLevelILOperation operation) +{ +#define ENUM_PRINTER(op) \ + case op: \ + printf(#op); \ + break; + + switch (operation) + { + ENUM_PRINTER(MLIL_NOP) + ENUM_PRINTER(MLIL_SET_VAR) + ENUM_PRINTER(MLIL_SET_VAR_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT) + ENUM_PRINTER(MLIL_LOAD) + ENUM_PRINTER(MLIL_LOAD_STRUCT) + ENUM_PRINTER(MLIL_STORE) + ENUM_PRINTER(MLIL_STORE_STRUCT) + ENUM_PRINTER(MLIL_VAR) + ENUM_PRINTER(MLIL_VAR_FIELD) + ENUM_PRINTER(MLIL_ADDRESS_OF) + ENUM_PRINTER(MLIL_ADDRESS_OF_FIELD) + ENUM_PRINTER(MLIL_CONST) + ENUM_PRINTER(MLIL_CONST_PTR) + ENUM_PRINTER(MLIL_ADD) + ENUM_PRINTER(MLIL_ADC) + ENUM_PRINTER(MLIL_SUB) + ENUM_PRINTER(MLIL_SBB) + ENUM_PRINTER(MLIL_AND) + ENUM_PRINTER(MLIL_OR) + ENUM_PRINTER(MLIL_XOR) + ENUM_PRINTER(MLIL_LSL) + ENUM_PRINTER(MLIL_LSR) + ENUM_PRINTER(MLIL_ASR) + ENUM_PRINTER(MLIL_ROL) + ENUM_PRINTER(MLIL_RLC) + ENUM_PRINTER(MLIL_ROR) + ENUM_PRINTER(MLIL_RRC) + ENUM_PRINTER(MLIL_MUL) + ENUM_PRINTER(MLIL_MULU_DP) + ENUM_PRINTER(MLIL_MULS_DP) + ENUM_PRINTER(MLIL_DIVU) + ENUM_PRINTER(MLIL_DIVU_DP) + ENUM_PRINTER(MLIL_DIVS) + ENUM_PRINTER(MLIL_DIVS_DP) + ENUM_PRINTER(MLIL_MODU) + ENUM_PRINTER(MLIL_MODU_DP) + ENUM_PRINTER(MLIL_MODS) + ENUM_PRINTER(MLIL_MODS_DP) + ENUM_PRINTER(MLIL_NEG) + ENUM_PRINTER(MLIL_NOT) + ENUM_PRINTER(MLIL_SX) + ENUM_PRINTER(MLIL_ZX) + ENUM_PRINTER(MLIL_LOW_PART) + ENUM_PRINTER(MLIL_JUMP) + ENUM_PRINTER(MLIL_JUMP_TO) + ENUM_PRINTER(MLIL_CALL) + ENUM_PRINTER(MLIL_CALL_UNTYPED) + ENUM_PRINTER(MLIL_CALL_OUTPUT) + ENUM_PRINTER(MLIL_CALL_PARAM) + ENUM_PRINTER(MLIL_RET) + ENUM_PRINTER(MLIL_NORET) + ENUM_PRINTER(MLIL_IF) + ENUM_PRINTER(MLIL_GOTO) + ENUM_PRINTER(MLIL_CMP_E) + ENUM_PRINTER(MLIL_CMP_NE) + ENUM_PRINTER(MLIL_CMP_SLT) + ENUM_PRINTER(MLIL_CMP_ULT) + ENUM_PRINTER(MLIL_CMP_SLE) + ENUM_PRINTER(MLIL_CMP_ULE) + ENUM_PRINTER(MLIL_CMP_SGE) + ENUM_PRINTER(MLIL_CMP_UGE) + ENUM_PRINTER(MLIL_CMP_SGT) + ENUM_PRINTER(MLIL_CMP_UGT) + ENUM_PRINTER(MLIL_TEST_BIT) + ENUM_PRINTER(MLIL_BOOL_TO_INT) + ENUM_PRINTER(MLIL_ADD_OVERFLOW) + ENUM_PRINTER(MLIL_SYSCALL) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED) + ENUM_PRINTER(MLIL_BP) + ENUM_PRINTER(MLIL_TRAP) + ENUM_PRINTER(MLIL_UNDEF) + ENUM_PRINTER(MLIL_UNIMPL) + ENUM_PRINTER(MLIL_UNIMPL_MEM) + ENUM_PRINTER(MLIL_SET_VAR_SSA) + ENUM_PRINTER(MLIL_SET_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_SET_VAR_SPLIT_SSA) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED) + ENUM_PRINTER(MLIL_SET_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_VAR_SSA) + ENUM_PRINTER(MLIL_VAR_SSA_FIELD) + ENUM_PRINTER(MLIL_VAR_ALIASED) + ENUM_PRINTER(MLIL_VAR_ALIASED_FIELD) + ENUM_PRINTER(MLIL_CALL_SSA) + ENUM_PRINTER(MLIL_CALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_SYSCALL_SSA) + ENUM_PRINTER(MLIL_SYSCALL_UNTYPED_SSA) + ENUM_PRINTER(MLIL_CALL_PARAM_SSA) + ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA) + ENUM_PRINTER(MLIL_LOAD_SSA) + ENUM_PRINTER(MLIL_LOAD_STRUCT_SSA) + ENUM_PRINTER(MLIL_STORE_SSA) + ENUM_PRINTER(MLIL_STORE_STRUCT_SSA) + ENUM_PRINTER(MLIL_VAR_PHI) + ENUM_PRINTER(MLIL_MEM_PHI) + default: + printf("", operation); + break; + } +} + + +static void PrintVariable(MediumLevelILFunction* func, const Variable& var) +{ + string name = func->GetFunction()->GetVariableName(var); + if (name.size() == 0) + printf(""); + else + printf("%s", name.c_str()); +} + + +static void PrintILExpr(const MediumLevelILInstruction& instr, size_t indent) +{ + PrintIndent(indent); + PrintOperation(instr.operation); + printf("\n"); + + indent++; + + for (auto& operand : instr.GetOperands()) + { + switch (operand.GetType()) + { + case IntegerMediumLevelOperand: + PrintIndent(indent); + printf("int 0x%" PRIx64 "\n", operand.GetInteger()); + break; + + case IndexMediumLevelOperand: + PrintIndent(indent); + printf("index %" PRIdPTR "\n", operand.GetIndex()); + break; + + case ExprMediumLevelOperand: + PrintILExpr(operand.GetExpr(), indent); + break; + + case VariableMediumLevelOperand: + PrintIndent(indent); + printf("var "); + PrintVariable(instr.function, operand.GetVariable()); + printf("\n"); + break; + + case SSAVariableMediumLevelOperand: + PrintIndent(indent); + printf("ssa var "); + PrintVariable(instr.function, operand.GetSSAVariable().var); + printf("#%" PRIdPTR "\n", operand.GetSSAVariable().version); + break; + + case IndexListMediumLevelOperand: + PrintIndent(indent); + printf("index list "); + for (auto i : operand.GetIndexList()) + printf("%" PRIdPTR " ", i); + printf("\n"); + break; + + case VariableListMediumLevelOperand: + PrintIndent(indent); + printf("var list "); + for (auto& i : operand.GetVariableList()) + { + PrintVariable(instr.function, i); + printf(" "); + } + printf("\n"); + break; + + case SSAVariableListMediumLevelOperand: + PrintIndent(indent); + printf("ssa var list "); + for (auto& i : operand.GetSSAVariableList()) + { + PrintVariable(instr.function, i.var); + printf("#%" PRIdPTR " ", i.version); + } + printf("\n"); + break; + + case ExprListMediumLevelOperand: + PrintIndent(indent); + printf("expr list\n"); + for (auto& i : operand.GetExprList()) + PrintILExpr(i, indent + 1); + break; + + default: + PrintIndent(indent); + printf("\n"); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Expected input filename\n"); + return 1; + } + + // In order to initiate the bundled plugins properly, the location + // of where bundled plugins directory is must be set. Since + // libbinaryninjacore is in the path get the path to it and use it to + // determine the plugins directory + SetBundledPluginDirectory(GetPluginsDirectory()); + InitCorePlugins(); + InitUserPlugins(); + + Ref bd = new BinaryData(new FileMetadata(), argv[1]); + Ref bv; + for (auto type : BinaryViewType::GetViewTypes()) + { + if (type->IsTypeValidForData(bd) && type->GetName() != "Raw") + { + bv = type->Create(bd); + break; + } + } + + if (!bv || bv->GetTypeName() == "Raw") + { + fprintf(stderr, "Input file does not appear to be an exectuable\n"); + return -1; + } + + bv->UpdateAnalysisAndWait(); + + // Go through all functions in the binary + for (auto& func : bv->GetAnalysisFunctionList()) + { + // Get the name of the function and display it + Ref sym = func->GetSymbol(); + if (sym) + printf("Function %s:\n", sym->GetFullName().c_str()); + else + printf("Function at 0x%" PRIx64 ":\n", func->GetStart()); + + // Fetch the medium level IL for the function + Ref il = func->GetMediumLevelIL(); + if (!il) + { + printf(" Does not have MLIL\n\n"); + continue; + } + + // Loop through all blocks in the function + for (auto& block : il->GetBasicBlocks()) + { + // Loop though each instruction in the block + for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++) + { + // Fetch IL instruction + MediumLevelILInstruction instr = (*il)[instrIndex]; + + // Display core's intrepretation of the IL instruction + vector tokens; + il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens); + printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address); + for (auto& token: tokens) + printf("%s", token.text.c_str()); + printf("\n"); + + // Generically parse the IL tree and display the parts + PrintILExpr(instr, 2); + + // Example of using visitors to find all constants in the instruction + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_CONST: + case MLIL_CONST_PTR: + printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant()); + return false; // Done parsing this + default: + break; + } + return true; // Parse any subexpressions + }); + + // Example of using the templated accessors for efficiently parsing load instructions + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + switch (expr.operation) + { + case MLIL_LOAD: + if (expr.GetSourceExpr().operation == MLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr().GetConstant()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 0cb733ac..690f0b41 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,460 +43,124 @@ LowLevelILFunction::LowLevelILFunction(BNLowLevelILFunction* func) } -uint64_t LowLevelILFunction::GetCurrentAddress() const -{ - return BNLowLevelILGetCurrentAddress(m_object); -} - - -void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t 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); -} - - -void LowLevelILFunction::ClearIndirectBranches() -{ - BNLowLevelILClearIndirectBranches(m_object); -} - - -void LowLevelILFunction::SetIndirectBranches(const vector& branches) -{ - BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; - for (size_t i = 0; i < branches.size(); i++) - { - branchList[i].arch = branches[i].arch->GetObject(); - branchList[i].address = branches[i].address; - } - BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); - delete[] branchList; -} - - -ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, - ExprId a, ExprId b, ExprId c, ExprId d) -{ - return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); -} - - -ExprId LowLevelILFunction::AddInstruction(size_t expr) -{ - return BNLowLevelILAddInstruction(m_object, expr); -} - - -ExprId LowLevelILFunction::Nop() -{ - return AddExpr(LLIL_NOP, 0, 0); -} - - -ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags) -{ - return AddExpr(LLIL_SET_REG, size, flags, reg, val); -} - - -ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val) -{ - return AddExpr(LLIL_SET_REG_SPLIT, size, 0, high, low, val); -} - - -ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val) -{ - return AddExpr(LLIL_SET_FLAG, 0, 0, flag, val); -} - - -ExprId LowLevelILFunction::Load(size_t size, ExprId addr) -{ - return AddExpr(LLIL_LOAD, size, 0, addr); -} - - -ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val) -{ - return AddExpr(LLIL_STORE, size, 0, addr, val); -} - - -ExprId LowLevelILFunction::Push(size_t size, ExprId val) -{ - return AddExpr(LLIL_PUSH, size, 0, val); -} - - -ExprId LowLevelILFunction::Pop(size_t size) -{ - return AddExpr(LLIL_POP, size, 0); -} - - -ExprId LowLevelILFunction::Register(size_t size, uint32_t reg) -{ - return AddExpr(LLIL_REG, size, 0, reg); -} - - -ExprId LowLevelILFunction::Const(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST, size, 0, val); -} - - -ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val) -{ - return AddExpr(LLIL_CONST_PTR, size, 0, val); -} - - -ExprId LowLevelILFunction::Flag(uint32_t reg) -{ - return AddExpr(LLIL_FLAG, 0, 0, reg); -} - - -ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex) -{ - return AddExpr(LLIL_FLAG_BIT, size, 0, flag, bitIndex); -} - - -ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ADD, size, flags, a, b); -} - - -ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_ADC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_SUB, size, flags, a, b); -} - - -ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_SBB, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_AND, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_OR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_XOR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags) +Ref LowLevelILFunction::GetFunction() const { - return AddExpr(LLIL_LSL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_LSR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ASR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RLC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_ROR, size, flags, a, b); -} - - -ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags) -{ - return AddExpr(LLIL_RRC, size, flags, a, b, carry); -} - - -ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MUL, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MULU_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MULS_DP, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_DIVS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_DIVS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODU, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODU_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags) -{ - return AddExpr(LLIL_MODS, size, flags, a, b); -} - - -ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags) -{ - return AddExpr(LLIL_MODS_DP, size, flags, high, low, div); -} - - -ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NEG, size, flags, a); -} - - -ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_NOT, size, flags, a); -} - - -ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_SX, size, flags, a); -} - - -ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_ZX, size, flags, a); -} - - -ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags) -{ - return AddExpr(LLIL_LOW_PART, size, flags, a); -} - - -ExprId LowLevelILFunction::Jump(ExprId dest) -{ - return AddExpr(LLIL_JUMP, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Call(ExprId dest) -{ - return AddExpr(LLIL_CALL, 0, 0, dest); -} - - -ExprId LowLevelILFunction::Return(size_t dest) -{ - return AddExpr(LLIL_RET, 0, 0, dest); -} - - -ExprId LowLevelILFunction::NoReturn() -{ - return AddExpr(LLIL_NORET, 0, 0); -} - - -ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond) -{ - return AddExpr(LLIL_FLAG_COND, 0, 0, (ExprId)cond); -} - - -ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_E, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_NE, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_ULT, size, 0, a, b); -} - - -ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b) -{ - return AddExpr(LLIL_CMP_SLE, size, 0, a, b); + BNFunction* func = BNGetLowLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); } -ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b) +Ref LowLevelILFunction::GetArchitecture() const { - return AddExpr(LLIL_CMP_ULE, size, 0, a, b); + Ref func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); } -ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyFunction(LowLevelILFunction* func) { - return AddExpr(LLIL_CMP_SGE, size, 0, a, b); + BNPrepareToCopyLowLevelILFunction(m_object, func->GetObject()); } -ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::PrepareToCopyBlock(BasicBlock* block) { - return AddExpr(LLIL_CMP_UGE, size, 0, a, b); + BNPrepareToCopyLowLevelILBasicBlock(m_object, block->GetObject()); } -ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b) +BNLowLevelILLabel* LowLevelILFunction::GetLabelForSourceInstruction(size_t i) { - return AddExpr(LLIL_CMP_SGT, size, 0, a, b); + return BNGetLabelForLowLevelILSourceInstruction(m_object, i); } -ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b) +uint64_t LowLevelILFunction::GetCurrentAddress() const { - return AddExpr(LLIL_CMP_UGT, size, 0, a, b); + return BNLowLevelILGetCurrentAddress(m_object); } -ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b) +void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_TEST_BIT, size, 0, a, b); + BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a) +size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) { - return AddExpr(LLIL_BOOL_TO_INT, size, 0, a); + return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); } -ExprId LowLevelILFunction::SystemCall() +void LowLevelILFunction::ClearIndirectBranches() { - return AddExpr(LLIL_SYSCALL, 0, 0); + BNLowLevelILClearIndirectBranches(m_object); } -ExprId LowLevelILFunction::Breakpoint() +void LowLevelILFunction::SetIndirectBranches(const vector& branches) { - return AddExpr(LLIL_BP, 0, 0); + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); + delete[] branchList; } -ExprId LowLevelILFunction::Trap(uint32_t num) +ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, + ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_TRAP, 0, 0, num); + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Undefined() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNDEF, 0, 0); + return BNLowLevelILAddExprWithLocation(m_object, addr, sourceOperand, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::Unimplemented() +ExprId LowLevelILFunction::AddExprWithLocation(BNLowLevelILOperation operation, const ILSourceLocation& loc, + size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { - return AddExpr(LLIL_UNIMPL, 0, 0); + if (loc.valid) + { + return BNLowLevelILAddExprWithLocation(m_object, loc.address, loc.sourceOperand, operation, + size, flags, a, b, c, d); + } + return BNLowLevelILAddExpr(m_object, operation, size, flags, a, b, c, d); } -ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr) +ExprId LowLevelILFunction::AddInstruction(size_t expr) { - return AddExpr(LLIL_UNIMPL_MEM, size, 0, addr); + return BNLowLevelILAddInstruction(m_object, expr); } -ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label) +ExprId LowLevelILFunction::Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNLowLevelILGoto(m_object, &label); } -ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f) +ExprId LowLevelILFunction::If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNLowLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNLowLevelILIf(m_object, operand, &t, &f); } @@ -540,6 +205,45 @@ ExprId LowLevelILFunction::AddOperandList(const vector operands) } +ExprId LowLevelILFunction::AddIndexList(const vector 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)BNLowLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSARegisterList(const vector& regs) +{ + uint64_t* operandList = new uint64_t[regs.size() * 2]; + for (size_t i = 0; i < regs.size(); i++) + { + operandList[i * 2] = regs[i].reg; + operandList[(i * 2) + 1] = regs[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size() * 2); + delete[] operandList; + return result; +} + + +ExprId LowLevelILFunction::AddSSAFlagList(const vector& flags) +{ + uint64_t* operandList = new uint64_t[flags.size() * 2]; + for (size_t i = 0; i < flags.size(); i++) + { + operandList[i * 2] = flags[i].flag; + operandList[(i * 2) + 1] = flags[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, flags.size() * 2); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) { if (operand.constant) @@ -599,18 +303,43 @@ ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) } -BNLowLevelILInstruction LowLevelILFunction::operator[](size_t i) const +BNLowLevelILInstruction LowLevelILFunction::GetRawExpr(size_t i) const { return BNGetLowLevelILByIndex(m_object, i); } +LowLevelILInstruction LowLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +LowLevelILInstruction LowLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return LowLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +LowLevelILInstruction LowLevelILFunction::GetExpr(size_t i) +{ + return LowLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t LowLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetLowLevelILIndexForInstruction(m_object, i); } +size_t LowLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetLowLevelILInstructionForExpr(m_object, expr); +} + + size_t LowLevelILFunction::GetInstructionCount() const { return BNGetLowLevelILInstructionCount(m_object); @@ -623,6 +352,18 @@ size_t LowLevelILFunction::GetExprCount() const } +void LowLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateLowLevelILOperand(m_object, i, operandIndex, value); +} + + +void LowLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceLowLevelILExpr(m_object, expr, newExpr); +} + + void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr) { BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr); @@ -765,15 +506,15 @@ size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t version) const +size_t LowLevelILFunction::GetSSARegisterDefinition(const SSARegister& reg) const { - return BNGetLowLevelILSSARegisterDefinition(m_object, reg, version); + return BNGetLowLevelILSSARegisterDefinition(m_object, reg.reg, reg.version); } -size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t version) const +size_t LowLevelILFunction::GetSSAFlagDefinition(const SSAFlag& flag) const { - return BNGetLowLevelILSSAFlagDefinition(m_object, flag, version); + return BNGetLowLevelILSSAFlagDefinition(m_object, flag.flag, flag.version); } @@ -783,10 +524,10 @@ size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) const +set LowLevelILFunction::GetSSARegisterUses(const SSARegister& reg) const { size_t count; - size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, version, &count); + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg.reg, reg.version, &count); set result; for (size_t i = 0; i < count; i++) @@ -797,10 +538,10 @@ set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t version) } -set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t version) const +set LowLevelILFunction::GetSSAFlagUses(const SSAFlag& flag) const { size_t count; - size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, version, &count); + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag.flag, flag.version, &count); set result; for (size_t i = 0; i < count; i++) @@ -825,16 +566,16 @@ set LowLevelILFunction::GetSSAMemoryUses(size_t version) const } -RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t version) +RegisterValue LowLevelILFunction::GetSSARegisterValue(const SSARegister& reg) { - BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, version); + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg.reg, reg.version); return RegisterValue::FromAPIObject(value); } -RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t version) +RegisterValue LowLevelILFunction::GetSSAFlagValue(const SSAFlag& flag) { - BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, version); + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag.flag, flag.version); return RegisterValue::FromAPIObject(value); } @@ -846,6 +587,12 @@ RegisterValue LowLevelILFunction::GetExprValue(size_t expr) } +RegisterValue LowLevelILFunction::GetExprValue(const LowLevelILInstruction& expr) +{ + return GetExprValue(expr.exprIndex); +} + + PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) { BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr); @@ -853,6 +600,12 @@ PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet LowLevelILFunction::GetPossibleExprValues(const LowLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) { BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp new file mode 100644 index 00000000..19bfd983 --- /dev/null +++ b/lowlevelilinstruction.cpp @@ -0,0 +1,2305 @@ +// Copyright (c) 2015-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. + +#ifdef BINARYNINJACORE_LIBRARY +#include "lowlevelilfunction.h" +#include "lowlevelilssafunction.h" +#include "mediumlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map + LowLevelILInstructionBase::operandTypeForUsage = { + {SourceExprLowLevelOperandUsage, ExprLowLevelOperand}, + {SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {SourceFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {DestExprLowLevelOperandUsage, ExprLowLevelOperand}, + {DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {DestFlagLowLevelOperandUsage, FlagLowLevelOperand}, + {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {LeftExprLowLevelOperandUsage, ExprLowLevelOperand}, + {RightExprLowLevelOperandUsage, ExprLowLevelOperand}, + {CarryExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighExprLowLevelOperandUsage, ExprLowLevelOperand}, + {LowExprLowLevelOperandUsage, ExprLowLevelOperand}, + {ConditionExprLowLevelOperandUsage, ExprLowLevelOperand}, + {HighRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, + {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, + {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, + {TargetLowLevelOperandUsage, IndexLowLevelOperand}, + {TrueTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {FalseTargetLowLevelOperandUsage, IndexLowLevelOperand}, + {BitIndexLowLevelOperandUsage, IndexLowLevelOperand}, + {SourceMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {DestMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand}, + {OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand}, + {ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, + {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, + {TargetListLowLevelOperandUsage, IndexListLowLevelOperand} + }; + + +unordered_map> + LowLevelILInstructionBase::operationOperandUsage = { + {LLIL_NOP, {}}, + {LLIL_POP, {}}, + {LLIL_NORET, {}}, + {LLIL_SYSCALL, {}}, + {LLIL_BP, {}}, + {LLIL_UNDEF, {}}, + {LLIL_UNIMPL, {}}, + {LLIL_SET_REG, {DestRegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA, {DestSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SSA_PARTIAL, {DestSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, + SourceExprLowLevelOperandUsage}}, + {LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOAD_SSA, {SourceExprLowLevelOperandUsage, SourceMemoryVersionLowLevelOperandUsage}}, + {LLIL_STORE, {DestExprLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_STORE_SSA, {DestExprLowLevelOperandUsage, DestMemoryVersionLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, SourceExprLowLevelOperandUsage}}, + {LLIL_REG, {SourceRegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA, {SourceSSARegisterLowLevelOperandUsage}}, + {LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}}, + {LLIL_FLAG, {SourceFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, + {LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, + {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, + {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, + {LLIL_CALL, {DestExprLowLevelOperandUsage}}, + {LLIL_RET, {DestExprLowLevelOperandUsage}}, + {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage}}, + {LLIL_GOTO, {TargetLowLevelOperandUsage}}, + {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage}}, + {LLIL_TRAP, {VectorLowLevelOperandUsage}}, + {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage}}, + {LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}}, + {LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, + {LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, + {LLIL_CONST, {ConstantLowLevelOperandUsage}}, + {LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}}, + {LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_OR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_XOR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_LSR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ASR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ROR, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MUL, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULU_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MULS_DP, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_E, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_NE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SLE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_ULE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGE, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_SGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_CMP_UGT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_TEST_BIT, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADD_OVERFLOW, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_ADC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_SBB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RLC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_RRC, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage, CarryExprLowLevelOperandUsage}}, + {LLIL_DIVU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_DIVS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODU_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_MODS_DP, {HighExprLowLevelOperandUsage, LowExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, + {LLIL_PUSH, {SourceExprLowLevelOperandUsage}}, + {LLIL_NEG, {SourceExprLowLevelOperandUsage}}, + {LLIL_NOT, {SourceExprLowLevelOperandUsage}}, + {LLIL_SX, {SourceExprLowLevelOperandUsage}}, + {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, + {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, + {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}} + }; + + +static unordered_map> + GetOperandIndexForOperandUsages() +{ + unordered_map> result; + for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case HighSSARegisterLowLevelOperandUsage: + case LowSSARegisterLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is an SSA register + operand++; + break; + case ParameterSSARegistersLowLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSARegistersLowLevelOperandUsage: + // OutputMemoryVersionLowLevelOperandUsage follows at same operand + break; + case StackSSARegisterLowLevelOperandUsage: + // StackMemoryVersionLowLevelOperandUsage follows at same operand + break; + default: + switch (LowLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSARegisterLowLevelOperand: + case SSAFlagLowLevelOperand: + case IndexListLowLevelOperand: + case SSARegisterListLowLevelOperand: + case SSAFlagListLowLevelOperand: + // SSA registers/flags and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map> + LowLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSARegister::SSARegister(): reg(BN_INVALID_REGISTER), version(0) +{ +} + + +SSARegister::SSARegister(const uint32_t r, size_t i): reg(r), version(i) +{ +} + + +SSARegister::SSARegister(const SSARegister& v): reg(v.reg), version(v.version) +{ +} + + +SSARegister& SSARegister::operator=(const SSARegister& v) +{ + reg = v.reg; + version = v.version; + return *this; +} + + +bool SSARegister::operator==(const SSARegister& v) const +{ + if (reg != v.reg) + return false; + return version == v.version; +} + + +bool SSARegister::operator!=(const SSARegister& v) const +{ + return !((*this) == v); +} + + +bool SSARegister::operator<(const SSARegister& v) const +{ + if (reg < v.reg) + return true; + if (v.reg < reg) + return false; + return version < v.version; +} + + +SSAFlag::SSAFlag(): flag(BN_INVALID_REGISTER), version(0) +{ +} + + +SSAFlag::SSAFlag(const uint32_t f, size_t i): flag(f), version(i) +{ +} + + +SSAFlag::SSAFlag(const SSAFlag& v): flag(v.flag), version(v.version) +{ +} + + +SSAFlag& SSAFlag::operator=(const SSAFlag& v) +{ + flag = v.flag; + version = v.version; + return *this; +} + + +bool SSAFlag::operator==(const SSAFlag& v) const +{ + if (flag != v.flag) + return false; + return version == v.version; +} + + +bool SSAFlag::operator!=(const SSAFlag& v) const +{ + return !((*this) == v); +} + + +bool SSAFlag::operator<(const SSAFlag& v) const +{ + if (flag < v.flag) + return true; + if (v.flag < flag) + return false; + return version < v.version; +} + + +bool LowLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool LowLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +LowLevelILIntegerList::ListIterator& LowLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 3) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[3]); +#else + instr = function->GetRawExpr((size_t)instr.operands[3]); +#endif + } + return *this; +} + + +uint64_t LowLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +LowLevelILIntegerList::LowLevelILIntegerList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::begin() const +{ + return m_start; +} + + +LowLevelILIntegerList::const_iterator LowLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t LowLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t LowLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIntegerList::operator vector() const +{ + vector result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t LowLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +LowLevelILIndexList::LowLevelILIndexList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILIndexList::const_iterator LowLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t LowLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILIndexList::operator vector() const +{ + vector result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const SSARegister LowLevelILSSARegisterList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t reg = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSARegister(reg, version); +} + + +LowLevelILSSARegisterList::LowLevelILSSARegisterList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSARegisterList::const_iterator LowLevelILSSARegisterList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSARegisterList::size() const +{ + return m_list.size() / 2; +} + + +const SSARegister LowLevelILSSARegisterList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSARegisterList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAFlag LowLevelILSSAFlagList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint32_t flag = (uint32_t)*cur; + ++cur; + size_t version = (size_t)*cur; + return SSAFlag(flag, version); +} + + +LowLevelILSSAFlagList::LowLevelILSSAFlagList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSAFlagList::const_iterator LowLevelILSSAFlagList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSAFlagList::size() const +{ + return m_list.size() / 2; +} + + +const SSAFlag LowLevelILSSAFlagList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSAFlagList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILOperand::LowLevelILOperand(const LowLevelILInstruction& instr, + LowLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = LowLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == LowLevelILInstructionBase::operandTypeForUsage.end()) + throw LowLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t LowLevelILOperand::GetInteger() const +{ + if (m_type != IntegerLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t LowLevelILOperand::GetIndex() const +{ + if (m_type != IndexLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + if (m_usage == StackMemoryVersionLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(2); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +LowLevelILInstruction LowLevelILOperand::GetExpr() const +{ + if (m_type != ExprLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetRegister() const +{ + if (m_type != RegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetFlag() const +{ + if (m_type != FlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +BNLowLevelILFlagCondition LowLevelILOperand::GetFlagCondition() const +{ + if (m_type != FlagConditionLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsFlagCondition(m_operandIndex); +} + + +SSARegister LowLevelILOperand::GetSSARegister() const +{ + if (m_type != SSARegisterLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) || + (m_usage == StackSSARegisterLowLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0); + return m_instr.GetRawOperandAsSSARegister(m_operandIndex); +} + + +SSAFlag LowLevelILOperand::GetSSAFlag() const +{ + if (m_type != SSAFlagLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlag(m_operandIndex); +} + + +LowLevelILIndexList LowLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const +{ + if (m_type != SSARegisterListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + if (m_usage == OutputSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1); + if (m_usage == ParameterSSARegistersLowLevelOperandUsage) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(0); + return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex); +} + + +LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const +{ + if (m_type != SSAFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSAFlagList(m_operandIndex); +} + + +const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*() +{ + LowLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(owner->m_instr, usage, i->second); +} + + +LowLevelILOperandList::LowLevelILOperandList(const LowLevelILInstruction& instr, + const vector& usageList, + const unordered_map& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +LowLevelILOperandList::const_iterator LowLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t LowLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const LowLevelILOperand LowLevelILOperandList::operator[](size_t i) const +{ + LowLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperand(m_instr, usage, indexMap->second); +} + + +LowLevelILOperandList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +LowLevelILInstruction::LowLevelILInstruction() +{ + operation = LLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + flags = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +LowLevelILInstruction::LowLevelILInstruction(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +LowLevelILInstruction::LowLevelILInstruction(const LowLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + flags = instr.flags; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + instructionIndex = instr.instructionIndex; +} + + +LowLevelILOperandList LowLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw LowLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw LowLevelILInstructionAccessException(); + return LowLevelILOperandList(*(const LowLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t LowLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t LowLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +uint32_t LowLevelILInstructionBase::GetRawOperandAsRegister(size_t operand) const +{ + return (uint32_t)operands[operand]; +} + + +BNLowLevelILFlagCondition LowLevelILInstructionBase::GetRawOperandAsFlagCondition(size_t operand) const +{ + return (BNLowLevelILFlagCondition)operands[operand]; +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return LowLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +SSARegister LowLevelILInstructionBase::GetRawOperandAsSSARegister(size_t operand) const +{ + return SSARegister((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +SSAFlag LowLevelILInstructionBase::GetRawOperandAsSSAFlag(size_t operand) const +{ + return SSAFlag((uint32_t)operands[operand], (size_t)operands[operand + 1]); +} + + +LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return LowLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const +{ + return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size_t operand) const +{ + return LowLevelILSSAFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterList(size_t operandIndex, const vector& regs) +{ + UpdateRawOperand(operandIndex, regs.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSARegisterList(regs)); +} + + +RegisterValue LowLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const LowLevelILInstruction*)this); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const LowLevelILInstruction*)this); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue LowLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet LowLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetSSAForm() const +{ + Ref ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return LowLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +LowLevelILInstruction LowLevelILInstructionBase::GetNonSSAForm() const +{ + Ref nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return LowLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILInstructionIndex() const +{ + return function->GetMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMediumLevelILExprIndex() const +{ + return function->GetMediumLevelILExprIndex(exprIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILInstructionIndex() const +{ + return function->GetMappedMediumLevelILInstructionIndex(instructionIndex); +} + + +size_t LowLevelILInstructionBase::GetMappedMediumLevelILExprIndex() const +{ + return function->GetMappedMediumLevelILExprIndex(exprIndex); +} + + +bool LowLevelILInstructionBase::HasMediumLevelIL() const +{ + Ref func = function->GetMediumLevelIL(); + if (!func) + return false; + return GetMediumLevelILExprIndex() < func->GetExprCount(); +} + + +bool LowLevelILInstructionBase::HasMappedMediumLevelIL() const +{ + Ref func = function->GetMappedMediumLevelIL(); + if (!func) + return false; + return GetMappedMediumLevelILExprIndex() < func->GetExprCount(); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMediumLevelIL() const +{ + Ref func = function->GetMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +MediumLevelILInstruction LowLevelILInstructionBase::GetMappedMediumLevelIL() const +{ + Ref func = function->GetMappedMediumLevelIL(); + if (!func) + throw MediumLevelILInstructionAccessException(); + size_t expr = GetMappedMediumLevelILExprIndex(); + if (expr >= func->GetExprCount()) + throw MediumLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void LowLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void LowLevelILInstruction::VisitExprs(const std::function& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case LLIL_SET_REG: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SSA_PARTIAL: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_REG_SPLIT_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_FLAG: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_SET_FLAG_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_LOAD: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_LOAD_SSA: + GetSourceExpr().VisitExprs(func); + break; + case LLIL_STORE: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case LLIL_STORE_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case LLIL_JUMP: + GetDestExpr().VisitExprs(func); + break; + case LLIL_JUMP_TO: + GetDestExpr().VisitExprs(func); + break; + case LLIL_IF: + GetConditionExpr().VisitExprs(func); + break; + case LLIL_CALL: + GetDestExpr().VisitExprs(func); + break; + case LLIL_CALL_SSA: + GetDestExpr().VisitExprs(func); + break; + case LLIL_RET: + GetDestExpr().VisitExprs(func); + break; + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const LowLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, + const std::function& subExprHandler) const +{ + vector labelList; + BNLowLevelILLabel* labelA; + BNLowLevelILLabel* labelB; + switch (operation) + { + case LLIL_NOP: + return dest->Nop(); + case LLIL_SET_REG: + return dest->SetRegister(size, GetDestRegister(), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_SET_REG_SPLIT: + return dest->SetRegisterSplit(size, GetHighRegister(), GetLowRegister(), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_SET_REG_SSA: + return dest->SetRegisterSSA(size, GetDestSSARegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_REG_SSA_PARTIAL: + return dest->SetRegisterSSAPartial(size, GetDestSSARegister(), + GetPartialRegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_REG_SPLIT_SSA: + return dest->SetRegisterSplitSSA(size, GetHighSSARegister(), + GetLowSSARegister(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_FLAG: + return dest->SetFlag(GetDestFlag(), subExprHandler(GetSourceExpr()), *this); + case LLIL_SET_FLAG_SSA: + return dest->SetFlagSSA(GetDestSSAFlag(), + subExprHandler(GetSourceExpr()), *this); + case LLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr()), + GetSourceMemoryVersion(), *this); + case LLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr()), + subExprHandler(GetSourceExpr()), flags, *this); + case LLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr()), + subExprHandler(GetSourceExpr()), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_REG: + return dest->Register(size, GetSourceRegister(), *this); + case LLIL_REG_SSA: + return dest->RegisterSSA(size, GetSourceSSARegister(), *this); + case LLIL_REG_SSA_PARTIAL: + return dest->RegisterSSAPartial(size, GetSourceSSARegister(), + GetPartialRegister(), *this); + case LLIL_FLAG: + return dest->Flag(GetSourceFlag(), *this); + case LLIL_FLAG_SSA: + return dest->FlagSSA(GetSourceSSAFlag(), *this); + case LLIL_FLAG_BIT: + return dest->FlagBit(size, GetSourceFlag(), GetBitIndex(), *this); + case LLIL_FLAG_BIT_SSA: + return dest->FlagBitSSA(size, GetSourceSSAFlag(), GetBitIndex(), *this); + case LLIL_JUMP: + return dest->Jump(subExprHandler(GetDestExpr()), *this); + case LLIL_CALL: + return dest->Call(subExprHandler(GetDestExpr()), *this); + case LLIL_RET: + return dest->Return(subExprHandler(GetDestExpr()), *this); + case LLIL_JUMP_TO: + for (auto target : GetTargetList()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr()), labelList, *this); + case LLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget()).address), *this); + } + return dest->Goto(*labelA, *this); + case LLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, *this); + case LLIL_FLAG_COND: + return dest->FlagCondition(GetFlagCondition(), *this); + case LLIL_TRAP: + return dest->Trap(GetVector(), *this); + case LLIL_CALL_SSA: + return dest->CallSSA(GetOutputSSARegisters(), subExprHandler(GetDestExpr()), + GetParameterSSARegisters(), GetStackSSARegister(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_SYSCALL_SSA: + return dest->SystemCallSSA(GetOutputSSARegisters(), + GetParameterSSARegisters(), GetStackSSARegister(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case LLIL_REG_PHI: + return dest->RegisterPhi(GetDestSSARegister(), GetSourceSSARegisters(), *this); + case LLIL_FLAG_PHI: + return dest->FlagPhi(GetDestSSAFlag(), GetSourceSSAFlags(), *this); + case LLIL_MEM_PHI: + return dest->MemoryPhi(GetDestMemoryVersion(), GetSourceMemoryVersions(), *this); + case LLIL_CONST: + return dest->Const(size, GetConstant(), *this); + case LLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant(), *this); + case LLIL_POP: + case LLIL_NORET: + case LLIL_SYSCALL: + case LLIL_BP: + case LLIL_UNDEF: + case LLIL_UNIMPL: + return dest->AddExprWithLocation(operation, *this, size, flags); + case LLIL_PUSH: + case LLIL_NEG: + case LLIL_NOT: + case LLIL_SX: + case LLIL_ZX: + case LLIL_LOW_PART: + case LLIL_BOOL_TO_INT: + case LLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsOneOperand().GetSourceExpr())); + case LLIL_ADD: + case LLIL_SUB: + case LLIL_AND: + case LLIL_OR: + case LLIL_XOR: + case LLIL_LSL: + case LLIL_LSR: + case LLIL_ASR: + case LLIL_ROL: + case LLIL_ROR: + case LLIL_MUL: + case LLIL_MULU_DP: + case LLIL_MULS_DP: + case LLIL_DIVU: + case LLIL_DIVS: + case LLIL_MODU: + case LLIL_MODS: + case LLIL_CMP_E: + case LLIL_CMP_NE: + case LLIL_CMP_SLT: + case LLIL_CMP_ULT: + case LLIL_CMP_SLE: + case LLIL_CMP_ULE: + case LLIL_CMP_SGE: + case LLIL_CMP_UGE: + case LLIL_CMP_SGT: + case LLIL_CMP_UGT: + case LLIL_TEST_BIT: + case LLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case LLIL_ADC: + case LLIL_SBB: + case LLIL_RLC: + case LLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case LLIL_DIVU_DP: + case LLIL_DIVS_DP: + case LLIL_MODU_DP: + case LLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, flags, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + default: + throw LowLevelILInstructionAccessException(); + } +} + + +bool LowLevelILInstruction::GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = LowLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == LowLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +LowLevelILInstruction LowLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSourceFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetSourceSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetSourceSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetDestFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetDestSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSAFlag LowLevelILInstruction::GetDestSSAFlag() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAFlagLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlag(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetPartialRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(PartialRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetStackSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILInstruction LowLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetHighRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetHighSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetLowRegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowRegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +SSARegister LowLevelILInstruction::GetLowSSARegister() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSARegisterLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +int64_t LowLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetBitIndex() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(BitIndexLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(StackMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(2); + throw LowLevelILInstructionAccessException(); +} + + +size_t LowLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputMemoryVersionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw LowLevelILInstructionAccessException(); +} + + +BNLowLevelILFlagCondition LowLevelILInstruction::GetFlagCondition() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FlagConditionLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsFlagCondition(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetOutputSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(1); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetParameterSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(0); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSARegistersLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAFlagsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAFlagList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexList LowLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +ExprId LowLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::SetRegister(size_t size, uint32_t reg, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG, loc, size, flags, reg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplit(size_t size, uint32_t high, uint32_t low, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT, loc, size, flags, high, low, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSA(size_t size, const SSARegister& reg, ExprId val, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA, loc, size, 0, reg.reg, reg.version, val); +} + + +ExprId LowLevelILFunction::SetRegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg, val); +} + + +ExprId LowLevelILFunction::SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, + ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_REG_SPLIT_SSA, loc, size, 0, + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, high.reg, high.version), + AddExprWithLocation(LLIL_REG_SPLIT_DEST_SSA, loc, size, 0, low.reg, low.version), val); +} + + +ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG, loc, 0, 0, flag, val); +} + + +ExprId LowLevelILFunction::SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SET_FLAG_SSA, loc, 0, 0, flag.flag, flag.version, val); +} + + +ExprId LowLevelILFunction::Load(size_t size, ExprId addr, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD, loc, size, flags, addr); +} + + +ExprId LowLevelILFunction::LoadSSA(size_t size, ExprId addr, size_t sourceMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOAD_SSA, loc, size, 0, addr, sourceMemoryVer); +} + + +ExprId LowLevelILFunction::Store(size_t size, ExprId addr, ExprId val, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE, loc, size, flags, addr, val); +} + + +ExprId LowLevelILFunction::StoreSSA(size_t size, ExprId addr, ExprId val, size_t newMemoryVer, size_t prevMemoryVer, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_STORE_SSA, loc, size, 0, addr, newMemoryVer, prevMemoryVer, val); +} + + +ExprId LowLevelILFunction::Push(size_t size, ExprId val, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_PUSH, loc, size, flags, val); +} + + +ExprId LowLevelILFunction::Pop(size_t size, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_POP, loc, size, flags); +} + + +ExprId LowLevelILFunction::Register(size_t size, uint32_t reg, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG, loc, size, 0, reg); +} + + +ExprId LowLevelILFunction::RegisterSSA(size_t size, const SSARegister& reg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA, loc, size, 0, reg.reg, reg.version); +} + + +ExprId LowLevelILFunction::RegisterSSAPartial(size_t size, const SSARegister& fullReg, uint32_t partialReg, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_SSA_PARTIAL, loc, size, 0, fullReg.reg, fullReg.version, partialReg); +} + + +ExprId LowLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CONST_PTR, loc, size, 0, val); +} + + +ExprId LowLevelILFunction::Flag(uint32_t flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG, loc, 0, 0, flag); +} + + +ExprId LowLevelILFunction::FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_SSA, loc, 0, 0, flag.flag, flag.version); +} + + +ExprId LowLevelILFunction::FlagBit(size_t size, uint32_t flag, uint32_t bitIndex, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT, loc, size, 0, flag, bitIndex); +} + + +ExprId LowLevelILFunction::FlagBitSSA(size_t size, const SSAFlag& flag, uint32_t bitIndex, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_BIT_SSA, loc, size, 0, flag.flag, flag.version, bitIndex); +} + + +ExprId LowLevelILFunction::Add(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADD, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::AddCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ADC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Sub(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SUB, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::SubBorrow(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SBB, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::And(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_AND, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Or(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_OR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::Xor(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_XOR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ShiftLeft(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::LogicalShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LSR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ArithShiftRight(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ASR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeft(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateLeftCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RLC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::RotateRight(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ROR, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::RotateRightCarry(size_t size, ExprId a, ExprId b, ExprId carry, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RRC, loc, size, flags, a, b, carry); +} + + +ExprId LowLevelILFunction::Mult(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MUL, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULU_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::MultDoublePrecSigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MULS_DP, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::DivSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_DIVS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModUnsigned(size_t size, ExprId a, ExprId b, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODU_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::ModSigned(size_t size, ExprId a, ExprId b, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS, loc, size, flags, a, b); +} + + +ExprId LowLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId div, uint32_t flags, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MODS_DP, loc, size, flags, high, low, div); +} + + +ExprId LowLevelILFunction::Neg(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NEG, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NOT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::ZeroExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_ZX, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::LowPart(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_LOW_PART, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::JumpTo(ExprId dest, const vector& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), dest, + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::SystemCallSSA(const vector& output, const vector& params, + const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, + output.size() * 2, AddSSARegisterList(output)), + AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), + AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + params.size() * 2, AddSSARegisterList(params))); +} + + +ExprId LowLevelILFunction::Return(size_t dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RET, loc, 0, 0, dest); +} + + +ExprId LowLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_NORET, loc, 0, 0); +} + + +ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond); +} + + +ExprId LowLevelILFunction::CompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_E, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_NE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SLE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_ULE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGE, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_SGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CMP_UGT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TEST_BIT, loc, size, 0, a, b); +} + + +ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BOOL_TO_INT, loc, size, 0, a); +} + + +ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_SYSCALL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BP, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Trap(uint32_t num, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_TRAP, loc, 0, 0, num); +} + + +ExprId LowLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNDEF, loc, 0, 0); +} + + +ExprId LowLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL, loc, 0, 0); +} + + +ExprId LowLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_UNIMPL_MEM, loc, size, 0, addr); +} + + +ExprId LowLevelILFunction::RegisterPhi(const SSARegister& dest, const vector& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_REG_PHI, loc, 0, 0, dest.reg, dest.version, + sources.size() * 2, AddSSARegisterList(sources)); +} + + +ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_PHI, loc, 0, 0, dest.flag, dest.version, + sources.size() * 2, AddSSAFlagList(sources)); +} + + +ExprId LowLevelILFunction::MemoryPhi(size_t dest, const vector& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_MEM_PHI, loc, 0, 0, dest, sources.size(), AddIndexList(sources)); +} diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h new file mode 100644 index 00000000..8f140c2a --- /dev/null +++ b/lowlevelilinstruction.h @@ -0,0 +1,906 @@ +// Copyright (c) 2015-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. + +#pragma once + +#include +#include +#include +#ifdef BINARYNINJACORE_LIBRARY +#include "type.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ +#ifdef BINARYNINJACORE_LIBRARY + typedef size_t ExprId; +#endif + + class LowLevelILFunction; + + template + struct LowLevelILInstructionAccessor {}; + + struct LowLevelILInstruction; + struct LowLevelILConstantInstruction; + struct LowLevelILOneOperandInstruction; + struct LowLevelILTwoOperandInstruction; + struct LowLevelILTwoOperandWithCarryInstruction; + struct LowLevelILDoublePrecisionInstruction; + struct LowLevelILLabel; + struct MediumLevelILInstruction; + class LowLevelILOperand; + class LowLevelILOperandList; + + struct SSARegister + { + uint32_t reg; + size_t version; + + SSARegister(); + SSARegister(uint32_t r, size_t i); + SSARegister(const SSARegister& v); + + SSARegister& operator=(const SSARegister& v); + bool operator==(const SSARegister& v) const; + bool operator!=(const SSARegister& v) const; + bool operator<(const SSARegister& v) const; + }; + + struct SSAFlag + { + uint32_t flag; + size_t version; + + SSAFlag(); + SSAFlag(uint32_t f, size_t i); + SSAFlag(const SSAFlag& v); + + SSAFlag& operator=(const SSAFlag& v); + bool operator==(const SSAFlag& v) const; + bool operator!=(const SSAFlag& v) const; + bool operator<(const SSAFlag& v) const; + }; + + enum LowLevelILOperandType + { + IntegerLowLevelOperand, + IndexLowLevelOperand, + ExprLowLevelOperand, + RegisterLowLevelOperand, + FlagLowLevelOperand, + FlagConditionLowLevelOperand, + SSARegisterLowLevelOperand, + SSAFlagLowLevelOperand, + IndexListLowLevelOperand, + SSARegisterListLowLevelOperand, + SSAFlagListLowLevelOperand + }; + + enum LowLevelILOperandUsage + { + SourceExprLowLevelOperandUsage, + SourceRegisterLowLevelOperandUsage, + SourceFlagLowLevelOperandUsage, + SourceSSARegisterLowLevelOperandUsage, + SourceSSAFlagLowLevelOperandUsage, + DestExprLowLevelOperandUsage, + DestRegisterLowLevelOperandUsage, + DestFlagLowLevelOperandUsage, + DestSSARegisterLowLevelOperandUsage, + DestSSAFlagLowLevelOperandUsage, + PartialRegisterLowLevelOperandUsage, + StackSSARegisterLowLevelOperandUsage, + StackMemoryVersionLowLevelOperandUsage, + LeftExprLowLevelOperandUsage, + RightExprLowLevelOperandUsage, + CarryExprLowLevelOperandUsage, + HighExprLowLevelOperandUsage, + LowExprLowLevelOperandUsage, + ConditionExprLowLevelOperandUsage, + HighRegisterLowLevelOperandUsage, + HighSSARegisterLowLevelOperandUsage, + LowRegisterLowLevelOperandUsage, + LowSSARegisterLowLevelOperandUsage, + ConstantLowLevelOperandUsage, + VectorLowLevelOperandUsage, + TargetLowLevelOperandUsage, + TrueTargetLowLevelOperandUsage, + FalseTargetLowLevelOperandUsage, + BitIndexLowLevelOperandUsage, + SourceMemoryVersionLowLevelOperandUsage, + DestMemoryVersionLowLevelOperandUsage, + FlagConditionLowLevelOperandUsage, + OutputSSARegistersLowLevelOperandUsage, + OutputMemoryVersionLowLevelOperandUsage, + ParameterSSARegistersLowLevelOperandUsage, + SourceSSARegistersLowLevelOperandUsage, + SourceSSAFlagsLowLevelOperandUsage, + SourceMemoryVersionsLowLevelOperandUsage, + TargetListLowLevelOperandUsage + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSARegister argument_type; +#else + typedef BinaryNinja::SSARegister argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.reg) ^ ((result_type)value.version << 32); + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAFlag argument_type; +#else + typedef BinaryNinja::SSAFlag argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.flag) ^ ((result_type)value.version << 32); + } + }; + + template<> struct hash + { + typedef BNLowLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::LowLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::LowLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class LowLevelILInstructionAccessException: public std::exception + { + public: + LowLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to LLIL instruction"; } + }; + + class LowLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; + const BNLowLevelILInstruction* instr; +#else + Ref function; + BNLowLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + LowLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + LowLevelILIntegerList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILIndexList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSARegisterList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSARegister operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegister operator[](size_t i) const; + + operator std::vector() const; + }; + + class LowLevelILSSAFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSAFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAFlag operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILInstructionBase: public BNLowLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + LowLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + LowLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + uint32_t GetRawOperandAsRegister(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const; + LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + SSARegister GetRawOperandAsSSARegister(size_t operand) const; + SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; + LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; + LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector& regs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + LowLevelILInstruction GetSSAForm() const; + LowLevelILInstruction GetNonSSAForm() const; + + size_t GetMediumLevelILInstructionIndex() const; + size_t GetMediumLevelILExprIndex() const; + size_t GetMappedMediumLevelILInstructionIndex() const; + size_t GetMappedMediumLevelILExprIndex() const; + + bool HasMediumLevelIL() const; + bool HasMappedMediumLevelIL() const; + MediumLevelILInstruction GetMediumLevelIL() const; + MediumLevelILInstruction GetMappedMediumLevelIL() const; + + void Replace(ExprId expr); + + template + LowLevelILInstructionAccessor& As() + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(LowLevelILInstructionAccessor*)this; + } + LowLevelILOneOperandInstruction& AsOneOperand() + { + return *(LowLevelILOneOperandInstruction*)this; + } + LowLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(LowLevelILTwoOperandInstruction*)this; + } + LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(LowLevelILTwoOperandWithCarryInstruction*)this; + } + LowLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(LowLevelILDoublePrecisionInstruction*)this; + } + + template + const LowLevelILInstructionAccessor& As() const + { + if (operation != N) + throw LowLevelILInstructionAccessException(); + return *(const LowLevelILInstructionAccessor*)this; + } + const LowLevelILConstantInstruction& AsConstant() const + { + return *(const LowLevelILConstantInstruction*)this; + } + const LowLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const LowLevelILOneOperandInstruction*)this; + } + const LowLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const LowLevelILTwoOperandInstruction*)this; + } + const LowLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const LowLevelILTwoOperandWithCarryInstruction*)this; + } + const LowLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const LowLevelILDoublePrecisionInstruction*)this; + } + }; + + struct LowLevelILInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction(); + LowLevelILInstruction(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, + size_t expr, size_t instrIdx); + LowLevelILInstruction(const LowLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(LowLevelILFunction* dest) const; + ExprId CopyTo(LowLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template LowLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template uint32_t GetSourceRegister() const { return As().GetSourceRegister(); } + template uint32_t GetSourceFlag() const { return As().GetSourceFlag(); } + template SSARegister GetSourceSSARegister() const { return As().GetSourceSSARegister(); } + template SSAFlag GetSourceSSAFlag() const { return As().GetSourceSSAFlag(); } + template LowLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template uint32_t GetDestRegister() const { return As().GetDestRegister(); } + template uint32_t GetDestFlag() const { return As().GetDestFlag(); } + template SSARegister GetDestSSARegister() const { return As().GetDestSSARegister(); } + template SSAFlag GetDestSSAFlag() const { return As().GetDestSSAFlag(); } + template uint32_t GetPartialRegister() const { return As().GetPartialRegister(); } + template SSARegister GetStackSSARegister() const { return As().GetStackSSARegister(); } + template LowLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template LowLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template LowLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template LowLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template LowLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template LowLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template uint32_t GetHighRegister() const { return As().GetHighRegister(); } + template SSARegister GetHighSSARegister() const { return As().GetHighSSARegister(); } + template uint32_t GetLowRegister() const { return As().GetLowRegister(); } + template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } + template int64_t GetConstant() const { return As().GetConstant(); } + template int64_t GetVector() const { return As().GetVector(); } + template size_t GetTarget() const { return As().GetTarget(); } + template size_t GetTrueTarget() const { return As().GetTrueTarget(); } + template size_t GetFalseTarget() const { return As().GetFalseTarget(); } + template size_t GetBitIndex() const { return As().GetBitIndex(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template size_t GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template BNLowLevelILFlagCondition GetFlagCondition() const { return As().GetFlagCondition(); } + template LowLevelILSSARegisterList GetOutputSSARegisters() const { return As().GetOutputSSARegisters(); } + template LowLevelILSSARegisterList GetParameterSSARegisters() const { return As().GetParameterSSARegisters(); } + template LowLevelILSSARegisterList GetSourceSSARegisters() const { return As().GetSourceSSARegisters(); } + template LowLevelILSSAFlagList GetSourceSSAFlags() const { return As().GetSourceSSAFlags(); } + template LowLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template LowLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + + template void SetDestSSAVersion(size_t version) { As().SetDestSSAVersion(version); } + template void SetSourceSSAVersion(size_t version) { As().SetSourceSSAVersion(version); } + template void SetHighSSAVersion(size_t version) { As().SetHighSSAVersion(version); } + template void SetLowSSAVersion(size_t version) { As().SetLowSSAVersion(version); } + template void SetStackSSAVersion(size_t version) { As().SetStackSSAVersion(version); } + template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSARegisters(const std::vector& regs) { As().SetOutputSSARegisters(regs); } + template void SetParameterSSARegisters(const std::vector& regs) { As().SetParameterSSARegisters(regs); } + + bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a LowLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + LowLevelILInstruction GetSourceExpr() const; + uint32_t GetSourceRegister() const; + uint32_t GetSourceFlag() const; + SSARegister GetSourceSSARegister() const; + SSAFlag GetSourceSSAFlag() const; + LowLevelILInstruction GetDestExpr() const; + uint32_t GetDestRegister() const; + uint32_t GetDestFlag() const; + SSARegister GetDestSSARegister() const; + SSAFlag GetDestSSAFlag() const; + uint32_t GetPartialRegister() const; + SSARegister GetStackSSARegister() const; + LowLevelILInstruction GetLeftExpr() const; + LowLevelILInstruction GetRightExpr() const; + LowLevelILInstruction GetCarryExpr() const; + LowLevelILInstruction GetHighExpr() const; + LowLevelILInstruction GetLowExpr() const; + LowLevelILInstruction GetConditionExpr() const; + uint32_t GetHighRegister() const; + SSARegister GetHighSSARegister() const; + uint32_t GetLowRegister() const; + SSARegister GetLowSSARegister() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetBitIndex() const; + size_t GetSourceMemoryVersion() const; + size_t GetDestMemoryVersion() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + LowLevelILSSARegisterList GetOutputSSARegisters() const; + LowLevelILSSARegisterList GetParameterSSARegisters() const; + LowLevelILSSARegisterList GetSourceSSARegisters() const; + LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILIndexList GetSourceMemoryVersions() const; + LowLevelILIndexList GetTargetList() const; + }; + + class LowLevelILOperand + { + LowLevelILInstruction m_instr; + LowLevelILOperandUsage m_usage; + LowLevelILOperandType m_type; + size_t m_operandIndex; + + public: + LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, + size_t operandIndex); + + LowLevelILOperandType GetType() const { return m_type; } + LowLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + LowLevelILInstruction GetExpr() const; + uint32_t GetRegister() const; + uint32_t GetFlag() const; + BNLowLevelILFlagCondition GetFlagCondition() const; + SSARegister GetSSARegister() const; + SSAFlag GetSSAFlag() const; + LowLevelILIndexList GetIndexList() const; + LowLevelILSSARegisterList GetSSARegisterList() const; + LowLevelILSSAFlagList GetSSAFlagList() const; + }; + + class LowLevelILOperandList + { + struct ListIterator + { + const LowLevelILOperandList* owner; + std::vector::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const LowLevelILOperand operator*(); + }; + + LowLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + LowLevelILOperandList(const LowLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const LowLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct LowLevelILConstantInstruction: public LowLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct LowLevelILOneOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct LowLevelILTwoOperandInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct LowLevelILTwoOperandWithCarryInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct LowLevelILDoublePrecisionInstruction: public LowLevelILInstructionBase + { + LowLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + LowLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from LowLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestRegister() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetHighRegister() const { return GetRawOperandAsRegister(0); } + uint32_t GetLowRegister() const { return GetRawOperandAsRegister(1); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetHighSSARegister() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegister(0); } + SSARegister GetLowSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetSourceSSARegister() const { return GetRawOperandAsSSARegister(0); } + uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetSourceSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + size_t GetBitIndex() const { return GetRawOperandAsIndex(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterList GetOutputSSARegisters() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterList(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); } + ssize_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); } + LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); } + void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); } + void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } + void SetParameterSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } + LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); } + LowLevelILSSAFlagList GetSourceSSAFlags() const { return GetRawOperandAsSSAFlagList(2); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + LowLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILConstantInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILDoublePrecisionInstruction {}; + + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILOneOperandInstruction {}; +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index b4abaa72..f978f681 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -19,6 +19,7 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -42,6 +43,24 @@ MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) } +Ref MediumLevelILFunction::GetFunction() const +{ + BNFunction* func = BNGetMediumLevelILOwnerFunction(m_object); + if (!func) + return nullptr; + return new Function(func); +} + + +Ref MediumLevelILFunction::GetArchitecture() const +{ + Ref func = GetFunction(); + if (!func) + return nullptr; + return func->GetArchitecture(); +} + + uint64_t MediumLevelILFunction::GetCurrentAddress() const { return BNMediumLevelILGetCurrentAddress(m_object); @@ -60,6 +79,24 @@ size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t a } +void MediumLevelILFunction::PrepareToCopyFunction(MediumLevelILFunction* func) +{ + BNPrepareToCopyMediumLevelILFunction(m_object, func->GetObject()); +} + + +void MediumLevelILFunction::PrepareToCopyBlock(BasicBlock* block) +{ + BNPrepareToCopyMediumLevelILBasicBlock(m_object, block->GetObject()); +} + + +BNMediumLevelILLabel* MediumLevelILFunction::GetLabelForSourceInstruction(size_t i) +{ + return BNGetLabelForMediumLevelILSourceInstruction(m_object, i); +} + + ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) { @@ -67,20 +104,44 @@ ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t } +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, uint64_t addr, + uint32_t sourceOperand, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExprWithLocation(m_object, operation, addr, sourceOperand, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddExprWithLocation(BNMediumLevelILOperation operation, const ILSourceLocation& loc, + size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + if (loc.valid) + { + return BNMediumLevelILAddExprWithLocation(m_object, operation, loc.address, loc.sourceOperand, + size, a, b, c, d, 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) +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILGotoWithLocation(m_object, &label, loc.address, loc.sourceOperand); return BNMediumLevelILGoto(m_object, &label); } -ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f, + const ILSourceLocation& loc) { + if (loc.valid) + return BNMediumLevelILIfWithLocation(m_object, operand, &t, &f, loc.address, loc.sourceOperand); return BNMediumLevelILIf(m_object, operand, &t, &f); } @@ -125,12 +186,67 @@ ExprId MediumLevelILFunction::AddOperandList(const vector operands) } -BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +ExprId MediumLevelILFunction::AddIndexList(const vector& 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; +} + + +ExprId MediumLevelILFunction::AddVariableList(const vector& vars) +{ + uint64_t* operandList = new uint64_t[vars.size()]; + for (size_t i = 0; i < vars.size(); i++) + operandList[i] = vars[i].ToIdentifier(); + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, vars.size()); + delete[] operandList; + return result; +} + + +ExprId MediumLevelILFunction::AddSSAVariableList(const vector& vars) +{ + uint64_t* operandList = new uint64_t[vars.size() * 2]; + for (size_t i = 0; i < vars.size(); i++) + { + operandList[i * 2] = vars[i].var.ToIdentifier(); + operandList[(i * 2) + 1] = vars[i].version; + } + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, vars.size() * 2); + delete[] operandList; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::GetRawExpr(size_t i) const { return BNGetMediumLevelILByIndex(m_object, i); } +MediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) +{ + return GetInstruction(i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetInstruction(size_t i) +{ + size_t expr = GetIndexForInstruction(i); + return MediumLevelILInstruction(this, GetRawExpr(expr), expr, i); +} + + +MediumLevelILInstruction MediumLevelILFunction::GetExpr(size_t i) +{ + return MediumLevelILInstruction(this, GetRawExpr(i), i, GetInstructionForExpr(i)); +} + + size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const { return BNGetMediumLevelILIndexForInstruction(m_object, i); @@ -155,12 +271,53 @@ size_t MediumLevelILFunction::GetExprCount() const } +void MediumLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value) +{ + BNUpdateMediumLevelILOperand(m_object, i, operandIndex, value); +} + + +void MediumLevelILFunction::MarkInstructionForRemoval(size_t i) +{ + BNMarkMediumLevelILInstructionForRemoval(m_object, i); +} + + +void MediumLevelILFunction::ReplaceInstruction(size_t i, ExprId expr) +{ + BNReplaceMediumLevelILInstruction(m_object, i, expr); +} + + +void MediumLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr) +{ + BNReplaceMediumLevelILExpr(m_object, expr, newExpr); +} + + void MediumLevelILFunction::Finalize() { BNFinalizeMediumLevelILFunction(m_object); } +void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases, + const set& knownAliases) +{ + BNVariable* vars = new BNVariable[knownAliases.size()]; + size_t i = 0; + for (auto& j : knownAliases) + { + vars[i].type = j.type; + vars[i].index = j.index; + vars[i].storage = j.storage; + } + + BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size()); + delete[] vars; +} + + bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector& tokens) { size_t count; @@ -217,6 +374,26 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc } +void MediumLevelILFunction::VisitInstructions( + const function& func) +{ + for (auto& i : GetBasicBlocks()) + for (size_t j = i->GetStart(); j < i->GetEnd(); j++) + func(i, GetInstruction(j)); +} + + +void MediumLevelILFunction::VisitAllExprs( + const function& func) +{ + VisitInstructions([&](BasicBlock* block, const MediumLevelILInstruction& instr) { + instr.VisitExprs([&](const MediumLevelILInstruction& expr) { + return func(block, expr); + }); + }); +} + + vector> MediumLevelILFunction::GetBasicBlocks() const { size_t count; @@ -273,9 +450,9 @@ size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const } -size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t version) const +size_t MediumLevelILFunction::GetSSAVarDefinition(const SSAVariable& var) const { - return BNGetMediumLevelILSSAVarDefinition(m_object, &var, version); + return BNGetMediumLevelILSSAVarDefinition(m_object, &var.var, var.version); } @@ -285,10 +462,10 @@ size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t version) const } -set MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t version) const +set MediumLevelILFunction::GetSSAVarUses(const SSAVariable& var) const { size_t count; - size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, version, &count); + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var.var, var.version, &count); set result; for (size_t i = 0; i < count; i++) @@ -341,9 +518,9 @@ set MediumLevelILFunction::GetVariableUses(const Variable& var) const } -RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t version) +RegisterValue MediumLevelILFunction::GetSSAVarValue(const SSAVariable& var) { - BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, version); + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var.var, var.version); return RegisterValue::FromAPIObject(value); } @@ -355,9 +532,15 @@ RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) } -PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t version, size_t instr) +RegisterValue MediumLevelILFunction::GetExprValue(const MediumLevelILInstruction& expr) { - BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, version, instr); + return GetExprValue(expr.exprIndex); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const SSAVariable& var, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var.var, var.version, instr); return PossibleValueSet::FromAPIObject(value); } @@ -369,6 +552,12 @@ PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) } +PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(const MediumLevelILInstruction& expr) +{ + return GetPossibleExprValues(expr.exprIndex); +} + + size_t MediumLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const { return BNGetMediumLevelILSSAVarVersionAtILInstruction(m_object, &var, instr); @@ -489,12 +678,12 @@ BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(siz } -map MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +unordered_map MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const { size_t count; BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); - map result; + unordered_map result; for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; @@ -531,3 +720,9 @@ Confidence> MediumLevelILFunction::GetExprType(size_t expr) return nullptr; return Confidence>(new Type(result.type), result.confidence); } + + +Confidence> MediumLevelILFunction::GetExprType(const MediumLevelILInstruction& expr) +{ + return GetExprType(expr.exprIndex); +} diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp new file mode 100644 index 00000000..73f2e59b --- /dev/null +++ b/mediumlevelilinstruction.cpp @@ -0,0 +1,2526 @@ +// Copyright (c) 2015-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. + +#ifdef BINARYNINJACORE_LIBRARY +#include "mediumlevelilfunction.h" +#include "mediumlevelilssafunction.h" +#include "lowlevelilfunction.h" +using namespace BinaryNinjaCore; +#else +#include "binaryninjaapi.h" +#include "mediumlevelilinstruction.h" +#include "lowlevelilinstruction.h" +using namespace BinaryNinja; +#endif + +using namespace std; + + +unordered_map + MediumLevelILInstructionBase::operandTypeForUsage = { + {SourceExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {SourceVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {SourceSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {PartialSSAVariableSourceMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {DestExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {DestVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {DestSSAVariableMediumLevelOperandUsage, SSAVariableMediumLevelOperand}, + {LeftExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {RightExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {CarryExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {LowExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {StackExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {ConditionExprMediumLevelOperandUsage, ExprMediumLevelOperand}, + {HighVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {HighSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {LowSSAVariableMediumLevelOperandUsage, VariableMediumLevelOperand}, + {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, + {DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {TargetListMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, + {ParameterVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, + {ParameterSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {ParameterSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, + {SourceSSAVariablesMediumLevelOperandUsages, SSAVariableListMediumLevelOperand} + }; + + +unordered_map> + MediumLevelILInstructionBase::operationOperandUsage = { + {MLIL_NOP, {}}, + {MLIL_NORET, {}}, + {MLIL_BP, {}}, + {MLIL_UNDEF, {}}, + {MLIL_UNIMPL, {}}, + {MLIL_SET_VAR, {DestVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_FIELD, {DestVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA, {DestSSAVariableMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SSA_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_SPLIT_SSA, {HighSSAVariableMediumLevelOperandUsage, LowSSAVariableMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_SET_VAR_ALIASED_FIELD, {DestSSAVariableMediumLevelOperandUsage, PartialSSAVariableSourceMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_LOAD_SSA, {SourceExprMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_LOAD_STRUCT_SSA, {SourceExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_STORE, {DestExprMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_SSA, {DestExprMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, SourceExprMediumLevelOperandUsage}}, + {MLIL_STORE_STRUCT_SSA, {DestExprMediumLevelOperandUsage, OffsetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, + SourceExprMediumLevelOperandUsage}}, + {MLIL_VAR, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_VAR_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_SSA, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_SSA_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED, {SourceSSAVariableMediumLevelOperandUsage}}, + {MLIL_VAR_ALIASED_FIELD, {SourceSSAVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, + {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, + {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, + {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetListMediumLevelOperandUsage}}, + {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage}}, + {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_CALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage}}, + {MLIL_SYSCALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage}}, + {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, + {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, + {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage}}, + {MLIL_GOTO, {TargetMediumLevelOperandUsage}}, + {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, + {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, + {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, + {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, + {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_OR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_XOR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_LSR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ASR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ROR, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MUL, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULU_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MULS_DP, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODU, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_MODS, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_E, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_NE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SLE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_ULE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGE, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_SGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_CMP_UGT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_TEST_BIT, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADD_OVERFLOW, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, + {MLIL_ADC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_SBB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RLC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_RRC, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage}}, + {MLIL_DIVU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_DIVS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODU_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_MODS_DP, {HighExprMediumLevelOperandUsage, LowExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage}}, + {MLIL_NEG, {SourceExprMediumLevelOperandUsage}}, + {MLIL_NOT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_SX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_ZX, {SourceExprMediumLevelOperandUsage}}, + {MLIL_LOW_PART, {SourceExprMediumLevelOperandUsage}}, + {MLIL_BOOL_TO_INT, {SourceExprMediumLevelOperandUsage}}, + {MLIL_UNIMPL_MEM, {SourceExprMediumLevelOperandUsage}} + }; + + +static unordered_map> + GetOperandIndexForOperandUsages() +{ + unordered_map> result; + for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) + { + result[operation.first] = unordered_map(); + + size_t operand = 0; + for (auto usage : operation.second) + { + result[operation.first][usage] = operand; + switch (usage) + { + case PartialSSAVariableSourceMediumLevelOperandUsage: + // SSA variables are usually two slots, but this one has a previously defined + // variables and thus only takes one slot + operand++; + break; + case OutputVariablesSubExprMediumLevelOperandUsage: + case ParameterVariablesMediumLevelOperandUsage: + // Represented as subexpression, so only takes one slot even though it is a list + operand++; + break; + case OutputSSAVariablesMediumLevelOperandUsage: + // OutputSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + case ParameterSSAVariablesMediumLevelOperandUsage: + // ParameterSSAMemoryVersionMediumLevelOperandUsage follows at same operand + break; + default: + switch (MediumLevelILInstructionBase::operandTypeForUsage[usage]) + { + case SSAVariableMediumLevelOperand: + case IndexListMediumLevelOperand: + case VariableListMediumLevelOperand: + case SSAVariableListMediumLevelOperand: + case ExprListMediumLevelOperand: + // SSA variables and lists take two operand slots + operand += 2; + break; + default: + operand++; + break; + } + break; + } + } + } + return result; +} + + +unordered_map> + MediumLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages(); + + +SSAVariable::SSAVariable(): version(0) +{ +} + + +SSAVariable::SSAVariable(const Variable& v, size_t i): var(v), version(i) +{ +} + + +SSAVariable::SSAVariable(const SSAVariable& v): var(v.var), version(v.version) +{ +} + + +SSAVariable& SSAVariable::operator=(const SSAVariable& v) +{ + var = v.var; + version = v.version; + return *this; +} + + +bool SSAVariable::operator==(const SSAVariable& v) const +{ + if (var != v.var) + return false; + return version == v.version; +} + + +bool SSAVariable::operator!=(const SSAVariable& v) const +{ + return !((*this) == v); +} + + +bool SSAVariable::operator<(const SSAVariable& v) const +{ + if (var < v.var) + return true; + if (v.var < var) + return false; + return version < v.version; +} + + +bool MediumLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const +{ + return count == a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const +{ + return count != a.count; +} + + +bool MediumLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const +{ + return count > a.count; +} + + +MediumLevelILIntegerList::ListIterator& MediumLevelILIntegerList::ListIterator::operator++() +{ + count--; + if (count == 0) + return *this; + + operand++; + if (operand >= 4) + { + operand = 0; +#ifdef BINARYNINJACORE_LIBRARY + instr = &function->GetRawExpr((size_t)instr->operands[4]); +#else + instr = function->GetRawExpr((size_t)instr.operands[4]); +#endif + } + return *this; +} + + +uint64_t MediumLevelILIntegerList::ListIterator::operator*() +{ +#ifdef BINARYNINJACORE_LIBRARY + return instr->operands[operand]; +#else + return instr.operands[operand]; +#endif +} + + +MediumLevelILIntegerList::MediumLevelILIntegerList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count) +{ + m_start.function = func; +#ifdef BINARYNINJACORE_LIBRARY + m_start.instr = &instr; +#else + m_start.instr = instr; +#endif + m_start.operand = 0; + m_start.count = count; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::begin() const +{ + return m_start; +} + + +MediumLevelILIntegerList::const_iterator MediumLevelILIntegerList::end() const +{ + const_iterator result; + result.function = m_start.function; + result.operand = 0; + result.count = 0; + return result; +} + + +size_t MediumLevelILIntegerList::size() const +{ + return m_start.count; +} + + +uint64_t MediumLevelILIntegerList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIntegerList::operator vector() const +{ + vector result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +size_t MediumLevelILIndexList::ListIterator::operator*() +{ + return (size_t)*pos; +} + + +MediumLevelILIndexList::MediumLevelILIndexList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILIndexList::const_iterator MediumLevelILIndexList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILIndexList::size() const +{ + return m_list.size(); +} + + +size_t MediumLevelILIndexList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILIndexList::operator vector() const +{ + vector result; + for (auto i : *this) + result.push_back(i); + return result; +} + + +const Variable MediumLevelILVariableList::ListIterator::operator*() +{ + return Variable::FromIdentifier(*pos); +} + + +MediumLevelILVariableList::MediumLevelILVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILVariableList::const_iterator MediumLevelILVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILVariableList::size() const +{ + return m_list.size(); +} + + +const Variable MediumLevelILVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILVariableList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const SSAVariable MediumLevelILSSAVariableList::ListIterator::operator*() +{ + MediumLevelILIntegerList::const_iterator cur = pos; + Variable var = Variable::FromIdentifier(*cur); + ++cur; + size_t version = (size_t)*cur; + return SSAVariable(var, version); +} + + +MediumLevelILSSAVariableList::MediumLevelILSSAVariableList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILSSAVariableList::const_iterator MediumLevelILSSAVariableList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILSSAVariableList::size() const +{ + return m_list.size() / 2; +} + + +const SSAVariable MediumLevelILSSAVariableList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILSSAVariableList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::ListIterator::operator*() +{ + return MediumLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), + (size_t)*pos, instructionIndex); +} + + +MediumLevelILInstructionList::MediumLevelILInstructionList(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count, size_t instrIndex): + m_list(func, instr, count), m_instructionIndex(instrIndex) +{ +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +MediumLevelILInstructionList::const_iterator MediumLevelILInstructionList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + result.instructionIndex = m_instructionIndex; + return result; +} + + +size_t MediumLevelILInstructionList::size() const +{ + return m_list.size(); +} + + +const MediumLevelILInstruction MediumLevelILInstructionList::operator[](size_t i) const +{ + if (i >= size()) + throw MediumLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +MediumLevelILInstructionList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILOperand::MediumLevelILOperand(const MediumLevelILInstruction& instr, + MediumLevelILOperandUsage usage, size_t operandIndex): + m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) +{ + auto i = MediumLevelILInstructionBase::operandTypeForUsage.find(m_usage); + if (i == MediumLevelILInstructionBase::operandTypeForUsage.end()) + throw MediumLevelILInstructionAccessException(); + m_type = i->second; +} + + +uint64_t MediumLevelILOperand::GetInteger() const +{ + if (m_type != IntegerMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsInteger(m_operandIndex); +} + + +size_t MediumLevelILOperand::GetIndex() const +{ + if (m_type != IndexMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAMemoryVersionMediumLevelOperandUsage) || + (m_usage == ParameterSSAMemoryVersionMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsIndex(0); + return m_instr.GetRawOperandAsIndex(m_operandIndex); +} + + +MediumLevelILInstruction MediumLevelILOperand::GetExpr() const +{ + if (m_type != ExprMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExpr(m_operandIndex); +} + + +Variable MediumLevelILOperand::GetVariable() const +{ + if (m_type != VariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsVariable(m_operandIndex); +} + + +SSAVariable MediumLevelILOperand::GetSSAVariable() const +{ + if (m_type != SSAVariableMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if (m_usage == PartialSSAVariableSourceMediumLevelOperandUsage) + return m_instr.GetRawOperandAsPartialSSAVariableSource(m_operandIndex - 2); + return m_instr.GetRawOperandAsSSAVariable(m_operandIndex); +} + + +MediumLevelILIndexList MediumLevelILOperand::GetIndexList() const +{ + if (m_type != IndexListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexList(m_operandIndex); +} + + +MediumLevelILVariableList MediumLevelILOperand::GetVariableList() const +{ + if (m_type != VariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputVariablesSubExprMediumLevelOperandUsage) || + (m_usage == ParameterVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsVariableList(0); + return m_instr.GetRawOperandAsVariableList(m_operandIndex); +} + + +MediumLevelILSSAVariableList MediumLevelILOperand::GetSSAVariableList() const +{ + if (m_type != SSAVariableListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + if ((m_usage == OutputSSAVariablesMediumLevelOperandUsage) || + (m_usage == ParameterSSAVariablesMediumLevelOperandUsage)) + return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSAVariableList(1); + return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex); +} + + +MediumLevelILInstructionList MediumLevelILOperand::GetExprList() const +{ + if (m_type != ExprListMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsExprList(m_operandIndex); +} + + +const MediumLevelILOperand MediumLevelILOperandList::ListIterator::operator*() +{ + MediumLevelILOperandUsage usage = *pos; + auto i = owner->m_operandIndexMap.find(usage); + if (i == owner->m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(owner->m_instr, usage, i->second); +} + + +MediumLevelILOperandList::MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const vector& usageList, + const unordered_map& operandIndexMap): + m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap) +{ +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::begin() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.begin(); + return result; +} + + +MediumLevelILOperandList::const_iterator MediumLevelILOperandList::end() const +{ + const_iterator result; + result.owner = this; + result.pos = m_usageList.end(); + return result; +} + + +size_t MediumLevelILOperandList::size() const +{ + return m_usageList.size(); +} + + +const MediumLevelILOperand MediumLevelILOperandList::operator[](size_t i) const +{ + MediumLevelILOperandUsage usage = m_usageList[i]; + auto indexMap = m_operandIndexMap.find(usage); + if (indexMap == m_operandIndexMap.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperand(m_instr, usage, indexMap->second); +} + + +MediumLevelILOperandList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + +MediumLevelILInstruction::MediumLevelILInstruction() +{ + operation = MLIL_UNDEF; + sourceOperand = BN_INVALID_OPERAND; + size = 0; + address = 0; + function = nullptr; + exprIndex = BN_INVALID_EXPR; + instructionIndex = BN_INVALID_EXPR; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t expr, size_t instrIdx) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + function = func; + exprIndex = expr; + instructionIndex = instrIdx; +} + + +MediumLevelILInstruction::MediumLevelILInstruction(const MediumLevelILInstructionBase& instr) +{ + operation = instr.operation; + sourceOperand = instr.sourceOperand; + size = instr.size; + operands[0] = instr.operands[0]; + operands[1] = instr.operands[1]; + operands[2] = instr.operands[2]; + operands[3] = instr.operands[3]; + operands[4] = instr.operands[4]; + address = instr.address; + function = instr.function; + exprIndex = instr.exprIndex; + instructionIndex = instr.instructionIndex; +} + + +MediumLevelILOperandList MediumLevelILInstructionBase::GetOperands() const +{ + auto usage = operationOperandUsage.find(operation); + if (usage == operationOperandUsage.end()) + throw MediumLevelILInstructionAccessException(); + auto operandIndex = operationOperandIndex.find(operation); + if (operandIndex == operationOperandIndex.end()) + throw MediumLevelILInstructionAccessException(); + return MediumLevelILOperandList(*(const MediumLevelILInstruction*)this, usage->second, operandIndex->second); +} + + +uint64_t MediumLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const +{ + return operands[operand]; +} + + +size_t MediumLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const +{ + return (size_t)operands[operand]; +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const +{ + return MediumLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand], instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetRawOperandAsVariable(size_t operand) const +{ + return Variable::FromIdentifier(operands[operand]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 1]); +} + + +SSAVariable MediumLevelILInstructionBase::GetRawOperandAsPartialSSAVariableSource(size_t operand) const +{ + return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 2]); +} + + +MediumLevelILIndexList MediumLevelILInstructionBase::GetRawOperandAsIndexList(size_t operand) const +{ + return MediumLevelILIndexList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILVariableList MediumLevelILInstructionBase::GetRawOperandAsVariableList(size_t operand) const +{ + return MediumLevelILVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILSSAVariableList MediumLevelILInstructionBase::GetRawOperandAsSSAVariableList(size_t operand) const +{ + return MediumLevelILSSAVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + +MediumLevelILInstructionList MediumLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const +{ + return MediumLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand], + instructionIndex); +} + + +void MediumLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value) +{ + operands[operandIndex] = value; + function->UpdateInstructionOperand(exprIndex, operandIndex, value); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operandIndex, const vector& vars) +{ + UpdateRawOperand(operandIndex, vars.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector& exprs) +{ + vector exprIndexList; + for (auto& i : exprs) + exprIndexList.push_back((ExprId)i.exprIndex); + UpdateRawOperand(operandIndex, exprIndexList.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprIndexList)); +} + + +void MediumLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector& exprs) +{ + UpdateRawOperand(operandIndex, exprs.size()); + UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprs)); +} + + +RegisterValue MediumLevelILInstructionBase::GetValue() const +{ + return function->GetExprValue(*(const MediumLevelILInstruction*)this); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleValues() const +{ + return function->GetPossibleExprValues(*(const MediumLevelILInstruction*)this); +} + + +Confidence> MediumLevelILInstructionBase::GetType() const +{ + return function->GetExprType(*(const MediumLevelILInstruction*)this); +} + + +size_t MediumLevelILInstructionBase::GetSSAVarVersion(const Variable& var) +{ + return function->GetSSAVarVersionAtInstruction(var, instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAMemoryVersion() +{ + return function->GetSSAMemoryVersionAtInstruction(instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForRegister(uint32_t reg) +{ + return function->GetVariableForRegisterAtInstruction(reg, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForFlag(uint32_t flag) +{ + return function->GetVariableForFlagAtInstruction(flag, instructionIndex); +} + + +Variable MediumLevelILInstructionBase::GetVariableForStackLocation(int64_t offset) +{ + return function->GetVariableForStackLocationAtInstruction(offset, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleSSAVarValues(const SSAVariable& var) +{ + return function->GetPossibleSSAVarValues(var, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValue(uint32_t reg) +{ + return function->GetRegisterValueAtInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetRegisterValueAfter(uint32_t reg) +{ + return function->GetRegisterValueAfterInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValues(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAtInstruction(reg, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleRegisterValuesAfter(uint32_t reg) +{ + return function->GetPossibleRegisterValuesAfterInstruction(reg, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValue(uint32_t flag) +{ + return function->GetFlagValueAtInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetFlagValueAfter(uint32_t flag) +{ + return function->GetFlagValueAfterInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValues(uint32_t flag) +{ + return function->GetPossibleFlagValuesAtInstruction(flag, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleFlagValuesAfter(uint32_t flag) +{ + return function->GetPossibleFlagValuesAfterInstruction(flag, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContents(int32_t offset, size_t len) +{ + return function->GetStackContentsAtInstruction(offset, len, instructionIndex); +} + + +RegisterValue MediumLevelILInstructionBase::GetStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContents(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAtInstruction(offset, len, instructionIndex); +} + + +PossibleValueSet MediumLevelILInstructionBase::GetPossibleStackContentsAfter(int32_t offset, size_t len) +{ + return function->GetPossibleStackContentsAfterInstruction(offset, len, instructionIndex); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(size_t branchInstr) +{ + return function->GetBranchDependenceAtInstruction(instructionIndex, branchInstr); +} + + +BNILBranchDependence MediumLevelILInstructionBase::GetBranchDependence(const MediumLevelILInstruction& branch) +{ + return GetBranchDependence(branch.instructionIndex); +} + + +unordered_map MediumLevelILInstructionBase::GetAllBranchDependence() +{ + return function->GetAllBranchDependenceAtInstruction(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAInstructionIndex() const +{ + return function->GetSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAInstructionIndex() const +{ + return function->GetNonSSAInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetSSAExprIndex() const +{ + return function->GetSSAExprIndex(exprIndex); +} + + +size_t MediumLevelILInstructionBase::GetNonSSAExprIndex() const +{ + return function->GetNonSSAExprIndex(exprIndex); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetSSAForm() const +{ + Ref ssa = function->GetSSAForm().GetPtr(); + if (!ssa) + return *this; + size_t expr = GetSSAExprIndex(); + size_t instr = GetSSAInstructionIndex(); + return MediumLevelILInstruction(ssa, ssa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +MediumLevelILInstruction MediumLevelILInstructionBase::GetNonSSAForm() const +{ + Ref nonSsa = function->GetNonSSAForm(); + if (!nonSsa) + return *this; + size_t expr = GetNonSSAExprIndex(); + size_t instr = GetNonSSAInstructionIndex(); + return MediumLevelILInstruction(nonSsa, nonSsa->GetRawExpr(GetSSAExprIndex()), expr, instr); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILInstructionIndex() const +{ + return function->GetLowLevelILInstructionIndex(instructionIndex); +} + + +size_t MediumLevelILInstructionBase::GetLowLevelILExprIndex() const +{ + return function->GetLowLevelILExprIndex(exprIndex); +} + + +bool MediumLevelILInstructionBase::HasLowLevelIL() const +{ + Ref func = function->GetLowLevelIL(); + if (!func) + return false; + return GetLowLevelILExprIndex() < func->GetExprCount(); +} + + +LowLevelILInstruction MediumLevelILInstructionBase::GetLowLevelIL() const +{ + Ref func = function->GetLowLevelIL(); + if (!func) + throw LowLevelILInstructionAccessException(); + size_t expr = GetLowLevelILExprIndex(); + if (GetLowLevelILExprIndex() >= func->GetExprCount()) + throw LowLevelILInstructionAccessException(); + return func->GetExpr(expr); +} + + +void MediumLevelILInstructionBase::MarkInstructionForRemoval() +{ + function->MarkInstructionForRemoval(instructionIndex); +} + + +void MediumLevelILInstructionBase::Replace(ExprId expr) +{ + function->ReplaceExpr(exprIndex, expr); +} + + +void MediumLevelILInstruction::VisitExprs(const std::function& func) const +{ + if (!func(*this)) + return; + switch (operation) + { + case MLIL_SET_VAR: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SPLIT_SSA: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_SSA_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_SET_VAR_ALIASED_FIELD: + GetSourceExpr().VisitExprs(func); + break; + case MLIL_CALL: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED: + GetDestExpr().VisitExprs(func); + break; + case MLIL_CALL_SSA: + GetDestExpr().VisitExprs(func); + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_CALL_UNTYPED_SSA: + GetDestExpr().VisitExprs(func); + break; + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; + case MLIL_RET: + for (auto& i : GetSourceExprs()) + i.VisitExprs(func); + break; + case MLIL_STORE: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_STRUCT: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_STORE_STRUCT_SSA: + GetDestExpr().VisitExprs(func); + GetSourceExpr().VisitExprs(func); + break; + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_JUMP_TO: + case MLIL_IF: + case MLIL_UNIMPL_MEM: + case MLIL_LOAD: + case MLIL_LOAD_STRUCT: + case MLIL_LOAD_SSA: + case MLIL_LOAD_STRUCT_SSA: + AsOneOperand().GetSourceExpr().VisitExprs(func); + break; + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + AsTwoOperand().GetLeftExpr().VisitExprs(func); + AsTwoOperand().GetRightExpr().VisitExprs(func); + break; + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + AsTwoOperandWithCarry().GetLeftExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetRightExpr().VisitExprs(func); + AsTwoOperandWithCarry().GetCarryExpr().VisitExprs(func); + break; + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + AsDoublePrecision().GetHighExpr().VisitExprs(func); + AsDoublePrecision().GetLowExpr().VisitExprs(func); + AsDoublePrecision().GetRightExpr().VisitExprs(func); + break; + default: + break; + } +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest) const +{ + return CopyTo(dest, [&](const MediumLevelILInstruction& subExpr) { + return subExpr.CopyTo(dest); + }); +} + + +ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, + const std::function& subExprHandler) const +{ + vector params; + vector labelList; + BNMediumLevelILLabel* labelA; + BNMediumLevelILLabel* labelB; + switch (operation) + { + case MLIL_NOP: + return dest->Nop(*this); + case MLIL_SET_VAR: + return dest->SetVar(size, GetDestVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SSA: + return dest->SetVarSSA(size, GetDestSSAVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_ALIASED: + return dest->SetVarAliased(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SPLIT: + return dest->SetVarSplit(size, GetHighVariable(), + GetLowVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SPLIT_SSA: + return dest->SetVarSSASplit(size, GetHighSSAVariable(), + GetLowSSAVariable(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_FIELD: + return dest->SetVarField(size, GetDestVariable(), + GetOffset(), subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_SSA_FIELD: + return dest->SetVarSSAField(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + GetOffset(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_SET_VAR_ALIASED_FIELD: + return dest->SetVarAliasedField(size, GetDestSSAVariable().var, + GetDestSSAVariable().version, + GetSourceSSAVariable().version, + GetOffset(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_VAR: + return dest->Var(size, GetSourceVariable(), *this); + case MLIL_VAR_FIELD: + return dest->VarField(size, GetSourceVariable(), + GetOffset(), *this); + case MLIL_VAR_SSA: + return dest->VarSSA(size, GetSourceSSAVariable(), *this); + case MLIL_VAR_SSA_FIELD: + return dest->VarSSAField(size, GetSourceSSAVariable(), + GetOffset(), *this); + case MLIL_VAR_ALIASED: + return dest->VarAliased(size, GetSourceSSAVariable().var, + GetSourceSSAVariable().version, *this); + case MLIL_VAR_ALIASED_FIELD: + return dest->VarAliasedField(size, GetSourceSSAVariable().var, + GetSourceSSAVariable().version, + GetOffset(), *this); + case MLIL_ADDRESS_OF: + return dest->AddressOf(GetSourceVariable(), *this); + case MLIL_ADDRESS_OF_FIELD: + return dest->AddressOfField(GetSourceVariable(), + GetOffset(), *this); + case MLIL_CALL: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Call(GetOutputVariables(), subExprHandler(GetDestExpr()), + params, *this); + case MLIL_CALL_UNTYPED: + return dest->CallUntyped(GetOutputVariables(), + subExprHandler(GetDestExpr()), GetParameterVariables(), + subExprHandler(GetStackExpr()), *this); + case MLIL_CALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->CallSSA(GetOutputSSAVariables(), subExprHandler(GetDestExpr()), + params, GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case MLIL_CALL_UNTYPED_SSA: + return dest->CallUntypedSSA(GetOutputSSAVariables(), + subExprHandler(GetDestExpr()), + GetParameterSSAVariables(), + GetDestMemoryVersion(), + GetSourceMemoryVersion(), + subExprHandler(GetStackExpr()), *this); + case MLIL_SYSCALL: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Syscall(GetOutputVariables(), params, *this); + case MLIL_SYSCALL_UNTYPED: + return dest->SyscallUntyped(GetOutputVariables(), + GetParameterVariables(), + subExprHandler(GetStackExpr()), *this); + case MLIL_SYSCALL_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->SyscallSSA(GetOutputSSAVariables(), params, + GetDestMemoryVersion(), GetSourceMemoryVersion(), *this); + case MLIL_SYSCALL_UNTYPED_SSA: + return dest->SyscallUntypedSSA(GetOutputSSAVariables(), + GetParameterSSAVariables(), + GetDestMemoryVersion(), + GetSourceMemoryVersion(), + subExprHandler(GetStackExpr()), *this); + case MLIL_RET: + for (auto& i : GetSourceExprs()) + params.push_back(subExprHandler(i)); + return dest->Return(params, *this); + case MLIL_NORET: + return dest->NoReturn(*this); + case MLIL_STORE: + return dest->Store(size, subExprHandler(GetDestExpr()), + subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_STRUCT: + return dest->StoreStruct(size, subExprHandler(GetDestExpr()), + GetOffset(), subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_SSA: + return dest->StoreSSA(size, subExprHandler(GetDestExpr()), + GetDestMemoryVersion(), GetSourceMemoryVersion(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_STORE_STRUCT_SSA: + return dest->StoreStructSSA(size, subExprHandler(GetDestExpr()), + GetOffset(), + GetDestMemoryVersion(), GetSourceMemoryVersion(), + subExprHandler(GetSourceExpr()), *this); + case MLIL_LOAD: + return dest->Load(size, subExprHandler(GetSourceExpr()), *this); + case MLIL_LOAD_STRUCT: + return dest->LoadStruct(size, subExprHandler(GetSourceExpr()), + GetOffset(), *this); + case MLIL_LOAD_SSA: + return dest->LoadSSA(size, subExprHandler(GetSourceExpr()), + GetSourceMemoryVersion(), *this); + case MLIL_LOAD_STRUCT_SSA: + return dest->LoadStructSSA(size, subExprHandler(GetSourceExpr()), + GetOffset(), GetSourceMemoryVersion(), *this); + case MLIL_NEG: + case MLIL_NOT: + case MLIL_SX: + case MLIL_ZX: + case MLIL_LOW_PART: + case MLIL_BOOL_TO_INT: + case MLIL_JUMP: + case MLIL_UNIMPL_MEM: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsOneOperand().GetSourceExpr())); + case MLIL_ADD: + case MLIL_SUB: + case MLIL_AND: + case MLIL_OR: + case MLIL_XOR: + case MLIL_LSL: + case MLIL_LSR: + case MLIL_ASR: + case MLIL_ROL: + case MLIL_ROR: + case MLIL_MUL: + case MLIL_MULU_DP: + case MLIL_MULS_DP: + case MLIL_DIVU: + case MLIL_DIVS: + case MLIL_MODU: + case MLIL_MODS: + case MLIL_CMP_E: + case MLIL_CMP_NE: + case MLIL_CMP_SLT: + case MLIL_CMP_ULT: + case MLIL_CMP_SLE: + case MLIL_CMP_ULE: + case MLIL_CMP_SGE: + case MLIL_CMP_UGE: + case MLIL_CMP_SGT: + case MLIL_CMP_UGT: + case MLIL_TEST_BIT: + case MLIL_ADD_OVERFLOW: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); + case MLIL_ADC: + case MLIL_SBB: + case MLIL_RLC: + case MLIL_RRC: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), + subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), + subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case MLIL_DIVU_DP: + case MLIL_DIVS_DP: + case MLIL_MODU_DP: + case MLIL_MODS_DP: + return dest->AddExprWithLocation(operation, *this, size, + subExprHandler(AsDoublePrecision().GetHighExpr()), + subExprHandler(AsDoublePrecision().GetLowExpr()), + subExprHandler(AsDoublePrecision().GetRightExpr())); + case MLIL_JUMP_TO: + for (auto target : GetTargetList()) + { + labelA = dest->GetLabelForSourceInstruction(target); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr()), *this); + labelList.push_back(labelA); + } + return dest->JumpTo(subExprHandler(GetDestExpr()), labelList, *this); + case MLIL_GOTO: + labelA = dest->GetLabelForSourceInstruction(GetTarget()); + if (!labelA) + { + return dest->Jump(dest->ConstPointer(function->GetArchitecture()->GetAddressSize(), + function->GetInstruction(GetTarget()).address), *this); + } + return dest->Goto(*labelA, *this); + case MLIL_IF: + labelA = dest->GetLabelForSourceInstruction(GetTrueTarget()); + labelB = dest->GetLabelForSourceInstruction(GetFalseTarget()); + if ((!labelA) || (!labelB)) + return dest->Undefined(*this); + return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, *this); + case MLIL_CONST: + return dest->Const(size, GetConstant(), *this); + case MLIL_CONST_PTR: + return dest->ConstPointer(size, GetConstant(), *this); + case MLIL_BP: + return dest->Breakpoint(*this); + case MLIL_TRAP: + return dest->Trap(GetVector(), *this); + case MLIL_UNDEF: + return dest->Undefined(*this); + case MLIL_UNIMPL: + return dest->Unimplemented(*this); + default: + throw MediumLevelILInstructionAccessException(); + } +} + + +bool MediumLevelILInstruction::GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const +{ + auto operationIter = MediumLevelILInstructionBase::operationOperandIndex.find(operation); + if (operationIter == MediumLevelILInstructionBase::operationOperandIndex.end()) + return false; + auto usageIter = operationIter->second.find(usage); + if (usageIter == operationIter->second.end()) + return false; + operandIndex = usageIter->second; + return true; +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetSourceExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetSourceVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetSourceSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + if (GetOperandIndexForUsage(PartialSSAVariableSourceMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsPartialSSAVariableSource(operandIndex - 2); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetDestExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetDestVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetDestSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLeftExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LeftExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetRightExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(RightExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetCarryExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(CarryExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetHighExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetLowExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetStackExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(StackExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstruction MediumLevelILInstruction::GetConditionExpr() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConditionExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetHighVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +Variable MediumLevelILInstruction::GetLowVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetHighSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(HighSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +SSAVariable MediumLevelILInstruction::GetLowSSAVariable() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(LowSSAVariableMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariable(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +uint64_t MediumLevelILInstruction::GetOffset() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OffsetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetConstant() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ConstantMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +int64_t MediumLevelILInstruction::GetVector() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(VectorMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetTrueTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TrueTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetFalseTarget() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(FalseTargetMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetDestMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(DestMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(OutputSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +size_t MediumLevelILInstruction::GetSourceMemoryVersion() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndex(operandIndex); + if (GetOperandIndexForUsage(ParameterSSAMemoryVersionMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsIndex(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetTargetList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(TargetListMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexList MediumLevelILInstruction::GetSourceMemoryVersions() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceMemoryVersionsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetOutputVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsVariableList(operandIndex); + if (GetOperandIndexForUsage(OutputVariablesSubExprMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetParameterExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILInstructionList MediumLevelILInstruction::GetSourceExprs() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceExprsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExprList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILVariableList MediumLevelILInstruction::GetParameterVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsVariableList(0); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetParameterSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(ParameterSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILSSAVariableList MediumLevelILInstruction::GetSourceSSAVariables() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SourceSSAVariablesMediumLevelOperandUsages, operandIndex)) + return GetRawOperandAsSSAVariableList(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + +ExprId MediumLevelILFunction::Nop(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOP, loc, 0); +} + + +ExprId MediumLevelILFunction::SetVar(size_t size, const Variable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR, loc, size, dest.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarField(size_t size, const Variable& dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_FIELD, loc, size, dest.ToIdentifier(), offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSplit(size_t size, const Variable& high, const Variable& low, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT, loc, size, high.ToIdentifier(), low.ToIdentifier(), src); +} + + +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const SSAVariable& dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA, loc, size, dest.var.ToIdentifier(), dest.version, src); +} + + +ExprId MediumLevelILFunction::SetVarSSAField(size_t size, const Variable& dest, + size_t newVersion, size_t prevVersion, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SSA_FIELD, loc, size, dest.ToIdentifier(), newVersion, prevVersion, + offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSSASplit(size_t size, const SSAVariable& high, const SSAVariable& low, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_SPLIT_SSA, loc, size, high.var.ToIdentifier(), high.version, + low.var.ToIdentifier(), low.version, src); +} + + +ExprId MediumLevelILFunction::SetVarAliased(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::SetVarAliasedField(size_t size, const Variable& dest, + size_t newMemVersion, size_t prevMemVersion, + uint64_t offset, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SET_VAR_ALIASED_FIELD, loc, size, dest.ToIdentifier(), + newMemVersion, prevMemVersion, offset, src); +} + + +ExprId MediumLevelILFunction::Load(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD, loc, size, src); +} + + +ExprId MediumLevelILFunction::LoadStruct(size_t size, ExprId src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT, loc, size, src, offset); +} + + +ExprId MediumLevelILFunction::LoadSSA(size_t size, ExprId src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_SSA, loc, size, src, memVersion); +} + + +ExprId MediumLevelILFunction::LoadStructSSA(size_t size, ExprId src, uint64_t offset, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOAD_STRUCT_SSA, loc, size, src, offset, memVersion); +} + + +ExprId MediumLevelILFunction::Store(size_t size, ExprId dest, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE, loc, size, dest, src); +} + + +ExprId MediumLevelILFunction::StoreStruct(size_t size, ExprId dest, uint64_t offset, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT, loc, size, dest, offset, src); +} + + +ExprId MediumLevelILFunction::StoreSSA(size_t size, ExprId dest, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_SSA, loc, size, dest, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::StoreStructSSA(size_t size, ExprId dest, uint64_t offset, + size_t newMemVersion, size_t prevMemVersion, ExprId src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_STORE_STRUCT_SSA, loc, size, dest, offset, newMemVersion, prevMemVersion, src); +} + + +ExprId MediumLevelILFunction::Var(size_t size, const Variable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR, loc, size, src.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::VarField(size_t size, const Variable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_FIELD, loc, size, src.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::VarSSA(size_t size, const SSAVariable& src, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA, loc, size, src.var.ToIdentifier(), src.version); +} + + +ExprId MediumLevelILFunction::VarSSAField(size_t size, const SSAVariable& src, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_SSA_FIELD, loc, size, src.var.ToIdentifier(), src.version, offset); +} + + +ExprId MediumLevelILFunction::VarAliased(size_t size, const Variable& src, size_t memVersion, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED, loc, size, src.ToIdentifier(), memVersion); +} + + +ExprId MediumLevelILFunction::VarAliasedField(size_t size, const Variable& src, + size_t memVersion, uint64_t offset, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_ALIASED_FIELD, loc, size, src.ToIdentifier(), memVersion, offset); +} + + +ExprId MediumLevelILFunction::AddressOf(const Variable& var, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF, loc, 0, var.ToIdentifier()); +} + + +ExprId MediumLevelILFunction::AddressOfField(const Variable& var, uint64_t offset, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADDRESS_OF_FIELD, loc, 0, var.ToIdentifier(), offset); +} + + +ExprId MediumLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST, loc, size, val); +} + + +ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CONST_PTR, loc, size, val); +} + + +ExprId MediumLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADD, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SUB, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SBB, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_AND, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_OR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_XOR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ShiftLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::LogicalShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LSR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ArithShiftRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ASR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeft(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::RotateRight(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ROR, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RRC, loc, size, left, right, carry); +} + + +ExprId MediumLevelILFunction::Mult(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MUL, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULS_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MULU_DP, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_DIVU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModSigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecSigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODS_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId high, ExprId low, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MODU_DP, loc, size, high, low, right); +} + + +ExprId MediumLevelILFunction::Neg(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NEG, loc, size, src); +} + + +ExprId MediumLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NOT, loc, size, src); +} + + +ExprId MediumLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SX, loc, size, src); +} + + +ExprId MediumLevelILFunction::ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ZX, loc, size, src); +} + + +ExprId MediumLevelILFunction::LowPart(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_LOW_PART, loc, size, src); +} + + +ExprId MediumLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP, loc, 0, dest); +} + + +ExprId MediumLevelILFunction::JumpTo(ExprId dest, const vector& targets, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size(), AddLabelList(targets)); +} + + +ExprId MediumLevelILFunction::Call(const vector& output, ExprId dest, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL, loc, 0, output.size(), AddVariableList(output), dest, + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::CallUntyped(const vector& output, ExprId dest, + const vector& params, ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Syscall(const vector& output, const vector& params, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL, loc, 0, output.size(), AddVariableList(output), + params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::SyscallUntyped(const vector& output, const vector& params, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT, loc, 0, output.size(), AddVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM, loc, 0, params.size(), AddVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::CallSSA(const vector& output, ExprId dest, const vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::CallUntypedSSA(const vector& output, ExprId dest, + const vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), dest, + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::SyscallSSA(const vector& output, const vector& params, + size_t newMemVersion, size_t prevMemVersion, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + params.size(), AddOperandList(params), prevMemVersion); +} + + +ExprId MediumLevelILFunction::SyscallUntypedSSA(const vector& output, + const vector& params, size_t newMemVersion, size_t prevMemVersion, + ExprId stack, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_SYSCALL_UNTYPED_SSA, loc, 0, + AddExprWithLocation(MLIL_CALL_OUTPUT_SSA, loc, 0, newMemVersion, + output.size() * 2, AddSSAVariableList(output)), + AddExprWithLocation(MLIL_CALL_PARAM_SSA, loc, 0, prevMemVersion, + params.size() * 2, AddSSAVariableList(params)), stack); +} + + +ExprId MediumLevelILFunction::Return(const vector& sources, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RET, loc, 0, sources.size(), AddOperandList(sources)); +} + + +ExprId MediumLevelILFunction::NoReturn(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_NORET, loc, 0); +} + + +ExprId MediumLevelILFunction::CompareEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_E, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareNotEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_NE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SLE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_ULE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGE, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_SGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CMP_UGT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::TestBit(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TEST_BIT, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BOOL_TO_INT, loc, size, src); +} + + +ExprId MediumLevelILFunction::AddOverflow(size_t size, ExprId left, ExprId right, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_ADD_OVERFLOW, loc, size, left, right); +} + + +ExprId MediumLevelILFunction::Breakpoint(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BP, loc, 0); +} + + +ExprId MediumLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_TRAP, loc, 0, vector); +} + + +ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNDEF, loc, 0); +} + + +ExprId MediumLevelILFunction::Unimplemented(const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL, loc, 0); +} + + +ExprId MediumLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId target, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_UNIMPL_MEM, loc, size, target); +} + + +ExprId MediumLevelILFunction::VarPhi(const SSAVariable& dest, const vector& sources, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_VAR_PHI, loc, 0, dest.var.ToIdentifier(), dest.version, + sources.size() * 2, AddSSAVariableList(sources)); +} + + +ExprId MediumLevelILFunction::MemoryPhi(size_t destMemVersion, const vector& sourceMemVersions, + const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_MEM_PHI, loc, 0, destMemVersion, + sourceMemVersions.size(), AddIndexList(sourceMemVersions)); +} diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h new file mode 100644 index 00000000..ef5e7567 --- /dev/null +++ b/mediumlevelilinstruction.h @@ -0,0 +1,982 @@ +// Copyright (c) 2015-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. + +#pragma once + +#include +#include +#include +#ifdef BINARYNINJACORE_LIBRARY +#include "variable.h" +#else +#include "binaryninjaapi.h" +#endif + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILFunction; + + template + struct MediumLevelILInstructionAccessor {}; + + struct MediumLevelILInstruction; + struct MediumLevelILConstantInstruction; + struct MediumLevelILOneOperandInstruction; + struct MediumLevelILTwoOperandInstruction; + struct MediumLevelILTwoOperandWithCarryInstruction; + struct MediumLevelILDoublePrecisionInstruction; + struct MediumLevelILLabel; + struct LowLevelILInstruction; + class MediumLevelILOperand; + class MediumLevelILOperandList; + + struct SSAVariable + { + Variable var; + size_t version; + + SSAVariable(); + SSAVariable(const Variable& v, size_t i); + SSAVariable(const SSAVariable& v); + + SSAVariable& operator=(const SSAVariable& v); + bool operator==(const SSAVariable& v) const; + bool operator!=(const SSAVariable& v) const; + bool operator<(const SSAVariable& v) const; + }; + + enum MediumLevelILOperandType + { + IntegerMediumLevelOperand, + IndexMediumLevelOperand, + ExprMediumLevelOperand, + VariableMediumLevelOperand, + SSAVariableMediumLevelOperand, + IndexListMediumLevelOperand, + VariableListMediumLevelOperand, + SSAVariableListMediumLevelOperand, + ExprListMediumLevelOperand + }; + + enum MediumLevelILOperandUsage + { + SourceExprMediumLevelOperandUsage, + SourceVariableMediumLevelOperandUsage, + SourceSSAVariableMediumLevelOperandUsage, + PartialSSAVariableSourceMediumLevelOperandUsage, + DestExprMediumLevelOperandUsage, + DestVariableMediumLevelOperandUsage, + DestSSAVariableMediumLevelOperandUsage, + LeftExprMediumLevelOperandUsage, + RightExprMediumLevelOperandUsage, + CarryExprMediumLevelOperandUsage, + HighExprMediumLevelOperandUsage, + LowExprMediumLevelOperandUsage, + StackExprMediumLevelOperandUsage, + ConditionExprMediumLevelOperandUsage, + HighVariableMediumLevelOperandUsage, + LowVariableMediumLevelOperandUsage, + HighSSAVariableMediumLevelOperandUsage, + LowSSAVariableMediumLevelOperandUsage, + OffsetMediumLevelOperandUsage, + ConstantMediumLevelOperandUsage, + VectorMediumLevelOperandUsage, + TargetMediumLevelOperandUsage, + TrueTargetMediumLevelOperandUsage, + FalseTargetMediumLevelOperandUsage, + DestMemoryVersionMediumLevelOperandUsage, + SourceMemoryVersionMediumLevelOperandUsage, + TargetListMediumLevelOperandUsage, + SourceMemoryVersionsMediumLevelOperandUsage, + OutputVariablesMediumLevelOperandUsage, + OutputVariablesSubExprMediumLevelOperandUsage, + OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAMemoryVersionMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage, + SourceExprsMediumLevelOperandUsage, + ParameterVariablesMediumLevelOperandUsage, + ParameterSSAVariablesMediumLevelOperandUsage, + ParameterSSAMemoryVersionMediumLevelOperandUsage, + SourceSSAVariablesMediumLevelOperandUsages + }; +} + +namespace std +{ +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::SSAVariable argument_type; +#else + typedef BinaryNinja::SSAVariable argument_type; +#endif + typedef uint64_t result_type; + result_type operator()(argument_type const& value) const + { + return ((result_type)value.var.ToIdentifier()) ^ ((result_type)value.version << 40); + } + }; + + template<> struct hash + { + typedef BNMediumLevelILOperation argument_type; + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; + +#ifdef BINARYNINJACORE_LIBRARY + template<> struct hash +#else + template<> struct hash +#endif + { +#ifdef BINARYNINJACORE_LIBRARY + typedef BinaryNinjaCore::MediumLevelILOperandUsage argument_type; +#else + typedef BinaryNinja::MediumLevelILOperandUsage argument_type; +#endif + typedef int result_type; + result_type operator()(argument_type const& value) const + { + return (result_type)value; + } + }; +} + +#ifdef BINARYNINJACORE_LIBRARY +namespace BinaryNinjaCore +#else +namespace BinaryNinja +#endif +{ + class MediumLevelILInstructionAccessException: public std::exception + { + public: + MediumLevelILInstructionAccessException(): std::exception() {} + virtual const char* what() const NOEXCEPT { return "invalid access to MLIL instruction"; } + }; + + class MediumLevelILIntegerList + { + struct ListIterator + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; + const BNMediumLevelILInstruction* instr; +#else + Ref function; + BNMediumLevelILInstruction instr; +#endif + size_t operand, count; + + bool operator==(const ListIterator& a) const; + bool operator!=(const ListIterator& a) const; + bool operator<(const ListIterator& a) const; + ListIterator& operator++(); + uint64_t operator*(); + MediumLevelILFunction* GetFunction() const { return function; } + }; + + ListIterator m_start; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIntegerList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + uint64_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILIndexList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + size_t operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIndexList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const Variable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const Variable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILSSAVariableList + { + struct ListIterator + { + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSAVariable operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILSSAVariableList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSAVariable operator[](size_t i) const; + + operator std::vector() const; + }; + + class MediumLevelILInstructionList + { + struct ListIterator + { + size_t instructionIndex; + MediumLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const MediumLevelILInstruction operator*(); + }; + + MediumLevelILIntegerList m_list; + size_t m_instructionIndex; + + public: + typedef ListIterator const_iterator; + + MediumLevelILInstructionList(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count, + size_t instructionIndex); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILInstruction operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILInstructionBase: public BNMediumLevelILInstruction + { +#ifdef BINARYNINJACORE_LIBRARY + MediumLevelILFunction* function; +#else + Ref function; +#endif + size_t exprIndex, instructionIndex; + + static std::unordered_map operandTypeForUsage; + static std::unordered_map> operationOperandUsage; + static std::unordered_map> operationOperandIndex; + + MediumLevelILOperandList GetOperands() const; + + uint64_t GetRawOperandAsInteger(size_t operand) const; + size_t GetRawOperandAsIndex(size_t operand) const; + MediumLevelILInstruction GetRawOperandAsExpr(size_t operand) const; + Variable GetRawOperandAsVariable(size_t operand) const; + SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; + SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const; + MediumLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; + MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; + MediumLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + + void UpdateRawOperand(size_t operandIndex, ExprId value); + void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const std::vector& vars); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector& exprs); + + RegisterValue GetValue() const; + PossibleValueSet GetPossibleValues() const; + Confidence> GetType() const; + + size_t GetSSAVarVersion(const Variable& var); + size_t GetSSAMemoryVersion(); + Variable GetVariableForRegister(uint32_t reg); + Variable GetVariableForFlag(uint32_t flag); + Variable GetVariableForStackLocation(int64_t offset); + + PossibleValueSet GetPossibleSSAVarValues(const SSAVariable& var); + RegisterValue GetRegisterValue(uint32_t reg); + RegisterValue GetRegisterValueAfter(uint32_t reg); + PossibleValueSet GetPossibleRegisterValues(uint32_t reg); + PossibleValueSet GetPossibleRegisterValuesAfter(uint32_t reg); + RegisterValue GetFlagValue(uint32_t flag); + RegisterValue GetFlagValueAfter(uint32_t flag); + PossibleValueSet GetPossibleFlagValues(uint32_t flag); + PossibleValueSet GetPossibleFlagValuesAfter(uint32_t flag); + RegisterValue GetStackContents(int32_t offset, size_t len); + RegisterValue GetStackContentsAfter(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContents(int32_t offset, size_t len); + PossibleValueSet GetPossibleStackContentsAfter(int32_t offset, size_t len); + + BNILBranchDependence GetBranchDependence(size_t branchInstr); + BNILBranchDependence GetBranchDependence(const MediumLevelILInstruction& branch); + std::unordered_map GetAllBranchDependence(); + + size_t GetSSAInstructionIndex() const; + size_t GetNonSSAInstructionIndex() const; + size_t GetSSAExprIndex() const; + size_t GetNonSSAExprIndex() const; + + MediumLevelILInstruction GetSSAForm() const; + MediumLevelILInstruction GetNonSSAForm() const; + + size_t GetLowLevelILInstructionIndex() const; + size_t GetLowLevelILExprIndex() const; + + bool HasLowLevelIL() const; + LowLevelILInstruction GetLowLevelIL() const; + + void MarkInstructionForRemoval(); + void Replace(ExprId expr); + + template + MediumLevelILInstructionAccessor& As() + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(MediumLevelILInstructionAccessor*)this; + } + MediumLevelILOneOperandInstruction& AsOneOperand() + { + return *(MediumLevelILOneOperandInstruction*)this; + } + MediumLevelILTwoOperandInstruction& AsTwoOperand() + { + return *(MediumLevelILTwoOperandInstruction*)this; + } + MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() + { + return *(MediumLevelILTwoOperandWithCarryInstruction*)this; + } + MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() + { + return *(MediumLevelILDoublePrecisionInstruction*)this; + } + + template + const MediumLevelILInstructionAccessor& As() const + { + if (operation != N) + throw MediumLevelILInstructionAccessException(); + return *(const MediumLevelILInstructionAccessor*)this; + } + const MediumLevelILConstantInstruction& AsConstant() const + { + return *(const MediumLevelILConstantInstruction*)this; + } + const MediumLevelILOneOperandInstruction& AsOneOperand() const + { + return *(const MediumLevelILOneOperandInstruction*)this; + } + const MediumLevelILTwoOperandInstruction& AsTwoOperand() const + { + return *(const MediumLevelILTwoOperandInstruction*)this; + } + const MediumLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const + { + return *(const MediumLevelILTwoOperandWithCarryInstruction*)this; + } + const MediumLevelILDoublePrecisionInstruction& AsDoublePrecision() const + { + return *(const MediumLevelILDoublePrecisionInstruction*)this; + } + }; + + struct MediumLevelILInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction(); + MediumLevelILInstruction(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, + size_t expr, size_t instrIdx); + MediumLevelILInstruction(const MediumLevelILInstructionBase& instr); + + void VisitExprs(const std::function& func) const; + + ExprId CopyTo(MediumLevelILFunction* dest) const; + ExprId CopyTo(MediumLevelILFunction* dest, + const std::function& subExprHandler) const; + + // Templated accessors for instruction operands, use these for efficient access to a known instruction + template MediumLevelILInstruction GetSourceExpr() const { return As().GetSourceExpr(); } + template Variable GetSourceVariable() const { return As().GetSourceVariable(); } + template SSAVariable GetSourceSSAVariable() const { return As().GetSourceSSAVariable(); } + template MediumLevelILInstruction GetDestExpr() const { return As().GetDestExpr(); } + template Variable GetDestVariable() const { return As().GetDestVariable(); } + template SSAVariable GetDestSSAVariable() const { return As().GetDestSSAVariable(); } + template MediumLevelILInstruction GetLeftExpr() const { return As().GetLeftExpr(); } + template MediumLevelILInstruction GetRightExpr() const { return As().GetRightExpr(); } + template MediumLevelILInstruction GetCarryExpr() const { return As().GetCarryExpr(); } + template MediumLevelILInstruction GetHighExpr() const { return As().GetHighExpr(); } + template MediumLevelILInstruction GetLowExpr() const { return As().GetLowExpr(); } + template MediumLevelILInstruction GetStackExpr() const { return As().GetStackExpr(); } + template MediumLevelILInstruction GetConditionExpr() const { return As().GetConditionExpr(); } + template Variable GetHighVariable() const { return As().GetHighVariable(); } + template Variable GetLowVariable() const { return As().GetLowVariable(); } + template SSAVariable GetHighSSAVariable() const { return As().GetHighSSAVariable(); } + template SSAVariable GetLowSSAVariable() const { return As().GetLowSSAVariable(); } + template uint64_t GetOffset() const { return As().GetOffset(); } + template int64_t GetConstant() const { return As().GetConstant(); } + template int64_t GetVector() const { return As().GetVector(); } + template size_t GetTarget() const { return As().GetTarget(); } + template size_t GetTrueTarget() const { return As().GetTrueTarget(); } + template size_t GetFalseTarget() const { return As().GetFalseTarget(); } + template size_t GetDestMemoryVersion() const { return As().GetDestMemoryVersion(); } + template size_t GetSourceMemoryVersion() const { return As().GetSourceMemoryVersion(); } + template MediumLevelILIndexList GetTargetList() const { return As().GetTargetList(); } + template MediumLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } + template MediumLevelILVariableList GetOutputVariables() const { return As().GetOutputVariables(); } + template MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As().GetOutputSSAVariables(); } + template MediumLevelILInstructionList GetParameterExprs() const { return As().GetParameterExprs(); } + template MediumLevelILInstructionList GetSourceExprs() const { return As().GetSourceExprs(); } + template MediumLevelILVariableList GetParameterVariables() const { return As().GetParameterVariables(); } + template MediumLevelILSSAVariableList GetParameterSSAVariables() const { return As().GetParameterSSAVariables(); } + template MediumLevelILSSAVariableList GetSourceSSAVariables() const { return As().GetSourceSSAVariables(); } + + template void SetDestSSAVersion(size_t version) { As().SetDestSSAVersion(version); } + template void SetSourceSSAVersion(size_t version) { As().SetSourceSSAVersion(version); } + template void SetHighSSAVersion(size_t version) { As().SetHighSSAVersion(version); } + template void SetLowSSAVersion(size_t version) { As().SetLowSSAVersion(version); } + template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } + template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } + template void SetOutputSSAVariables(const std::vector& vars) { As().SetOutputSSAVariables(vars); } + template void SetParameterSSAVariables(const std::vector& vars) { As().SetParameterSSAVariables(vars); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + template void SetParameterExprs(const std::vector& params) { As().SetParameterExprs(params); } + + bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const; + + // Generic accessors for instruction operands, these will throw a MediumLevelILInstructionAccessException + // on type mismatch. These are slower than the templated versions above. + MediumLevelILInstruction GetSourceExpr() const; + Variable GetSourceVariable() const; + SSAVariable GetSourceSSAVariable() const; + MediumLevelILInstruction GetDestExpr() const; + Variable GetDestVariable() const; + SSAVariable GetDestSSAVariable() const; + MediumLevelILInstruction GetLeftExpr() const; + MediumLevelILInstruction GetRightExpr() const; + MediumLevelILInstruction GetCarryExpr() const; + MediumLevelILInstruction GetHighExpr() const; + MediumLevelILInstruction GetLowExpr() const; + MediumLevelILInstruction GetStackExpr() const; + MediumLevelILInstruction GetConditionExpr() const; + Variable GetHighVariable() const; + Variable GetLowVariable() const; + SSAVariable GetHighSSAVariable() const; + SSAVariable GetLowSSAVariable() const; + uint64_t GetOffset() const; + int64_t GetConstant() const; + int64_t GetVector() const; + size_t GetTarget() const; + size_t GetTrueTarget() const; + size_t GetFalseTarget() const; + size_t GetDestMemoryVersion() const; + size_t GetSourceMemoryVersion() const; + MediumLevelILIndexList GetTargetList() const; + MediumLevelILIndexList GetSourceMemoryVersions() const; + MediumLevelILVariableList GetOutputVariables() const; + MediumLevelILSSAVariableList GetOutputSSAVariables() const; + MediumLevelILInstructionList GetParameterExprs() const; + MediumLevelILInstructionList GetSourceExprs() const; + MediumLevelILVariableList GetParameterVariables() const; + MediumLevelILSSAVariableList GetParameterSSAVariables() const; + MediumLevelILSSAVariableList GetSourceSSAVariables() const; + }; + + class MediumLevelILOperand + { + MediumLevelILInstruction m_instr; + MediumLevelILOperandUsage m_usage; + MediumLevelILOperandType m_type; + size_t m_operandIndex; + + public: + MediumLevelILOperand(const MediumLevelILInstruction& instr, MediumLevelILOperandUsage usage, + size_t operandIndex); + + MediumLevelILOperandType GetType() const { return m_type; } + MediumLevelILOperandUsage GetUsage() const { return m_usage; } + + uint64_t GetInteger() const; + size_t GetIndex() const; + MediumLevelILInstruction GetExpr() const; + Variable GetVariable() const; + SSAVariable GetSSAVariable() const; + MediumLevelILIndexList GetIndexList() const; + MediumLevelILVariableList GetVariableList() const; + MediumLevelILSSAVariableList GetSSAVariableList() const; + MediumLevelILInstructionList GetExprList() const; + }; + + class MediumLevelILOperandList + { + struct ListIterator + { + const MediumLevelILOperandList* owner; + std::vector::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const MediumLevelILOperand operator*(); + }; + + MediumLevelILInstruction m_instr; + const std::vector& m_usageList; + const std::unordered_map& m_operandIndexMap; + + public: + typedef ListIterator const_iterator; + + MediumLevelILOperandList(const MediumLevelILInstruction& instr, + const std::vector& usageList, + const std::unordered_map& operandIndexMap); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const MediumLevelILOperand operator[](size_t i) const; + + operator std::vector() const; + }; + + struct MediumLevelILConstantInstruction: public MediumLevelILInstructionBase + { + int64_t GetConstant() const { return GetRawOperandAsInteger(0); } + }; + + struct MediumLevelILOneOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + }; + + struct MediumLevelILTwoOperandInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + }; + + struct MediumLevelILTwoOperandWithCarryInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); } + }; + + struct MediumLevelILDoublePrecisionInstruction: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(2); } + }; + + // Implementations of each instruction to fetch the correct operand value for the valid operands, these + // are derived from MediumLevelILInstructionBase so that invalid operand accessor functions will generate + // a compiler error. + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetDestVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetHighVariable() const { return GetRawOperandAsVariable(0); } + Variable GetLowVariable() const { return GetRawOperandAsVariable(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetHighSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetLowSSAVariable() const { return GetRawOperandAsSSAVariable(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetHighSSAVersion(size_t version) { UpdateRawOperand(1, version); } + void SetLowSSAVersion(size_t version) { UpdateRawOperand(3, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(1); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(2); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + MediumLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(4); } + void SetDestMemoryVersion(size_t version) { UpdateRawOperand(2, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(2); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(1, version); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + Variable GetSourceVariable() const { return GetRawOperandAsVariable(0); } + uint64_t GetOffset() const { return GetRawOperandAsInteger(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsVariableList(0); } + MediumLevelILVariableList GetParameterVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsVariableList(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(2); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(4); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(4, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(2, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsIndex(3); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { UpdateRawOperand(3, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + void SetParameterExprs(const std::vector& params) { UpdateRawOperandAsExprList(1, params); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); } + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSAVariableList(1); } + MediumLevelILSSAVariableList GetParameterSSAVariables() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSAVariableList(1); } + size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(0); } + MediumLevelILInstruction GetStackExpr() const { return GetRawOperandAsExpr(2); } + void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); } + void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(0, version); } + void SetOutputSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSAVariableList(1, vars); } + void SetParameterSSAVariables(const std::vector& vars) { GetRawOperandAsExpr(1).UpdateRawOperandAsSSAVariableList(1, vars); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); } + size_t GetTrueTarget() const { return GetRawOperandAsIndex(1); } + size_t GetFalseTarget() const { return GetRawOperandAsIndex(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetTarget() const { return GetRawOperandAsIndex(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + int64_t GetVector() const { return GetRawOperandAsInteger(0); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); } + MediumLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + size_t GetDestMemoryVersion() const { return GetRawOperandAsIndex(0); } + MediumLevelILIndexList GetSourceMemoryVersions() const { return GetRawOperandAsIndexList(1); } + }; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandWithCarryInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILDoublePrecisionInstruction {}; + + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILOneOperandInstruction {}; +} diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index eefbe787..8647fb35 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -39,7 +39,7 @@ class SSAVariable(object): def __eq__(self, other): return ( - (self.var.identifier, self.version) == + (self.var.identifier, self.version) == (other.var.identifier, other.version) ) @@ -90,9 +90,9 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], @@ -100,9 +100,9 @@ class MediumLevelILInstruction(object): 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_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], @@ -151,7 +151,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "ssa_var"), ("low", "ssa_var"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], -- cgit v1.3.1 From c2c0d3fbbe6341a82b088f15c8732c10ff2a8ca5 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Thu, 10 Aug 2017 14:43:55 -0400 Subject: Fix get_ssa_var_possible_values API call to core. --- python/mediumlevelil.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'python/mediumlevelil.py') diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8647fb35..feca0937 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -426,7 +426,8 @@ class MediumLevelILInstruction(object): var_data.index = ssa_var.var.index var_data.storage = ssa_var.var.storage value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) return result def get_ssa_var_version(self, var): -- cgit v1.3.1 From 22edfd701bff068067b43a8e6a682202d19ce122 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 8 Aug 2017 23:55:48 -0400 Subject: Fixing llil and mlil incoming/outgoing edges, and dominator apis --- python/basicblock.py | 18 +++++++++++------- python/lowlevelil.py | 3 +++ python/mediumlevelil.py | 4 ++++ 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'python/mediumlevelil.py') diff --git a/python/basicblock.py b/python/basicblock.py index fc7a870e..9ecf90d0 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -64,6 +64,10 @@ class BasicBlock(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _create_instance(self, view, handle): + """Internal method used to instantiante child instances""" + return BasicBlock(view, handle) + @property def function(self): """Basic block function (read-only)""" @@ -117,7 +121,7 @@ class BasicBlock(object): for i in xrange(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: - target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None result.append(BasicBlockEdge(branch_type, self, target, edges[i].backEdge)) @@ -133,7 +137,7 @@ class BasicBlock(object): for i in xrange(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: - target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: target = None result.append(BasicBlockEdge(branch_type, self, target, edges[i].backEdge)) @@ -152,7 +156,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockDominators(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -163,7 +167,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockStrictDominators(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -173,7 +177,7 @@ class BasicBlock(object): result = core.BNGetBasicBlockImmediateDominator(self.handle) if not result: return None - return BasicBlock(self.view, result) + return self._create_instance(self.view, result) @property def dominator_tree_children(self): @@ -182,7 +186,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -193,7 +197,7 @@ class BasicBlock(object): blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(BasicBlock(self.view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 9f532e6f..e50f80c6 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1716,6 +1716,9 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): else: return self.il_function[self.end + idx] + def _create_instance(self, view, handle): + """Internal method by super to instantiante child instances""" + return LowLevelILBasicBlock(view, handle, self.il_function) def LLIL_TEMP(n): return n | 0x80000000 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index feca0937..c837aa42 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -885,3 +885,7 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): return self.il_function[idx + self.start] else: return self.il_function[self.end + idx] + + def _create_instance(self, view, handle): + """Internal method by super to instantiante child instances""" + return MediumLevelILBasicBlock(view, handle, self.il_function) -- cgit v1.3.1 From 5e25409d02479285d1f16d6cc55df1b267e9ba06 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 17 Aug 2017 02:04:50 -0400 Subject: Support custom calling conventions in the type parser and type objects --- architecture.cpp | 85 ------------------------------------- binaryninjaapi.h | 81 ++++++++++++++++++----------------- binaryninjacore.h | 30 +++++++------ platform.cpp | 85 +++++++++++++++++++++++++++++++++++++ python/architecture.py | 93 ----------------------------------------- python/binaryview.py | 22 +++++----- python/function.py | 15 +++---- python/generator.cpp | 63 ++++++++++++++++++++++------ python/mediumlevelil.py | 5 ++- python/platform.py | 109 ++++++++++++++++++++++++++++++++++++++++++++---- python/types.py | 90 ++++++++++++++++++++++++++++++++------- type.cpp | 47 +++++++++++++-------- 12 files changed, 423 insertions(+), 302 deletions(-) (limited to 'python/mediumlevelil.py') diff --git a/architecture.cpp b/architecture.cpp index 8fd38de2..eb588394 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -787,91 +787,6 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n } -bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map>& types, map>& variables, - map>& functions, string& errors, const vector& includeDirs, - const string& autoTypeSource) -{ - BNTypeParserResult result; - char* errorStr; - const char** includeDirList = new const char*[includeDirs.size()]; - - for (size_t i = 0; i < includeDirs.size(); i++) - includeDirList[i] = includeDirs[i].c_str(); - - types.clear(); - variables.clear(); - functions.clear(); - - bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); - errors = errorStr; - BNFreeString(errorStr); - if (!ok) - return false; - - for (size_t i = 0; i < result.typeCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); - types[name] = new Type(BNNewTypeReference(result.types[i].type)); - } - for (size_t i = 0; i < result.variableCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); - types[name] = new Type(BNNewTypeReference(result.variables[i].type)); - } - for (size_t i = 0; i < result.functionCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); - types[name] = new Type(BNNewTypeReference(result.functions[i].type)); - } - BNFreeTypeParserResult(&result); - return true; -} - - -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, - map>& variables, map>& functions, - string& errors, const vector& includeDirs, const string& autoTypeSource) -{ - BNTypeParserResult result; - char* errorStr; - const char** includeDirList = new const char*[includeDirs.size()]; - - for (size_t i = 0; i < includeDirs.size(); i++) - includeDirList[i] = includeDirs[i].c_str(); - - types.clear(); - variables.clear(); - functions.clear(); - - bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, - includeDirList, includeDirs.size(), autoTypeSource.c_str()); - errors = errorStr; - BNFreeString(errorStr); - if (!ok) - return false; - - for (size_t i = 0; i < result.typeCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); - types[name] = new Type(BNNewTypeReference(result.types[i].type)); - } - for (size_t i = 0; i < result.variableCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); - variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); - } - for (size_t i = 0; i < result.functionCount; i++) - { - QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); - functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); - } - BNFreeTypeParserResult(&result); - return true; -} - - void Architecture::RegisterCallingConvention(CallingConvention* cc) { BNRegisterCallingConvention(m_object, cc->GetObject()); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 63cab888..8213675d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1743,19 +1743,6 @@ namespace BinaryNinja uint64_t defaultValue = 0); void SetBinaryViewTypeConstant(const std::string& type, const std::string& name, uint64_t value); - bool ParseTypesFromSource(const std::string& source, const std::string& fileName, - std::map>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector(), - const std::string& autoTypeSource = ""); - bool ParseTypesFromSourceFile(const std::string& fileName, - std::map>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector(), - const std::string& autoTypeSource = ""); - void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); Ref GetCallingConventionByName(const std::string& name); @@ -1821,10 +1808,28 @@ namespace BinaryNinja class NamedTypeReference; class Enumeration; - struct NameAndType + 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 FunctionParameter { std::string name; Confidence> type; + bool defaultLocation; + Variable location; }; struct QualifiedNameAndType @@ -1848,7 +1853,7 @@ namespace BinaryNinja bool IsFloat() const; Confidence> GetChildType() const; Confidence> GetCallingConvention() const; - std::vector GetParameters() const; + std::vector GetParameters() const; Confidence HasVariableArguments() const; Confidence CanReturn() const; Ref GetStructure() const; @@ -1867,14 +1872,17 @@ namespace BinaryNinja void SetFunctionCanReturn(const Confidence& canReturn); - std::string GetString() const; + std::string GetString(Platform* platform = nullptr) const; std::string GetTypeAndName(const QualifiedName& name) const; - std::string GetStringBeforeName() const; - std::string GetStringAfterName() const; + std::string GetStringBeforeName(Platform* platform = nullptr) const; + std::string GetStringAfterName(Platform* platform = nullptr) const; - std::vector GetTokens() const; - std::vector GetTokensBeforeName() const; - std::vector GetTokensAfterName() const; + std::vector GetTokens(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector GetTokensBeforeName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; + std::vector GetTokensAfterName(Platform* platform = nullptr, + uint8_t baseConfidence = BN_FULL_CONFIDENCE) const; Ref Duplicate() const; @@ -1897,7 +1905,7 @@ namespace BinaryNinja static Ref ArrayType(const Confidence>& type, uint64_t elem); static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg = Confidence(false, 0)); + const std::vector& params, const Confidence& varArg = Confidence(false, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2052,22 +2060,6 @@ namespace BinaryNinja static bool IsBackEdge(BasicBlock* source, BasicBlock* target); }; - 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; @@ -3178,6 +3170,19 @@ namespace BinaryNinja Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); std::string GetAutoPlatformTypeIdSource(); + + bool ParseTypesFromSource(const std::string& source, const std::string& fileName, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map>& types, + std::map>& variables, + std::map>& functions, std::string& errors, + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index 6b5d5acc..3c8757ed 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1132,11 +1132,13 @@ extern "C" uint8_t confidence; }; - struct BNNameAndType + struct BNFunctionParameter { char* name; BNType* type; uint8_t typeConfidence; + bool defaultLocation; + BNVariable location; }; struct BNQualifiedNameAndType @@ -2197,7 +2199,6 @@ extern "C" BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNQualifiedNameAndType* result, char** errors); - BINARYNINJACOREAPI void BNFreeNameAndType(BNNameAndType* obj); BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); @@ -2602,7 +2603,7 @@ extern "C" BNBoolWithConfidence* cnst, BNBoolWithConfidence* vltl, BNReferenceType refType); BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, - BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params, + BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, size_t paramCount, BNBoolWithConfidence* varArg); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); @@ -2620,8 +2621,8 @@ extern "C" BINARYNINJACOREAPI bool BNIsTypeFloatingPoint(BNType* type); BINARYNINJACOREAPI BNTypeWithConfidence BNGetChildType(BNType* type); BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type); - BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count); - BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count); + BINARYNINJACOREAPI BNFunctionParameter* BNGetTypeParameters(BNType* type, size_t* count); + BINARYNINJACOREAPI void BNFreeTypeParameterList(BNFunctionParameter* types, size_t count); BINARYNINJACOREAPI BNBoolWithConfidence BNTypeHasVariableArguments(BNType* type); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionTypeCanReturn(BNType* type); BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type); @@ -2637,12 +2638,15 @@ extern "C" BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); - BINARYNINJACOREAPI char* BNGetTypeString(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); - BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokens(BNType* type, size_t* count); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensBeforeName(BNType* type, size_t* count); - BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, size_t* count); + BINARYNINJACOREAPI char* BNGetTypeString(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type, BNPlatform* platform); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokens(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensBeforeName(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); + BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, BNPlatform* platform, + uint8_t baseConfidence, size_t* count); BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); @@ -2698,10 +2702,10 @@ extern "C" // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, const char** includeDirs, size_t includeDirCount); - BINARYNINJACOREAPI bool BNParseTypesFromSource(BNArchitecture* arch, const char* source, const char* fileName, + BINARYNINJACOREAPI bool BNParseTypesFromSource(BNPlatform* platform, const char* source, const char* fileName, BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, const char* autoTypeSource); - BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNArchitecture* arch, const char* fileName, + BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNPlatform* platform, const char* fileName, BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, const char* autoTypeSource); BINARYNINJACOREAPI void BNFreeTypeParserResult(BNTypeParserResult* result); diff --git a/platform.cpp b/platform.cpp index 2a095da2..a9ab888f 100644 --- a/platform.cpp +++ b/platform.cpp @@ -402,3 +402,88 @@ string Platform::GetAutoPlatformTypeIdSource() BNFreeString(str); return result; } + + +bool Platform::ParseTypesFromSource(const string& source, const string& fileName, + map>& types, map>& variables, + map>& functions, string& errors, const vector& includeDirs, + const string& autoTypeSource) +{ + BNTypeParserResult result; + char* errorStr; + const char** includeDirList = new const char*[includeDirs.size()]; + + for (size_t i = 0; i < includeDirs.size(); i++) + includeDirList[i] = includeDirs[i].c_str(); + + types.clear(); + variables.clear(); + functions.clear(); + + bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, + &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); + errors = errorStr; + BNFreeString(errorStr); + if (!ok) + return false; + + for (size_t i = 0; i < result.typeCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } + for (size_t i = 0; i < result.variableCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); + types[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } + for (size_t i = 0; i < result.functionCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + types[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } + BNFreeTypeParserResult(&result); + return true; +} + + +bool Platform::ParseTypesFromSourceFile(const string& fileName, map>& types, + map>& variables, map>& functions, + string& errors, const vector& includeDirs, const string& autoTypeSource) +{ + BNTypeParserResult result; + char* errorStr; + const char** includeDirList = new const char*[includeDirs.size()]; + + for (size_t i = 0; i < includeDirs.size(); i++) + includeDirList[i] = includeDirs[i].c_str(); + + types.clear(); + variables.clear(); + functions.clear(); + + bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, + includeDirList, includeDirs.size(), autoTypeSource.c_str()); + errors = errorStr; + BNFreeString(errorStr); + if (!ok) + return false; + + for (size_t i = 0; i < result.typeCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } + for (size_t i = 0; i < result.variableCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); + variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } + for (size_t i = 0; i < result.functionCount; i++) + { + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); + functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } + BNFreeTypeParserResult(&result); + return true; +} diff --git a/python/architecture.py b/python/architecture.py index 61559934..72403fec 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1674,99 +1674,6 @@ class Architecture(object): """ core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) - def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): - """ - ``parse_types_from_source`` parses the source string and any needed headers searching for them in - the optional list of directories provided in ``include_dirs``. - - :param str source: source string to be parsed - :param str filename: optional source filename - :param list(str) include_dirs: optional list of string filename include directories - :param str auto_type_source: optional source of types if used for automatically generated types - :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult - :Example: - - >>> arch.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') - ({types: {'bas': }, variables: {'foo': }, functions:{'bar': - }}, '') - >>> - """ - - if filename is None: - filename = "input" - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, - len(include_dirs), auto_type_source) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - raise SyntaxError(error_str) - type_dict = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) - core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) - - def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): - """ - ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in - the optional list of directories provided in ``include_dirs``. - - :param str filename: filename of file to be parsed - :param list(str) include_dirs: optional list of string filename include directories - :param str auto_type_source: optional source of types if used for automatically generated types - :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) - :rtype: TypeParserResult - :Example: - - >>> file = "/Users/binja/tmp.c" - >>> open(file).read() - 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' - >>> arch.parse_types_from_source_file(file) - ({types: {'bas': }, variables: {'foo': }, functions: - {'bar': }}, '') - >>> - """ - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, - len(include_dirs), auto_type_source) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - raise SyntaxError(error_str) - type_dict = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type)) - core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) - def register_calling_convention(self, cc): """ ``register_calling_convention`` registers a new calling convention for the Architecture. diff --git a/python/binaryview.py b/python/binaryview.py index a43bd5b5..bdba11af 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -217,7 +217,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_added(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type), confidence = var[0].typeConfidence) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_added(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -226,7 +226,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_removed(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type), confidence = var[0].typeConfidence) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_removed(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -235,7 +235,7 @@ class BinaryDataNotificationCallbacks(object): def _data_var_updated(self, ctxt, view, var): try: address = var[0].address - var_type = types.Type(core.BNNewTypeReference(var[0].type), confidence = var[0].typeConfidence) + var_type = types.Type(core.BNNewTypeReference(var[0].type), platform = self.view.platform, confidence = var[0].typeConfidence) auto_discovered = var[0].autoDiscovered self.notify.data_var_updated(self.view, DataVariable(address, var_type, auto_discovered)) except: @@ -256,14 +256,14 @@ class BinaryDataNotificationCallbacks(object): def _type_defined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_defined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_defined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj), platform = self.view.platform)) except: log.log_error(traceback.format_exc()) def _type_undefined(self, ctxt, view, name, type_obj): try: qualified_name = types.QualifiedName._from_core_struct(name[0]) - self.notify.type_undefined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj))) + self.notify.type_undefined(view, qualified_name, types.Type(core.BNNewTypeReference(type_obj), platform = self.view.platform)) except: log.log_error(traceback.format_exc()) @@ -860,7 +860,7 @@ class BinaryView(object): result = {} for i in xrange(0, count.value): addr = var_list[i].address - var_type = types.Type(core.BNNewTypeReference(var_list[i].type), confidence = var_list[i].typeConfidence) + var_type = types.Type(core.BNNewTypeReference(var_list[i].type), platform = self.platform, confidence = var_list[i].typeConfidence) auto_discovered = var_list[i].autoDiscovered result[addr] = DataVariable(addr, var_type, auto_discovered) core.BNFreeDataVariables(var_list, count.value) @@ -874,7 +874,7 @@ class BinaryView(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self.platform) core.BNFreeTypeList(type_list, count.value) return result @@ -1915,7 +1915,7 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, types.Type(var.type, confidence = var.typeConfidence), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type, platform = self.platform, confidence = var.typeConfidence), var.autoDiscovered) def get_functions_containing(self, addr): """ @@ -2918,7 +2918,7 @@ class BinaryView(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError(error_str) - type_obj = types.Type(core.BNNewTypeReference(result.type)) + type_obj = types.Type(core.BNNewTypeReference(result.type), platform = self.platform) name = types.QualifiedName._from_core_struct(result.name) core.BNFreeQualifiedNameAndType(result) return type_obj, name @@ -2942,7 +2942,7 @@ class BinaryView(object): obj = core.BNGetAnalysisTypeByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self.platform) def get_type_by_id(self, id): """ @@ -2963,7 +2963,7 @@ class BinaryView(object): obj = core.BNGetAnalysisTypeById(self.handle, id) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self.platform) def get_type_name_by_id(self, id): """ diff --git a/python/function.py b/python/function.py index cf9bd759..55151e16 100644 --- a/python/function.py +++ b/python/function.py @@ -211,7 +211,7 @@ class Variable(object): if var_type is None: var_type_conf = core.BNGetVariableType(func.handle, var) if var_type_conf.type: - var_type = types.Type(var_type_conf.type, confidence = var_type_conf.confidence) + var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence) else: var_type = None @@ -443,7 +443,7 @@ class Function(object): @property def function_type(self): """Function type object""" - return types.Type(core.BNGetFunctionType(self.handle)) + return types.Type(core.BNGetFunctionType(self.handle), platform = self.platform) @function_type.setter def function_type(self, value): @@ -457,7 +457,7 @@ class Function(object): 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), confidence = v[i].typeConfidence))) + types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -470,7 +470,7 @@ class Function(object): 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), confidence = v[i].typeConfidence))) + types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) core.BNFreeVariableList(v, count.value) return result @@ -518,7 +518,7 @@ class Function(object): result = core.BNGetFunctionReturnType(self.handle) if not result.type: return None - return types.Type(result.type, confidence = result.confidence) + return types.Type(result.type, platform = self.platform, confidence = result.confidence) @return_type.setter def return_type(self, value): @@ -778,7 +778,7 @@ class Function(object): refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - var_type = types.Type(core.BNNewTypeReference(refs[i].type), confidence = refs[i].typeConfidence) + var_type = types.Type(core.BNNewTypeReference(refs[i].type), platform = self.platform, confidence = refs[i].typeConfidence) 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, refs[i].size)) @@ -1132,7 +1132,8 @@ class Function(object): 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), confidence = found_var.typeConfidence)) + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type), platform = self.platform, + confidence = found_var.typeConfidence)) core.BNFreeVariableNameAndType(found_var) return result diff --git a/python/generator.cpp b/python/generator.cpp index 554f82cd..f838b36d 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -172,7 +172,7 @@ int main(int argc, char* argv[]) return 1; } - bool ok = arch->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); + bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "Errors: %s", errors.c_str()); if (!ok) return 1; @@ -237,22 +237,61 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Structure definitions\n"); + set structsToProcess; + set finishedStructs; for (auto& i : types) + structsToProcess.insert(i.first); + while (structsToProcess.size() != 0) { - string name; - if (i.first.size() != 1) - continue; - name = i.first[0]; - if ((i.second->GetClass() == StructureTypeClass) && (i.second->GetStructure()->GetMembers().size() != 0)) + set currentStructList = structsToProcess; + structsToProcess.clear(); + bool processedSome = false; + for (auto& i : currentStructList) { - fprintf(out, "%s._fields_ = [\n", name.c_str()); - for (auto& j : i.second->GetStructure()->GetMembers()) + string name; + if (i.size() != 1) + continue; + Ref type = types[i]; + name = i[0]; + if ((type->GetClass() == StructureTypeClass) && (type->GetStructure()->GetMembers().size() != 0)) { - fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); - OutputType(out, j.type); - fprintf(out, "),\n"); + bool requiresDependency = false; + for (auto& j : type->GetStructure()->GetMembers()) + { + if ((j.type->GetClass() == NamedTypeReferenceClass) && + (types[j.type->GetNamedTypeReference()->GetName()]->GetClass() == StructureTypeClass) && + (finishedStructs.count(j.type->GetNamedTypeReference()->GetName()) == 0)) + { + // This structure needs another structure that isn't fully defined yet, need to wait + // for the dependencies to be defined + structsToProcess.insert(i); + requiresDependency = true; + break; + } + } + + if (requiresDependency) + continue; + + fprintf(out, "%s._fields_ = [\n", name.c_str()); + for (auto& j : type->GetStructure()->GetMembers()) + { + fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); + OutputType(out, j.type); + fprintf(out, "),\n"); + } + fprintf(out, "\t]\n"); + finishedStructs.insert(i); + processedSome = true; } - fprintf(out, "\t]\n"); + } + + if (!processedSome) + { + fprintf(stderr, "Detected dependency cycle in structures\n"); + for (auto& i : structsToProcess) + fprintf(stderr, "%s\n", i.GetString().c_str()); + return 1; } } diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index c837aa42..3e7a6997 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -417,7 +417,10 @@ class MediumLevelILInstruction(object): """Type of expression""" result = core.BNGetMediumLevelILExprType(self.function.handle, self.expr_index) if result.type: - return types.Type(result.type, confidence = result.confidence) + platform = None + if self.function.source_function: + platform = self.function.source_function.platform + return types.Type(result.type, platform = platform, confidence = result.confidence) return None def get_ssa_var_possible_values(self, ssa_var): diff --git a/python/platform.py b/python/platform.py index 1c2fdcd3..5e63d836 100644 --- a/python/platform.py +++ b/python/platform.py @@ -234,7 +234,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -246,7 +246,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -258,7 +258,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type)) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -270,7 +270,7 @@ class Platform(object): result = {} for i in xrange(0, count.value): name = types.QualifiedName._from_core_struct(call_list[i].name) - t = types.Type(core.BNNewTypeReference(call_list[i].type)) + t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) core.BNFreeSystemCallList(call_list, count.value) return result @@ -325,21 +325,21 @@ class Platform(object): obj = core.BNGetPlatformTypeByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_variable_by_name(self, name): name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformVariableByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_function_by_name(self, name): name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformFunctionByName(self.handle, name) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def get_system_call_name(self, number): return core.BNGetPlatformSystemCallName(self.handle, number) @@ -348,7 +348,7 @@ class Platform(object): obj = core.BNGetPlatformSystemCallType(self.handle, number) if not obj: return None - return types.Type(obj) + return types.Type(obj, platform = self) def generate_auto_platform_type_id(self, name): name = types.QualifiedName(name)._get_core_struct() @@ -360,3 +360,96 @@ class Platform(object): def get_auto_platform_type_id_source(self): return core.BNGetAutoPlatformTypeIdSource(self.handle) + + def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): + """ + ``parse_types_from_source`` parses the source string and any needed headers searching for them in + the optional list of directories provided in ``include_dirs``. + + :param str source: source string to be parsed + :param str filename: optional source filename + :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult + :Example: + + >>> platform.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') + ({types: {'bas': }, variables: {'foo': }, functions:{'bar': + }}, '') + >>> + """ + + if filename is None: + filename = "input" + dir_buf = (ctypes.c_char_p * len(include_dirs))() + for i in xrange(0, len(include_dirs)): + dir_buf[i] = str(include_dirs[i]) + parse = core.BNTypeParserResult() + errors = ctypes.c_char_p() + result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) + error_str = errors.value + core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) + if not result: + raise SyntaxError(error_str) + type_dict = {} + variables = {} + functions = {} + for i in xrange(0, parse.typeCount): + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + for i in xrange(0, parse.variableCount): + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + for i in xrange(0, parse.functionCount): + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + core.BNFreeTypeParserResult(parse) + return types.TypeParserResult(type_dict, variables, functions) + + def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): + """ + ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in + the optional list of directories provided in ``include_dirs``. + + :param str filename: filename of file to be parsed + :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types + :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult + :Example: + + >>> file = "/Users/binja/tmp.c" + >>> open(file).read() + 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' + >>> platform.parse_types_from_source_file(file) + ({types: {'bas': }, variables: {'foo': }, functions: + {'bar': }}, '') + >>> + """ + dir_buf = (ctypes.c_char_p * len(include_dirs))() + for i in xrange(0, len(include_dirs)): + dir_buf[i] = str(include_dirs[i]) + parse = core.BNTypeParserResult() + errors = ctypes.c_char_p() + result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) + error_str = errors.value + core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) + if not result: + raise SyntaxError(error_str) + type_dict = {} + variables = {} + functions = {} + for i in xrange(0, parse.typeCount): + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + for i in xrange(0, parse.variableCount): + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + for i in xrange(0, parse.functionCount): + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + core.BNFreeTypeParserResult(parse) + return types.TypeParserResult(type_dict, variables, functions) diff --git a/python/types.py b/python/types.py index e297ddd2..fd2ee27e 100644 --- a/python/types.py +++ b/python/types.py @@ -24,7 +24,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType import callingconvention import function @@ -199,10 +199,23 @@ class Symbol(object): raise AttributeError("attribute '%s' is read only" % name) +class FunctionParameter(object): + def __init__(self, param_type, name = "", location = None): + self.type = param_type + self.name = name + self.location = location + + def __repr__(self): + if (self.location is not None) and (self.location.name != self.name): + return "%s %s%s @ %s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name(), self.location.name) + return "%s %s%s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name()) + + class Type(object): - def __init__(self, handle, confidence = max_confidence): + def __init__(self, handle, platform = None, confidence = max_confidence): self.handle = handle self.confidence = confidence + self.platform = platform def __del__(self): core.BNFreeType(self.handle) @@ -255,7 +268,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def element_type(self): @@ -263,7 +276,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def return_value(self): @@ -271,7 +284,7 @@ class Type(object): result = core.BNGetChildType(self.handle) if not result.type: return None - return Type(result.type, confidence = result.confidence) + return Type(result.type, platform = self.platform, confidence = result.confidence) @property def calling_convention(self): @@ -288,7 +301,18 @@ class Type(object): params = core.BNGetTypeParameters(self.handle, count) result = [] for i in xrange(0, count.value): - result.append((Type(core.BNNewTypeReference(params[i].type), confidence = params[i].typeConfidence), params[i].name)) + param_type = Type(core.BNNewTypeReference(params[i].type), platform = self.platform, confidence = params[i].typeConfidence) + if params[i].defaultLocation: + param_location = None + else: + name = params[i].name + if (params[i].location.type == VariableSourceType.RegisterVariableSourceType) and (self.platform is not None): + name = self.platform.arch.get_reg_name(params[i].location.storage) + elif params[i].location.type == VariableSourceType.StackVariableSourceType: + name = "arg_%x" % params[i].location.storage + param_location = function.Variable(None, params[i].location.type, params[i].location.index, + params[i].location.storage, name, param_type) + result.append(FunctionParameter(param_type, params[i].name, param_location)) core.BNFreeTypeParameterList(params, count.value) return result @@ -339,7 +363,10 @@ class Type(object): return core.BNGetTypeOffset(self.handle) def __str__(self): - return core.BNGetTypeString(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeString(self.handle, platform) def __repr__(self): if self.confidence < max_confidence: @@ -347,16 +374,28 @@ class Type(object): return "" % str(self) def get_string_before_name(self): - return core.BNGetTypeStringBeforeName(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeStringBeforeName(self.handle, platform) def get_string_after_name(self): - return core.BNGetTypeStringAfterName(self.handle) + platform = None + if self.platform is not None: + platform = self.platform.handle + return core.BNGetTypeStringAfterName(self.handle, platform) @property def tokens(self): """Type string as a list of tokens (read-only)""" + return self.get_tokens() + + def get_tokens(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokens(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokens(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -371,9 +410,12 @@ class Type(object): core.BNFreeTokenList(tokens, count.value) return result - def get_tokens_before_name(self): + def get_tokens_before_name(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokensBeforeName(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokensBeforeName(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -388,9 +430,12 @@ class Type(object): core.BNFreeTokenList(tokens, count.value) return result - def get_tokens_after_name(self): + def get_tokens_after_name(self, base_confidence = max_confidence): count = ctypes.c_ulonglong() - tokens = core.BNGetTypeTokensAfterName(self.handle, count) + platform = None + if self.platform is not None: + platform = self.platform.handle + tokens = core.BNGetTypeTokensAfterName(self.handle, platform, base_confidence, count) result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) @@ -515,16 +560,29 @@ class Type(object): :param CallingConvention calling_convention: optional argument for function calling convention :param bool variable_arguments: optional argument for functions that have a variable number of arguments """ - param_buf = (core.BNNameAndType * len(params))() + param_buf = (core.BNFunctionParameter * len(params))() for i in xrange(0, len(params)): if isinstance(params[i], Type): param_buf[i].name = "" param_buf[i].type = params[i].handle param_buf[i].typeConfidence = params[i].confidence + param_buf[i].defaultLocation = True + elif isinstance(params[i], FunctionParameter): + param_buf[i].name = params[i].name + param_buf[i].type = params[i].type.handle + param_buf[i].typeConfidence = params[i].type.confidence + if params[i].location is None: + param_buf[i].defaultLocation = True + else: + param_buf[i].defaultLocation = False + param_buf[i].location.type = params[i].location.type + param_buf[i].location.index = params[i].location.index + param_buf[i].location.storage = params[i].location.storage else: param_buf[i].name = params[i][1] param_buf[i].type = params[i][0].handle param_buf[i].typeConfidence = params[i][0].confidence + param_buf[i].defaultLocation = True ret_conf = core.BNTypeWithConfidence() ret_conf.type = ret.handle @@ -565,7 +623,7 @@ class Type(object): return core.BNGetAutoDemangledTypeIdSource() def with_confidence(self, confidence): - return Type(handle = core.BNNewTypeReference(self.handle), confidence = confidence) + return Type(handle = core.BNNewTypeReference(self.handle), platform = self.platform, confidence = confidence) def __setattr__(self, name, value): try: diff --git a/type.cpp b/type.cpp index 398a7216..aa891557 100644 --- a/type.cpp +++ b/type.cpp @@ -349,17 +349,21 @@ Confidence> Type::GetCallingConvention() const } -vector Type::GetParameters() const +vector Type::GetParameters() const { size_t count; - BNNameAndType* types = BNGetTypeParameters(m_object, &count); + BNFunctionParameter* types = BNGetTypeParameters(m_object, &count); - vector result; + vector result; for (size_t i = 0; i < count; i++) { - NameAndType param; + FunctionParameter param; param.name = types[i].name; param.type = Confidence>(new Type(BNNewTypeReference(types[i].type)), types[i].typeConfidence); + param.defaultLocation = types[i].defaultLocation; + param.location.type = types[i].location.type; + param.location.index = types[i].location.index; + param.location.storage = types[i].location.storage; result.push_back(param); } @@ -421,9 +425,9 @@ uint64_t Type::GetOffset() const } -string Type::GetString() const +string Type::GetString(Platform* platform) const { - char* str = BNGetTypeString(m_object); + char* str = BNGetTypeString(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; @@ -438,28 +442,29 @@ string Type::GetTypeAndName(const QualifiedName& nameList) const return outName; } -string Type::GetStringBeforeName() const +string Type::GetStringBeforeName(Platform* platform) const { - char* str = BNGetTypeStringBeforeName(m_object); + char* str = BNGetTypeStringBeforeName(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; } -string Type::GetStringAfterName() const +string Type::GetStringAfterName(Platform* platform) const { - char* str = BNGetTypeStringAfterName(m_object); + char* str = BNGetTypeStringAfterName(m_object, platform ? platform->GetObject() : nullptr); string result = str; BNFreeString(str); return result; } -vector Type::GetTokens() const +vector Type::GetTokens(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokens(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokens(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; for (size_t i = 0; i < count; i++) @@ -481,10 +486,11 @@ vector Type::GetTokens() const } -vector Type::GetTokensBeforeName() const +vector Type::GetTokensBeforeName(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokensBeforeName(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokensBeforeName(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; for (size_t i = 0; i < count; i++) @@ -506,10 +512,11 @@ vector Type::GetTokensBeforeName() const } -vector Type::GetTokensAfterName() const +vector Type::GetTokensAfterName(Platform* platform, uint8_t baseConfidence) const { size_t count; - BNInstructionTextToken* tokens = BNGetTypeTokensAfterName(m_object, &count); + BNInstructionTextToken* tokens = BNGetTypeTokensAfterName(m_object, + platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; for (size_t i = 0; i < count; i++) @@ -656,7 +663,7 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, - const std::vector& params, const Confidence& varArg) + const std::vector& params, const Confidence& varArg) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -666,12 +673,16 @@ Ref Type::FunctionType(const Confidence>& returnValue, callingConventionConf.convention = callingConvention ? callingConvention->GetObject() : nullptr; callingConventionConf.confidence = callingConvention.GetConfidence(); - BNNameAndType* paramArray = new BNNameAndType[params.size()]; + BNFunctionParameter* paramArray = new BNFunctionParameter[params.size()]; for (size_t i = 0; i < params.size(); i++) { paramArray[i].name = (char*)params[i].name.c_str(); paramArray[i].type = params[i].type->GetObject(); paramArray[i].typeConfidence = params[i].type.GetConfidence(); + paramArray[i].defaultLocation = params[i].defaultLocation; + paramArray[i].location.type = params[i].location.type; + paramArray[i].location.index = params[i].location.index; + paramArray[i].location.storage = params[i].location.storage; } BNBoolWithConfidence varArgConf; -- cgit v1.3.1 From 71a1a997e9be461a841a0f801bd19a23ad62f106 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 24 Aug 2017 22:26:16 -0400 Subject: Add MLIL instruction for dealing with direct access to GOT/IAT entries --- binaryninjaapi.h | 1 + binaryninjacore.h | 5 ++++- mediumlevelilinstruction.cpp | 9 +++++++++ mediumlevelilinstruction.h | 1 + python/function.py | 6 ++++++ python/mediumlevelil.py | 1 + 6 files changed, 22 insertions(+), 1 deletion(-) (limited to 'python/mediumlevelil.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f5f51908..1b02e2f1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2727,6 +2727,7 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation()); ExprId Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index 6ba7fda4..44858e6f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -224,7 +224,8 @@ extern "C" DataSymbolToken = 65, LocalVariableToken = 66, ImportToken = 67, - AddressDisplayToken = 68 + AddressDisplayToken = 68, + IndirectImportToken = 69 }; enum BNInstructionTextTokenContext @@ -651,6 +652,7 @@ extern "C" ConstantPointerValue, StackFrameOffset, ReturnAddressValue, + ImportedAddressValue, // The following are only valid in BNPossibleValueSet SignedRangeValue, @@ -746,6 +748,7 @@ extern "C" MLIL_ADDRESS_OF_FIELD, MLIL_CONST, MLIL_CONST_PTR, + MLIL_IMPORT, MLIL_ADD, MLIL_ADC, MLIL_SUB, diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 73f2e59b..ec6aa1c6 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -149,6 +149,7 @@ unordered_map> {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, {MLIL_CONST, {ConstantMediumLevelOperandUsage}}, {MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}}, + {MLIL_IMPORT, {ConstantMediumLevelOperandUsage}}, {MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, {MLIL_AND, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}}, @@ -1552,6 +1553,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->Const(size, GetConstant(), *this); case MLIL_CONST_PTR: return dest->ConstPointer(size, GetConstant(), *this); + case MLIL_IMPORT: + return dest->ImportedAddress(size, GetConstant(), *this); case MLIL_BP: return dest->Breakpoint(*this); case MLIL_TRAP: @@ -2086,6 +2089,12 @@ ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSo } +ExprId MediumLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_IMPORT, loc, size, val); +} + + ExprId MediumLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_ADD, loc, size, left, right); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 066259eb..9a76cb6c 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -934,6 +934,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILConstantInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILTwoOperandInstruction {}; diff --git a/python/function.py b/python/function.py index 553b156f..4af95738 100644 --- a/python/function.py +++ b/python/function.py @@ -67,6 +67,8 @@ class RegisterValue(object): self.is_constant = True elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value + elif value.state == RegisterValueType.ImportedAddressValue: + self.value = value.value self.confidence = confidence def __repr__(self): @@ -80,6 +82,8 @@ class RegisterValue(object): return "" % self.offset if self.type == RegisterValueType.ReturnAddressValue: return "" + if self.type == RegisterValueType.ImportedAddressValue: + return "" % self.value return "" def _to_api_object(self): @@ -95,6 +99,8 @@ class RegisterValue(object): result.value = self.value elif self.type == RegisterValueType.StackFrameOffset: result.value = self.offset + elif self.type == RegisterValueType.ImportedAddressValue: + result.value = self.value return result diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 3e7a6997..07759a47 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -89,6 +89,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], + MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], -- cgit v1.3.1