diff options
| -rw-r--r-- | architecture.cpp | 90 | ||||
| -rw-r--r-- | binaryninjaapi.h | 38 | ||||
| -rw-r--r-- | binaryninjacore.h | 28 | ||||
| -rw-r--r-- | callingconvention.cpp | 10 | ||||
| -rw-r--r-- | lowlevelil.cpp | 14 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 394 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 149 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 33 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 1 | ||||
| -rw-r--r-- | python/architecture.py | 101 | ||||
| -rw-r--r-- | python/callingconvention.py | 4 | ||||
| -rw-r--r-- | python/function.py | 59 | ||||
| -rw-r--r-- | python/lowlevelil.py | 165 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 9 |
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": |
