summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp9
-rw-r--r--binaryninjaapi.h220
-rw-r--r--binaryninjacore.h179
-rw-r--r--flowgraph.cpp21
-rw-r--r--function.cpp12
-rw-r--r--highlevelil.cpp300
-rw-r--r--highlevelilinstruction.cpp2091
-rw-r--r--highlevelilinstruction.h713
-rw-r--r--linearviewobject.cpp7
-rw-r--r--python/__init__.py1
-rw-r--r--python/flowgraph.py20
-rw-r--r--python/function.py38
-rw-r--r--python/highlevelil.py729
-rw-r--r--python/lineardisassembly.py6
-rw-r--r--python/scriptingprovider.py2
15 files changed, 4344 insertions, 4 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 25d8b0db..6ca7733e 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -2228,6 +2228,15 @@ Ref<MediumLevelILFunction> DisassemblyTextRenderer::GetMediumLevelILFunction() c
}
+Ref<HighLevelILFunction> DisassemblyTextRenderer::GetHighLevelILFunction() const
+{
+ BNHighLevelILFunction* result = BNGetDisassemblyTextRendererHighLevelILFunction(m_object);
+ if (result)
+ return new HighLevelILFunction(result);
+ return nullptr;
+}
+
+
void DisassemblyTextRenderer::SetBasicBlock(BasicBlock* block)
{
BNSetDisassemblyTextRendererBasicBlock(m_object, block ? block->GetObject() : nullptr);
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index c91b13c4..ed10caca 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2927,6 +2927,7 @@ __attribute__ ((format (printf, 1, 2)))
class FlowGraph;
class MediumLevelILFunction;
+ class HighLevelILFunction;
class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction>
{
@@ -2986,6 +2987,8 @@ __attribute__ ((format (printf, 1, 2)))
Ref<MediumLevelILFunction> GetMediumLevelIL() const;
Ref<MediumLevelILFunction> GetMediumLevelILIfAvailable() const;
+ Ref<HighLevelILFunction> GetHighLevelIL() const;
+ Ref<HighLevelILFunction> GetHighLevelILIfAvailable() const;
Ref<Type> GetType() const;
Confidence<Ref<Type>> GetReturnType() const;
@@ -3261,10 +3264,13 @@ __attribute__ ((format (printf, 1, 2)))
bool IsILGraph() const;
bool IsLowLevelILGraph() const;
bool IsMediumLevelILGraph() const;
+ bool IsHighLevelILGraph() const;
Ref<LowLevelILFunction> GetLowLevelILFunction() const;
Ref<MediumLevelILFunction> GetMediumLevelILFunction() const;
+ Ref<HighLevelILFunction> GetHighLevelILFunction() const;
void SetLowLevelILFunction(LowLevelILFunction* func);
void SetMediumLevelILFunction(MediumLevelILFunction* func);
+ void SetHighLevelILFunction(HighLevelILFunction* func);
void Show(const std::string& title);
@@ -3309,6 +3315,11 @@ __attribute__ ((format (printf, 1, 2)))
address(instr.address), sourceOperand(instr.sourceOperand), valid(true)
{
}
+
+ ILSourceLocation(const BNHighLevelILInstruction& instr):
+ address(instr.address), sourceOperand(instr.sourceOperand), valid(true)
+ {
+ }
};
struct LowLevelILInstruction;
@@ -4010,6 +4021,213 @@ __attribute__ ((format (printf, 1, 2)))
Ref<FlowGraph> CreateFunctionGraph(DisassemblySettings* settings = nullptr);
};
+ struct HighLevelILInstruction;
+
+ class HighLevelILFunction: public CoreRefCountObject<BNHighLevelILFunction,
+ BNNewHighLevelILFunctionReference, BNFreeHighLevelILFunction>
+ {
+ public:
+ HighLevelILFunction(Architecture* arch, Function* func = nullptr);
+ HighLevelILFunction(BNHighLevelILFunction* func);
+
+ Ref<Function> GetFunction() const;
+ Ref<Architecture> GetArchitecture() const;
+
+ uint64_t GetCurrentAddress() const;
+ void SetCurrentAddress(Architecture* arch, uint64_t addr);
+
+ HighLevelILInstruction GetRootExpr();
+ void SetRootExpr(ExprId expr);
+ void SetRootExpr(const HighLevelILInstruction& expr);
+
+ ExprId AddExpr(BNHighLevelILOperation operation, size_t size,
+ ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0);
+ ExprId AddExprWithLocation(BNHighLevelILOperation 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(BNHighLevelILOperation 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 Block(const std::vector<ExprId>& exprs, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId If(ExprId condition, ExprId trueExpr, ExprId falseExpr,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId While(ExprId condition, ExprId loopExpr, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId For(ExprId initExpr, ExprId condition, ExprId updateExpr, ExprId loopExpr,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Switch(ExprId condition, ExprId defaultExpr, const std::vector<ExprId>& cases,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Case(ExprId condition, ExprId expr, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Break(const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Return(const std::vector<ExprId>& sources, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Goto(size_t target, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Label(size_t target, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Assign(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId AssignUnpack(const std::vector<ExprId>& output, ExprId src,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId VarPhi(const SSAVariable& dest, const std::vector<SSAVariable>& sources,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId StructField(size_t size, ExprId src, uint64_t offset,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId ArrayIndex(size_t size, ExprId src, ExprId idx, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Split(size_t size, ExprId high, ExprId low, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Deref(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId DerefField(size_t size, ExprId src, uint64_t offset,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId AddressOf(ExprId src, 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 ExternPointer(size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatConstSingle(float val, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatConstDouble(double 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());
+ 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 left, ExprId right,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId DivDoublePrecUnsigned(size_t size, ExprId left, 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 left, ExprId right,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId ModDoublePrecUnsigned(size_t size, ExprId left, 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 Call(ExprId dest, const std::vector<ExprId>& params,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Syscall(const std::vector<ExprId>& params, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId TailCall(ExprId dest, const std::vector<ExprId>& params,
+ 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 Intrinsic(uint32_t intrinsic, const std::vector<ExprId>& params,
+ 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 FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Floor(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId Ceil(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation());
+
+ std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand);
+ ExprId AddOperandList(const std::vector<ExprId> operands);
+ ExprId AddSSAVariableList(const std::vector<SSAVariable>& vars);
+
+ BNHighLevelILInstruction GetRawExpr(size_t i) const;
+ HighLevelILInstruction operator[](size_t i);
+ HighLevelILInstruction GetInstruction(size_t i);
+ HighLevelILInstruction 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;
+
+ std::vector<Ref<BasicBlock>> GetBasicBlocks() const;
+ Ref<BasicBlock> GetBasicBlockForInstruction(size_t i) const;
+
+ Ref<MediumLevelILFunction> GetMediumLevelIL() const;
+ size_t GetMediumLevelILExprIndex(size_t expr) const;
+
+ void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value);
+ void ReplaceExpr(size_t expr, size_t newExpr);
+
+ void Finalize();
+
+ std::vector<DisassemblyTextLine> GetExprText(ExprId expr, bool asFullAst = true);
+ std::vector<DisassemblyTextLine> GetExprText(const HighLevelILInstruction& instr, bool asFullAst = true);
+
+ void VisitAllExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func);
+
+ Ref<FlowGraph> CreateFunctionGraph(DisassemblySettings* settings = nullptr);
+ };
+
class FunctionRecognizer
{
static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il);
@@ -4919,6 +5137,7 @@ __attribute__ ((format (printf, 1, 2)))
Ref<Function> GetFunction() const;
Ref<LowLevelILFunction> GetLowLevelILFunction() const;
Ref<MediumLevelILFunction> GetMediumLevelILFunction() const;
+ Ref<HighLevelILFunction> GetHighLevelILFunction() const;
Ref<BasicBlock> GetBasicBlock() const;
Ref<Architecture> GetArchitecture() const;
@@ -5000,6 +5219,7 @@ __attribute__ ((format (printf, 1, 2)))
static Ref<LinearViewObject> CreateMediumLevelILSSAForm(BinaryView* view, DisassemblySettings* settings);
static Ref<LinearViewObject> CreateMappedMediumLevelIL(BinaryView* view, DisassemblySettings* settings);
static Ref<LinearViewObject> CreateMappedMediumLevelILSSAForm(BinaryView* view, DisassemblySettings* settings);
+ static Ref<LinearViewObject> CreateHighLevelIL(BinaryView* view, DisassemblySettings* settings);
};
class LinearViewCursor: public CoreRefCountObject<BNLinearViewCursor,
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 941540f0..5487baab 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -133,6 +133,7 @@ extern "C"
struct BNTemporaryFile;
struct BNLowLevelILFunction;
struct BNMediumLevelILFunction;
+ struct BNHighLevelILFunction;
struct BNType;
struct BNTypeBuilder;
struct BNTypeLibrary;
@@ -515,7 +516,8 @@ extern "C"
MediumLevelILFunctionGraph = 4,
MediumLevelILSSAFormFunctionGraph = 5,
MappedMediumLevelILFunctionGraph = 6,
- MappedMediumLevelILSSAFormFunctionGraph = 7
+ MappedMediumLevelILSSAFormFunctionGraph = 7,
+ HighLevelILFunctionGraph = 8
};
enum BNDisassemblyOption
@@ -531,6 +533,7 @@ extern "C"
// Linear disassembly options
GroupLinearDisassemblyFunctions = 64,
+ HighLevelILLinearDisassembly = 65,
// Debugging options
ShowFlagUsage = 128
@@ -1043,6 +1046,130 @@ extern "C"
int64_t storage;
};
+ enum BNHighLevelILOperation
+ {
+ HLIL_NOP,
+
+ HLIL_BLOCK,
+ HLIL_IF,
+ HLIL_WHILE,
+ HLIL_DO_WHILE,
+ HLIL_FOR,
+ HLIL_SWITCH,
+ HLIL_CASE,
+ HLIL_BREAK,
+ HLIL_JUMP,
+ HLIL_RET,
+ HLIL_NORET,
+ HLIL_GOTO,
+ HLIL_LABEL,
+
+ HLIL_ASSIGN,
+ HLIL_ASSIGN_UNPACK,
+ HLIL_VAR,
+ HLIL_STRUCT_FIELD,
+ HLIL_ARRAY_INDEX,
+ HLIL_SPLIT,
+ HLIL_DEREF,
+ HLIL_DEREF_FIELD,
+ HLIL_ADDRESS_OF,
+ HLIL_CONST,
+ HLIL_CONST_PTR,
+ HLIL_EXTERN_PTR,
+ HLIL_FLOAT_CONST,
+ HLIL_IMPORT,
+ HLIL_ADD,
+ HLIL_ADC,
+ HLIL_SUB,
+ HLIL_SBB,
+ HLIL_AND,
+ HLIL_OR,
+ HLIL_XOR,
+ HLIL_LSL,
+ HLIL_LSR,
+ HLIL_ASR,
+ HLIL_ROL,
+ HLIL_RLC,
+ HLIL_ROR,
+ HLIL_RRC,
+ HLIL_MUL,
+ HLIL_MULU_DP,
+ HLIL_MULS_DP,
+ HLIL_DIVU,
+ HLIL_DIVU_DP,
+ HLIL_DIVS,
+ HLIL_DIVS_DP,
+ HLIL_MODU,
+ HLIL_MODU_DP,
+ HLIL_MODS,
+ HLIL_MODS_DP,
+ HLIL_NEG,
+ HLIL_NOT,
+ HLIL_SX,
+ HLIL_ZX,
+ HLIL_LOW_PART,
+ HLIL_CALL,
+ HLIL_CMP_E,
+ HLIL_CMP_NE,
+ HLIL_CMP_SLT,
+ HLIL_CMP_ULT,
+ HLIL_CMP_SLE,
+ HLIL_CMP_ULE,
+ HLIL_CMP_SGE,
+ HLIL_CMP_UGE,
+ HLIL_CMP_SGT,
+ HLIL_CMP_UGT,
+ HLIL_TEST_BIT,
+ HLIL_BOOL_TO_INT,
+ HLIL_ADD_OVERFLOW,
+ HLIL_SYSCALL,
+ HLIL_TAILCALL,
+ HLIL_INTRINSIC,
+ HLIL_BP,
+ HLIL_TRAP,
+ HLIL_UNDEF,
+ HLIL_UNIMPL,
+ HLIL_UNIMPL_MEM,
+
+ // Floating point
+ HLIL_FADD,
+ HLIL_FSUB,
+ HLIL_FMUL,
+ HLIL_FDIV,
+ HLIL_FSQRT,
+ HLIL_FNEG,
+ HLIL_FABS,
+ HLIL_FLOAT_TO_INT,
+ HLIL_INT_TO_FLOAT,
+ HLIL_FLOAT_CONV,
+ HLIL_ROUND_TO_INT,
+ HLIL_FLOOR,
+ HLIL_CEIL,
+ HLIL_FTRUNC,
+ HLIL_FCMP_E,
+ HLIL_FCMP_NE,
+ HLIL_FCMP_LT,
+ HLIL_FCMP_LE,
+ HLIL_FCMP_GE,
+ HLIL_FCMP_GT,
+ HLIL_FCMP_O,
+ HLIL_FCMP_UO,
+
+ // The following instructions are only used in SSA form
+ HLIL_VAR_SSA,
+ HLIL_VAR_PHI
+ };
+
+ struct BNHighLevelILInstruction
+ {
+ BNHighLevelILOperation operation;
+ uint32_t sourceOperand;
+ size_t size;
+ uint64_t operands[5];
+ uint64_t address;
+ size_t parent;
+ };
+
// Callbacks
struct BNLogListener
{
@@ -2698,6 +2825,8 @@ __attribute__ ((format (printf, 1, 2)))
BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list);
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func);
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelILIfAvailable(BNFunction* func);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFunctionHighLevelIL(BNFunction* func);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFunctionHighLevelILIfAvailable(BNFunction* func);
BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch,
uint64_t addr, uint32_t reg);
BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch,
@@ -2811,11 +2940,14 @@ __attribute__ ((format (printf, 1, 2)))
BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNCreateMediumLevelILDisassemblyTextRenderer(BNMediumLevelILFunction* func,
BNDisassemblySettings* settings);
+ BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNCreateHighLevelILDisassemblyTextRenderer(BNHighLevelILFunction* func,
+ BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNDisassemblyTextRenderer* BNNewDisassemblyTextRendererReference(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI void BNFreeDisassemblyTextRenderer(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNFunction* BNGetDisassemblyTextRendererFunction(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetDisassemblyTextRendererLowLevelILFunction(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetDisassemblyTextRendererMediumLevelILFunction(BNDisassemblyTextRenderer* renderer);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetDisassemblyTextRendererHighLevelILFunction(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNBasicBlock* BNGetDisassemblyTextRendererBasicBlock(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNArchitecture* BNGetDisassemblyTextRendererArchitecture(BNDisassemblyTextRenderer* renderer);
BINARYNINJACOREAPI BNDisassemblySettings* BNGetDisassemblyTextRendererSettings(BNDisassemblyTextRenderer* renderer);
@@ -2990,6 +3122,8 @@ __attribute__ ((format (printf, 1, 2)))
BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewMappedMediumLevelILSSAForm(BNBinaryView* view,
BNDisassemblySettings* settings);
+ BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewHighLevelIL(BNBinaryView* view,
+ BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNLinearViewObject* BNNewLinearViewObjectReference(BNLinearViewObject* obj);
BINARYNINJACOREAPI void BNFreeLinearViewObject(BNLinearViewObject* obj);
BINARYNINJACOREAPI BNLinearViewObject* BNGetFirstLinearViewObjectChild(BNLinearViewObject* obj);
@@ -3200,6 +3334,8 @@ __attribute__ ((format (printf, 1, 2)))
BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNFlowGraph* BNCreateMediumLevelILFunctionGraph(BNMediumLevelILFunction* func,
BNDisassemblySettings* settings);
+ BINARYNINJACOREAPI BNFlowGraph* BNCreateHighLevelILFunctionGraph(BNHighLevelILFunction* func,
+ BNDisassemblySettings* settings);
BINARYNINJACOREAPI BNFlowGraph* BNCreateCustomFlowGraph(BNCustomFlowGraph* callbacks);
BINARYNINJACOREAPI BNFlowGraph* BNNewFlowGraphReference(BNFlowGraph* graph);
BINARYNINJACOREAPI void BNFreeFlowGraph(BNFlowGraph* graph);
@@ -3222,10 +3358,13 @@ __attribute__ ((format (printf, 1, 2)))
BINARYNINJACOREAPI bool BNIsILFlowGraph(BNFlowGraph* graph);
BINARYNINJACOREAPI bool BNIsLowLevelILFlowGraph(BNFlowGraph* graph);
BINARYNINJACOREAPI bool BNIsMediumLevelILFlowGraph(BNFlowGraph* graph);
+ BINARYNINJACOREAPI bool BNIsHighLevelILFlowGraph(BNFlowGraph* graph);
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFlowGraphLowLevelILFunction(BNFlowGraph* graph);
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFlowGraphMediumLevelILFunction(BNFlowGraph* graph);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNGetFlowGraphHighLevelILFunction(BNFlowGraph* graph);
BINARYNINJACOREAPI void BNSetFlowGraphLowLevelILFunction(BNFlowGraph* graph, BNLowLevelILFunction* func);
BINARYNINJACOREAPI void BNSetFlowGraphMediumLevelILFunction(BNFlowGraph* graph, BNMediumLevelILFunction* func);
+ BINARYNINJACOREAPI void BNSetFlowGraphHighLevelILFunction(BNFlowGraph* graph, BNHighLevelILFunction* func);
BINARYNINJACOREAPI BNFlowGraphNode** BNGetFlowGraphNodes(BNFlowGraph* graph, size_t* count);
BINARYNINJACOREAPI BNFlowGraphNode* BNGetFlowGraphNode(BNFlowGraph* graph, size_t i);
@@ -3567,12 +3706,50 @@ __attribute__ ((format (printf, 1, 2)))
BNMediumLevelILFunction* func, size_t instr, size_t* count);
BINARYNINJACOREAPI void BNFreeILBranchDependenceList(BNILBranchInstructionAndDependence* branches);
+ BINARYNINJACOREAPI BNBasicBlock** BNGetHighLevelILBasicBlockList(BNHighLevelILFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNBasicBlock* BNGetHighLevelILBasicBlockForInstruction(BNHighLevelILFunction* func, size_t i);
+
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func);
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);
+ // High-level IL
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNCreateHighLevelILFunction(BNArchitecture* arch, BNFunction* func);
+ BINARYNINJACOREAPI BNHighLevelILFunction* BNNewHighLevelILFunctionReference(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI void BNFreeHighLevelILFunction(BNHighLevelILFunction* func);
+
+ BINARYNINJACOREAPI BNFunction* BNGetHighLevelILOwnerFunction(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI uint64_t BNHighLevelILGetCurrentAddress(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI void BNHighLevelILSetCurrentAddress(BNHighLevelILFunction* func, BNArchitecture* arch, uint64_t addr);
+ BINARYNINJACOREAPI size_t BNHighLevelILAddExpr(BNHighLevelILFunction* func, BNHighLevelILOperation operation, size_t size,
+ uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e);
+ BINARYNINJACOREAPI size_t BNHighLevelILAddExprWithLocation(BNHighLevelILFunction* func, BNHighLevelILOperation 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 BNGetHighLevelILRootExpr(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI void BNSetHighLevelILRootExpr(BNHighLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI void BNFinalizeHighLevelILFunction(BNHighLevelILFunction* func);
+
+ BINARYNINJACOREAPI size_t BNHighLevelILAddOperandList(BNHighLevelILFunction* func, uint64_t* operands, size_t count);
+ BINARYNINJACOREAPI uint64_t* BNHighLevelILGetOperandList(BNHighLevelILFunction* func, size_t expr, size_t operand, size_t* count);
+ BINARYNINJACOREAPI void BNHighLevelILFreeOperandList(uint64_t* operands);
+
+ BINARYNINJACOREAPI BNHighLevelILInstruction BNGetHighLevelILByIndex(BNHighLevelILFunction* func, size_t i);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILIndexForInstruction(BNHighLevelILFunction* func, size_t i);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionForExpr(BNHighLevelILFunction* func, size_t expr);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILInstructionCount(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetHighLevelILExprCount(BNHighLevelILFunction* func);
+
+ BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForHighLevelILFunction(BNHighLevelILFunction* func);
+ BINARYNINJACOREAPI size_t BNGetMediumLevelILExprIndexFromHighLevelIL(BNHighLevelILFunction* func, size_t expr);
+
+ BINARYNINJACOREAPI void BNUpdateHighLevelILOperand(BNHighLevelILFunction* func, size_t instr, size_t operandIndex, uint64_t value);
+ BINARYNINJACOREAPI void BNReplaceHighLevelILExpr(BNHighLevelILFunction* func, size_t expr, size_t newExpr);
+
+ BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetHighLevelILExprText(BNHighLevelILFunction* func, size_t expr,
+ bool asFullAst, size_t* count);
+
// Type Libraries
BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibrary(BNArchitecture* arch, const char* name);
BINARYNINJACOREAPI BNTypeLibrary* BNNewTypeLibraryReference(BNTypeLibrary* lib);
diff --git a/flowgraph.cpp b/flowgraph.cpp
index 51a634b9..be7e498b 100644
--- a/flowgraph.cpp
+++ b/flowgraph.cpp
@@ -329,6 +329,12 @@ bool FlowGraph::IsMediumLevelILGraph() const
}
+bool FlowGraph::IsHighLevelILGraph() const
+{
+ return BNIsHighLevelILFlowGraph(m_object);
+}
+
+
Ref<LowLevelILFunction> FlowGraph::GetLowLevelILFunction() const
{
BNLowLevelILFunction* func = BNGetFlowGraphLowLevelILFunction(m_object);
@@ -347,6 +353,15 @@ Ref<MediumLevelILFunction> FlowGraph::GetMediumLevelILFunction() const
}
+Ref<HighLevelILFunction> FlowGraph::GetHighLevelILFunction() const
+{
+ BNHighLevelILFunction* func = BNGetFlowGraphHighLevelILFunction(m_object);
+ if (!func)
+ return nullptr;
+ return new HighLevelILFunction(func);
+}
+
+
void FlowGraph::SetLowLevelILFunction(LowLevelILFunction* func)
{
BNSetFlowGraphLowLevelILFunction(m_object, func ? func->GetObject() : nullptr);
@@ -359,6 +374,12 @@ void FlowGraph::SetMediumLevelILFunction(MediumLevelILFunction* func)
}
+void FlowGraph::SetHighLevelILFunction(HighLevelILFunction* func)
+{
+ BNSetFlowGraphHighLevelILFunction(m_object, func ? func->GetObject() : nullptr);
+}
+
+
void FlowGraph::Show(const string& title)
{
ShowGraphReport(title, this);
diff --git a/function.cpp b/function.cpp
index 0cffb6bc..304a59e2 100644
--- a/function.cpp
+++ b/function.cpp
@@ -545,6 +545,18 @@ Ref<MediumLevelILFunction> Function::GetMediumLevelILIfAvailable() const
}
+Ref<HighLevelILFunction> Function::GetHighLevelIL() const
+{
+ return new HighLevelILFunction(BNGetFunctionHighLevelIL(m_object));
+}
+
+
+Ref<HighLevelILFunction> Function::GetHighLevelILIfAvailable() const
+{
+ return new HighLevelILFunction(BNGetFunctionHighLevelILIfAvailable(m_object));
+}
+
+
Ref<Type> Function::GetType() const
{
return new Type(BNGetFunctionType(m_object));
diff --git a/highlevelil.cpp b/highlevelil.cpp
new file mode 100644
index 00000000..10fb9703
--- /dev/null
+++ b/highlevelil.cpp
@@ -0,0 +1,300 @@
+// Copyright (c) 2019 Vector 35 Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#include "binaryninjaapi.h"
+#include "highlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+HighLevelILFunction::HighLevelILFunction(Architecture* arch, Function* func)
+{
+ m_object = BNCreateHighLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr);
+}
+
+
+HighLevelILFunction::HighLevelILFunction(BNHighLevelILFunction* func)
+{
+ m_object = func;
+}
+
+
+Ref<Function> HighLevelILFunction::GetFunction() const
+{
+ BNFunction* func = BNGetHighLevelILOwnerFunction(m_object);
+ if (!func)
+ return nullptr;
+ return new Function(func);
+}
+
+
+Ref<Architecture> HighLevelILFunction::GetArchitecture() const
+{
+ Ref<Function> func = GetFunction();
+ if (!func)
+ return nullptr;
+ return func->GetArchitecture();
+}
+
+
+uint64_t HighLevelILFunction::GetCurrentAddress() const
+{
+ return BNHighLevelILGetCurrentAddress(m_object);
+}
+
+
+void HighLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr)
+{
+ BNHighLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr);
+}
+
+
+HighLevelILInstruction HighLevelILFunction::GetRootExpr()
+{
+ return GetExpr(BNGetHighLevelILRootExpr(m_object));
+}
+
+
+void HighLevelILFunction::SetRootExpr(ExprId expr)
+{
+ BNSetHighLevelILRootExpr(m_object, expr);
+}
+
+
+void HighLevelILFunction::SetRootExpr(const HighLevelILInstruction& expr)
+{
+ BNSetHighLevelILRootExpr(m_object, expr.exprIndex);
+}
+
+
+ExprId HighLevelILFunction::AddExpr(BNHighLevelILOperation operation, size_t size,
+ ExprId a, ExprId b, ExprId c, ExprId d, ExprId e)
+{
+ return BNHighLevelILAddExpr(m_object, operation, size, a, b, c, d, e);
+}
+
+
+ExprId HighLevelILFunction::AddExprWithLocation(BNHighLevelILOperation operation, uint64_t addr,
+ uint32_t sourceOperand, size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e)
+{
+ return BNHighLevelILAddExprWithLocation(m_object, operation, addr, sourceOperand, size, a, b, c, d, e);
+}
+
+
+ExprId HighLevelILFunction::AddExprWithLocation(BNHighLevelILOperation operation, const ILSourceLocation& loc,
+ size_t size, ExprId a, ExprId b, ExprId c, ExprId d, ExprId e)
+{
+ if (loc.valid)
+ {
+ return BNHighLevelILAddExprWithLocation(m_object, operation, loc.address, loc.sourceOperand,
+ size, a, b, c, d, e);
+ }
+ return BNHighLevelILAddExpr(m_object, operation, size, a, b, c, d, e);
+}
+
+
+vector<uint64_t> HighLevelILFunction::GetOperandList(ExprId expr, size_t listOperand)
+{
+ size_t count;
+ uint64_t* operands = BNHighLevelILGetOperandList(m_object, expr, listOperand, &count);
+ vector<uint64_t> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.push_back(operands[i]);
+ BNMediumLevelILFreeOperandList(operands);
+ return result;
+}
+
+
+ExprId HighLevelILFunction::AddOperandList(const vector<ExprId> operands)
+{
+ uint64_t* operandList = new uint64_t[operands.size()];
+ for (size_t i = 0; i < operands.size(); i++)
+ operandList[i] = operands[i];
+ ExprId result = (ExprId)BNHighLevelILAddOperandList(m_object, operandList, operands.size());
+ delete[] operandList;
+ return result;
+}
+
+
+ExprId HighLevelILFunction::AddSSAVariableList(const vector<SSAVariable>& 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)BNHighLevelILAddOperandList(m_object, operandList, vars.size() * 2);
+ delete[] operandList;
+ return result;
+}
+
+
+BNHighLevelILInstruction HighLevelILFunction::GetRawExpr(size_t i) const
+{
+ return BNGetHighLevelILByIndex(m_object, i);
+}
+
+
+HighLevelILInstruction HighLevelILFunction::operator[](size_t i)
+{
+ return GetInstruction(i);
+}
+
+
+HighLevelILInstruction HighLevelILFunction::GetInstruction(size_t i)
+{
+ size_t expr = GetIndexForInstruction(i);
+ return HighLevelILInstruction(this, GetRawExpr(expr), expr);
+}
+
+
+HighLevelILInstruction HighLevelILFunction::GetExpr(size_t i)
+{
+ return HighLevelILInstruction(this, GetRawExpr(i), i);
+}
+
+
+size_t HighLevelILFunction::GetIndexForInstruction(size_t i) const
+{
+ return BNGetHighLevelILIndexForInstruction(m_object, i);
+}
+
+
+size_t HighLevelILFunction::GetInstructionForExpr(size_t expr) const
+{
+ return BNGetHighLevelILInstructionForExpr(m_object, expr);
+}
+
+
+size_t HighLevelILFunction::GetInstructionCount() const
+{
+ return BNGetHighLevelILInstructionCount(m_object);
+}
+
+
+size_t HighLevelILFunction::GetExprCount() const
+{
+ return BNGetHighLevelILExprCount(m_object);
+}
+
+
+vector<Ref<BasicBlock>> HighLevelILFunction::GetBasicBlocks() const
+{
+ size_t count;
+ BNBasicBlock** blocks = BNGetHighLevelILBasicBlockList(m_object, &count);
+
+ vector<Ref<BasicBlock>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i])));
+
+ BNFreeBasicBlockList(blocks, count);
+ return result;
+}
+
+
+Ref<BasicBlock> HighLevelILFunction::GetBasicBlockForInstruction(size_t i) const
+{
+ BNBasicBlock* block = BNGetHighLevelILBasicBlockForInstruction(m_object, i);
+ if (!block)
+ return nullptr;
+ return new BasicBlock(block);
+}
+
+
+Ref<MediumLevelILFunction> HighLevelILFunction::GetMediumLevelIL() const
+{
+ BNMediumLevelILFunction* result = BNGetMediumLevelILForHighLevelILFunction(m_object);
+ if (!result)
+ return nullptr;
+ return new MediumLevelILFunction(result);
+}
+
+
+size_t HighLevelILFunction::GetMediumLevelILExprIndex(size_t expr) const
+{
+ return BNGetMediumLevelILExprIndexFromHighLevelIL(m_object, expr);
+}
+
+
+void HighLevelILFunction::UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value)
+{
+ BNUpdateHighLevelILOperand(m_object, i, operandIndex, value);
+}
+
+
+void HighLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr)
+{
+ BNReplaceHighLevelILExpr(m_object, expr, newExpr);
+}
+
+
+void HighLevelILFunction::Finalize()
+{
+ BNFinalizeHighLevelILFunction(m_object);
+}
+
+
+vector<DisassemblyTextLine> HighLevelILFunction::GetExprText(ExprId expr, bool asFullAst)
+{
+ size_t count;
+ BNDisassemblyTextLine* lines = BNGetHighLevelILExprText(m_object, expr, asFullAst, &count);
+
+ vector<DisassemblyTextLine> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ DisassemblyTextLine line;
+ line.addr = lines[i].addr;
+ line.instrIndex = lines[i].instrIndex;
+ line.highlight = lines[i].highlight;
+ line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].tokens, lines[i].count);
+ line.tags = Tag::ConvertTagList(lines[i].tags, lines[i].tagCount);
+ result.push_back(line);
+ }
+
+ BNFreeDisassemblyTextLines(lines, count);
+ return result;
+}
+
+
+vector<DisassemblyTextLine> HighLevelILFunction::GetExprText(const HighLevelILInstruction& instr, bool asFullAst)
+{
+ return GetExprText(instr.exprIndex, asFullAst);
+}
+
+
+void HighLevelILFunction::VisitAllExprs(
+ const function<bool(const HighLevelILInstruction& expr)>& func)
+{
+ GetRootExpr().VisitExprs([&](const HighLevelILInstruction& expr) {
+ return func(expr);
+ });
+}
+
+
+Ref<FlowGraph> HighLevelILFunction::CreateFunctionGraph(DisassemblySettings* settings)
+{
+ BNFlowGraph* graph = BNCreateHighLevelILFunctionGraph(m_object, settings ? settings->GetObject() : nullptr);
+ return new CoreFlowGraph(graph);
+}
diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp
new file mode 100644
index 00000000..311d4e93
--- /dev/null
+++ b/highlevelilinstruction.cpp
@@ -0,0 +1,2091 @@
+// Copyright (c) 2019 Vector 35 Inc
+//
+// 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 "highlevelilfunction.h"
+#include "mediumlevelilfunction.h"
+#include "mediumlevelilssafunction.h"
+using namespace BinaryNinjaCore;
+#else
+#include "binaryninjaapi.h"
+#include "highlevelilinstruction.h"
+#include "mediumlevelilinstruction.h"
+using namespace BinaryNinja;
+#endif
+
+using namespace std;
+
+
+unordered_map<HighLevelILOperandUsage, HighLevelILOperandType>
+ HighLevelILInstructionBase::operandTypeForUsage = {
+ {SourceExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {VariableHighLevelOperandUsage, VariableHighLevelOperand},
+ {SSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand},
+ {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand},
+ {DestExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {LeftExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {RightExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {CarryExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {IndexExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {ConditionExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {TrueExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {FalseExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {LoopExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {InitExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {UpdateExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {DefaultExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {HighExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {LowExprHighLevelOperandUsage, ExprHighLevelOperand},
+ {OffsetHighLevelOperandUsage, IntegerHighLevelOperand},
+ {ConstantHighLevelOperandUsage, IntegerHighLevelOperand},
+ {VectorHighLevelOperandUsage, IntegerHighLevelOperand},
+ {IntrinsicHighLevelOperandUsage, IntrinsicHighLevelOperand},
+ {TargetHighLevelOperandUsage, IndexHighLevelOperand},
+ {ParameterExprsHighLevelOperandUsage, ExprListHighLevelOperand},
+ {SourceExprsHighLevelOperandUsage, ExprListHighLevelOperand},
+ {DestExprsHighLevelOperandUsage, ExprListHighLevelOperand},
+ {BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand},
+ {CasesHighLevelOperandUsage, ExprListHighLevelOperand},
+ {SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand}
+ };
+
+
+unordered_map<BNHighLevelILOperation, vector<HighLevelILOperandUsage>>
+ HighLevelILInstructionBase::operationOperandUsage = {
+ {HLIL_NOP, {}},
+ {HLIL_BREAK, {}},
+ {HLIL_NORET, {}},
+ {HLIL_BP, {}},
+ {HLIL_UNDEF, {}},
+ {HLIL_UNIMPL, {}},
+ {HLIL_BLOCK, {BlockExprsHighLevelOperandUsage}},
+ {HLIL_IF, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage,
+ FalseExprHighLevelOperandUsage}},
+ {HLIL_WHILE, {ConditionExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}},
+ {HLIL_DO_WHILE, {LoopExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage}},
+ {HLIL_FOR, {InitExprHighLevelOperandUsage, ConditionExprHighLevelOperandUsage,
+ UpdateExprHighLevelOperandUsage, LoopExprHighLevelOperandUsage}},
+ {HLIL_SWITCH, {ConditionExprHighLevelOperandUsage, DefaultExprHighLevelOperandUsage,
+ CasesHighLevelOperandUsage}},
+ {HLIL_CASE, {ConditionExprHighLevelOperandUsage, TrueExprHighLevelOperandUsage}},
+ {HLIL_JUMP, {DestExprHighLevelOperandUsage}},
+ {HLIL_RET, {SourceExprsHighLevelOperandUsage}},
+ {HLIL_GOTO, {TargetHighLevelOperandUsage}},
+ {HLIL_LABEL, {TargetHighLevelOperandUsage}},
+ {HLIL_ASSIGN, {DestExprHighLevelOperandUsage, SourceExprHighLevelOperandUsage}},
+ {HLIL_ASSIGN_UNPACK, {DestExprsHighLevelOperandUsage, SourceExprHighLevelOperandUsage}},
+ {HLIL_VAR, {VariableHighLevelOperandUsage}},
+ {HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}},
+ {HLIL_VAR_PHI, {DestSSAVariableHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage}},
+ {HLIL_STRUCT_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage}},
+ {HLIL_ARRAY_INDEX, {SourceExprHighLevelOperandUsage, IndexExprHighLevelOperandUsage}},
+ {HLIL_SPLIT, {HighExprHighLevelOperandUsage, LowExprHighLevelOperandUsage}},
+ {HLIL_DEREF, {SourceExprHighLevelOperandUsage}},
+ {HLIL_DEREF_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage}},
+ {HLIL_ADDRESS_OF, {SourceExprHighLevelOperandUsage}},
+ {HLIL_CALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}},
+ {HLIL_SYSCALL, {ParameterExprsHighLevelOperandUsage}},
+ {HLIL_TAILCALL, {DestExprHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}},
+ {HLIL_INTRINSIC, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage}},
+ {HLIL_TRAP, {VectorHighLevelOperandUsage}},
+ {HLIL_CONST, {ConstantHighLevelOperandUsage}},
+ {HLIL_CONST_PTR, {ConstantHighLevelOperandUsage}},
+ {HLIL_EXTERN_PTR, {ConstantHighLevelOperandUsage, OffsetHighLevelOperandUsage}},
+ {HLIL_FLOAT_CONST, {ConstantHighLevelOperandUsage}},
+ {HLIL_IMPORT, {ConstantHighLevelOperandUsage}},
+ {HLIL_ADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_SUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_AND, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_OR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_XOR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_LSL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_LSR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_ASR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_ROL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_ROR, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MULU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MULS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_DIVU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_DIVS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MODU, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MODS, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_SLT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_ULT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_SLE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_ULE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_SGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_UGE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_SGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_CMP_UGT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_TEST_BIT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_ADD_OVERFLOW, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_ADC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage,
+ CarryExprHighLevelOperandUsage}},
+ {HLIL_SBB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage,
+ CarryExprHighLevelOperandUsage}},
+ {HLIL_RLC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage,
+ CarryExprHighLevelOperandUsage}},
+ {HLIL_RRC, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage,
+ CarryExprHighLevelOperandUsage}},
+ {HLIL_DIVU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_DIVS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MODU_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_MODS_DP, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_NEG, {SourceExprHighLevelOperandUsage}},
+ {HLIL_NOT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_SX, {SourceExprHighLevelOperandUsage}},
+ {HLIL_ZX, {SourceExprHighLevelOperandUsage}},
+ {HLIL_LOW_PART, {SourceExprHighLevelOperandUsage}},
+ {HLIL_BOOL_TO_INT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_UNIMPL_MEM, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FSUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FMUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FDIV, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FSQRT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FNEG, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FABS, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FLOAT_TO_INT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_INT_TO_FLOAT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FLOAT_CONV, {SourceExprHighLevelOperandUsage}},
+ {HLIL_ROUND_TO_INT, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FLOOR, {SourceExprHighLevelOperandUsage}},
+ {HLIL_CEIL, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FTRUNC, {SourceExprHighLevelOperandUsage}},
+ {HLIL_FCMP_E, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_NE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_LT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_LE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_GE, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_GT, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_O, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
+ {HLIL_FCMP_UO, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}}
+ };
+
+
+static unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> GetOperandIndexForOperandUsages()
+{
+ unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>> result;
+ result.reserve(HighLevelILInstructionBase::operationOperandUsage.size());
+ for (auto& operation : HighLevelILInstructionBase::operationOperandUsage)
+ {
+ result[operation.first] = unordered_map<HighLevelILOperandUsage, size_t>();
+ result[operation.first].reserve(operation.second.size());
+ size_t operand = 0;
+ for (auto usage : operation.second)
+ {
+ result[operation.first][usage] = operand;
+ switch (HighLevelILInstructionBase::operandTypeForUsage[usage])
+ {
+ case SSAVariableHighLevelOperand:
+ case SSAVariableListHighLevelOperand:
+ case ExprListHighLevelOperand:
+ // SSA variables and lists take two operand slots
+ operand += 2;
+ break;
+ default:
+ operand++;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+
+unordered_map<BNHighLevelILOperation, unordered_map<HighLevelILOperandUsage, size_t>>
+ HighLevelILInstructionBase::operationOperandIndex = GetOperandIndexForOperandUsages();
+
+
+bool HighLevelILIntegerList::ListIterator::operator==(const ListIterator& a) const
+{
+ return count == a.count;
+}
+
+
+bool HighLevelILIntegerList::ListIterator::operator!=(const ListIterator& a) const
+{
+ return count != a.count;
+}
+
+
+bool HighLevelILIntegerList::ListIterator::operator<(const ListIterator& a) const
+{
+ return count > a.count;
+}
+
+
+HighLevelILIntegerList::ListIterator& HighLevelILIntegerList::ListIterator::operator++()
+{
+ count--;
+ if (count == 0)
+ return *this;
+
+ operand++;
+ if (operand >= 4)
+ {
+ operand = 0;
+ instr = function->GetRawExpr((size_t)instr.operands[4]);
+ }
+ return *this;
+}
+
+
+uint64_t HighLevelILIntegerList::ListIterator::operator*()
+{
+ return instr.operands[operand];
+}
+
+
+HighLevelILIntegerList::HighLevelILIntegerList(HighLevelILFunction* func,
+ const BNHighLevelILInstruction& instr, size_t count)
+{
+ m_start.function = func;
+ m_start.instr = instr;
+ m_start.operand = 0;
+ m_start.count = count;
+}
+
+
+HighLevelILIntegerList::const_iterator HighLevelILIntegerList::begin() const
+{
+ return m_start;
+}
+
+
+HighLevelILIntegerList::const_iterator HighLevelILIntegerList::end() const
+{
+ const_iterator result;
+ result.function = m_start.function;
+ result.operand = 0;
+ result.count = 0;
+ return result;
+}
+
+
+size_t HighLevelILIntegerList::size() const
+{
+ return m_start.count;
+}
+
+
+uint64_t HighLevelILIntegerList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw HighLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+HighLevelILIntegerList::operator vector<uint64_t>() const
+{
+ vector<uint64_t> result;
+ for (auto i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
+const HighLevelILInstruction HighLevelILInstructionList::ListIterator::operator*()
+{
+ return HighLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), (size_t)*pos);
+}
+
+
+HighLevelILInstructionList::HighLevelILInstructionList(HighLevelILFunction* func,
+ const BNHighLevelILInstruction& instr, size_t count): m_list(func, instr, count)
+{
+}
+
+
+HighLevelILInstructionList::const_iterator HighLevelILInstructionList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ return result;
+}
+
+
+HighLevelILInstructionList::const_iterator HighLevelILInstructionList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ return result;
+}
+
+
+size_t HighLevelILInstructionList::size() const
+{
+ return m_list.size();
+}
+
+
+const HighLevelILInstruction HighLevelILInstructionList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw HighLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+HighLevelILInstructionList::operator vector<HighLevelILInstruction>() const
+{
+ vector<HighLevelILInstruction> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
+const SSAVariable HighLevelILSSAVariableList::ListIterator::operator*()
+{
+ HighLevelILIntegerList::const_iterator cur = pos;
+ Variable var = Variable::FromIdentifier(*cur);
+ ++cur;
+ size_t version = (size_t)*cur;
+ return SSAVariable(var, version);
+}
+
+
+HighLevelILSSAVariableList::HighLevelILSSAVariableList(HighLevelILFunction* func,
+ const BNHighLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1))
+{
+}
+
+
+HighLevelILSSAVariableList::const_iterator HighLevelILSSAVariableList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ return result;
+}
+
+
+HighLevelILSSAVariableList::const_iterator HighLevelILSSAVariableList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ return result;
+}
+
+
+size_t HighLevelILSSAVariableList::size() const
+{
+ return m_list.size() / 2;
+}
+
+
+const SSAVariable HighLevelILSSAVariableList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw HighLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+HighLevelILSSAVariableList::operator vector<SSAVariable>() const
+{
+ vector<SSAVariable> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
+HighLevelILOperand::HighLevelILOperand(const HighLevelILInstruction& instr,
+ HighLevelILOperandUsage usage, size_t operandIndex):
+ m_instr(instr), m_usage(usage), m_operandIndex(operandIndex)
+{
+ auto i = HighLevelILInstructionBase::operandTypeForUsage.find(m_usage);
+ if (i == HighLevelILInstructionBase::operandTypeForUsage.end())
+ throw HighLevelILInstructionAccessException();
+ m_type = i->second;
+}
+
+
+uint64_t HighLevelILOperand::GetInteger() const
+{
+ if (m_type != IntegerHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsInteger(m_operandIndex);
+}
+
+
+size_t HighLevelILOperand::GetIndex() const
+{
+ if (m_type != IndexHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsIndex(m_operandIndex);
+}
+
+
+uint32_t HighLevelILOperand::GetIntrinsic() const
+{
+ if (m_type != IntrinsicHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return (uint32_t)m_instr.GetRawOperandAsInteger(m_operandIndex);
+}
+
+
+HighLevelILInstruction HighLevelILOperand::GetExpr() const
+{
+ if (m_type != ExprHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsExpr(m_operandIndex);
+}
+
+
+Variable HighLevelILOperand::GetVariable() const
+{
+ if (m_type != VariableHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsVariable(m_operandIndex);
+}
+
+
+SSAVariable HighLevelILOperand::GetSSAVariable() const
+{
+ if (m_type != SSAVariableHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsSSAVariable(m_operandIndex);
+}
+
+
+HighLevelILInstructionList HighLevelILOperand::GetExprList() const
+{
+ if (m_type != ExprListHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsExprList(m_operandIndex);
+}
+
+
+HighLevelILSSAVariableList HighLevelILOperand::GetSSAVariableList() const
+{
+ if (m_type != SSAVariableListHighLevelOperand)
+ throw HighLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsSSAVariableList(m_operandIndex);
+}
+
+
+const HighLevelILOperand HighLevelILOperandList::ListIterator::operator*()
+{
+ HighLevelILOperandUsage usage = *pos;
+ auto i = owner->m_operandIndexMap.find(usage);
+ if (i == owner->m_operandIndexMap.end())
+ throw HighLevelILInstructionAccessException();
+ return HighLevelILOperand(owner->m_instr, usage, i->second);
+}
+
+
+HighLevelILOperandList::HighLevelILOperandList(const HighLevelILInstruction& instr,
+ const vector<HighLevelILOperandUsage>& usageList,
+ const unordered_map<HighLevelILOperandUsage, size_t>& operandIndexMap):
+ m_instr(instr), m_usageList(usageList), m_operandIndexMap(operandIndexMap)
+{
+}
+
+
+HighLevelILOperandList::const_iterator HighLevelILOperandList::begin() const
+{
+ const_iterator result;
+ result.owner = this;
+ result.pos = m_usageList.begin();
+ return result;
+}
+
+
+HighLevelILOperandList::const_iterator HighLevelILOperandList::end() const
+{
+ const_iterator result;
+ result.owner = this;
+ result.pos = m_usageList.end();
+ return result;
+}
+
+
+size_t HighLevelILOperandList::size() const
+{
+ return m_usageList.size();
+}
+
+
+const HighLevelILOperand HighLevelILOperandList::operator[](size_t i) const
+{
+ HighLevelILOperandUsage usage = m_usageList[i];
+ auto indexMap = m_operandIndexMap.find(usage);
+ if (indexMap == m_operandIndexMap.end())
+ throw HighLevelILInstructionAccessException();
+ return HighLevelILOperand(m_instr, usage, indexMap->second);
+}
+
+
+HighLevelILOperandList::operator vector<HighLevelILOperand>() const
+{
+ vector<HighLevelILOperand> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
+HighLevelILInstruction::HighLevelILInstruction()
+{
+ operation = HLIL_UNDEF;
+ sourceOperand = BN_INVALID_OPERAND;
+ size = 0;
+ address = 0;
+ function = nullptr;
+ exprIndex = BN_INVALID_EXPR;
+ parent = BN_INVALID_EXPR;
+}
+
+
+HighLevelILInstruction::HighLevelILInstruction(HighLevelILFunction* func,
+ const BNHighLevelILInstruction& instr, size_t expr)
+{
+ 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;
+ parent = instr.parent;
+ function = func;
+ exprIndex = expr;
+}
+
+
+HighLevelILInstruction::HighLevelILInstruction(const HighLevelILInstructionBase& 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;
+ parent = instr.parent;
+}
+
+
+HighLevelILOperandList HighLevelILInstructionBase::GetOperands() const
+{
+ auto usage = operationOperandUsage.find(operation);
+ if (usage == operationOperandUsage.end())
+ throw HighLevelILInstructionAccessException();
+ auto operandIndex = operationOperandIndex.find(operation);
+ if (operandIndex == operationOperandIndex.end())
+ throw HighLevelILInstructionAccessException();
+ return HighLevelILOperandList(*(const HighLevelILInstruction*)this, usage->second, operandIndex->second);
+}
+
+
+uint64_t HighLevelILInstructionBase::GetRawOperandAsInteger(size_t operand) const
+{
+ return operands[operand];
+}
+
+
+size_t HighLevelILInstructionBase::GetRawOperandAsIndex(size_t operand) const
+{
+ return (size_t)operands[operand];
+}
+
+
+HighLevelILInstruction HighLevelILInstructionBase::GetRawOperandAsExpr(size_t operand) const
+{
+ return HighLevelILInstruction(function, function->GetRawExpr(operands[operand]), operands[operand]);
+}
+
+
+Variable HighLevelILInstructionBase::GetRawOperandAsVariable(size_t operand) const
+{
+ return Variable::FromIdentifier(operands[operand]);
+}
+
+
+SSAVariable HighLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operand) const
+{
+ return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 1]);
+}
+
+
+HighLevelILInstructionList HighLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const
+{
+ return HighLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+}
+
+
+HighLevelILSSAVariableList HighLevelILInstructionBase::GetRawOperandAsSSAVariableList(size_t operand) const
+{
+ return HighLevelILSSAVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+}
+
+
+void HighLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value)
+{
+ operands[operandIndex] = value;
+ function->UpdateInstructionOperand(exprIndex, operandIndex, value);
+}
+
+
+void HighLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<HighLevelILInstruction>& exprs)
+{
+ vector<ExprId> exprIndexList;
+ for (auto& i : exprs)
+ exprIndexList.push_back((ExprId)i.exprIndex);
+ UpdateRawOperand(operandIndex, exprIndexList.size());
+ UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprIndexList));
+}
+
+
+void HighLevelILInstructionBase::UpdateRawOperandAsExprList(size_t operandIndex, const vector<ExprId>& exprs)
+{
+ UpdateRawOperand(operandIndex, exprs.size());
+ UpdateRawOperand(operandIndex + 1, function->AddOperandList(exprs));
+}
+
+
+void HighLevelILInstructionBase::UpdateRawOperandAsSSAVariableList(size_t operandIndex, const vector<SSAVariable>& vars)
+{
+ UpdateRawOperand(operandIndex, vars.size() * 2);
+ UpdateRawOperand(operandIndex + 1, function->AddSSAVariableList(vars));
+}
+
+
+size_t HighLevelILInstructionBase::GetMediumLevelILExprIndex() const
+{
+ return function->GetMediumLevelILExprIndex(exprIndex);
+}
+
+
+bool HighLevelILInstructionBase::HasMediumLevelIL() const
+{
+ Ref<MediumLevelILFunction> func = function->GetMediumLevelIL();
+ if (!func)
+ return false;
+ Ref<MediumLevelILFunction> ssa = func->GetSSAForm().GetPtr();
+ if (!ssa)
+ return false;
+ return GetMediumLevelILExprIndex() < ssa->GetExprCount();
+}
+
+
+MediumLevelILInstruction HighLevelILInstructionBase::GetMediumLevelIL() const
+{
+ return GetMediumLevelILSSAForm().GetNonSSAForm();
+}
+
+
+MediumLevelILInstruction HighLevelILInstructionBase::GetMediumLevelILSSAForm() const
+{
+ Ref<MediumLevelILFunction> func = function->GetMediumLevelIL();
+ if (!func)
+ throw MediumLevelILInstructionAccessException();
+ Ref<MediumLevelILFunction> ssa = func->GetSSAForm().GetPtr();
+ if (!ssa)
+ throw MediumLevelILInstructionAccessException();
+ size_t expr = GetMediumLevelILExprIndex();
+ if (expr >= ssa->GetExprCount())
+ throw MediumLevelILInstructionAccessException();
+ return ssa->GetExpr(expr);
+}
+
+
+void HighLevelILInstructionBase::Replace(ExprId expr)
+{
+ function->ReplaceExpr(exprIndex, expr);
+}
+
+
+size_t HighLevelILInstructionBase::GetInstructionIndex() const
+{
+ return function->GetInstructionForExpr(exprIndex);
+}
+
+
+HighLevelILInstruction HighLevelILInstructionBase::GetInstruction() const
+{
+ return function->GetInstruction(GetInstructionIndex());
+}
+
+
+void HighLevelILInstruction::VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const
+{
+ stack<size_t> toProcess;
+ vector<HighLevelILInstruction> exprs;
+
+ toProcess.push(exprIndex);
+ while (!toProcess.empty())
+ {
+ HighLevelILInstruction cur = function->GetExpr(toProcess.top());
+ toProcess.pop();
+ if (!func(cur))
+ continue;
+ switch (cur.operation)
+ {
+ case HLIL_BLOCK:
+ exprs = cur.GetBlockExprs<HLIL_BLOCK>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ break;
+ case HLIL_IF:
+ toProcess.push(cur.GetFalseExpr<HLIL_IF>().exprIndex);
+ toProcess.push(cur.GetTrueExpr<HLIL_IF>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_IF>().exprIndex);
+ break;
+ case HLIL_WHILE:
+ toProcess.push(cur.GetLoopExpr<HLIL_WHILE>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_WHILE>().exprIndex);
+ break;
+ case HLIL_DO_WHILE:
+ toProcess.push(cur.GetConditionExpr<HLIL_DO_WHILE>().exprIndex);
+ toProcess.push(cur.GetLoopExpr<HLIL_DO_WHILE>().exprIndex);
+ break;
+ case HLIL_FOR:
+ toProcess.push(cur.GetLoopExpr<HLIL_FOR>().exprIndex);
+ toProcess.push(cur.GetUpdateExpr<HLIL_FOR>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_FOR>().exprIndex);
+ toProcess.push(cur.GetInitExpr<HLIL_FOR>().exprIndex);
+ break;
+ case HLIL_SWITCH:
+ exprs = cur.GetCases<HLIL_SWITCH>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ toProcess.push(cur.GetDefaultExpr<HLIL_SWITCH>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_SWITCH>().exprIndex);
+ break;
+ case HLIL_CASE:
+ toProcess.push(cur.GetTrueExpr<HLIL_CASE>().exprIndex);
+ toProcess.push(cur.GetConditionExpr<HLIL_CASE>().exprIndex);
+ break;
+ case HLIL_ASSIGN:
+ toProcess.push(cur.GetSourceExpr<HLIL_ASSIGN>().exprIndex);
+ toProcess.push(cur.GetDestExpr<HLIL_ASSIGN>().exprIndex);
+ break;
+ case HLIL_ASSIGN_UNPACK:
+ toProcess.push(cur.GetSourceExpr<HLIL_ASSIGN_UNPACK>().exprIndex);
+ exprs = cur.GetDestExprs<HLIL_ASSIGN_UNPACK>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ break;
+ case HLIL_STRUCT_FIELD:
+ toProcess.push(cur.GetSourceExpr<HLIL_STRUCT_FIELD>().exprIndex);
+ break;
+ case HLIL_ARRAY_INDEX:
+ toProcess.push(cur.GetIndexExpr<HLIL_ARRAY_INDEX>().exprIndex);
+ toProcess.push(cur.GetSourceExpr<HLIL_ARRAY_INDEX>().exprIndex);
+ break;
+ case HLIL_SPLIT:
+ toProcess.push(cur.GetLowExpr<HLIL_SPLIT>().exprIndex);
+ toProcess.push(cur.GetHighExpr<HLIL_SPLIT>().exprIndex);
+ break;
+ case HLIL_DEREF_FIELD:
+ toProcess.push(cur.GetSourceExpr<HLIL_DEREF_FIELD>().exprIndex);
+ break;
+ case HLIL_CALL:
+ exprs = cur.GetParameterExprs<HLIL_CALL>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ toProcess.push(cur.GetDestExpr<HLIL_CALL>().exprIndex);
+ break;
+ case HLIL_SYSCALL:
+ exprs = cur.GetParameterExprs<HLIL_SYSCALL>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ break;
+ case HLIL_TAILCALL:
+ exprs = cur.GetParameterExprs<HLIL_TAILCALL>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ toProcess.push(cur.GetDestExpr<HLIL_TAILCALL>().exprIndex);
+ break;
+ case HLIL_RET:
+ exprs = cur.GetSourceExprs<HLIL_RET>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ break;
+ case HLIL_DEREF:
+ case HLIL_ADDRESS_OF:
+ case HLIL_NEG:
+ case HLIL_NOT:
+ case HLIL_SX:
+ case HLIL_ZX:
+ case HLIL_LOW_PART:
+ case HLIL_BOOL_TO_INT:
+ case HLIL_JUMP:
+ case HLIL_UNIMPL_MEM:
+ case HLIL_FSQRT:
+ case HLIL_FNEG:
+ case HLIL_FABS:
+ case HLIL_FLOAT_TO_INT:
+ case HLIL_INT_TO_FLOAT:
+ case HLIL_FLOAT_CONV:
+ case HLIL_ROUND_TO_INT:
+ case HLIL_FLOOR:
+ case HLIL_CEIL:
+ case HLIL_FTRUNC:
+ toProcess.push(cur.AsOneOperand().GetSourceExpr().exprIndex);
+ break;
+ case HLIL_ADD:
+ case HLIL_SUB:
+ case HLIL_AND:
+ case HLIL_OR:
+ case HLIL_XOR:
+ case HLIL_LSL:
+ case HLIL_LSR:
+ case HLIL_ASR:
+ case HLIL_ROL:
+ case HLIL_ROR:
+ case HLIL_MUL:
+ case HLIL_MULU_DP:
+ case HLIL_MULS_DP:
+ case HLIL_DIVU:
+ case HLIL_DIVS:
+ case HLIL_MODU:
+ case HLIL_MODS:
+ case HLIL_DIVU_DP:
+ case HLIL_DIVS_DP:
+ case HLIL_MODU_DP:
+ case HLIL_MODS_DP:
+ case HLIL_CMP_E:
+ case HLIL_CMP_NE:
+ case HLIL_CMP_SLT:
+ case HLIL_CMP_ULT:
+ case HLIL_CMP_SLE:
+ case HLIL_CMP_ULE:
+ case HLIL_CMP_SGE:
+ case HLIL_CMP_UGE:
+ case HLIL_CMP_SGT:
+ case HLIL_CMP_UGT:
+ case HLIL_TEST_BIT:
+ case HLIL_ADD_OVERFLOW:
+ case HLIL_FADD:
+ case HLIL_FSUB:
+ case HLIL_FMUL:
+ case HLIL_FDIV:
+ case HLIL_FCMP_E:
+ case HLIL_FCMP_NE:
+ case HLIL_FCMP_LT:
+ case HLIL_FCMP_LE:
+ case HLIL_FCMP_GE:
+ case HLIL_FCMP_GT:
+ case HLIL_FCMP_O:
+ case HLIL_FCMP_UO:
+ toProcess.push(cur.AsTwoOperand().GetRightExpr().exprIndex);
+ toProcess.push(cur.AsTwoOperand().GetLeftExpr().exprIndex);
+ break;
+ case HLIL_ADC:
+ case HLIL_SBB:
+ case HLIL_RLC:
+ case HLIL_RRC:
+ toProcess.push(cur.AsTwoOperandWithCarry().GetCarryExpr().exprIndex);
+ toProcess.push(cur.AsTwoOperandWithCarry().GetRightExpr().exprIndex);
+ toProcess.push(cur.AsTwoOperandWithCarry().GetLeftExpr().exprIndex);
+ break;
+ case HLIL_INTRINSIC:
+ exprs = cur.GetParameterExprs<HLIL_INTRINSIC>();
+ for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
+ toProcess.push(i->exprIndex);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest) const
+{
+ return CopyTo(dest, [&](const HighLevelILInstruction& subExpr) {
+ return subExpr.CopyTo(dest);
+ });
+}
+
+
+ExprId HighLevelILInstruction::CopyTo(HighLevelILFunction* dest,
+ const std::function<ExprId(const HighLevelILInstruction& subExpr)>& subExprHandler) const
+{
+ vector<ExprId> output, params;
+ switch (operation)
+ {
+ case HLIL_NOP:
+ return dest->Nop(*this);
+ case HLIL_BLOCK:
+ for (auto& i : GetBlockExprs<HLIL_BLOCK>())
+ params.push_back(subExprHandler(i));
+ return dest->Block(params, *this);
+ case HLIL_IF:
+ return dest->If(subExprHandler(GetConditionExpr<HLIL_IF>()),
+ subExprHandler(GetTrueExpr<HLIL_IF>()), subExprHandler(GetFalseExpr<HLIL_IF>()), *this);
+ case HLIL_WHILE:
+ return dest->While(subExprHandler(GetConditionExpr<HLIL_WHILE>()),
+ subExprHandler(GetLoopExpr<HLIL_WHILE>()), *this);
+ case HLIL_DO_WHILE:
+ return dest->DoWhile(subExprHandler(GetLoopExpr<HLIL_WHILE>()),
+ subExprHandler(GetConditionExpr<HLIL_WHILE>()), *this);
+ case HLIL_FOR:
+ return dest->For(subExprHandler(GetInitExpr<HLIL_FOR>()),
+ subExprHandler(GetConditionExpr<HLIL_FOR>()), subExprHandler(GetUpdateExpr<HLIL_FOR>()),
+ subExprHandler(GetLoopExpr<HLIL_FOR>()), *this);
+ case HLIL_SWITCH:
+ for (auto& i : GetCases<HLIL_SWITCH>())
+ params.push_back(subExprHandler(i));
+ return dest->Switch(subExprHandler(GetConditionExpr<HLIL_SWITCH>()),
+ subExprHandler(GetDefaultExpr<HLIL_SWITCH>()), params, *this);
+ case HLIL_CASE:
+ return dest->Case(subExprHandler(GetConditionExpr<HLIL_CASE>()),
+ subExprHandler(GetTrueExpr<HLIL_CASE>()), *this);
+ case HLIL_BREAK:
+ return dest->Break(*this);
+ case HLIL_ASSIGN:
+ return dest->Assign(size, subExprHandler(GetDestExpr<HLIL_ASSIGN>()),
+ subExprHandler(GetSourceExpr<HLIL_ASSIGN>()), *this);
+ case HLIL_ASSIGN_UNPACK:
+ for (auto& i : GetDestExprs<HLIL_ASSIGN_UNPACK>())
+ output.push_back(subExprHandler(i));
+ return dest->AssignUnpack(output,
+ subExprHandler(GetSourceExpr<HLIL_ASSIGN_UNPACK>()), *this);
+ case HLIL_VAR:
+ return dest->Var(size, GetVariable<HLIL_VAR>(), *this);
+ case HLIL_VAR_SSA:
+ return dest->VarSSA(size, GetSSAVariable<HLIL_VAR_SSA>(), *this);
+ case HLIL_VAR_PHI:
+ return dest->VarPhi(GetDestSSAVariable<HLIL_VAR_PHI>(), GetSourceSSAVariables<HLIL_VAR_PHI>(), *this);
+ case HLIL_STRUCT_FIELD:
+ return dest->StructField(size, subExprHandler(GetSourceExpr<HLIL_STRUCT_FIELD>()),
+ GetOffset<HLIL_STRUCT_FIELD>(), *this);
+ case HLIL_ARRAY_INDEX:
+ return dest->ArrayIndex(size, subExprHandler(GetSourceExpr<HLIL_ARRAY_INDEX>()),
+ subExprHandler(GetIndexExpr<HLIL_ARRAY_INDEX>()), *this);
+ case HLIL_SPLIT:
+ return dest->Split(size, subExprHandler(GetHighExpr<HLIL_SPLIT>()),
+ subExprHandler(GetLowExpr<HLIL_SPLIT>()), *this);
+ case HLIL_DEREF:
+ return dest->Deref(size, subExprHandler(GetSourceExpr<HLIL_DEREF>()), *this);
+ case HLIL_DEREF_FIELD:
+ return dest->DerefField(size, subExprHandler(GetSourceExpr<HLIL_DEREF_FIELD>()),
+ GetOffset<HLIL_DEREF_FIELD>(), *this);
+ case HLIL_ADDRESS_OF:
+ return dest->AddressOf(subExprHandler(GetSourceExpr<HLIL_ADDRESS_OF>()), *this);
+ case HLIL_CALL:
+ for (auto& i : GetParameterExprs<HLIL_CALL>())
+ params.push_back(subExprHandler(i));
+ return dest->Call(subExprHandler(GetDestExpr<HLIL_CALL>()), params, *this);
+ case HLIL_SYSCALL:
+ for (auto& i : GetParameterExprs<HLIL_SYSCALL>())
+ params.push_back(subExprHandler(i));
+ return dest->Syscall(params, *this);
+ case HLIL_TAILCALL:
+ for (auto& i : GetParameterExprs<HLIL_TAILCALL>())
+ params.push_back(subExprHandler(i));
+ return dest->TailCall(subExprHandler(GetDestExpr<HLIL_TAILCALL>()), params, *this);
+ case HLIL_RET:
+ for (auto& i : GetSourceExprs<HLIL_RET>())
+ params.push_back(subExprHandler(i));
+ return dest->Return(params, *this);
+ case HLIL_NORET:
+ return dest->NoReturn(*this);
+ case HLIL_NEG:
+ case HLIL_NOT:
+ case HLIL_SX:
+ case HLIL_ZX:
+ case HLIL_LOW_PART:
+ case HLIL_BOOL_TO_INT:
+ case HLIL_JUMP:
+ case HLIL_UNIMPL_MEM:
+ case HLIL_FSQRT:
+ case HLIL_FNEG:
+ case HLIL_FABS:
+ case HLIL_FLOAT_TO_INT:
+ case HLIL_INT_TO_FLOAT:
+ case HLIL_FLOAT_CONV:
+ case HLIL_ROUND_TO_INT:
+ case HLIL_FLOOR:
+ case HLIL_CEIL:
+ case HLIL_FTRUNC:
+ return dest->AddExprWithLocation(operation, *this, size,
+ subExprHandler(AsOneOperand().GetSourceExpr()));
+ case HLIL_ADD:
+ case HLIL_SUB:
+ case HLIL_AND:
+ case HLIL_OR:
+ case HLIL_XOR:
+ case HLIL_LSL:
+ case HLIL_LSR:
+ case HLIL_ASR:
+ case HLIL_ROL:
+ case HLIL_ROR:
+ case HLIL_MUL:
+ case HLIL_MULU_DP:
+ case HLIL_MULS_DP:
+ case HLIL_DIVU:
+ case HLIL_DIVS:
+ case HLIL_MODU:
+ case HLIL_MODS:
+ case HLIL_DIVU_DP:
+ case HLIL_DIVS_DP:
+ case HLIL_MODU_DP:
+ case HLIL_MODS_DP:
+ case HLIL_CMP_E:
+ case HLIL_CMP_NE:
+ case HLIL_CMP_SLT:
+ case HLIL_CMP_ULT:
+ case HLIL_CMP_SLE:
+ case HLIL_CMP_ULE:
+ case HLIL_CMP_SGE:
+ case HLIL_CMP_UGE:
+ case HLIL_CMP_SGT:
+ case HLIL_CMP_UGT:
+ case HLIL_TEST_BIT:
+ case HLIL_ADD_OVERFLOW:
+ case HLIL_FADD:
+ case HLIL_FSUB:
+ case HLIL_FMUL:
+ case HLIL_FDIV:
+ case HLIL_FCMP_E:
+ case HLIL_FCMP_NE:
+ case HLIL_FCMP_LT:
+ case HLIL_FCMP_LE:
+ case HLIL_FCMP_GE:
+ case HLIL_FCMP_GT:
+ case HLIL_FCMP_O:
+ case HLIL_FCMP_UO:
+ return dest->AddExprWithLocation(operation, *this, size,
+ subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr()));
+ case HLIL_ADC:
+ case HLIL_SBB:
+ case HLIL_RLC:
+ case HLIL_RRC:
+ return dest->AddExprWithLocation(operation, *this, size,
+ subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()),
+ subExprHandler(AsTwoOperandWithCarry().GetRightExpr()),
+ subExprHandler(AsTwoOperandWithCarry().GetCarryExpr()));
+ case HLIL_CONST:
+ return dest->Const(size, GetConstant<HLIL_CONST>(), *this);
+ case HLIL_CONST_PTR:
+ return dest->ConstPointer(size, GetConstant<HLIL_CONST_PTR>(), *this);
+ case HLIL_EXTERN_PTR:
+ return dest->ExternPointer(size, GetConstant<HLIL_EXTERN_PTR>(), GetOffset<HLIL_EXTERN_PTR>(), *this);
+ case HLIL_FLOAT_CONST:
+ return dest->FloatConstRaw(size, GetConstant<HLIL_FLOAT_CONST>(), *this);
+ case HLIL_IMPORT:
+ return dest->ImportedAddress(size, GetConstant<HLIL_IMPORT>(), *this);
+ case HLIL_BP:
+ return dest->Breakpoint(*this);
+ case HLIL_TRAP:
+ return dest->Trap(GetVector<HLIL_TRAP>(), *this);
+ case HLIL_INTRINSIC:
+ for (auto& i : GetParameterExprs<HLIL_INTRINSIC>())
+ params.push_back(subExprHandler(i));
+ return dest->Intrinsic(GetIntrinsic<HLIL_INTRINSIC>(), params, *this);
+ case HLIL_UNDEF:
+ return dest->Undefined(*this);
+ case HLIL_UNIMPL:
+ return dest->Unimplemented(*this);
+ default:
+ throw HighLevelILInstructionAccessException();
+ }
+}
+
+
+bool HighLevelILInstruction::GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const
+{
+ auto operationIter = HighLevelILInstructionBase::operationOperandIndex.find(operation);
+ if (operationIter == HighLevelILInstructionBase::operationOperandIndex.end())
+ return false;
+ auto usageIter = operationIter->second.find(usage);
+ if (usageIter == operationIter->second.end())
+ return false;
+ operandIndex = usageIter->second;
+ return true;
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetSourceExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SourceExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+Variable HighLevelILInstruction::GetVariable() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(VariableHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsVariable(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+SSAVariable HighLevelILInstruction::GetSSAVariable() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SSAVariableHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSAVariable(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+SSAVariable HighLevelILInstruction::GetDestSSAVariable() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DestSSAVariableHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSAVariable(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetDestExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DestExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetLeftExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(LeftExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetRightExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(RightExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetCarryExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(CarryExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetIndexExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(IndexExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetConditionExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(ConditionExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetTrueExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(TrueExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetFalseExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(FalseExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetLoopExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(LoopExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetInitExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(InitExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetUpdateExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(UpdateExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetDefaultExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DefaultExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetHighExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(HighExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstruction HighLevelILInstruction::GetLowExpr() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(LowExprHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+uint64_t HighLevelILInstruction::GetOffset() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(OffsetHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsInteger(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+int64_t HighLevelILInstruction::GetConstant() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(ConstantHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsInteger(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+int64_t HighLevelILInstruction::GetVector() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(VectorHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsInteger(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+uint32_t HighLevelILInstruction::GetIntrinsic() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(IntrinsicHighLevelOperandUsage, operandIndex))
+ return (uint32_t)GetRawOperandAsInteger(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+size_t HighLevelILInstruction::GetTarget() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(TargetHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsIndex(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstructionList HighLevelILInstruction::GetParameterExprs() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(ParameterExprsHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExprList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstructionList HighLevelILInstruction::GetSourceExprs() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SourceExprsHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExprList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstructionList HighLevelILInstruction::GetDestExprs() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DestExprsHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExprList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstructionList HighLevelILInstruction::GetBlockExprs() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(BlockExprsHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExprList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILInstructionList HighLevelILInstruction::GetCases() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(CasesHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExprList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+HighLevelILSSAVariableList HighLevelILInstruction::GetSourceSSAVariables() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SourceSSAVariablesHighLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSAVariableList(operandIndex);
+ throw HighLevelILInstructionAccessException();
+}
+
+
+ExprId HighLevelILFunction::Nop(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_NOP, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::Block(const std::vector<ExprId>& exprs, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_BLOCK, loc, 0, exprs.size(), AddOperandList(exprs));
+}
+
+
+ExprId HighLevelILFunction::If(ExprId condition, ExprId trueExpr, ExprId falseExpr,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_IF, loc, 0, condition, trueExpr, falseExpr);
+}
+
+
+ExprId HighLevelILFunction::While(ExprId condition, ExprId loopExpr, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_WHILE, loc, 0, condition, loopExpr);
+}
+
+
+ExprId HighLevelILFunction::DoWhile(ExprId loopExpr, ExprId condition, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DO_WHILE, loc, 0, loopExpr, condition);
+}
+
+
+ExprId HighLevelILFunction::For(ExprId initExpr, ExprId condition, ExprId updateExpr, ExprId loopExpr,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FOR, loc, 0, initExpr, condition, updateExpr, loopExpr);
+}
+
+
+ExprId HighLevelILFunction::Switch(ExprId condition, ExprId defaultExpr, const std::vector<ExprId>& cases,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SWITCH, loc, 0, condition, defaultExpr,
+ cases.size(), AddOperandList(cases));
+}
+
+
+ExprId HighLevelILFunction::Case(ExprId condition, ExprId expr, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CASE, loc, 0, condition, expr);
+}
+
+
+ExprId HighLevelILFunction::Break(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_BREAK, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_JUMP, loc, 0, dest);
+}
+
+
+ExprId HighLevelILFunction::Return(const vector<ExprId>& sources, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_RET, loc, 0, sources.size(), AddOperandList(sources));
+}
+
+
+ExprId HighLevelILFunction::NoReturn(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_NORET, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::Goto(size_t target, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_GOTO, loc, 0, target);
+}
+
+
+ExprId HighLevelILFunction::Label(size_t target, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_LABEL, loc, 0, target);
+}
+
+
+ExprId HighLevelILFunction::Assign(size_t size, ExprId dest, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ASSIGN, loc, size, dest, src);
+}
+
+
+ExprId HighLevelILFunction::AssignUnpack(const vector<ExprId>& output, ExprId src,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ASSIGN_UNPACK, loc, 0, output.size(), AddOperandList(output), src);
+}
+
+
+ExprId HighLevelILFunction::Var(size_t size, const Variable& src,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_VAR, loc, size, src.ToIdentifier());
+}
+
+
+ExprId HighLevelILFunction::VarSSA(size_t size, const SSAVariable& src,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_VAR_SSA, loc, size, src.var.ToIdentifier(), src.version);
+}
+
+
+ExprId HighLevelILFunction::VarPhi(const SSAVariable& dest, const vector<SSAVariable>& sources, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_VAR_PHI, loc, 0, dest.var.ToIdentifier(), dest.version,
+ sources.size() * 2, AddSSAVariableList(sources));
+}
+
+
+ExprId HighLevelILFunction::StructField(size_t size, ExprId src, uint64_t offset, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_STRUCT_FIELD, loc, size, src, offset);
+}
+
+
+ExprId HighLevelILFunction::Split(size_t size, ExprId high, ExprId low, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SPLIT, loc, size, high, low);
+}
+
+
+ExprId HighLevelILFunction::ArrayIndex(size_t size, ExprId src, ExprId idx, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_STRUCT_FIELD, loc, size, src, idx);
+}
+
+
+ExprId HighLevelILFunction::Deref(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DEREF, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::DerefField(size_t size, ExprId src, uint64_t offset, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DEREF_FIELD, loc, size, src, offset);
+}
+
+
+ExprId HighLevelILFunction::AddressOf(ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ADDRESS_OF, loc, 0, src);
+}
+
+
+ExprId HighLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CONST, loc, size, val);
+}
+
+
+ExprId HighLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CONST_PTR, loc, size, val);
+}
+
+
+ExprId HighLevelILFunction::ExternPointer(size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_EXTERN_PTR, loc, size, val, offset);
+}
+
+
+ExprId HighLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FLOAT_CONST, loc, size, val);
+}
+
+
+ExprId HighLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc)
+{
+ union
+ {
+ float f;
+ uint32_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(HLIL_FLOAT_CONST, loc, 4, bits.i);
+}
+
+
+ExprId HighLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc)
+{
+ union
+ {
+ double f;
+ uint64_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(HLIL_FLOAT_CONST, loc, 8, bits.i);
+}
+
+
+ExprId HighLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_IMPORT, loc, size, val);
+}
+
+
+ExprId HighLevelILFunction::Add(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ADD, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::AddWithCarry(size_t size, ExprId left, ExprId right, ExprId carry,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ADC, loc, size, left, right, carry);
+}
+
+
+ExprId HighLevelILFunction::Sub(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SUB, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::SubWithBorrow(size_t size, ExprId left, ExprId right, ExprId carry,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SBB, loc, size, left, right, carry);
+}
+
+
+ExprId HighLevelILFunction::And(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_AND, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::Or(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_OR, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::Xor(size_t size, ExprId left, ExprId right, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_XOR, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ShiftLeft(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_LSL, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::LogicalShiftRight(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_LSR, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ArithShiftRight(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ASR, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::RotateLeft(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ROL, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::RotateLeftCarry(size_t size, ExprId left, ExprId right, ExprId carry,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_RRC, loc, size, left, right, carry);
+}
+
+
+ExprId HighLevelILFunction::RotateRight(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ROR, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::RotateRightCarry(size_t size, ExprId left, ExprId right, ExprId carry,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_RRC, loc, size, left, right, carry);
+}
+
+
+ExprId HighLevelILFunction::Mult(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MUL, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::MultDoublePrecSigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MULS_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::MultDoublePrecUnsigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MULU_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::DivSigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DIVS, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::DivUnsigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DIVU, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::DivDoublePrecSigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DIVS_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::DivDoublePrecUnsigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_DIVU_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ModSigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MODS, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ModUnsigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MODU, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ModDoublePrecSigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MODS_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::ModDoublePrecUnsigned(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_MODU_DP, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::Neg(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_NEG, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_NOT, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SX, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ZX, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::LowPart(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_LOW_PART, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::Call(ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CALL, loc, 0, dest, params.size(), AddOperandList(params));
+}
+
+
+ExprId HighLevelILFunction::Syscall(const vector<ExprId>& params,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_SYSCALL, loc, 0, params.size(), AddOperandList(params));
+}
+
+
+ExprId HighLevelILFunction::TailCall(ExprId dest, const vector<ExprId>& params, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_TAILCALL, loc, 0, dest, params.size(), AddOperandList(params));
+}
+
+
+ExprId HighLevelILFunction::CompareEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_E, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareNotEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_NE, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareSignedLessThan(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_SLT, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareUnsignedLessThan(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_ULT, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareSignedLessEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_SLE, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareUnsignedLessEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_ULE, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareSignedGreaterEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_SGE, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareUnsignedGreaterEqual(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_UGE, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareSignedGreaterThan(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_SGT, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::CompareUnsignedGreaterThan(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CMP_UGT, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::TestBit(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_TEST_BIT, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::BoolToInt(size_t size, ExprId src, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_BOOL_TO_INT, loc, size, src);
+}
+
+
+ExprId HighLevelILFunction::AddOverflow(size_t size, ExprId left, ExprId right,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ADD_OVERFLOW, loc, size, left, right);
+}
+
+
+ExprId HighLevelILFunction::Breakpoint(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_BP, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_TRAP, loc, 0, vector);
+}
+
+
+ExprId HighLevelILFunction::Intrinsic(uint32_t intrinsic, const vector<ExprId>& params,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_INTRINSIC, loc, 0, intrinsic,
+ params.size(), AddOperandList(params));
+}
+
+
+ExprId HighLevelILFunction::Undefined(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_UNDEF, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::Unimplemented(const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_UNIMPL, loc, 0);
+}
+
+
+ExprId HighLevelILFunction::UnimplementedMemoryRef(size_t size, ExprId target,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_UNIMPL_MEM, loc, size, target);
+}
+
+
+ExprId HighLevelILFunction::FloatAdd(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FADD, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatSub(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FSUB, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatMult(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FMUL, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatDiv(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FDIV, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatSqrt(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FSQRT, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatNeg(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FNEG, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatAbs(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FABS, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatToInt(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FLOAT_TO_INT, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::IntToFloat(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_INT_TO_FLOAT, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatConvert(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FLOAT_CONV, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::RoundToInt(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_ROUND_TO_INT, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::Floor(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FLOOR, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::Ceil(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_CEIL, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatTrunc(size_t size, ExprId a, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FTRUNC, loc, size, a);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_E, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareNotEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_NE, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareLessThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_LT, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_LE, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_GE, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_GT, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_O, loc, size, a, b);
+}
+
+
+ExprId HighLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(HLIL_FCMP_UO, loc, size, a, b);
+}
diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h
new file mode 100644
index 00000000..2ec67fd3
--- /dev/null
+++ b/highlevelilinstruction.h
@@ -0,0 +1,713 @@
+// Copyright (c) 2019 Vector 35 Inc
+//
+// 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 <functional>
+#include <unordered_map>
+#include <vector>
+#ifdef BINARYNINJACORE_LIBRARY
+#include "variable.h"
+#else
+#include "binaryninjaapi.h"
+#endif
+#include "mediumlevelilinstruction.h"
+
+#ifdef BINARYNINJACORE_LIBRARY
+namespace BinaryNinjaCore
+#else
+namespace BinaryNinja
+#endif
+{
+ class HighLevelILFunction;
+
+ template <BNHighLevelILOperation N>
+ struct HighLevelILInstructionAccessor {};
+
+ struct HighLevelILInstruction;
+ struct HighLevelILConstantInstruction;
+ struct HighLevelILOneOperandInstruction;
+ struct HighLevelILTwoOperandInstruction;
+ struct HighLevelILTwoOperandWithCarryInstruction;
+ struct HighLevelILDoublePrecisionInstruction;
+ struct MediumLevelILInstruction;
+ class HighLevelILOperand;
+ class HighLevelILOperandList;
+
+ enum HighLevelILOperandType
+ {
+ IntegerHighLevelOperand,
+ IndexHighLevelOperand,
+ IntrinsicHighLevelOperand,
+ ExprHighLevelOperand,
+ VariableHighLevelOperand,
+ SSAVariableHighLevelOperand,
+ ExprListHighLevelOperand,
+ SSAVariableListHighLevelOperand
+ };
+
+ enum HighLevelILOperandUsage
+ {
+ SourceExprHighLevelOperandUsage,
+ VariableHighLevelOperandUsage,
+ SSAVariableHighLevelOperandUsage,
+ DestSSAVariableHighLevelOperandUsage,
+ DestExprHighLevelOperandUsage,
+ LeftExprHighLevelOperandUsage,
+ RightExprHighLevelOperandUsage,
+ CarryExprHighLevelOperandUsage,
+ IndexExprHighLevelOperandUsage,
+ ConditionExprHighLevelOperandUsage,
+ TrueExprHighLevelOperandUsage,
+ FalseExprHighLevelOperandUsage,
+ LoopExprHighLevelOperandUsage,
+ InitExprHighLevelOperandUsage,
+ UpdateExprHighLevelOperandUsage,
+ DefaultExprHighLevelOperandUsage,
+ HighExprHighLevelOperandUsage,
+ LowExprHighLevelOperandUsage,
+ OffsetHighLevelOperandUsage,
+ ConstantHighLevelOperandUsage,
+ VectorHighLevelOperandUsage,
+ IntrinsicHighLevelOperandUsage,
+ TargetHighLevelOperandUsage,
+ ParameterExprsHighLevelOperandUsage,
+ SourceExprsHighLevelOperandUsage,
+ DestExprsHighLevelOperandUsage,
+ BlockExprsHighLevelOperandUsage,
+ CasesHighLevelOperandUsage,
+ SourceSSAVariablesHighLevelOperandUsage
+ };
+}
+
+namespace std
+{
+ template<> struct hash<BNHighLevelILOperation>
+ {
+ typedef BNHighLevelILOperation argument_type;
+ typedef int result_type;
+ result_type operator()(argument_type const& value) const
+ {
+ return (result_type)value;
+ }
+ };
+
+#ifdef BINARYNINJACORE_LIBRARY
+ template<> struct hash<BinaryNinjaCore::HighLevelILOperandUsage>
+#else
+ template<> struct hash<BinaryNinja::HighLevelILOperandUsage>
+#endif
+ {
+#ifdef BINARYNINJACORE_LIBRARY
+ typedef BinaryNinjaCore::HighLevelILOperandUsage argument_type;
+#else
+ typedef BinaryNinja::HighLevelILOperandUsage 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 HighLevelILInstructionAccessException: public std::exception
+ {
+ public:
+ HighLevelILInstructionAccessException(): std::exception() {}
+ virtual const char* what() const NOEXCEPT { return "invalid access to HLIL instruction"; }
+ };
+
+ class HighLevelILIntegerList
+ {
+ struct ListIterator
+ {
+#ifdef BINARYNINJACORE_LIBRARY
+ HighLevelILFunction* function;
+#else
+ Ref<HighLevelILFunction> function;
+#endif
+ BNHighLevelILInstruction instr;
+ 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*();
+ HighLevelILFunction* GetFunction() const { return function; }
+ };
+
+ ListIterator m_start;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ HighLevelILIntegerList(HighLevelILFunction* func, const BNHighLevelILInstruction& 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<uint64_t>() const;
+ };
+
+ class HighLevelILInstructionList
+ {
+ struct ListIterator
+ {
+ size_t instructionIndex;
+ HighLevelILIntegerList::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 HighLevelILInstruction operator*();
+ };
+
+ HighLevelILIntegerList m_list;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ HighLevelILInstructionList(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t count);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const HighLevelILInstruction operator[](size_t i) const;
+
+ operator std::vector<HighLevelILInstruction>() const;
+ };
+
+ class HighLevelILSSAVariableList
+ {
+ struct ListIterator
+ {
+ HighLevelILIntegerList::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*();
+ };
+
+ HighLevelILIntegerList m_list;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ HighLevelILSSAVariableList(HighLevelILFunction* func, const BNHighLevelILInstruction& 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<SSAVariable>() const;
+ };
+
+ struct HighLevelILInstructionBase: public BNHighLevelILInstruction
+ {
+#ifdef BINARYNINJACORE_LIBRARY
+ HighLevelILFunction* function;
+#else
+ Ref<HighLevelILFunction> function;
+#endif
+ size_t exprIndex;
+
+ static std::unordered_map<HighLevelILOperandUsage, HighLevelILOperandType> operandTypeForUsage;
+ static std::unordered_map<BNHighLevelILOperation,
+ std::vector<HighLevelILOperandUsage>> operationOperandUsage;
+ static std::unordered_map<BNHighLevelILOperation,
+ std::unordered_map<HighLevelILOperandUsage, size_t>> operationOperandIndex;
+
+ HighLevelILOperandList GetOperands() const;
+
+ uint64_t GetRawOperandAsInteger(size_t operand) const;
+ size_t GetRawOperandAsIndex(size_t operand) const;
+ HighLevelILInstruction GetRawOperandAsExpr(size_t operand) const;
+ Variable GetRawOperandAsVariable(size_t operand) const;
+ SSAVariable GetRawOperandAsSSAVariable(size_t operand) const;
+ HighLevelILInstructionList GetRawOperandAsExprList(size_t operand) const;
+ HighLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const;
+
+ void UpdateRawOperand(size_t operandIndex, ExprId value);
+ void UpdateRawOperandAsSSAVariableList(size_t operandIndex, const std::vector<SSAVariable>& vars);
+ void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<HighLevelILInstruction>& exprs);
+ void UpdateRawOperandAsExprList(size_t operandIndex, const std::vector<size_t>& exprs);
+
+ size_t GetMediumLevelILExprIndex() const;
+ bool HasMediumLevelIL() const;
+ MediumLevelILInstruction GetMediumLevelIL() const;
+ MediumLevelILInstruction GetMediumLevelILSSAForm() const;
+
+ void Replace(ExprId expr);
+
+ size_t GetInstructionIndex() const;
+ HighLevelILInstruction GetInstruction() const;
+
+ template <BNHighLevelILOperation N>
+ HighLevelILInstructionAccessor<N>& As()
+ {
+ if (operation != N)
+ throw HighLevelILInstructionAccessException();
+ return *(HighLevelILInstructionAccessor<N>*)this;
+ }
+ HighLevelILOneOperandInstruction& AsOneOperand()
+ {
+ return *(HighLevelILOneOperandInstruction*)this;
+ }
+ HighLevelILTwoOperandInstruction& AsTwoOperand()
+ {
+ return *(HighLevelILTwoOperandInstruction*)this;
+ }
+ HighLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry()
+ {
+ return *(HighLevelILTwoOperandWithCarryInstruction*)this;
+ }
+
+ template <BNHighLevelILOperation N>
+ const HighLevelILInstructionAccessor<N>& As() const
+ {
+ if (operation != N)
+ throw HighLevelILInstructionAccessException();
+ return *(const HighLevelILInstructionAccessor<N>*)this;
+ }
+ const HighLevelILConstantInstruction& AsConstant() const
+ {
+ return *(const HighLevelILConstantInstruction*)this;
+ }
+ const HighLevelILOneOperandInstruction& AsOneOperand() const
+ {
+ return *(const HighLevelILOneOperandInstruction*)this;
+ }
+ const HighLevelILTwoOperandInstruction& AsTwoOperand() const
+ {
+ return *(const HighLevelILTwoOperandInstruction*)this;
+ }
+ const HighLevelILTwoOperandWithCarryInstruction& AsTwoOperandWithCarry() const
+ {
+ return *(const HighLevelILTwoOperandWithCarryInstruction*)this;
+ }
+ };
+
+ struct HighLevelILInstruction: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction();
+ HighLevelILInstruction(HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t expr);
+ HighLevelILInstruction(const HighLevelILInstructionBase& instr);
+
+ void VisitExprs(const std::function<bool(const HighLevelILInstruction& expr)>& func) const;
+
+ ExprId CopyTo(HighLevelILFunction* dest) const;
+ ExprId CopyTo(HighLevelILFunction* dest,
+ const std::function<ExprId(const HighLevelILInstruction& subExpr)>& subExprHandler) const;
+
+ // Templated accessors for instruction operands, use these for efficient access to a known instruction
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); }
+ template <BNHighLevelILOperation N> Variable GetVariable() const { return As<N>().GetVariable(); }
+ template <BNHighLevelILOperation N> SSAVariable GetSSAVariable() const { return As<N>().GetSSAVariable(); }
+ template <BNHighLevelILOperation N> SSAVariable GetDestSSAVariable() const { return As<N>().GetDestSSAVariable(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetIndexExpr() const { return As<N>().GetIndexExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetConditionExpr() const { return As<N>().GetConditionExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetTrueExpr() const { return As<N>().GetTrueExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetFalseExpr() const { return As<N>().GetFalseExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetLoopExpr() const { return As<N>().GetLoopExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetInitExpr() const { return As<N>().GetInitExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetUpdateExpr() const { return As<N>().GetUpdateExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetDefaultExpr() const { return As<N>().GetDefaultExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetHighExpr() const { return As<N>().GetHighExpr(); }
+ template <BNHighLevelILOperation N> HighLevelILInstruction GetLowExpr() const { return As<N>().GetLowExpr(); }
+ template <BNHighLevelILOperation N> uint64_t GetOffset() const { return As<N>().GetOffset(); }
+ template <BNHighLevelILOperation N> int64_t GetConstant() const { return As<N>().GetConstant(); }
+ template <BNHighLevelILOperation N> int64_t GetVector() const { return As<N>().GetVector(); }
+ template <BNHighLevelILOperation N> uint32_t GetIntrinsic() const { return As<N>().GetIntrinsic(); }
+ template <BNHighLevelILOperation N> size_t GetTarget() const { return As<N>().GetTarget(); }
+ template <BNHighLevelILOperation N> HighLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); }
+ template <BNHighLevelILOperation N> HighLevelILInstructionList GetSourceExprs() const { return As<N>().GetSourceExprs(); }
+ template <BNHighLevelILOperation N> HighLevelILInstructionList GetDestExprs() const { return As<N>().GetDestExprs(); }
+ template <BNHighLevelILOperation N> HighLevelILInstructionList GetBlockExprs() const { return As<N>().GetBlockExprs(); }
+ template <BNHighLevelILOperation N> HighLevelILInstructionList GetCases() const { return As<N>().GetCases(); }
+ template <BNHighLevelILOperation N> HighLevelILSSAVariableList GetSourceSSAVariables() const { return As<N>().GetSourceSSAVariables(); }
+
+ template <BNHighLevelILOperation N> void SetSSAVersion(size_t version) { As<N>().SetSSAVersion(version); }
+ template <BNHighLevelILOperation N> void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); }
+ template <BNHighLevelILOperation N> void SetParameterExprs(const std::vector<ExprId>& params) { As<N>().SetParameterExprs(params); }
+ template <BNHighLevelILOperation N> void SetSourceExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetSourceExprs(params); }
+ template <BNHighLevelILOperation N> void SetSourceExprs(const std::vector<ExprId>& params) { As<N>().SetSourceExprs(params); }
+ template <BNHighLevelILOperation N> void SetDestExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetDestExprs(params); }
+ template <BNHighLevelILOperation N> void SetDestExprs(const std::vector<ExprId>& params) { As<N>().SetDestExprs(params); }
+ template <BNHighLevelILOperation N> void SetBlockExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetBlockExprs(params); }
+ template <BNHighLevelILOperation N> void SetBlockExprs(const std::vector<ExprId>& params) { As<N>().SetBlockExprs(params); }
+ template <BNHighLevelILOperation N> void SetCases(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetCases(params); }
+ template <BNHighLevelILOperation N> void SetCases(const std::vector<ExprId>& params) { As<N>().SetCases(params); }
+ template <BNHighLevelILOperation N> void SetSourceSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetSourceSSAVariables(vars); }
+
+ bool GetOperandIndexForUsage(HighLevelILOperandUsage usage, size_t& operandIndex) const;
+
+ // Generic accessors for instruction operands, these will throw a HighLevelILInstructionAccessException
+ // on type mismatch. These are slower than the templated versions above.
+ HighLevelILInstruction GetSourceExpr() const;
+ Variable GetVariable() const;
+ SSAVariable GetSSAVariable() const;
+ SSAVariable GetDestSSAVariable() const;
+ HighLevelILInstruction GetDestExpr() const;
+ HighLevelILInstruction GetLeftExpr() const;
+ HighLevelILInstruction GetRightExpr() const;
+ HighLevelILInstruction GetCarryExpr() const;
+ HighLevelILInstruction GetIndexExpr() const;
+ HighLevelILInstruction GetConditionExpr() const;
+ HighLevelILInstruction GetTrueExpr() const;
+ HighLevelILInstruction GetFalseExpr() const;
+ HighLevelILInstruction GetLoopExpr() const;
+ HighLevelILInstruction GetInitExpr() const;
+ HighLevelILInstruction GetUpdateExpr() const;
+ HighLevelILInstruction GetDefaultExpr() const;
+ HighLevelILInstruction GetHighExpr() const;
+ HighLevelILInstruction GetLowExpr() const;
+ uint64_t GetOffset() const;
+ int64_t GetConstant() const;
+ int64_t GetVector() const;
+ uint32_t GetIntrinsic() const;
+ size_t GetTarget() const;
+ HighLevelILInstructionList GetParameterExprs() const;
+ HighLevelILInstructionList GetSourceExprs() const;
+ HighLevelILInstructionList GetDestExprs() const;
+ HighLevelILInstructionList GetBlockExprs() const;
+ HighLevelILInstructionList GetCases() const;
+ HighLevelILSSAVariableList GetSourceSSAVariables() const;
+ };
+
+ class HighLevelILOperand
+ {
+ HighLevelILInstruction m_instr;
+ HighLevelILOperandUsage m_usage;
+ HighLevelILOperandType m_type;
+ size_t m_operandIndex;
+
+ public:
+ HighLevelILOperand(const HighLevelILInstruction& instr, HighLevelILOperandUsage usage,
+ size_t operandIndex);
+
+ HighLevelILOperandType GetType() const { return m_type; }
+ HighLevelILOperandUsage GetUsage() const { return m_usage; }
+
+ uint64_t GetInteger() const;
+ size_t GetIndex() const;
+ uint32_t GetIntrinsic() const;
+ HighLevelILInstruction GetExpr() const;
+ Variable GetVariable() const;
+ SSAVariable GetSSAVariable() const;
+ HighLevelILInstructionList GetExprList() const;
+ HighLevelILSSAVariableList GetSSAVariableList() const;
+ };
+
+ class HighLevelILOperandList
+ {
+ struct ListIterator
+ {
+ const HighLevelILOperandList* owner;
+ std::vector<HighLevelILOperandUsage>::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 HighLevelILOperand operator*();
+ };
+
+ HighLevelILInstruction m_instr;
+ const std::vector<HighLevelILOperandUsage>& m_usageList;
+ const std::unordered_map<HighLevelILOperandUsage, size_t>& m_operandIndexMap;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ HighLevelILOperandList(const HighLevelILInstruction& instr,
+ const std::vector<HighLevelILOperandUsage>& usageList,
+ const std::unordered_map<HighLevelILOperandUsage, size_t>& operandIndexMap);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const HighLevelILOperand operator[](size_t i) const;
+
+ operator std::vector<HighLevelILOperand>() const;
+ };
+
+ struct HighLevelILConstantInstruction: public HighLevelILInstructionBase
+ {
+ int64_t GetConstant() const { return GetRawOperandAsInteger(0); }
+ };
+
+ struct HighLevelILOneOperandInstruction: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); }
+ };
+
+ struct HighLevelILTwoOperandInstruction: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); }
+ };
+
+ struct HighLevelILTwoOperandWithCarryInstruction: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetLeftExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetRightExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetCarryExpr() const { return GetRawOperandAsExpr(2); }
+ };
+
+ // Implementations of each instruction to fetch the correct operand value for the valid operands, these
+ // are derived from HighLevelILInstructionBase so that invalid operand accessor functions will generate
+ // a compiler error.
+ template <> struct HighLevelILInstructionAccessor<HLIL_BLOCK>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstructionList GetBlockExprs() const { return GetRawOperandAsExprList(0); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_IF>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetFalseExpr() const { return GetRawOperandAsExpr(2); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_WHILE>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_DO_WHILE>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_FOR>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetInitExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstruction GetUpdateExpr() const { return GetRawOperandAsExpr(2); }
+ HighLevelILInstruction GetLoopExpr() const { return GetRawOperandAsExpr(3); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_SWITCH>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetDefaultExpr() const { return GetRawOperandAsExpr(1); }
+ HighLevelILInstructionList GetCases() const { return GetRawOperandAsExprList(2); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_CASE>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetConditionExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetTrueExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_GOTO>: public HighLevelILInstructionBase
+ {
+ size_t GetTarget() const { return GetRawOperandAsIndex(0); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_LABEL>: public HighLevelILInstructionBase
+ {
+ size_t GetTarget() const { return GetRawOperandAsIndex(0); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_RET>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); }
+ void SetSourceExprs(const std::vector<ExprId>& exprs) { UpdateRawOperandAsExprList(0, exprs); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_ASSIGN>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_STRUCT_FIELD>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); }
+ uint64_t GetOffset() const { return GetRawOperandAsInteger(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_DEREF_FIELD>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); }
+ uint64_t GetOffset() const { return GetRawOperandAsInteger(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_ARRAY_INDEX>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetIndexExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_SPLIT>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_VAR>: public HighLevelILInstructionBase
+ {
+ Variable GetVariable() const { return GetRawOperandAsVariable(0); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_VAR_SSA>: public HighLevelILInstructionBase
+ {
+ SSAVariable GetSSAVariable() const { return GetRawOperandAsSSAVariable(0); }
+ void SetSSAVersion(size_t version) { UpdateRawOperand(1, version); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_VAR_PHI>: public HighLevelILInstructionBase
+ {
+ SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); }
+ HighLevelILSSAVariableList GetSourceSSAVariables() const { return GetRawOperandAsSSAVariableList(2); }
+ void SetSourceSSAVariables(const std::vector<SSAVariable>& vars) { UpdateRawOperandAsSSAVariableList(2, vars); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_JUMP>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_CALL>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_SYSCALL>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(0); }
+ };
+ template <> struct HighLevelILInstructionAccessor<HLIL_TAILCALL>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
+ HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(1); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_ASSIGN_UNPACK>: public HighLevelILInstructionBase
+ {
+ HighLevelILInstructionList GetDestExprs() const { return GetRawOperandAsExprList(0); }
+ HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_INTRINSIC>: public HighLevelILInstructionBase
+ {
+ uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); }
+ HighLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_TRAP>: public HighLevelILInstructionBase
+ {
+ int64_t GetVector() const { return GetRawOperandAsInteger(0); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_EXTERN_PTR>: public HighLevelILConstantInstruction
+ {
+ int64_t GetConstant() const { return GetRawOperandAsInteger(0); }
+ int64_t GetOffset() const { return GetRawOperandAsInteger(1); }
+ };
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_NOP>: public HighLevelILInstructionBase {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_BREAK>: public HighLevelILInstructionBase {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_NORET>: public HighLevelILInstructionBase {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_BP>: public HighLevelILInstructionBase {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_UNDEF>: public HighLevelILInstructionBase {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_UNIMPL>: public HighLevelILInstructionBase {};
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_CONST>: public HighLevelILConstantInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CONST_PTR>: public HighLevelILConstantInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_CONST>: public HighLevelILConstantInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_IMPORT>: public HighLevelILConstantInstruction {};
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_ADD>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_SUB>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_AND>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_OR>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_XOR>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_LSL>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_LSR>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ASR>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ROL>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ROR>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MUL>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MULU_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MULS_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_DIVU>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_DIVS>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MODU>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MODS>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_DIVU_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_DIVS_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MODU_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_MODS_DP>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_E>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_NE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SLT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_ULT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SLE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_ULE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SGE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_UGE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_SGT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CMP_UGT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_TEST_BIT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ADD_OVERFLOW>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FADD>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FSUB>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FMUL>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FDIV>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_E>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_NE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_LT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_LE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_GE>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_GT>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_O>: public HighLevelILTwoOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FCMP_UO>: public HighLevelILTwoOperandInstruction {};
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_ADC>: public HighLevelILTwoOperandWithCarryInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_SBB>: public HighLevelILTwoOperandWithCarryInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_RLC>: public HighLevelILTwoOperandWithCarryInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_RRC>: public HighLevelILTwoOperandWithCarryInstruction {};
+
+ template <> struct HighLevelILInstructionAccessor<HLIL_DEREF>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ADDRESS_OF>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_NEG>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_NOT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_SX>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ZX>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_LOW_PART>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_BOOL_TO_INT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_UNIMPL_MEM>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FSQRT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FNEG>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FABS>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_TO_INT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_INT_TO_FLOAT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FLOAT_CONV>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_ROUND_TO_INT>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FLOOR>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_CEIL>: public HighLevelILOneOperandInstruction {};
+ template <> struct HighLevelILInstructionAccessor<HLIL_FTRUNC>: public HighLevelILOneOperandInstruction {};
+}
diff --git a/linearviewobject.cpp b/linearviewobject.cpp
index 19c7e4b3..b12038d7 100644
--- a/linearviewobject.cpp
+++ b/linearviewobject.cpp
@@ -253,3 +253,10 @@ Ref<LinearViewObject> LinearViewObject::CreateMappedMediumLevelILSSAForm(BinaryV
return new LinearViewObject(BNCreateLinearViewMappedMediumLevelILSSAForm(view->GetObject(),
settings ? settings->GetObject() : nullptr));
}
+
+
+Ref<LinearViewObject> LinearViewObject::CreateHighLevelIL(BinaryView* view, DisassemblySettings* settings)
+{
+ return new LinearViewObject(BNCreateLinearViewHighLevelIL(view->GetObject(),
+ settings ? settings->GetObject() : nullptr));
+}
diff --git a/python/__init__.py b/python/__init__.py
index 95cb1f82..f0c4446f 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -45,6 +45,7 @@ from binaryninja.function import *
from binaryninja.log import *
from binaryninja.lowlevelil import *
from binaryninja.mediumlevelil import *
+from binaryninja.highlevelil import *
from binaryninja.types import *
from binaryninja.typelibrary import *
from binaryninja.functionrecognizer import *
diff --git a/python/flowgraph.py b/python/flowgraph.py
index 32303c93..6c3f41f7 100644
--- a/python/flowgraph.py
+++ b/python/flowgraph.py
@@ -30,6 +30,7 @@ from binaryninja import function
from binaryninja import binaryview
from binaryninja import lowlevelil
from binaryninja import mediumlevelil
+from binaryninja import highlevelil
from binaryninja import basicblock
from binaryninja import log
from binaryninja import highlight
@@ -532,6 +533,10 @@ class FlowGraph(object):
return core.BNIsMediumLevelILFlowGraph(self.handle)
@property
+ def is_high_level_il(self):
+ return core.BNIsHighLevelILFlowGraph(self.handle)
+
+ @property
def il_function(self):
if self.is_low_level_il:
il_func = core.BNGetFlowGraphLowLevelILFunction(self.handle)
@@ -549,6 +554,14 @@ class FlowGraph(object):
if function is None:
return None
return mediumlevelil.MediumLevelILFunction(function.arch, il_func, function)
+ if self.is_high_level_il:
+ il_func = core.BNGetFlowGraphHighLevelILFunction(self.handle)
+ if not il_func:
+ return None
+ function = self.function
+ if function is None:
+ return None
+ return highlevelil.HighLevelILFunction(function.arch, il_func, function)
return None
@il_function.setter
@@ -556,12 +569,19 @@ class FlowGraph(object):
if isinstance(func, lowlevelil.LowLevelILFunction):
core.BNSetFlowGraphLowLevelILFunction(self.handle, func.handle)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
elif isinstance(func, mediumlevelil.MediumLevelILFunction):
core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, func.handle)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
+ elif isinstance(func, highlevelil.HighLevelILFunction):
+ core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, func.handle)
elif func is None:
core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
else:
raise TypeError("expected IL function for setting il_function property")
diff --git a/python/function.py b/python/function.py
index 7cee467c..dfb83e34 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1217,7 +1217,10 @@ class Function(object):
@property
def llil_if_available(self):
"""returns LowLevelILFunction used to represent Function low level IL, or None if not loaded (read-only)"""
- return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionLowLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self)
@property
def lifted_il(self):
@@ -1227,7 +1230,10 @@ class Function(object):
@property
def lifted_il_if_available(self):
"""returns LowLevelILFunction used to represent lifted IL, or None if not loaded (read-only)"""
- return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionLiftedILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self)
@property
def medium_level_il(self):
@@ -1242,7 +1248,28 @@ class Function(object):
@property
def mlil_if_available(self):
"""Function medium level IL, or None if not loaded (read-only)"""
- return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionMediumLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, result, self)
+
+ @property
+ def high_level_il(self):
+ """Deprecated property provided for compatibility. Use hlil instead."""
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self)
+
+ @property
+ def hlil(self):
+ """Function high level IL (read-only)"""
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self)
+
+ @property
+ def hlil_if_available(self):
+ """Function high level IL, or None if not loaded (read-only)"""
+ result = core.BNGetFunctionHighLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, result, self)
@property
def function_type(self):
@@ -3004,6 +3031,8 @@ class DisassemblyTextRenderer(object):
self.handle = core.BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_obj)
elif isinstance(func, binaryninja.mediumlevelil.MediumLevelILFunction):
self.handle = core.BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_obj)
+ elif isinstance(func, binaryninja.highlevelil.HighLevelILFunction):
+ self.handle = core.BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_obj)
else:
raise TypeError("invalid function object")
else:
@@ -3024,6 +3053,9 @@ class DisassemblyTextRenderer(object):
mlil = core.BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle)
if mlil:
return binaryninja.mediumlevelil.MediumLevelILFunction(handle = mlil)
+ hlil = core.BNGetDisassemblyTextRendererHighLevelILFunction(self.handle)
+ if hlil:
+ return binaryninja.highlevelil.HighLevelILFunction(handle = hlil)
return None
@property
diff --git a/python/highlevelil.py b/python/highlevelil.py
new file mode 100644
index 00000000..d657ddc4
--- /dev/null
+++ b/python/highlevelil.py
@@ -0,0 +1,729 @@
+# Copyright (c) 2019 Vector 35 Inc
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import ctypes
+import struct
+
+# Binary Ninja components
+import binaryninja
+from binaryninja import _binaryninjacore as core
+from binaryninja.enums import HighLevelILOperation, InstructionTextTokenType
+from binaryninja import function
+from binaryninja import lowlevelil
+from binaryninja import mediumlevelil
+from binaryninja import basicblock
+
+# 2-3 compatibility
+from binaryninja import range
+
+
+class HighLevelILOperationAndSize(object):
+ def __init__(self, operation, size):
+ self._operation = operation
+ self._size = size
+
+ def __repr__(self):
+ if self._size == 0:
+ return "<%s>" % self._operation.name
+ return "<%s %d>" % (self._operation.name, self._size)
+
+ def __eq__(self, other):
+ if isinstance(other, HighLevelILOperation):
+ return other == self._operation
+ if isinstance(other, HighLevelILOperationAndSize):
+ return other.size == self._size and other.operation == self._operation
+ else:
+ return False
+
+ @property
+ def operation(self):
+ """ """
+ return self._operation
+
+ @operation.setter
+ def operation(self, value):
+ self._operation = value
+
+ @property
+ def size(self):
+ """ """
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+
+class HighLevelILInstruction(object):
+ """
+ ``class HighLevelILInstruction`` High Level Intermediate Language Instructions form an abstract syntax tree of
+ the code. Control flow structures are present as high level constructs in the HLIL tree.
+ """
+
+ ILOperations = {
+ HighLevelILOperation.HLIL_NOP: [],
+ HighLevelILOperation.HLIL_BLOCK: [("body", "expr_list")],
+ HighLevelILOperation.HLIL_IF: [("condition", "expr"), ("true", "expr"), ("false", "expr")],
+ HighLevelILOperation.HLIL_WHILE: [("condition", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_DO_WHILE: [("body", "expr"), ("condition", "expr")],
+ HighLevelILOperation.HLIL_FOR: [("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_SWITCH: [("condition", "expr"), ("default", "expr"), ("cases", "expr_list")],
+ HighLevelILOperation.HLIL_CASE: [("condition", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_BREAK: [],
+ HighLevelILOperation.HLIL_JUMP: [("dest", "expr")],
+ HighLevelILOperation.HLIL_RET: [("src", "expr_list")],
+ HighLevelILOperation.HLIL_NORET: [],
+ HighLevelILOperation.HLIL_GOTO: [("target", "int")],
+ HighLevelILOperation.HLIL_LABEL: [("target", "int")],
+ HighLevelILOperation.HLIL_ASSIGN: [("dest", "expr"), ("src", "expr")],
+ HighLevelILOperation.HLIL_ASSIGN_UNPACK: [("dest", "expr_list"), ("src", "expr")],
+ HighLevelILOperation.HLIL_VAR: [("var", "var")],
+ HighLevelILOperation.HLIL_VAR_SSA: [("var", "var_ssa")],
+ HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")],
+ HighLevelILOperation.HLIL_STRUCT_FIELD: [("src", "expr"), ("offset", "int")],
+ HighLevelILOperation.HLIL_ARRAY_INDEX: [("src", "expr"), ("index", "expr")],
+ HighLevelILOperation.HLIL_SPLIT: [("high", "expr"), ("low", "expr")],
+ HighLevelILOperation.HLIL_DEREF: [("src", "expr")],
+ HighLevelILOperation.HLIL_DEREF_FIELD: [("src", "expr"), ("offset", "int")],
+ HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")],
+ HighLevelILOperation.HLIL_CONST: [("constant", "int")],
+ HighLevelILOperation.HLIL_CONST_PTR: [("constant", "int")],
+ HighLevelILOperation.HLIL_EXTERN_PTR: [("constant", "int"), ("offset", "int")],
+ HighLevelILOperation.HLIL_FLOAT_CONST: [("constant", "float")],
+ HighLevelILOperation.HLIL_IMPORT: [("constant", "int")],
+ HighLevelILOperation.HLIL_ADD: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_SUB: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_AND: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_OR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_XOR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_LSL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_LSR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ASR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ROL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_ROR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_MUL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVU: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVS: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODU: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODS: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_NEG: [("src", "expr")],
+ HighLevelILOperation.HLIL_NOT: [("src", "expr")],
+ HighLevelILOperation.HLIL_SX: [("src", "expr")],
+ HighLevelILOperation.HLIL_ZX: [("src", "expr")],
+ HighLevelILOperation.HLIL_LOW_PART: [("src", "expr")],
+ HighLevelILOperation.HLIL_CALL: [("dest", "expr"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_CMP_E: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_NE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SLT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_ULT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SLE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_ULE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SGE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_UGE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SGT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_UGT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_TEST_BIT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_BOOL_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_SYSCALL: [("params", "expr_list")],
+ HighLevelILOperation.HLIL_TAILCALL: [("dest", "expr"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_BP: [],
+ HighLevelILOperation.HLIL_TRAP: [("vector", "int")],
+ HighLevelILOperation.HLIL_INTRINSIC: [("intrinsic", "intrinsic"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_UNDEF: [],
+ HighLevelILOperation.HLIL_UNIMPL: [],
+ HighLevelILOperation.HLIL_UNIMPL_MEM: [("src", "expr")],
+ HighLevelILOperation.HLIL_FADD: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FSUB: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FMUL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FDIV: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FSQRT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FNEG: [("src", "expr")],
+ HighLevelILOperation.HLIL_FABS: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOAT_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_INT_TO_FLOAT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOAT_CONV: [("src", "expr")],
+ HighLevelILOperation.HLIL_ROUND_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOOR: [("src", "expr")],
+ HighLevelILOperation.HLIL_CEIL: [("src", "expr")],
+ HighLevelILOperation.HLIL_FTRUNC: [("src", "expr")],
+ HighLevelILOperation.HLIL_FCMP_E: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_NE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_LT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_LE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_GE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_GT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_O: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")]
+ }
+
+ def __init__(self, func, expr_index, as_ast = True):
+ instr = core.BNGetHighLevelILByIndex(func.handle, expr_index)
+ self._function = func
+ self._expr_index = expr_index
+ self._operation = HighLevelILOperation(instr.operation)
+ self._size = instr.size
+ self._address = instr.address
+ self._source_operand = instr.sourceOperand
+ self._parent = instr.parent
+ self._as_ast = as_ast
+ operands = HighLevelILInstruction.ILOperations[instr.operation]
+ self._operands = []
+ i = 0
+ for operand in operands:
+ name, operand_type = operand
+ if operand_type == "int":
+ value = instr.operands[i]
+ value = (value & ((1 << 63) - 1)) - (value & (1 << 63))
+ elif operand_type == "float":
+ if instr.size == 4:
+ value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0]
+ elif instr.size == 8:
+ value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0]
+ else:
+ value = instr.operands[i]
+ elif operand_type == "expr":
+ value = HighLevelILInstruction(func, instr.operands[i], self._as_ast)
+ elif operand_type == "intrinsic":
+ value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i])
+ elif operand_type == "var":
+ value = function.Variable.from_identifier(self._function.source_function, instr.operands[i])
+ elif operand_type == "var_ssa":
+ var = function.Variable.from_identifier(self._function.source_function, instr.operands[i])
+ version = instr.operands[i + 1]
+ i += 1
+ value = mediumlevelil.SSAVariable(var, version)
+ elif operand_type == "int_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ value = []
+ for j in range(count.value):
+ value.append(operand_list[j])
+ core.BNHighLevelILFreeOperandList(operand_list)
+ elif operand_type == "expr_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ i += 1
+ value = []
+ for j in range(count.value):
+ value.append(HighLevelILInstruction(func, operand_list[j], self._as_ast))
+ core.BNHighLevelILFreeOperandList(operand_list)
+ elif operand_type == "var_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ i += 1
+ value = []
+ for j in range(count.value // 2):
+ var_id = operand_list[j * 2]
+ var_version = operand_list[(j * 2) + 1]
+ value.append(mediumlevelil.SSAVariable(function.Variable.from_identifier(self._function.source_function,
+ var_id), var_version))
+ core.BNHighLevelILFreeOperandList(operand_list)
+ self._operands.append(value)
+ self.__dict__[name] = value
+ i += 1
+
+ def __str__(self):
+ lines = self.lines
+ if lines is None:
+ return "invalid"
+ result = []
+ for line in lines:
+ cur = ""
+ for token in line.tokens:
+ cur += token.text
+ result.append(cur)
+ return '\n'.join(result)
+
+ def __repr__(self):
+ lines = self.lines
+ continuation = ""
+ if lines is None:
+ first_line = "<invalid>"
+ else:
+ first_line = ""
+ for token in lines[0].tokens:
+ first_line += token.text
+ if len(lines) > 1:
+ continuation = "..."
+ return "<%s: %s%s>" % (self._operation.name, first_line, continuation)
+
+ def __eq__(self, value):
+ if not isinstance(value, type(self)):
+ return False
+ return self._function == value.function and self._expr_index == value.expr_index
+
+ @property
+ def lines(self):
+ """HLIL text lines (read-only)"""
+ count = ctypes.c_ulonglong()
+ lines = core.BNGetHighLevelILExprText(self._function.handle, self._expr_index, self._as_ast, count)
+ result = []
+ for i in range(0, count.value):
+ addr = lines[i].addr
+ if lines[i].instrIndex != 0xffffffffffffffff:
+ il_instr = self._function[lines[i].instrIndex]
+ else:
+ il_instr = None
+ color = binaryninja.highlight.HighlightColor._from_core_struct(lines[i].highlight)
+ tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count)
+ result.append(binaryninja.function.DisassemblyTextLine(tokens, addr, il_instr, color))
+ core.BNFreeDisassemblyTextLines(lines, count.value)
+ return result
+
+ @property
+ def prefix_operands(self):
+ """All operands in the expression tree in prefix order"""
+ result = [HighLevelILOperationAndSize(self._operation, self._size)]
+ for operand in self._operands:
+ if isinstance(operand, HighLevelILInstruction):
+ result += operand.prefix_operands
+ else:
+ result.append(operand)
+ return result
+
+ @property
+ def postfix_operands(self):
+ """All operands in the expression tree in postfix order"""
+ result = []
+ for operand in self._operands:
+ if isinstance(operand, HighLevelILInstruction):
+ result += operand.postfix_operands
+ else:
+ result.append(operand)
+ result.append(HighLevelILOperationAndSize(self._operation, self._size))
+ return result
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+ @property
+ def function(self):
+ """ """
+ return self._function
+
+ @function.setter
+ def function(self, value):
+ self._function = value
+
+ @property
+ def expr_index(self):
+ """ """
+ return self._expr_index
+
+ @expr_index.setter
+ def expr_index(self, value):
+ self._expr_index = value
+
+ @property
+ def instr_index(self):
+ """Index of the statement that this expression belongs to (read-only)"""
+ return core.BNGetHighLevelILInstructionForExpr(self._function.handle, self._expr_index)
+
+ @property
+ def instr(self):
+ """The statement that this expression belongs to (read-only)"""
+ return self._function[self.instr_index]
+
+ @property
+ def ast(self):
+ """This expression with full AST printing (read-only)"""
+ if self._as_ast:
+ return self
+ return HighLevelILInstruction(self._function, self._expr_index, True)
+
+ @property
+ def non_ast(self):
+ """This expression without full AST printing (read-only)"""
+ if self._as_ast:
+ return self
+ return HighLevelILInstruction(self._function, self._expr_index, False)
+
+ @property
+ def operation(self):
+ """ """
+ return self._operation
+
+ @operation.setter
+ def operation(self, value):
+ self._operation = value
+
+ @property
+ def size(self):
+ """ """
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+ @property
+ def address(self):
+ """ """
+ return self._address
+
+ @address.setter
+ def address(self, value):
+ self._address = value
+
+ @property
+ def source_operand(self):
+ """ """
+ return self._source_operand
+
+ @source_operand.setter
+ def source_operand(self, value):
+ self._source_operand = value
+
+ @property
+ def operands(self):
+ """ """
+ return self._operands
+
+ @operands.setter
+ def operands(self, value):
+ self._operands = value
+
+ @property
+ def parent(self):
+ if self._parent >= core.BNGetHighLevelILExprCount(self._function.handle):
+ return None
+ return HighLevelILInstruction(self._function, self._parent, self._as_ast)
+
+ @property
+ def medium_level_il(self):
+ """Medium level IL form of this expression"""
+ expr = self._function.get_medium_level_il_expr_index(self._expr_index)
+ if expr is None:
+ return None
+ return mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il.ssa_form, expr)
+
+ @property
+ def mlil(self):
+ """Alias for medium_level_il"""
+ return self.medium_level_il
+
+ @property
+ def il_basic_block(self):
+ """IL basic block object containing this expression (read-only) (only available on finalized functions)"""
+ return HighLevelILBasicBlock(self._function.source_function.view, core.BNGetHighLevelILBasicBlockForInstruction(self._function.handle, self._instr_index), self._function)
+
+
+class HighLevelILExpr(object):
+ """
+ ``class HighLevelILExpr`` hold the index of IL Expressions.
+
+ .. note:: This class shouldn't be instantiated directly. Rather the helper members of HighLevelILFunction should be \
+ used instead.
+ """
+ def __init__(self, index):
+ self._index = index
+
+ @property
+ def index(self):
+ """ """
+ return self._index
+
+ @index.setter
+ def index(self, value):
+ self._index = value
+
+
+class HighLevelILFunction(object):
+ """
+ ``class HighLevelILFunction`` contains the a HighLevelILInstruction object that makes up the abstract syntax tree of
+ a binaryninja.function.
+ """
+ def __init__(self, arch = None, handle = None, source_func = None):
+ self._arch = arch
+ self._source_function = source_func
+ if handle is not None:
+ self.handle = core.handle_of_type(handle, core.BNHighLevelILFunction)
+ if self._source_function is None:
+ self._source_function = binaryninja.function.Function(handle = core.BNGetHighLevelILOwnerFunction(self.handle))
+ if self._arch is None:
+ self._arch = self._source_function.arch
+ else:
+ if self._source_function is None:
+ self.handle = None
+ raise ValueError("IL functions must be created with an associated function")
+ if self._arch is None:
+ self._arch = self._source_function.arch
+ func_handle = self._source_function.handle
+ self.handle = core.BNCreateHighLevelILFunction(arch.handle, func_handle)
+
+ def __hash__(self):
+ return hash(('HLIL', self._source_function))
+
+ def __del__(self):
+ if self.handle is not None:
+ core.BNFreeHighLevelILFunction(self.handle)
+
+ def __eq__(self, value):
+ if not isinstance(value, HighLevelILFunction):
+ return False
+ return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents)
+
+ def __ne__(self, value):
+ if not isinstance(value, HighLevelILFunction):
+ return True
+ return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents)
+
+ @property
+ def current_address(self):
+ """Current IL Address (read/write)"""
+ return core.BNHighLevelILGetCurrentAddress(self.handle)
+
+ @current_address.setter
+ def current_address(self, value):
+ core.BNHighLevelILSetCurrentAddress(self.handle, self._arch.handle, value)
+
+ def set_current_address(self, value, arch = None):
+ if arch is None:
+ arch = self._arch
+ core.BNHighLevelILSetCurrentAddress(self.handle, arch.handle, value)
+
+ @property
+ def root(self):
+ """Root of the abstract syntax tree"""
+ expr_index = core.BNGetHighLevelILRootExpr(self.handle)
+ if expr_index >= core.BNGetHighLevelILExprCount(self.handle):
+ return None
+ return HighLevelILInstruction(self, expr_index)
+
+ @root.setter
+ def root(self, value):
+ core.BNSetHighLevelILRootExpr(value.expr_index)
+
+ @property
+ def basic_blocks(self):
+ """list of HighLevelILBasicBlock objects (read-only)"""
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count)
+ result = []
+ view = None
+ if self._source_function is not None:
+ view = self._source_function.view
+ for i in range(0, count.value):
+ result.append(HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self))
+ core.BNFreeBasicBlockList(blocks, count.value)
+ return result
+
+ @property
+ def instructions(self):
+ """A generator of hlil instructions of the current function"""
+ for block in self.basic_blocks:
+ for i in block:
+ yield i
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+ def __len__(self):
+ return int(core.BNGetHighLevelILInstructionCount(self.handle))
+
+ def __getitem__(self, i):
+ if isinstance(i, slice) or isinstance(i, tuple):
+ raise IndexError("expected integer instruction index")
+ if isinstance(i, HighLevelILExpr):
+ return HighLevelILInstruction(self, i.index)
+ # for backwards compatibility
+ if isinstance(i, HighLevelILInstruction):
+ return i
+ if (i < 0) or (i >= len(self)):
+ raise IndexError("index out of range")
+ return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False)
+
+ def __setitem__(self, i, j):
+ raise IndexError("instruction modification not implemented")
+
+ def __iter__(self):
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count)
+ view = None
+ if self._source_function is not None:
+ view = self._source_function.view
+ try:
+ for i in range(0, count.value):
+ yield HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)
+ finally:
+ core.BNFreeBasicBlockList(blocks, count.value)
+
+ def __str__(self):
+ return str(self.root)
+
+ def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0):
+ if isinstance(operation, str):
+ operation = HighLevelILOperation[operation]
+ elif isinstance(operation, HighLevelILOperation):
+ operation = operation.value
+ return HighLevelILExpr(core.BNHighLevelILAddExpr(self.handle, operation, size, a, b, c, d, e))
+
+ def append(self, expr):
+ """
+ ``append`` adds the HighLevelILExpr ``expr`` to the current HighLevelILFunction.
+
+ :param HighLevelILExpr expr: the HighLevelILExpr to add to the current HighLevelILFunction
+ :return: number of HighLevelILExpr in the current function
+ :rtype: int
+ """
+ return core.BNHighLevelILAddInstruction(self.handle, expr.index)
+
+ def add_operand_list(self, operands):
+ """
+ ``add_operand_list`` returns an operand list expression for the given list of integer operands.
+
+ :param list(int) operands: list of operand numbers
+ :return: an operand list expression
+ :rtype: HighLevelILExpr
+ """
+ operand_list = (ctypes.c_ulonglong * len(operands))()
+ for i in range(len(operands)):
+ operand_list[i] = operands[i]
+ return HighLevelILExpr(core.BNHighLevelILAddOperandList(self.handle, operand_list, len(operands)))
+
+ def operand(self, n, expr):
+ """
+ ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification.
+
+ :param int n:
+ :param HighLevelILExpr expr:
+ :return: returns the expression ``expr`` unmodified
+ :rtype: HighLevelILExpr
+ """
+ core.BNHighLevelILSetExprSourceOperand(self.handle, expr.index, n)
+ return expr
+
+ def finalize(self):
+ """
+ ``finalize`` ends the function and computes the list of basic blocks.
+
+ :rtype: None
+ """
+ core.BNFinalizeHighLevelILFunction(self.handle)
+
+ def create_graph(self, settings = None):
+ if settings is not None:
+ settings_obj = settings.handle
+ else:
+ settings_obj = None
+ return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateHighLevelILFunctionGraph(self.handle, settings_obj))
+
+ @property
+ def arch(self):
+ """ """
+ return self._arch
+
+ @arch.setter
+ def arch(self, value):
+ self._arch = value
+
+ @property
+ def source_function(self):
+ """ """
+ return self._source_function
+
+ @source_function.setter
+ def source_function(self, value):
+ self._source_function = value
+
+ @property
+ def medium_level_il(self):
+ """Medium level IL for this function"""
+ result = core.BNGetMediumLevelILForHighLevelILFunction(self.handle)
+ if not result:
+ return None
+ return mediumlevelil.MediumLevelILFunction(self._arch, result, self._source_function)
+
+ @property
+ def mlil(self):
+ """Alias for medium_level_il"""
+ return self.medium_level_il
+
+ def get_medium_level_il_expr_index(self, expr):
+ medium_il = self.medium_level_il
+ if medium_il is None:
+ return None
+ medium_il = medium_il.ssa_form
+ if medium_il is None:
+ return None
+ result = core.BNGetMediumLevelILExprIndexFromHighLevelIL(self.handle, expr)
+ if result >= core.BNGetMediumLevelILExprCount(medium_il.handle):
+ return None
+ return result
+
+
+class HighLevelILBasicBlock(basicblock.BasicBlock):
+ def __init__(self, view, handle, owner):
+ super(HighLevelILBasicBlock, self).__init__(handle, view)
+ self.il_function = owner
+
+ def __iter__(self):
+ for idx in range(self.start, self.end):
+ yield self.il_function[idx]
+
+ def __getitem__(self, idx):
+ size = self.end - self.start
+ if idx > size or idx < -size:
+ raise IndexError("list index is out of range")
+ if idx >= 0:
+ return self.il_function[idx + self.start]
+ else:
+ return self.il_function[self.end + idx]
+
+ def _create_instance(self, handle, view):
+ """Internal method by super to instantiate child instances"""
+ return HighLevelILBasicBlock(view, handle, self.il_function)
+
+ def __hash__(self):
+ return hash((self.start, self.end, self.il_function))
+
+ def __contains__(self, instruction):
+ if type(instruction) != HighLevelILInstruction or instruction.il_basic_block != self:
+ return False
+ if instruction.instr_index >= self.start and instruction.instr_index <= self.end:
+ return True
+ else:
+ return False
+
+ @property
+ def il_function(self):
+ """ """
+ return self._il_function
+
+ @il_function.setter
+ def il_function(self, value):
+ self._il_function = value
diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py
index ec213a19..10124bad 100644
--- a/python/lineardisassembly.py
+++ b/python/lineardisassembly.py
@@ -300,6 +300,12 @@ class LinearViewObject(object):
settings = settings.handle
return LinearViewObject(core.BNCreateLinearViewMappedMediumLevelILSSAForm(view.handle, settings))
+ @classmethod
+ def hlil(cls, view, settings = None):
+ if settings is not None:
+ settings = settings.handle
+ return LinearViewObject(core.BNCreateLinearViewHighLevelIL(view.handle, settings))
+
class LinearViewCursor(object):
def __init__(self, root_object, handle = None):
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 81167e8e..73cb2a0d 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -625,9 +625,11 @@ class PythonScriptingInstance(ScriptingInstance):
if self.active_func is None:
self.locals["current_llil"] = None
self.locals["current_mlil"] = None
+ self.locals["current_hlil"] = None
else:
self.locals["current_llil"] = self.active_func.llil
self.locals["current_mlil"] = self.active_func.mlil
+ self.locals["current_hlil"] = self.active_func.hlil
def get_selected_data(self):