summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp90
-rw-r--r--binaryninjaapi.h38
-rw-r--r--binaryninjacore.h28
-rw-r--r--callingconvention.cpp10
-rw-r--r--lowlevelil.cpp14
-rw-r--r--lowlevelilinstruction.cpp394
-rw-r--r--lowlevelilinstruction.h149
-rw-r--r--mediumlevelilinstruction.cpp33
-rw-r--r--mediumlevelilinstruction.h1
-rw-r--r--python/architecture.py101
-rw-r--r--python/callingconvention.py4
-rw-r--r--python/function.py59
-rw-r--r--python/lowlevelil.py165
-rw-r--r--python/mediumlevelil.py9
14 files changed, 1091 insertions, 4 deletions
diff --git a/architecture.cpp b/architecture.cpp
index eb588394..56af3f80 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -359,6 +359,34 @@ uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count)
}
+char* Architecture::GetRegisterStackNameCallback(void* ctxt, uint32_t regStack)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ string result = arch->GetRegisterStackName(regStack);
+ return BNAllocString(result.c_str());
+}
+
+
+uint32_t* Architecture::GetAllRegisterStacksCallback(void* ctxt, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<uint32_t> regs = arch->GetAllRegisterStacks();
+ *count = regs.size();
+
+ uint32_t* result = new uint32_t[regs.size()];
+ for (size_t i = 0; i < regs.size(); i++)
+ result[i] = regs[i];
+ return result;
+}
+
+
+void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ *result = arch->GetRegisterStackInfo(regStack);
+}
+
+
bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors)
{
Architecture* arch = (Architecture*)ctxt;
@@ -467,6 +495,9 @@ void Architecture::Register(Architecture* arch)
callbacks.getStackPointerRegister = GetStackPointerRegisterCallback;
callbacks.getLinkRegister = GetLinkRegisterCallback;
callbacks.getGlobalRegisters = GetGlobalRegistersCallback;
+ callbacks.getRegisterStackName = GetRegisterStackNameCallback;
+ callbacks.getAllRegisterStacks = GetAllRegisterStacksCallback;
+ callbacks.getRegisterStackInfo = GetRegisterStackInfoCallback;
callbacks.assemble = AssembleCallback;
callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback;
callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback;
@@ -682,6 +713,36 @@ bool Architecture::IsGlobalRegister(uint32_t reg)
}
+string Architecture::GetRegisterStackName(uint32_t regStack)
+{
+ char regStr[32];
+ sprintf(regStr, "reg_stack_%" PRIu32, regStack);
+ return regStr;
+}
+
+
+vector<uint32_t> Architecture::GetAllRegisterStacks()
+{
+ return vector<uint32_t>();
+}
+
+
+BNRegisterStackInfo Architecture::GetRegisterStackInfo(uint32_t)
+{
+ BNRegisterStackInfo result;
+ result.firstStorageReg = BN_INVALID_REGISTER;
+ result.count = 0;
+ result.stackTopReg = BN_INVALID_REGISTER;
+ return result;
+}
+
+
+uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg)
+{
+ return BNGetArchitectureRegisterStackForRegister(m_object, reg);
+}
+
+
vector<uint32_t> Architecture::GetModifiedRegistersOnWrite(uint32_t reg)
{
size_t count;
@@ -1116,6 +1177,35 @@ vector<uint32_t> CoreArchitecture::GetGlobalRegisters()
}
+string CoreArchitecture::GetRegisterStackName(uint32_t regStack)
+{
+ char* name = BNGetArchitectureRegisterStackName(m_object, regStack);
+ string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+
+vector<uint32_t> CoreArchitecture::GetAllRegisterStacks()
+{
+ size_t count;
+ uint32_t* regs = BNGetAllArchitectureRegisterStacks(m_object, &count);
+
+ vector<uint32_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(regs[i]);
+
+ BNFreeRegisterList(regs);
+ return result;
+}
+
+
+BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack)
+{
+ return BNGetArchitectureRegisterStackInfo(m_object, regStack);
+}
+
+
bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors)
{
char* errorStr = nullptr;
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 7d686142..5c122966 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1610,6 +1610,10 @@ namespace BinaryNinja
static uint32_t GetLinkRegisterCallback(void* ctxt);
static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count);
+ static char* GetRegisterStackNameCallback(void* ctxt, uint32_t regStack);
+ static uint32_t* GetAllRegisterStacksCallback(void* ctxt, size_t* count);
+ static void GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result);
+
static bool AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
static bool IsNeverBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
static bool IsAlwaysBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
@@ -1676,6 +1680,11 @@ namespace BinaryNinja
std::vector<uint32_t> GetModifiedRegistersOnWrite(uint32_t reg);
uint32_t GetRegisterByName(const std::string& name);
+ virtual std::string GetRegisterStackName(uint32_t regStack);
+ virtual std::vector<uint32_t> GetAllRegisterStacks();
+ virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack);
+ uint32_t GetRegisterStackForRegister(uint32_t reg);
+
virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors);
/*! IsNeverBranchPatchAvailable returns true if the instruction at addr can be patched to never branch.
@@ -1800,6 +1809,10 @@ namespace BinaryNinja
virtual uint32_t GetLinkRegister() override;
virtual std::vector<uint32_t> GetGlobalRegisters() override;
+ virtual std::string GetRegisterStackName(uint32_t regStack) override;
+ virtual std::vector<uint32_t> GetAllRegisterStacks() override;
+ virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override;
+
virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override;
virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
@@ -2394,6 +2407,7 @@ namespace BinaryNinja
struct LowLevelILInstruction;
struct SSARegister;
+ struct SSARegisterStack;
struct SSAFlag;
class LowLevelILFunction: public CoreRefCountObject<BNLowLevelILFunction,
@@ -2436,6 +2450,14 @@ namespace BinaryNinja
const ILSourceLocation& loc = ILSourceLocation());
ExprId SetRegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low, ExprId val,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId SetRegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, ExprId val,
+ uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackPush(size_t size, uint32_t regStack, ExprId val, uint32_t flags = 0,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId SetRegisterStackTopRelativeSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion,
+ ExprId entry, const SSARegister& top, ExprId val, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion,
+ uint32_t reg, ExprId val, const ILSourceLocation& loc = ILSourceLocation());
ExprId SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation());
ExprId SetFlagSSA(const SSAFlag& flag, ExprId val, const ILSourceLocation& loc = ILSourceLocation());
ExprId Load(size_t size, ExprId addr, uint32_t flags = 0,
@@ -2456,8 +2478,18 @@ namespace BinaryNinja
ExprId RegisterSplit(size_t size, uint32_t high, uint32_t low, const ILSourceLocation& loc = ILSourceLocation());
ExprId RegisterSplitSSA(size_t size, const SSARegister& high, const SSARegister& low,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackPop(size_t size, uint32_t regStack, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackTopRelativeSSA(size_t size, const SSARegisterStack& regStack, ExprId entry,
+ const SSARegister& top, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackAbsoluteSSA(size_t size, const SSARegisterStack& regStack, uint32_t reg,
+ 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 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 Flag(uint32_t flag, const ILSourceLocation& loc = ILSourceLocation());
ExprId FlagSSA(const SSAFlag& flag, const ILSourceLocation& loc = ILSourceLocation());
ExprId FlagBit(size_t size, uint32_t flag, uint32_t bitIndex,
@@ -2566,6 +2598,8 @@ namespace BinaryNinja
ExprId UnimplementedMemoryRef(size_t size, ExprId addr, const ILSourceLocation& loc = ILSourceLocation());
ExprId RegisterPhi(const SSARegister& dest, const std::vector<SSARegister>& sources,
const ILSourceLocation& loc = ILSourceLocation());
+ ExprId RegisterStackPhi(const SSARegisterStack& dest, const std::vector<SSARegisterStack>& sources,
+ const ILSourceLocation& loc = ILSourceLocation());
ExprId FlagPhi(const SSAFlag& dest, const std::vector<SSAFlag>& sources,
const ILSourceLocation& loc = ILSourceLocation());
ExprId MemoryPhi(size_t dest, const std::vector<size_t>& sources,
@@ -2602,6 +2636,7 @@ namespace BinaryNinja
ExprId AddOperandList(const std::vector<ExprId> operands);
ExprId AddIndexList(const std::vector<size_t> operands);
ExprId AddSSARegisterList(const std::vector<SSARegister>& regs);
+ ExprId AddSSARegisterStackList(const std::vector<SSARegisterStack>& regStacks);
ExprId AddSSAFlagList(const std::vector<SSAFlag>& flags);
ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size);
@@ -2765,6 +2800,9 @@ namespace BinaryNinja
const ILSourceLocation& loc = ILSourceLocation());
ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
+ ExprId 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,
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 9bbea512..f50c28c8 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -281,14 +281,19 @@ extern "C"
LLIL_SET_REG, // Not valid in SSA form (see LLIL_SET_REG_SSA)
LLIL_SET_REG_SPLIT, // Not valid in SSA form (see LLIL_SET_REG_SPLIT_SSA)
LLIL_SET_FLAG, // Not valid in SSA form (see LLIL_SET_FLAG_SSA)
+ LLIL_SET_REG_STACK_REL, // Not valid in SSA form (see LLIL_SET_REG_STACK_REL_SSA)
+ LLIL_REG_STACK_PUSH, // Not valid in SSA form (expanded)
LLIL_LOAD, // Not valid in SSA form (see LLIL_LOAD_SSA)
LLIL_STORE, // Not valid in SSA form (see LLIL_STORE_SSA)
LLIL_PUSH, // Not valid in SSA form (expanded)
LLIL_POP, // Not valid in SSA form (expanded)
LLIL_REG, // Not valid in SSA form (see LLIL_REG_SSA)
LLIL_REG_SPLIT, // Not valid in SSA form (see LLIL_REG_SPLIT_SSA)
+ LLIL_REG_STACK_REL, // Not valid in SSA form (see LLIL_REG_STACK_REL_SSA)
+ LLIL_REG_STACK_POP, // Not valid in SSA form (expanded)
LLIL_CONST,
LLIL_CONST_PTR,
+ LLIL_FLOAT_CONST,
LLIL_FLAG, // Not valid in SSA form (see LLIL_FLAG_SSA)
LLIL_FLAG_BIT, // Not valid in SSA form (see LLIL_FLAG_BIT_SSA)
LLIL_ADD,
@@ -373,10 +378,15 @@ extern "C"
LLIL_SET_REG_SSA,
LLIL_SET_REG_SSA_PARTIAL,
LLIL_SET_REG_SPLIT_SSA,
+ LLIL_SET_REG_STACK_REL_SSA,
+ LLIL_SET_REG_STACK_ABS_SSA,
LLIL_REG_SPLIT_DEST_SSA, // Only valid within an LLIL_SET_REG_SPLIT_SSA instruction
+ LLIL_REG_STACK_DEST_SSA, // Only valid within LLIL_SET_REG_STACK_REL_SSA or LLIL_SET_REG_STACK_ABS_SSA
LLIL_REG_SSA,
LLIL_REG_SSA_PARTIAL,
LLIL_REG_SPLIT_SSA,
+ LLIL_REG_STACK_REL_SSA,
+ LLIL_REG_STACK_ABS_SSA,
LLIL_SET_FLAG_SSA,
LLIL_FLAG_SSA,
LLIL_FLAG_BIT_SSA,
@@ -388,6 +398,7 @@ extern "C"
LLIL_LOAD_SSA,
LLIL_STORE_SSA,
LLIL_REG_PHI,
+ LLIL_REG_STACK_PHI,
LLIL_FLAG_PHI,
LLIL_MEM_PHI
};
@@ -666,6 +677,13 @@ extern "C"
BNImplicitRegisterExtend extend;
};
+ struct BNRegisterStackInfo
+ {
+ uint32_t firstStorageReg;
+ uint32_t count;
+ uint32_t stackTopReg;
+ };
+
enum BNRegisterValueType
{
UndeterminedValue,
@@ -771,6 +789,7 @@ extern "C"
MLIL_ADDRESS_OF_FIELD,
MLIL_CONST,
MLIL_CONST_PTR,
+ MLIL_FLOAT_CONST,
MLIL_IMPORT,
MLIL_ADD,
MLIL_ADC,
@@ -1071,6 +1090,10 @@ extern "C"
uint32_t (*getLinkRegister)(void* ctxt);
uint32_t* (*getGlobalRegisters)(void* ctxt, size_t* count);
+ char* (*getRegisterStackName)(void* ctxt, uint32_t regStack);
+ uint32_t* (*getAllRegisterStacks)(void* ctxt, size_t* count);
+ void (*getRegisterStackInfo)(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result);
+
bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
bool (*isNeverBranchPatchAvailable)(void* ctxt, const uint8_t* data, uint64_t addr, size_t len);
@@ -2022,6 +2045,11 @@ extern "C"
BINARYNINJACOREAPI bool BNIsArchitectureGlobalRegister(BNArchitecture* arch, uint32_t reg);
BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterByName(BNArchitecture* arch, const char* name);
+ BINARYNINJACOREAPI char* BNGetArchitectureRegisterStackName(BNArchitecture* arch, uint32_t regStack);
+ BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureRegisterStacks(BNArchitecture* arch, size_t* count);
+ BINARYNINJACOREAPI BNRegisterStackInfo BNGetArchitectureRegisterStackInfo(BNArchitecture* arch, uint32_t regStack);
+ BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterStackForRegister(BNArchitecture* arch, uint32_t reg);
+
BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
BINARYNINJACOREAPI bool BNIsArchitectureNeverBranchPatchAvailable(BNArchitecture* arch, const uint8_t* data,
diff --git a/callingconvention.cpp b/callingconvention.cpp
index 945ba25f..b29d51e2 100644
--- a/callingconvention.cpp
+++ b/callingconvention.cpp
@@ -264,8 +264,16 @@ vector<uint32_t> CallingConvention::GetImplicitlyDefinedRegisters()
}
-RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*)
+RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t reg, Function*)
{
+ uint32_t regStack = GetArchitecture()->GetRegisterStackForRegister(reg);
+ if ((regStack != BN_INVALID_REGISTER) && (reg == GetArchitecture()->GetRegisterStackInfo(regStack).stackTopReg))
+ {
+ RegisterValue value;
+ value.state = ConstantValue;
+ value.value = 0;
+ return value;
+ }
return RegisterValue();
}
diff --git a/lowlevelil.cpp b/lowlevelil.cpp
index 690f0b41..c72d4b68 100644
--- a/lowlevelil.cpp
+++ b/lowlevelil.cpp
@@ -230,6 +230,20 @@ ExprId LowLevelILFunction::AddSSARegisterList(const vector<SSARegister>& regs)
}
+ExprId LowLevelILFunction::AddSSARegisterStackList(const vector<SSARegisterStack>& regStacks)
+{
+ uint64_t* operandList = new uint64_t[regStacks.size() * 2];
+ for (size_t i = 0; i < regStacks.size(); i++)
+ {
+ operandList[i * 2] = regStacks[i].regStack;
+ operandList[(i * 2) + 1] = regStacks[i].version;
+ }
+ ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regStacks.size() * 2);
+ delete[] operandList;
+ return result;
+}
+
+
ExprId LowLevelILFunction::AddSSAFlagList(const vector<SSAFlag>& flags)
{
uint64_t* operandList = new uint64_t[flags.size() * 2];
diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp
index 501b7b72..4130dd2a 100644
--- a/lowlevelilinstruction.cpp
+++ b/lowlevelilinstruction.cpp
@@ -37,17 +37,23 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType>
LowLevelILInstructionBase::operandTypeForUsage = {
{SourceExprLowLevelOperandUsage, ExprLowLevelOperand},
{SourceRegisterLowLevelOperandUsage, RegisterLowLevelOperand},
+ {SourceRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand},
{SourceFlagLowLevelOperandUsage, FlagLowLevelOperand},
{SourceSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
+ {SourceSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand},
{SourceSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand},
{DestExprLowLevelOperandUsage, ExprLowLevelOperand},
{DestRegisterLowLevelOperandUsage, RegisterLowLevelOperand},
+ {DestRegisterStackLowLevelOperandUsage, RegisterStackLowLevelOperand},
{DestFlagLowLevelOperandUsage, FlagLowLevelOperand},
{DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
+ {DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand},
{DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand},
{PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand},
+ {PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand},
{StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
{StackMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand},
+ {TopSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand},
{LeftExprLowLevelOperandUsage, ExprLowLevelOperand},
{RightExprLowLevelOperandUsage, ExprLowLevelOperand},
{CarryExprLowLevelOperandUsage, ExprLowLevelOperand},
@@ -70,6 +76,7 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType>
{OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand},
{ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
{SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
+ {SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand},
{SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand},
{SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand},
{TargetListLowLevelOperandUsage, IndexListLowLevelOperand}
@@ -93,6 +100,15 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
SourceExprLowLevelOperandUsage}},
{LLIL_SET_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage,
LowSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
+ {LLIL_SET_REG_STACK_REL, {DestRegisterStackLowLevelOperandUsage, DestExprLowLevelOperandUsage,
+ SourceExprLowLevelOperandUsage}},
+ {LLIL_REG_STACK_PUSH, {DestRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
+ {LLIL_SET_REG_STACK_REL_SSA, {DestSSARegisterStackLowLevelOperandUsage,
+ PartialSSARegisterStackSourceLowLevelOperandUsage, DestExprLowLevelOperandUsage,
+ TopSSARegisterLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
+ {LLIL_SET_REG_STACK_ABS_SSA, {DestSSARegisterStackLowLevelOperandUsage,
+ PartialSSARegisterStackSourceLowLevelOperandUsage, DestRegisterLowLevelOperandUsage,
+ SourceExprLowLevelOperandUsage}},
{LLIL_SET_FLAG, {DestFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
{LLIL_SET_FLAG_SSA, {DestSSAFlagLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
{LLIL_LOAD, {SourceExprLowLevelOperandUsage}},
@@ -105,6 +121,11 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{LLIL_REG_SSA_PARTIAL, {SourceSSARegisterLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage}},
{LLIL_REG_SPLIT, {HighRegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage}},
{LLIL_REG_SPLIT_SSA, {HighSSARegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage}},
+ {LLIL_REG_STACK_REL, {SourceRegisterStackLowLevelOperandUsage, SourceExprLowLevelOperandUsage}},
+ {LLIL_REG_STACK_POP, {SourceRegisterStackLowLevelOperandUsage}},
+ {LLIL_REG_STACK_REL_SSA, {SourceSSARegisterStackLowLevelOperandUsage, TopSSARegisterLowLevelOperandUsage,
+ SourceExprLowLevelOperandUsage}},
+ {LLIL_REG_STACK_ABS_SSA, {SourceSSARegisterStackLowLevelOperandUsage, SourceRegisterLowLevelOperandUsage}},
{LLIL_FLAG, {SourceFlagLowLevelOperandUsage}},
{LLIL_FLAG_BIT, {SourceFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}},
{LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}},
@@ -126,10 +147,12 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage,
ParameterSSARegistersLowLevelOperandUsage}},
{LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}},
+ {LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}},
{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}},
{LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}},
{LLIL_CONST, {ConstantLowLevelOperandUsage}},
{LLIL_CONST_PTR, {ConstantLowLevelOperandUsage}},
+ {LLIL_FLOAT_CONST, {ConstantLowLevelOperandUsage}},
{LLIL_ADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}},
{LLIL_SUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}},
{LLIL_AND, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}},
@@ -211,6 +234,8 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage
{
case HighSSARegisterLowLevelOperandUsage:
case LowSSARegisterLowLevelOperandUsage:
+ case PartialSSARegisterStackSourceLowLevelOperandUsage:
+ case TopSSARegisterLowLevelOperandUsage:
// Represented as subexpression, so only takes one slot even though it is an SSA register
operand++;
break;
@@ -224,13 +249,18 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage
case StackSSARegisterLowLevelOperandUsage:
// StackMemoryVersionLowLevelOperandUsage follows at same operand
break;
+ case DestSSARegisterStackLowLevelOperandUsage:
+ // PartialSSARegisterStackSourceLowLevelOperandUsage follows at same operand
+ break;
default:
switch (LowLevelILInstructionBase::operandTypeForUsage[usage])
{
case SSARegisterLowLevelOperand:
+ case SSARegisterStackLowLevelOperand:
case SSAFlagLowLevelOperand:
case IndexListLowLevelOperand:
case SSARegisterListLowLevelOperand:
+ case SSARegisterStackListLowLevelOperand:
case SSAFlagListLowLevelOperand:
// SSA registers/flags and lists take two operand slots
operand += 2;
@@ -298,6 +328,53 @@ bool SSARegister::operator<(const SSARegister& v) const
}
+SSARegisterStack::SSARegisterStack(): regStack(BN_INVALID_REGISTER), version(0)
+{
+}
+
+
+SSARegisterStack::SSARegisterStack(const uint32_t r, size_t i): regStack(r), version(i)
+{
+}
+
+
+SSARegisterStack::SSARegisterStack(const SSARegisterStack& v): regStack(v.regStack), version(v.version)
+{
+}
+
+
+SSARegisterStack& SSARegisterStack::operator=(const SSARegisterStack& v)
+{
+ regStack = v.regStack;
+ version = v.version;
+ return *this;
+}
+
+
+bool SSARegisterStack::operator==(const SSARegisterStack& v) const
+{
+ if (regStack != v.regStack)
+ return false;
+ return version == v.version;
+}
+
+
+bool SSARegisterStack::operator!=(const SSARegisterStack& v) const
+{
+ return !((*this) == v);
+}
+
+
+bool SSARegisterStack::operator<(const SSARegisterStack& v) const
+{
+ if (regStack < v.regStack)
+ return true;
+ if (v.regStack < regStack)
+ return false;
+ return version < v.version;
+}
+
+
SSAFlag::SSAFlag(): flag(BN_INVALID_REGISTER), version(0)
{
}
@@ -561,6 +638,64 @@ LowLevelILSSARegisterList::operator vector<SSARegister>() const
}
+const SSARegisterStack LowLevelILSSARegisterStackList::ListIterator::operator*()
+{
+ LowLevelILIntegerList::const_iterator cur = pos;
+ uint32_t regStack = (uint32_t)*cur;
+ ++cur;
+ size_t version = (size_t)*cur;
+ return SSARegisterStack(regStack, version);
+}
+
+
+LowLevelILSSARegisterStackList::LowLevelILSSARegisterStackList(LowLevelILFunction* func,
+ const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1))
+{
+}
+
+
+LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ return result;
+}
+
+
+LowLevelILSSARegisterStackList::const_iterator LowLevelILSSARegisterStackList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ return result;
+}
+
+
+size_t LowLevelILSSARegisterStackList::size() const
+{
+ return m_list.size() / 2;
+}
+
+
+const SSARegisterStack LowLevelILSSARegisterStackList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw LowLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+LowLevelILSSARegisterStackList::operator vector<SSARegisterStack>() const
+{
+ vector<SSARegisterStack> result;
+ for (auto& i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
const SSAFlag LowLevelILSSAFlagList::ListIterator::operator*()
{
LowLevelILIntegerList::const_iterator cur = pos;
@@ -666,6 +801,14 @@ uint32_t LowLevelILOperand::GetRegister() const
}
+uint32_t LowLevelILOperand::GetRegisterStack() const
+{
+ if (m_type != RegisterStackLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsRegister(m_operandIndex);
+}
+
+
uint32_t LowLevelILOperand::GetFlag() const
{
if (m_type != FlagLowLevelOperand)
@@ -687,12 +830,24 @@ SSARegister LowLevelILOperand::GetSSARegister() const
if (m_type != SSARegisterLowLevelOperand)
throw LowLevelILInstructionAccessException();
if ((m_usage == HighSSARegisterLowLevelOperandUsage) || (m_usage == LowSSARegisterLowLevelOperandUsage) ||
- (m_usage == StackSSARegisterLowLevelOperandUsage))
+ (m_usage == StackSSARegisterLowLevelOperandUsage) || (m_usage == TopSSARegisterLowLevelOperandUsage))
return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegister(0);
return m_instr.GetRawOperandAsSSARegister(m_operandIndex);
}
+SSARegisterStack LowLevelILOperand::GetSSARegisterStack() const
+{
+ if (m_type != SSARegisterStackLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ if (m_usage == DestSSARegisterStackLowLevelOperandUsage)
+ return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterStack(0);
+ if (m_usage == PartialSSARegisterStackSourceLowLevelOperandUsage)
+ return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0);
+ return m_instr.GetRawOperandAsSSARegisterStack(m_operandIndex);
+}
+
+
SSAFlag LowLevelILOperand::GetSSAFlag() const
{
if (m_type != SSAFlagLowLevelOperand)
@@ -721,6 +876,14 @@ LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const
}
+LowLevelILSSARegisterStackList LowLevelILOperand::GetSSARegisterStackList() const
+{
+ if (m_type != SSARegisterStackListLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsSSARegisterStackList(m_operandIndex);
+}
+
+
LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const
{
if (m_type != SSAFlagListLowLevelOperand)
@@ -886,6 +1049,18 @@ SSARegister LowLevelILInstructionBase::GetRawOperandAsSSARegister(size_t operand
}
+SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsSSARegisterStack(size_t operand) const
+{
+ return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 1]);
+}
+
+
+SSARegisterStack LowLevelILInstructionBase::GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const
+{
+ return SSARegisterStack((uint32_t)operands[operand], (size_t)operands[operand + 2]);
+}
+
+
SSAFlag LowLevelILInstructionBase::GetRawOperandAsSSAFlag(size_t operand) const
{
return SSAFlag((uint32_t)operands[operand], (size_t)operands[operand + 1]);
@@ -904,6 +1079,12 @@ LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterL
}
+LowLevelILSSARegisterStackList LowLevelILInstructionBase::GetRawOperandAsSSARegisterStackList(size_t operand) const
+{
+ return LowLevelILSSARegisterStackList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+}
+
+
LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size_t operand) const
{
return LowLevelILSSAFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
@@ -1147,12 +1328,32 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL
case LLIL_SET_REG_SPLIT_SSA:
GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>().VisitExprs(func);
break;
+ case LLIL_SET_REG_STACK_REL:
+ GetDestExpr<LLIL_SET_REG_STACK_REL>().VisitExprs(func);
+ GetSourceExpr<LLIL_SET_REG_STACK_REL>().VisitExprs(func);
+ break;
+ case LLIL_REG_STACK_PUSH:
+ GetSourceExpr<LLIL_REG_STACK_PUSH>().VisitExprs(func);
+ break;
+ case LLIL_SET_REG_STACK_REL_SSA:
+ GetDestExpr<LLIL_SET_REG_STACK_REL_SSA>().VisitExprs(func);
+ GetSourceExpr<LLIL_SET_REG_STACK_REL_SSA>().VisitExprs(func);
+ break;
+ case LLIL_SET_REG_STACK_ABS_SSA:
+ GetSourceExpr<LLIL_SET_REG_STACK_ABS_SSA>().VisitExprs(func);
+ break;
case LLIL_SET_FLAG:
GetSourceExpr<LLIL_SET_FLAG>().VisitExprs(func);
break;
case LLIL_SET_FLAG_SSA:
GetSourceExpr<LLIL_SET_FLAG_SSA>().VisitExprs(func);
break;
+ case LLIL_REG_STACK_REL:
+ GetSourceExpr<LLIL_REG_STACK_REL>().VisitExprs(func);
+ break;
+ case LLIL_REG_STACK_REL_SSA:
+ GetSourceExpr<LLIL_REG_STACK_REL_SSA>().VisitExprs(func);
+ break;
case LLIL_LOAD:
GetSourceExpr<LLIL_LOAD>().VisitExprs(func);
break;
@@ -1300,6 +1501,25 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
return dest->SetRegisterSplitSSA(size, GetHighSSARegister<LLIL_SET_REG_SPLIT_SSA>(),
GetLowSSARegister<LLIL_SET_REG_SPLIT_SSA>(),
subExprHandler(GetSourceExpr<LLIL_SET_REG_SPLIT_SSA>()), *this);
+ case LLIL_SET_REG_STACK_REL:
+ return dest->SetRegisterStackTopRelative(size, GetDestRegisterStack<LLIL_SET_REG_STACK_REL>(),
+ subExprHandler(GetDestExpr<LLIL_SET_REG_STACK_REL>()),
+ subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_REL>()), flags, *this);
+ case LLIL_REG_STACK_PUSH:
+ return dest->RegisterStackPush(size, GetDestRegisterStack<LLIL_REG_STACK_PUSH>(),
+ subExprHandler(GetSourceExpr<LLIL_REG_STACK_PUSH>()), flags, *this);
+ case LLIL_SET_REG_STACK_REL_SSA:
+ return dest->SetRegisterStackTopRelativeSSA(size, GetDestSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().regStack,
+ GetDestSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().version,
+ GetSourceSSARegisterStack<LLIL_SET_REG_STACK_REL_SSA>().version,
+ subExprHandler(GetDestExpr<LLIL_SET_REG_STACK_REL_SSA>()), GetTopSSARegister<LLIL_SET_REG_STACK_REL_SSA>(),
+ subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_REL_SSA>()), *this);
+ case LLIL_SET_REG_STACK_ABS_SSA:
+ return dest->SetRegisterStackAbsoluteSSA(size, GetDestSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().regStack,
+ GetDestSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().version,
+ GetSourceSSARegisterStack<LLIL_SET_REG_STACK_ABS_SSA>().version,
+ GetDestRegister<LLIL_SET_REG_STACK_ABS_SSA>(),
+ subExprHandler(GetSourceExpr<LLIL_SET_REG_STACK_ABS_SSA>()), *this);
case LLIL_SET_FLAG:
return dest->SetFlag(GetDestFlag<LLIL_SET_FLAG>(), subExprHandler(GetSourceExpr<LLIL_SET_FLAG>()), *this);
case LLIL_SET_FLAG_SSA:
@@ -1330,6 +1550,18 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
case LLIL_REG_SPLIT_SSA:
return dest->RegisterSplitSSA(size, GetHighSSARegister<LLIL_REG_SPLIT_SSA>(),
GetLowSSARegister<LLIL_REG_SPLIT_SSA>(), *this);
+ case LLIL_REG_STACK_REL:
+ return dest->RegisterStackTopRelative(size, GetSourceRegisterStack<LLIL_REG_STACK_REL>(),
+ subExprHandler(GetSourceExpr<LLIL_REG_STACK_REL>()), *this);
+ case LLIL_REG_STACK_POP:
+ return dest->RegisterStackPop(size, GetSourceRegisterStack<LLIL_REG_STACK_POP>(), *this);
+ case LLIL_REG_STACK_REL_SSA:
+ return dest->RegisterStackTopRelativeSSA(size, GetSourceSSARegisterStack<LLIL_REG_STACK_REL_SSA>(),
+ subExprHandler(GetSourceExpr<LLIL_REG_STACK_REL_SSA>()),
+ GetTopSSARegister<LLIL_REG_STACK_REL_SSA>(), *this);
+ case LLIL_REG_STACK_ABS_SSA:
+ return dest->RegisterStackAbsoluteSSA(size, GetSourceSSARegisterStack<LLIL_REG_STACK_ABS_SSA>(),
+ GetSourceRegister<LLIL_REG_STACK_ABS_SSA>(), *this);
case LLIL_FLAG:
return dest->Flag(GetSourceFlag<LLIL_FLAG>(), *this);
case LLIL_FLAG_SSA:
@@ -1384,6 +1616,9 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this);
case LLIL_REG_PHI:
return dest->RegisterPhi(GetDestSSARegister<LLIL_REG_PHI>(), GetSourceSSARegisters<LLIL_REG_PHI>(), *this);
+ case LLIL_REG_STACK_PHI:
+ return dest->RegisterStackPhi(GetDestSSARegisterStack<LLIL_REG_STACK_PHI>(),
+ GetSourceSSARegisterStacks<LLIL_REG_STACK_PHI>(), *this);
case LLIL_FLAG_PHI:
return dest->FlagPhi(GetDestSSAFlag<LLIL_FLAG_PHI>(), GetSourceSSAFlags<LLIL_FLAG_PHI>(), *this);
case LLIL_MEM_PHI:
@@ -1392,6 +1627,8 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
return dest->Const(size, GetConstant<LLIL_CONST>(), *this);
case LLIL_CONST_PTR:
return dest->ConstPointer(size, GetConstant<LLIL_CONST_PTR>(), *this);
+ case LLIL_FLOAT_CONST:
+ return dest->FloatConstRaw(size, GetConstant<LLIL_FLOAT_CONST>(), *this);
case LLIL_POP:
case LLIL_NORET:
case LLIL_SYSCALL:
@@ -1506,6 +1743,15 @@ uint32_t LowLevelILInstruction::GetSourceRegister() const
}
+uint32_t LowLevelILInstruction::GetSourceRegisterStack() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SourceRegisterStackLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsRegister(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
uint32_t LowLevelILInstruction::GetSourceFlag() const
{
size_t operandIndex;
@@ -1524,6 +1770,17 @@ SSARegister LowLevelILInstruction::GetSourceSSARegister() const
}
+SSARegisterStack LowLevelILInstruction::GetSourceSSARegisterStack() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(PartialSSARegisterStackSourceLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex).GetRawOperandAsPartialSSARegisterStackSource(0);
+ if (GetOperandIndexForUsage(SourceSSARegisterStackLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSARegisterStack(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
SSAFlag LowLevelILInstruction::GetSourceSSAFlag() const
{
size_t operandIndex;
@@ -1551,6 +1808,15 @@ uint32_t LowLevelILInstruction::GetDestRegister() const
}
+uint32_t LowLevelILInstruction::GetDestRegisterStack() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DestRegisterStackLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsRegister(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
uint32_t LowLevelILInstruction::GetDestFlag() const
{
size_t operandIndex;
@@ -1569,6 +1835,15 @@ SSARegister LowLevelILInstruction::GetDestSSARegister() const
}
+SSARegisterStack LowLevelILInstruction::GetDestSSARegisterStack() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(DestSSARegisterStackLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterStack(0);
+ throw LowLevelILInstructionAccessException();
+}
+
+
SSAFlag LowLevelILInstruction::GetDestSSAFlag() const
{
size_t operandIndex;
@@ -1596,6 +1871,15 @@ SSARegister LowLevelILInstruction::GetStackSSARegister() const
}
+SSARegister LowLevelILInstruction::GetTopSSARegister() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(TopSSARegisterLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegister(0);
+ throw LowLevelILInstructionAccessException();
+}
+
+
LowLevelILInstruction LowLevelILInstruction::GetLeftExpr() const
{
size_t operandIndex;
@@ -1789,6 +2073,15 @@ LowLevelILSSARegisterList LowLevelILInstruction::GetSourceSSARegisters() const
}
+LowLevelILSSARegisterStackList LowLevelILInstruction::GetSourceSSARegisterStacks() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(SourceSSARegisterStacksLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsSSARegisterStackList(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const
{
size_t operandIndex;
@@ -1859,6 +2152,39 @@ ExprId LowLevelILFunction::SetRegisterSplitSSA(size_t size, const SSARegister& h
}
+ExprId LowLevelILFunction::SetRegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry,
+ ExprId val, uint32_t flags, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_SET_REG_STACK_REL, loc, size, flags, regStack, entry, val);
+}
+
+
+ExprId LowLevelILFunction::RegisterStackPush(size_t size, uint32_t regStack, ExprId val,
+ uint32_t flags, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_PUSH, loc, size, flags, regStack, val);
+}
+
+
+ExprId LowLevelILFunction::SetRegisterStackTopRelativeSSA(size_t size, uint32_t regStack,
+ size_t destVersion, size_t srcVersion, ExprId entry, const SSARegister& top,
+ ExprId val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_SET_REG_STACK_REL_SSA, loc, size, 0,
+ AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion),
+ entry, AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version), val);
+}
+
+
+ExprId LowLevelILFunction::SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack,
+ size_t destVersion, size_t srcVersion, uint32_t reg, ExprId val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_SET_REG_STACK_REL_SSA, loc, size, 0,
+ AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion),
+ reg, val);
+}
+
+
ExprId LowLevelILFunction::SetFlag(uint32_t flag, ExprId val, const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_SET_FLAG, loc, 0, 0, flag, val);
@@ -1943,6 +2269,34 @@ ExprId LowLevelILFunction::RegisterSplitSSA(size_t size, const SSARegister& high
}
+ExprId LowLevelILFunction::RegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_REL, loc, size, 0, regStack, entry);
+}
+
+
+ExprId LowLevelILFunction::RegisterStackPop(size_t size, uint32_t regStack, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_POP, loc, size, 0, regStack);
+}
+
+
+ExprId LowLevelILFunction::RegisterStackTopRelativeSSA(size_t size, const SSARegisterStack& regStack, ExprId entry,
+ const SSARegister& top, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_REL_SSA, loc, size, 0, regStack.regStack, regStack.version, entry,
+ AddExprWithLocation(LLIL_REG_SSA, loc, 0, 0, top.reg, top.version));
+}
+
+
+ExprId LowLevelILFunction::RegisterStackAbsoluteSSA(size_t size, const SSARegisterStack& regStack, uint32_t reg,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_ABS_SSA, loc, size, 0, regStack.regStack, regStack.version, reg);
+}
+
+
ExprId LowLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_CONST, loc, size, 0, val);
@@ -1955,6 +2309,36 @@ ExprId LowLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSourc
}
+ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_FLOAT_CONST, loc, size, 0, val);
+}
+
+
+ExprId LowLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc)
+{
+ union
+ {
+ float f;
+ uint32_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 4, 0, bits.i);
+}
+
+
+ExprId LowLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc)
+{
+ union
+ {
+ double f;
+ uint64_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(LLIL_FLOAT_CONST, loc, 8, 0, bits.i);
+}
+
+
ExprId LowLevelILFunction::Flag(uint32_t flag, const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_FLAG, loc, 0, 0, flag);
@@ -2358,6 +2742,14 @@ ExprId LowLevelILFunction::RegisterPhi(const SSARegister& dest, const vector<SSA
}
+ExprId LowLevelILFunction::RegisterStackPhi(const SSARegisterStack& dest, const vector<SSARegisterStack>& sources,
+ const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(LLIL_REG_STACK_PHI, loc, 0, 0, dest.regStack, dest.version,
+ sources.size() * 2, AddSSARegisterStackList(sources));
+}
+
+
ExprId LowLevelILFunction::FlagPhi(const SSAFlag& dest, const vector<SSAFlag>& sources,
const ILSourceLocation& loc)
{
diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h
index 8c8fe55f..4e02632e 100644
--- a/lowlevelilinstruction.h
+++ b/lowlevelilinstruction.h
@@ -69,6 +69,21 @@ namespace BinaryNinja
bool operator<(const SSARegister& v) const;
};
+ struct SSARegisterStack
+ {
+ uint32_t regStack;
+ size_t version;
+
+ SSARegisterStack();
+ SSARegisterStack(uint32_t r, size_t i);
+ SSARegisterStack(const SSARegisterStack& v);
+
+ SSARegisterStack& operator=(const SSARegisterStack& v);
+ bool operator==(const SSARegisterStack& v) const;
+ bool operator!=(const SSARegisterStack& v) const;
+ bool operator<(const SSARegisterStack& v) const;
+ };
+
struct SSAFlag
{
uint32_t flag;
@@ -90,12 +105,15 @@ namespace BinaryNinja
IndexLowLevelOperand,
ExprLowLevelOperand,
RegisterLowLevelOperand,
+ RegisterStackLowLevelOperand,
FlagLowLevelOperand,
FlagConditionLowLevelOperand,
SSARegisterLowLevelOperand,
+ SSARegisterStackLowLevelOperand,
SSAFlagLowLevelOperand,
IndexListLowLevelOperand,
SSARegisterListLowLevelOperand,
+ SSARegisterStackListLowLevelOperand,
SSAFlagListLowLevelOperand
};
@@ -103,17 +121,23 @@ namespace BinaryNinja
{
SourceExprLowLevelOperandUsage,
SourceRegisterLowLevelOperandUsage,
+ SourceRegisterStackLowLevelOperandUsage,
SourceFlagLowLevelOperandUsage,
SourceSSARegisterLowLevelOperandUsage,
+ SourceSSARegisterStackLowLevelOperandUsage,
SourceSSAFlagLowLevelOperandUsage,
DestExprLowLevelOperandUsage,
DestRegisterLowLevelOperandUsage,
+ DestRegisterStackLowLevelOperandUsage,
DestFlagLowLevelOperandUsage,
DestSSARegisterLowLevelOperandUsage,
+ DestSSARegisterStackLowLevelOperandUsage,
DestSSAFlagLowLevelOperandUsage,
PartialRegisterLowLevelOperandUsage,
+ PartialSSARegisterStackSourceLowLevelOperandUsage,
StackSSARegisterLowLevelOperandUsage,
StackMemoryVersionLowLevelOperandUsage,
+ TopSSARegisterLowLevelOperandUsage,
LeftExprLowLevelOperandUsage,
RightExprLowLevelOperandUsage,
CarryExprLowLevelOperandUsage,
@@ -136,6 +160,7 @@ namespace BinaryNinja
OutputMemoryVersionLowLevelOperandUsage,
ParameterSSARegistersLowLevelOperandUsage,
SourceSSARegistersLowLevelOperandUsage,
+ SourceSSARegisterStacksLowLevelOperandUsage,
SourceSSAFlagsLowLevelOperandUsage,
SourceMemoryVersionsLowLevelOperandUsage,
TargetListLowLevelOperandUsage
@@ -163,6 +188,24 @@ namespace std
};
#ifdef BINARYNINJACORE_LIBRARY
+ template<> struct hash<BinaryNinjaCore::SSARegisterStack>
+#else
+ template<> struct hash<BinaryNinja::SSARegisterStack>
+#endif
+ {
+#ifdef BINARYNINJACORE_LIBRARY
+ typedef BinaryNinjaCore::SSARegisterStack argument_type;
+#else
+ typedef BinaryNinja::SSARegisterStack argument_type;
+#endif
+ typedef uint64_t result_type;
+ result_type operator()(argument_type const& value) const
+ {
+ return ((result_type)value.regStack) ^ ((result_type)value.version << 32);
+ }
+ };
+
+#ifdef BINARYNINJACORE_LIBRARY
template<> struct hash<BinaryNinjaCore::SSAFlag>
#else
template<> struct hash<BinaryNinja::SSAFlag>
@@ -312,6 +355,33 @@ namespace BinaryNinja
operator std::vector<SSARegister>() const;
};
+ class LowLevelILSSARegisterStackList
+ {
+ struct ListIterator
+ {
+ LowLevelILIntegerList::const_iterator pos;
+ bool operator==(const ListIterator& a) const { return pos == a.pos; }
+ bool operator!=(const ListIterator& a) const { return pos != a.pos; }
+ bool operator<(const ListIterator& a) const { return pos < a.pos; }
+ ListIterator& operator++() { ++pos; ++pos; return *this; }
+ const SSARegisterStack operator*();
+ };
+
+ LowLevelILIntegerList m_list;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ LowLevelILSSARegisterStackList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const SSARegisterStack operator[](size_t i) const;
+
+ operator std::vector<SSARegisterStack>() const;
+ };
+
class LowLevelILSSAFlagList
{
struct ListIterator
@@ -362,9 +432,12 @@ namespace BinaryNinja
BNLowLevelILFlagCondition GetRawOperandAsFlagCondition(size_t operand) const;
LowLevelILInstruction GetRawOperandAsExpr(size_t operand) const;
SSARegister GetRawOperandAsSSARegister(size_t operand) const;
+ SSARegisterStack GetRawOperandAsSSARegisterStack(size_t operand) const;
+ SSARegisterStack GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const;
SSAFlag GetRawOperandAsSSAFlag(size_t operand) const;
LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const;
LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const;
+ LowLevelILSSARegisterStackList GetRawOperandAsSSARegisterStackList(size_t operand) const;
LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const;
void UpdateRawOperand(size_t operandIndex, ExprId value);
@@ -467,16 +540,21 @@ namespace BinaryNinja
// Templated accessors for instruction operands, use these for efficient access to a known instruction
template <BNLowLevelILOperation N> LowLevelILInstruction GetSourceExpr() const { return As<N>().GetSourceExpr(); }
template <BNLowLevelILOperation N> uint32_t GetSourceRegister() const { return As<N>().GetSourceRegister(); }
+ template <BNLowLevelILOperation N> uint32_t GetSourceRegisterStack() const { return As<N>().GetSourceRegisterStack(); }
template <BNLowLevelILOperation N> uint32_t GetSourceFlag() const { return As<N>().GetSourceFlag(); }
template <BNLowLevelILOperation N> SSARegister GetSourceSSARegister() const { return As<N>().GetSourceSSARegister(); }
+ template <BNLowLevelILOperation N> SSARegisterStack GetSourceSSARegisterStack() const { return As<N>().GetSourceSSARegisterStack(); }
template <BNLowLevelILOperation N> SSAFlag GetSourceSSAFlag() const { return As<N>().GetSourceSSAFlag(); }
template <BNLowLevelILOperation N> LowLevelILInstruction GetDestExpr() const { return As<N>().GetDestExpr(); }
template <BNLowLevelILOperation N> uint32_t GetDestRegister() const { return As<N>().GetDestRegister(); }
+ template <BNLowLevelILOperation N> uint32_t GetDestRegisterStack() const { return As<N>().GetDestRegisterStack(); }
template <BNLowLevelILOperation N> uint32_t GetDestFlag() const { return As<N>().GetDestFlag(); }
template <BNLowLevelILOperation N> SSARegister GetDestSSARegister() const { return As<N>().GetDestSSARegister(); }
+ template <BNLowLevelILOperation N> SSARegisterStack GetDestSSARegisterStack() const { return As<N>().GetDestSSARegisterStack(); }
template <BNLowLevelILOperation N> SSAFlag GetDestSSAFlag() const { return As<N>().GetDestSSAFlag(); }
template <BNLowLevelILOperation N> uint32_t GetPartialRegister() const { return As<N>().GetPartialRegister(); }
template <BNLowLevelILOperation N> SSARegister GetStackSSARegister() const { return As<N>().GetStackSSARegister(); }
+ template <BNLowLevelILOperation N> SSARegister GetTopSSARegister() const { return As<N>().GetTopSSARegister(); }
template <BNLowLevelILOperation N> LowLevelILInstruction GetLeftExpr() const { return As<N>().GetLeftExpr(); }
template <BNLowLevelILOperation N> LowLevelILInstruction GetRightExpr() const { return As<N>().GetRightExpr(); }
template <BNLowLevelILOperation N> LowLevelILInstruction GetCarryExpr() const { return As<N>().GetCarryExpr(); }
@@ -498,6 +576,7 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetOutputSSARegisters() const { return As<N>().GetOutputSSARegisters(); }
template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetParameterSSARegisters() const { return As<N>().GetParameterSSARegisters(); }
template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetSourceSSARegisters() const { return As<N>().GetSourceSSARegisters(); }
+ template <BNLowLevelILOperation N> LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const { return As<N>().GetSourceSSARegisterStacks(); }
template <BNLowLevelILOperation N> LowLevelILSSAFlagList GetSourceSSAFlags() const { return As<N>().GetSourceSSAFlags(); }
template <BNLowLevelILOperation N> LowLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); }
template <BNLowLevelILOperation N> LowLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); }
@@ -507,6 +586,7 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> void SetHighSSAVersion(size_t version) { As<N>().SetHighSSAVersion(version); }
template <BNLowLevelILOperation N> void SetLowSSAVersion(size_t version) { As<N>().SetLowSSAVersion(version); }
template <BNLowLevelILOperation N> void SetStackSSAVersion(size_t version) { As<N>().SetStackSSAVersion(version); }
+ template <BNLowLevelILOperation N> void SetTopSSAVersion(size_t version) { As<N>().SetTopSSAVersion(version); }
template <BNLowLevelILOperation N> void SetDestMemoryVersion(size_t version) { As<N>().SetDestMemoryVersion(version); }
template <BNLowLevelILOperation N> void SetSourceMemoryVersion(size_t version) { As<N>().SetSourceMemoryVersion(version); }
template <BNLowLevelILOperation N> void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetOutputSSARegisters(regs); }
@@ -518,16 +598,21 @@ namespace BinaryNinja
// on type mismatch. These are slower than the templated versions above.
LowLevelILInstruction GetSourceExpr() const;
uint32_t GetSourceRegister() const;
+ uint32_t GetSourceRegisterStack() const;
uint32_t GetSourceFlag() const;
SSARegister GetSourceSSARegister() const;
+ SSARegisterStack GetSourceSSARegisterStack() const;
SSAFlag GetSourceSSAFlag() const;
LowLevelILInstruction GetDestExpr() const;
uint32_t GetDestRegister() const;
+ uint32_t GetDestRegisterStack() const;
uint32_t GetDestFlag() const;
SSARegister GetDestSSARegister() const;
+ SSARegisterStack GetDestSSARegisterStack() const;
SSAFlag GetDestSSAFlag() const;
uint32_t GetPartialRegister() const;
SSARegister GetStackSSARegister() const;
+ SSARegister GetTopSSARegister() const;
LowLevelILInstruction GetLeftExpr() const;
LowLevelILInstruction GetRightExpr() const;
LowLevelILInstruction GetCarryExpr() const;
@@ -549,6 +634,7 @@ namespace BinaryNinja
LowLevelILSSARegisterList GetOutputSSARegisters() const;
LowLevelILSSARegisterList GetParameterSSARegisters() const;
LowLevelILSSARegisterList GetSourceSSARegisters() const;
+ LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const;
LowLevelILSSAFlagList GetSourceSSAFlags() const;
LowLevelILIndexList GetSourceMemoryVersions() const;
LowLevelILIndexList GetTargetList() const;
@@ -572,12 +658,15 @@ namespace BinaryNinja
size_t GetIndex() const;
LowLevelILInstruction GetExpr() const;
uint32_t GetRegister() const;
+ uint32_t GetRegisterStack() const;
uint32_t GetFlag() const;
BNLowLevelILFlagCondition GetFlagCondition() const;
SSARegister GetSSARegister() const;
+ SSARegisterStack GetSSARegisterStack() const;
SSAFlag GetSSAFlag() const;
LowLevelILIndexList GetIndexList() const;
LowLevelILSSARegisterList GetSSARegisterList() const;
+ LowLevelILSSARegisterStackList GetSSARegisterStackList() const;
LowLevelILSSAFlagList GetSSAFlagList() const;
};
@@ -671,6 +760,37 @@ namespace BinaryNinja
void SetHighSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); }
void SetLowSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_REL>: public LowLevelILInstructionBase
+ {
+ uint32_t GetDestRegisterStack() const { return GetRawOperandAsRegister(0); }
+ LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_PUSH>: public LowLevelILInstructionBase
+ {
+ uint32_t GetDestRegisterStack() const { return GetRawOperandAsRegister(0); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_REL_SSA>: public LowLevelILInstructionBase
+ {
+ SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); }
+ SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); }
+ LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
+ SSARegister GetTopSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(3); }
+ void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); }
+ void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); }
+ void SetTopSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_SET_REG_STACK_ABS_SSA>: public LowLevelILInstructionBase
+ {
+ SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsSSARegisterStack(0); }
+ SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsExpr(0).GetRawOperandAsPartialSSARegisterStackSource(0); }
+ uint32_t GetDestRegister() const { return GetRawOperandAsRegister(1); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
+ void SetDestSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(1, version); }
+ void SetSourceSSAVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(2, version); }
+ };
template <> struct LowLevelILInstructionAccessor<LLIL_SET_FLAG>: public LowLevelILInstructionBase
{
uint32_t GetDestFlag() const { return GetRawOperandAsRegister(0); }
@@ -721,6 +841,29 @@ namespace BinaryNinja
uint32_t GetPartialRegister() const { return GetRawOperandAsRegister(2); }
void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_REL>: public LowLevelILInstructionBase
+ {
+ uint32_t GetSourceRegisterStack() const { return GetRawOperandAsRegister(0); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(1); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_POP>: public LowLevelILInstructionBase
+ {
+ uint32_t GetSourceRegisterStack() const { return GetRawOperandAsRegister(0); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_REL_SSA>: public LowLevelILInstructionBase
+ {
+ SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); }
+ LowLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
+ SSARegister GetTopSSARegister() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegister(0); }
+ void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); }
+ void SetTopSSAVersion(size_t version) { GetRawOperandAsExpr(3).UpdateRawOperand(1, version); }
+ };
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_ABS_SSA>: public LowLevelILInstructionBase
+ {
+ SSARegisterStack GetSourceSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); }
+ uint32_t GetSourceRegister() const { return GetRawOperandAsRegister(2); }
+ void SetSourceSSAVersion(size_t version) { UpdateRawOperand(1, version); }
+ };
template <> struct LowLevelILInstructionAccessor<LLIL_FLAG>: public LowLevelILInstructionBase
{
uint32_t GetSourceFlag() const { return GetRawOperandAsRegister(0); }
@@ -832,6 +975,11 @@ namespace BinaryNinja
SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); }
LowLevelILSSARegisterList GetSourceSSARegisters() const { return GetRawOperandAsSSARegisterList(2); }
};
+ template <> struct LowLevelILInstructionAccessor<LLIL_REG_STACK_PHI>: public LowLevelILInstructionBase
+ {
+ SSARegisterStack GetDestSSARegisterStack() const { return GetRawOperandAsSSARegisterStack(0); }
+ LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const { return GetRawOperandAsSSARegisterStackList(2); }
+ };
template <> struct LowLevelILInstructionAccessor<LLIL_FLAG_PHI>: public LowLevelILInstructionBase
{
SSAFlag GetDestSSAFlag() const { return GetRawOperandAsSSAFlag(0); }
@@ -853,6 +1001,7 @@ namespace BinaryNinja
template <> struct LowLevelILInstructionAccessor<LLIL_CONST>: public LowLevelILConstantInstruction {};
template <> struct LowLevelILInstructionAccessor<LLIL_CONST_PTR>: public LowLevelILConstantInstruction {};
+ template <> struct LowLevelILInstructionAccessor<LLIL_FLOAT_CONST>: public LowLevelILConstantInstruction {};
template <> struct LowLevelILInstructionAccessor<LLIL_ADD>: public LowLevelILTwoOperandInstruction {};
template <> struct LowLevelILInstructionAccessor<LLIL_SUB>: public LowLevelILTwoOperandInstruction {};
diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp
index b0e607b2..c3b4014f 100644
--- a/mediumlevelilinstruction.cpp
+++ b/mediumlevelilinstruction.cpp
@@ -149,6 +149,7 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>>
{MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}},
{MLIL_CONST, {ConstantMediumLevelOperandUsage}},
{MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}},
+ {MLIL_FLOAT_CONST, {ConstantMediumLevelOperandUsage}},
{MLIL_IMPORT, {ConstantMediumLevelOperandUsage}},
{MLIL_ADD, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}},
{MLIL_SUB, {LeftExprMediumLevelOperandUsage, RightExprMediumLevelOperandUsage}},
@@ -1598,6 +1599,8 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest,
return dest->Const(size, GetConstant<MLIL_CONST>(), *this);
case MLIL_CONST_PTR:
return dest->ConstPointer(size, GetConstant<MLIL_CONST_PTR>(), *this);
+ case MLIL_FLOAT_CONST:
+ return dest->FloatConstRaw(size, GetConstant<MLIL_FLOAT_CONST>(), *this);
case MLIL_IMPORT:
return dest->ImportedAddress(size, GetConstant<MLIL_IMPORT>(), *this);
case MLIL_BP:
@@ -2131,6 +2134,36 @@ ExprId MediumLevelILFunction::ConstPointer(size_t size, uint64_t val, const ILSo
}
+ExprId MediumLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc)
+{
+ return AddExprWithLocation(MLIL_FLOAT_CONST, loc, size, val);
+}
+
+
+ExprId MediumLevelILFunction::FloatConstSingle(float val, const ILSourceLocation& loc)
+{
+ union
+ {
+ float f;
+ uint32_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(MLIL_FLOAT_CONST, loc, 4, bits.i);
+}
+
+
+ExprId MediumLevelILFunction::FloatConstDouble(double val, const ILSourceLocation& loc)
+{
+ union
+ {
+ double f;
+ uint64_t i;
+ } bits;
+ bits.f = val;
+ return AddExprWithLocation(MLIL_FLOAT_CONST, loc, 8, bits.i);
+}
+
+
ExprId MediumLevelILFunction::ImportedAddress(size_t size, uint64_t val, const ILSourceLocation& loc)
{
return AddExprWithLocation(MLIL_IMPORT, loc, size, val);
diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h
index aa4600df..85630843 100644
--- a/mediumlevelilinstruction.h
+++ b/mediumlevelilinstruction.h
@@ -925,6 +925,7 @@ namespace BinaryNinja
template <> struct MediumLevelILInstructionAccessor<MLIL_CONST>: public MediumLevelILConstantInstruction {};
template <> struct MediumLevelILInstructionAccessor<MLIL_CONST_PTR>: public MediumLevelILConstantInstruction {};
+ template <> struct MediumLevelILInstructionAccessor<MLIL_FLOAT_CONST>: public MediumLevelILConstantInstruction {};
template <> struct MediumLevelILInstructionAccessor<MLIL_IMPORT>: public MediumLevelILConstantInstruction {};
template <> struct MediumLevelILInstructionAccessor<MLIL_ADD>: public MediumLevelILTwoOperandInstruction {};
diff --git a/python/architecture.py b/python/architecture.py
index 72403fec..289b0abd 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -122,6 +122,7 @@ class Architecture(object):
flag_roles = {}
flags_required_for_flag_condition = {}
flags_written_by_flag_write_type = {}
+ reg_stacks = {}
__metaclass__ = _ArchitectureMetaClass
next_address = 0
@@ -216,6 +217,19 @@ class Architecture(object):
for i in xrange(0, count.value):
self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i]))
core.BNFreeRegisterList(regs)
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetAllArchitectureRegisterStacks(self.handle, count)
+ self.__dict__["reg_stacks"] = {}
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureRegisterStackName(self.handle, regs[i])
+ info = core.BNGetArchitectureRegisterStackInfo(self.handle, regs[i])
+ storage = []
+ for j in xrange(0, info.count):
+ storage.append(core.BNGetArchitectureRegisterName(self.handle, info.firstStorageReg + j))
+ top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg)
+ self.reg_stacks[name] = function.RegisterStackInfo(storage, top)
+ core.BNFreeRegisterList(regs)
else:
startup._init_plugins()
@@ -259,6 +273,9 @@ class Architecture(object):
self._get_stack_pointer_register)
self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register)
self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers)
+ self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__(self._get_register_stack_name)
+ self._cb.getAllRegisterStacks = self._cb.getAllRegisterStacks.__class__(self._get_all_register_stacks)
+ self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__(self._get_register_stack_info)
self._cb.assemble = self._cb.assemble.__class__(self._assemble)
self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
self._is_never_branch_patch_available)
@@ -280,6 +297,25 @@ class Architecture(object):
self._regs_by_index = {}
self.__dict__["regs"] = self.__class__.regs
reg_index = 0
+
+ # Registers used for storage in register stacks must be sequential, so allocate these in order first
+ self._all_reg_stacks = {}
+ self._reg_stacks_by_index = {}
+ self.__dict__["reg_stacks"] = self.__class__.reg_stacks
+ reg_stack_index = 0
+ for reg_stack in self.reg_stacks:
+ info = self.reg_stacks[reg_stack]
+ for reg in info.storage_regs:
+ self._all_regs[reg] = reg_index
+ self._regs_by_index[reg_index] = reg
+ self.regs[reg].index = reg_index
+ reg_index += 1
+ if reg_stack not in self._all_reg_stacks:
+ self._all_reg_stacks[reg_stack] = reg_stack_index
+ self._reg_stacks_by_index[reg_stack_index] = reg_stack
+ self.reg_stacks[reg_stack].index = reg_stack_index
+ reg_stack_index += 1
+
for reg in self.regs:
info = self.regs[reg]
if reg not in self._all_regs:
@@ -744,6 +780,47 @@ class Architecture(object):
count[0] = 0
return None
+ def _get_register_stack_name(self, ctxt, reg_stack):
+ try:
+ if reg_stack in self._reg_stacks_by_index:
+ return core.BNAllocString(self._reg_stacks_by_index[reg_stack])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
+ def _get_all_register_stacks(self, ctxt, count):
+ try:
+ regs = self._reg_stacks_by_index.keys()
+ count[0] = len(regs)
+ reg_buf = (ctypes.c_uint * len(regs))()
+ for i in xrange(0, len(regs)):
+ reg_buf[i] = regs[i]
+ result = ctypes.cast(reg_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, reg_buf)
+ return result.value
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_register_stack_info(self, ctxt, reg_stack, result):
+ try:
+ if reg_stack not in self._reg_stacks_by_index:
+ result[0].firstStorageReg = 0
+ result[0].count = 0
+ result[0].stackTopReg = 0
+ return
+ info = self.__class__.regs[self._reg_stacks_by_index[reg_stack]]
+ result[0].firstStorageReg = self._all_regs[info.storage_regs[0]]
+ result[0].count = len(info.storage_regs)
+ result[0].stackTopReg = self._all_regs[info.stack_top_reg]
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ result[0].firstStorageReg = 0
+ result[0].count = 0
+ result[0].stackTopReg = 0
+
def _assemble(self, ctxt, code, addr, result, errors):
try:
data, error_str = self.perform_assemble(code, addr)
@@ -1251,6 +1328,23 @@ class Architecture(object):
"""
return core.BNGetArchitectureRegisterName(self.handle, reg)
+ def get_reg_stack_name(self, reg_stack):
+ """
+ ``get_reg_stack_name`` gets a register stack name from a register stack number.
+
+ :param int reg_stack: register stack number
+ :return: the corresponding register string
+ :rtype: str
+ """
+ return core.BNGetArchitectureRegisterStackName(self.handle, reg_stack)
+
+ def get_reg_stack_for_reg(self, reg):
+ reg = self.get_reg_index(reg)
+ result = core.BNGetArchitectureRegisterStackForRegister(self.handle, reg)
+ if result == 0xffffffff:
+ return None
+ return self.get_reg_stack_name(result)
+
def get_flag_name(self, flag):
"""
``get_flag_name`` gets a flag name from a flag number.
@@ -1268,6 +1362,13 @@ class Architecture(object):
return reg.index
return reg
+ def get_reg_stack_index(self, reg_stack):
+ if isinstance(reg_stack, str):
+ return self.reg_stacks[reg_stack].index
+ elif isinstance(reg_stack, lowlevelil.ILRegisterStack):
+ return reg_stack.index
+ return reg_stack
+
def get_flag_index(self, flag):
if isinstance(flag, str):
return self._flags[flag]
diff --git a/python/callingconvention.py b/python/callingconvention.py
index e72475c9..18662fc5 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -308,6 +308,10 @@ class CallingConvention(object):
return self.name
def perform_get_incoming_reg_value(self, reg, func):
+ reg_stack = self.arch.get_reg_stack_for_reg(reg)
+ if reg_stack is not None:
+ if reg == self.arch.reg_stacks[reg_stack].stack_top_reg:
+ return function.RegisterValue.constant(0)
return function.RegisterValue()
def perform_get_incoming_flag_value(self, reg, func):
diff --git a/python/function.py b/python/function.py
index 5daa7b2a..eb8796f1 100644
--- a/python/function.py
+++ b/python/function.py
@@ -51,11 +51,11 @@ class LookupTableEntry(object):
class RegisterValue(object):
def __init__(self, arch = None, value = None, confidence = types.max_confidence):
+ self.is_constant = False
if value is None:
self.type = RegisterValueType.UndeterminedValue
else:
self.type = RegisterValueType(value.state)
- self.is_constant = False
if value.state == RegisterValueType.EntryValue:
self.arch = arch
if arch is not None:
@@ -103,6 +103,54 @@ class RegisterValue(object):
result.value = self.value
return result
+ @classmethod
+ def undetermined(self):
+ return RegisterValue()
+
+ @classmethod
+ def entry_value(self, arch, reg):
+ result = RegisterValue()
+ result.type = RegisterValueType.EntryValue
+ result.arch = arch
+ result.reg = reg
+ return result
+
+ @classmethod
+ def constant(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ConstantValue
+ result.value = value
+ result.is_constant = True
+ return result
+
+ @classmethod
+ def constant_ptr(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ConstantPointerValue
+ result.value = value
+ result.is_constant = True
+ return result
+
+ @classmethod
+ def stack_frame_offset(self, offset):
+ result = RegisterValue()
+ result.type = RegisterValueType.StackFrameOffset
+ result.offset = offset
+ return result
+
+ @classmethod
+ def imported_address(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ImportedAddressValue
+ result.value = value
+ return result
+
+ @classmethod
+ def return_address(self):
+ result = RegisterValue()
+ result.type = RegisterValueType.ReturnAddressValue
+ return result
+
class ValueRange(object):
def __init__(self, start, end, step):
@@ -1678,6 +1726,15 @@ class RegisterInfo(object):
return "<reg: size %d, offset %d in %s%s>" % (self.size, self.offset, self.full_width_reg, extend)
+class RegisterStackInfo(object):
+ def __init__(self, storage_regs, stack_top_reg):
+ self.storage_regs = storage_regs
+ self.stack_top_reg = stack_top_reg
+
+ def __repr__(self):
+ return "<reg stack: %d regs, stack top in %s>" % (len(self.storage_regs), self.stack_top_reg)
+
+
class InstructionBranch(object):
def __init__(self, branch_type, target = 0, arch = None):
self.type = branch_type
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index a3b1fcb6..f5a39b7e 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -26,6 +26,7 @@ from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionText
import function
import basicblock
import mediumlevelil
+import struct
class LowLevelILLabel(object):
@@ -61,6 +62,26 @@ class ILRegister(object):
return self.info == other.info
+class ILRegisterStack(object):
+ def __init__(self, arch, reg_stack):
+ self.arch = arch
+ self.index = reg_stack
+ self.name = self.arch.get_reg_stack_name(self.index)
+
+ @property
+ def info(self):
+ return self.arch.reg_stacks[self.name]
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.info == other.info
+
+
class ILFlag(object):
def __init__(self, arch, flag):
self.arch = arch
@@ -87,6 +108,15 @@ class SSARegister(object):
return "<ssa %s version %d>" % (repr(self.reg), self.version)
+class SSARegisterStack(object):
+ def __init__(self, reg_stack, version):
+ self.reg_stack = reg_stack
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.reg_stack), self.version)
+
+
class SSAFlag(object):
def __init__(self, flag, version):
self.flag = flag
@@ -118,15 +148,20 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_NOP: [],
LowLevelILOperation.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_STACK_REL: [("stack", "reg_stack"), ("dest", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_PUSH: [("stack", "reg_stack"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_FLAG: [("dest", "flag"), ("src", "expr")],
LowLevelILOperation.LLIL_LOAD: [("src", "expr")],
LowLevelILOperation.LLIL_STORE: [("dest", "expr"), ("src", "expr")],
LowLevelILOperation.LLIL_PUSH: [("src", "expr")],
LowLevelILOperation.LLIL_POP: [],
LowLevelILOperation.LLIL_REG: [("src", "reg")],
- LowLevelILOperation.LLIL_REG_SPLIT: [("hi", "reg", "lo", "reg")],
+ LowLevelILOperation.LLIL_REG_SPLIT: [("hi", "reg"), ("lo", "reg")],
+ LowLevelILOperation.LLIL_REG_STACK_REL: [("stack", "reg_stack"), ("src", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_POP: [("stack", "reg_stack")],
LowLevelILOperation.LLIL_CONST: [("constant", "int")],
LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")],
+ LowLevelILOperation.LLIL_FLOAT_CONST: [("constant", "float")],
LowLevelILOperation.LLIL_FLAG: [("src", "flag")],
LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")],
LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")],
@@ -207,10 +242,15 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg_ssa"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_STACK_REL_SSA: [("stack", "expr"), ("dest", "expr"), ("top", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_STACK_ABS_SSA: [("stack", "expr"), ("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_STACK_DEST_SSA: [("src", "reg_stack_ssa_dest_and_src")],
LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")],
LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "reg")],
LowLevelILOperation.LLIL_REG_SPLIT_SSA: [("hi", "reg_ssa"), ("lo", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_STACK_REL_SSA: [("stack", "reg_stack_ssa"), ("src", "expr"), ("top", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_ABS_SSA: [("stack", "reg_stack_ssa"), ("src", "reg")],
LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag_ssa"), ("src", "expr")],
LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag_ssa")],
LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag_ssa"), ("bit", "int")],
@@ -222,6 +262,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_REG_STACK_PHI: [("dest", "reg_stack_ssa"), ("src", "reg_stack_ssa_list")],
LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")],
LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
}
@@ -248,14 +289,35 @@ class LowLevelILInstruction(object):
name, operand_type = operand
if operand_type == "int":
value = instr.operands[i]
+ 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 = LowLevelILInstruction(func, instr.operands[i])
elif operand_type == "reg":
value = ILRegister(func.arch, instr.operands[i])
+ elif operand_type == "reg_stack":
+ value = ILRegisterStack(func.arch, instr.operands[i])
elif operand_type == "reg_ssa":
reg = ILRegister(func.arch, instr.operands[i])
i += 1
value = SSARegister(reg, instr.operands[i])
+ elif operand_type == "reg_stack_ssa":
+ reg_stack = ILRegisterStack(func.arch, instr.operands[i])
+ i += 1
+ value = SSARegisterStack(reg_stack, instr.operands[i])
+ elif operand_type == "reg_stack_ssa_dest_and_src":
+ reg_stack = ILRegisterStack(func.arch, instr.operands[i])
+ i += 1
+ value = SSARegisterStack(reg_stack, instr.operands[i])
+ i += 1
+ self.operands.append(value)
+ self.dest = value
+ value = SSARegisterStack(reg_stack, instr.operands[i])
elif operand_type == "flag":
value = ILFlag(func.arch, instr.operands[i])
elif operand_type == "flag_ssa":
@@ -282,6 +344,16 @@ class LowLevelILInstruction(object):
reg_version = operand_list[(i * 2) + 1]
value.append(SSARegister(ILRegister(func.arch, reg), reg_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_stack_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for i in xrange(count.value / 2):
+ reg_stack = operand_list[i * 2]
+ reg_version = operand_list[(i * 2) + 1]
+ value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), reg_version))
+ core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "flag_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
@@ -729,6 +801,38 @@ class LowLevelILFunction(object):
lo = self.arch.get_reg_index(lo)
return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags)
+ def set_reg_stack_top_relative(self, size, reg_stack, entry, value, flags = 0):
+ """
+ ``set_reg_stack_top_relative`` sets the top-relative entry ``entry`` of size ``size`` in register
+ stack ``reg_stack`` to the expression ``value``
+
+ :param int size: size of the register parameter in bytes
+ :param str reg_stack: the register stack name
+ :param LowLevelILExpr entry: an expression for which stack entry to set
+ :param LowLevelILExpr value: an expression to set the entry to
+ :param str flags: which flags are set by this operation
+ :return: The expression ``reg_stack[entry] = value``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_SET_REG_STACK_REL, reg_stack, entry.index, value.index,
+ size = size, flags = flags)
+
+ def reg_stack_push(self, size, reg_stack, value, flags = 0):
+ """
+ ``reg_stack_push`` pushes the expression ``value`` of size ``size`` onto the top of the register
+ stack ``reg_stack``
+
+ :param int size: size of the register parameter in bytes
+ :param str reg_stack: the register stack name
+ :param LowLevelILExpr value: an expression to push
+ :param str flags: which flags are set by this operation
+ :return: The expression ``reg_stack.push(value)``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_PUSH, reg_stack, value.index, size = size, flags = flags)
+
def set_flag(self, flag, value):
"""
``set_flag`` sets the flag ``flag`` to the LowLevelILExpr ``value``
@@ -811,6 +915,33 @@ class LowLevelILFunction(object):
lo = self.arch.get_reg_index(lo)
return self.expr(LowLevelILOperation.LLIL_REG_SPLIT, hi, lo, size=size)
+ def reg_stack_top_relative(self, size, reg_stack, entry):
+ """
+ ``reg_stack_top_relative`` returns a register stack entry of size ``size`` at top-relative
+ location ``entry`` in register stack with name ``reg_stack``
+
+ :param int size: the size of the register in bytes
+ :param str reg_stack: the name of the register stack
+ :param LowLevelILExpr entry: an expression for which stack entry to fetch
+ :return: The expression ``reg_stack[entry]``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_REL, reg_stack, entry.index, size=size)
+
+ def reg_stack_pop(self, size, reg_stack):
+ """
+ ``reg_stack_pop`` returns the top entry of size ``size`` in register stack with name ``reg_stack``, and
+ removes the entry from the stack
+
+ :param int size: the size of the register in bytes
+ :param str reg_stack: the name of the register stack
+ :return: The expression ``reg_stack.pop``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_POP, reg_stack, size=size)
+
def const(self, size, value):
"""
``const`` returns an expression for the constant integer ``value`` with size ``size``
@@ -833,6 +964,38 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size)
+ def float_const_raw(self, size, value):
+ """
+ ``float_const_raw`` returns an expression for the constant raw binary floating point
+ value ``value`` with size ``size``
+
+ :param int size: the size of the constant in bytes
+ :param int value: integer value for the raw binary representation of the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, value, size=size)
+
+ def float_const_single(self, value):
+ """
+ ``float_const_single`` returns an expression for the single precision floating point value ``value``
+
+ :param float value: float value for the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("I", struct.pack("f", value))[0], size=4)
+
+ def float_const_double(self, value):
+ """
+ ``float_const_double`` returns an expression for the double precision floating point value ``value``
+
+ :param float value: float value for the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("Q", struct.pack("d", value))[0], size=8)
+
def flag(self, reg):
"""
``flag`` returns a flag expression for the given flag name.
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 05b558d2..144c7e0b 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -27,6 +27,7 @@ import function
import basicblock
import lowlevelil
import types
+import struct
class SSAVariable(object):
@@ -90,6 +91,7 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")],
MediumLevelILOperation.MLIL_CONST: [("constant", "int")],
MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")],
+ MediumLevelILOperation.MLIL_FLOAT_CONST: [("constant", "float")],
MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")],
MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
@@ -211,6 +213,13 @@ class MediumLevelILInstruction(object):
name, operand_type = operand
if operand_type == "int":
value = instr.operands[i]
+ 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 = MediumLevelILInstruction(func, instr.operands[i])
elif operand_type == "var":