summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-11-27 17:15:03 -0500
committerRusty Wagner <rusty@vector35.com>2017-11-27 17:15:03 -0500
commitc24b1bd108ee2885d7164cecd15f75aa1715a8df (patch)
tree29dd59ac7c2ad4d7d77d36c89dd5f26ab270ea6e
parentd5db0ddb807265b295bb6b4ff07613776945c92b (diff)
Register stack adjustments in calling conventions
-rw-r--r--binaryninjaapi.h21
-rw-r--r--binaryninjacore.h29
-rw-r--r--callingconvention.cpp44
-rw-r--r--function.cpp48
-rw-r--r--lowlevelilinstruction.cpp172
-rw-r--r--lowlevelilinstruction.h57
-rw-r--r--python/architecture.py2
-rw-r--r--python/callingconvention.py85
-rw-r--r--python/function.py67
-rw-r--r--python/lowlevelil.py24
-rw-r--r--python/types.py15
11 files changed, 512 insertions, 52 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 5c122966..af067ae9 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2208,6 +2208,7 @@ namespace BinaryNinja
Confidence<std::vector<Variable>> GetParameterVariables() const;
Confidence<bool> HasVariableArguments() const;
Confidence<size_t> GetStackAdjustment() const;
+ std::map<uint32_t, Confidence<int32_t>> GetRegisterStackAdjustments() const;
Confidence<std::set<uint32_t>> GetClobberedRegisters() const;
void SetAutoType(Type* type);
@@ -2217,6 +2218,7 @@ namespace BinaryNinja
void SetAutoHasVariableArguments(const Confidence<bool>& varArgs);
void SetAutoCanReturn(const Confidence<bool>& returns);
void SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust);
+ void SetAutoRegisterStackAdjustments(const std::map<uint32_t, Confidence<int32_t>>& regStackAdjust);
void SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered);
void SetUserType(Type* type);
@@ -2226,6 +2228,7 @@ namespace BinaryNinja
void SetHasVariableArguments(const Confidence<bool>& varArgs);
void SetCanReturn(const Confidence<bool>& returns);
void SetStackAdjustment(const Confidence<size_t>& stackAdjust);
+ void SetRegisterStackAdjustments(const std::map<uint32_t, Confidence<int32_t>>& regStackAdjust);
void SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered);
void ApplyImportedTypes(Symbol* sym);
@@ -2558,11 +2561,12 @@ namespace BinaryNinja
ExprId JumpTo(ExprId dest, const std::vector<BNLowLevelILLabel*>& targets,
const ILSourceLocation& loc = ILSourceLocation());
ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation());
- ExprId CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc = ILSourceLocation());
- ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<SSARegister>& params,
+ ExprId CallStackAdjust(ExprId dest, size_t adjust, const std::map<uint32_t, int32_t>& regStackAdjust,
+ const ILSourceLocation& loc = ILSourceLocation());
+ ExprId CallSSA(const std::vector<SSARegister>& output, ExprId dest, const std::vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer,
const ILSourceLocation& loc = ILSourceLocation());
- ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<SSARegister>& params,
+ ExprId SystemCallSSA(const std::vector<SSARegister>& output, const std::vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer,
const ILSourceLocation& loc = ILSourceLocation());
ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation());
@@ -3184,6 +3188,11 @@ namespace BinaryNinja
static void GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result);
static void GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result);
+ static void GetIncomingVariableForParameterVariableCallback(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result);
+ static void GetParameterVariableForIncomingVariableCallback(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result);
+
public:
Ref<Architecture> GetArchitecture() const;
std::string GetName() const;
@@ -3204,6 +3213,9 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters();
virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func);
virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func);
+
+ virtual Variable GetIncomingVariableForParameterVariable(const Variable& var, Function* func);
+ virtual Variable GetParameterVariableForIncomingVariable(const Variable& var, Function* func);
};
class CoreCallingConvention: public CallingConvention
@@ -3227,6 +3239,9 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters() override;
virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override;
virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func) override;
+
+ virtual Variable GetIncomingVariableForParameterVariable(const Variable& var, Function* func) override;
+ virtual Variable GetParameterVariableForIncomingVariable(const Variable& var, Function* func) override;
};
/*!
diff --git a/binaryninjacore.h b/binaryninjacore.h
index c32d42e3..278299bc 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -1341,6 +1341,11 @@ extern "C"
uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count);
void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result);
void (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func, BNRegisterValue* result);
+
+ void (*getIncomingVariableForParameterVariable)(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result);
+ void (*getParameterVariableForIncomingVariable)(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result);
};
struct BNVariableNameAndType
@@ -1658,6 +1663,13 @@ extern "C"
ArrayDataType
};
+ struct BNRegisterStackAdjustment
+ {
+ uint32_t regStack;
+ int32_t adjustment;
+ uint8_t confidence;
+ };
+
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
BINARYNINJACOREAPI void BNFreeString(char* str);
BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size);
@@ -2173,6 +2185,8 @@ extern "C"
BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars);
BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func);
BINARYNINJACOREAPI BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func);
+ BINARYNINJACOREAPI BNRegisterStackAdjustment* BNGetFunctionRegisterStackAdjustments(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI void BNFreeRegisterStackAdjustments(BNRegisterStackAdjustment* adjustments);
BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func);
BINARYNINJACOREAPI void BNFreeClobberedRegisters(BNRegisterSetWithConfidence* regs);
@@ -2182,6 +2196,8 @@ extern "C"
BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs);
BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns);
BINARYNINJACOREAPI void BNSetAutoFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust);
+ BINARYNINJACOREAPI void BNSetAutoFunctionRegisterStackAdjustments(BNFunction* func,
+ BNRegisterStackAdjustment* adjustments, size_t count);
BINARYNINJACOREAPI void BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs);
BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type);
@@ -2190,6 +2206,8 @@ extern "C"
BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs);
BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns);
BINARYNINJACOREAPI void BNSetUserFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust);
+ BINARYNINJACOREAPI void BNSetUserFunctionRegisterStackAdjustments(BNFunction* func,
+ BNRegisterStackAdjustment* adjustments, size_t count);
BINARYNINJACOREAPI void BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs);
BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym);
@@ -2241,7 +2259,7 @@ extern "C"
BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings);
BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count);
- BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count);
+ BINARYNINJACOREAPI void BNFreeVariableNameAndTypeList(BNVariableNameAndType* vars, size_t count);
BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset,
BNTypeWithConfidence* type, const char* name);
BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset,
@@ -2917,6 +2935,15 @@ extern "C"
BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func);
BINARYNINJACOREAPI BNRegisterValue BNGetIncomingFlagValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func);
+ BINARYNINJACOREAPI BNVariable BNGetIncomingVariableForParameterVariable(BNCallingConvention* cc,
+ const BNVariable* var, BNFunction* func);
+ BINARYNINJACOREAPI BNVariable BNGetParameterVariableForIncomingVariable(BNCallingConvention* cc,
+ const BNVariable* var, BNFunction* func);
+ BINARYNINJACOREAPI BNVariable BNGetDefaultIncomingVariableForParameterVariable(BNCallingConvention* cc,
+ const BNVariable* var);
+ BINARYNINJACOREAPI BNVariable BNGetDefaultParameterVariableForIncomingVariable(BNCallingConvention* cc,
+ const BNVariable* var);
+
BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureDefaultCallingConvention(BNArchitecture* arch);
BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureCdeclCallingConvention(BNArchitecture* arch);
BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureStdcallCallingConvention(BNArchitecture* arch);
diff --git a/callingconvention.cpp b/callingconvention.cpp
index b29d51e2..2eb57567 100644
--- a/callingconvention.cpp
+++ b/callingconvention.cpp
@@ -49,6 +49,8 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback;
cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback;
cc.getIncomingFlagValue = GetIncomingFlagValueCallback;
+ cc.getIncomingVariableForParameterVariable = GetIncomingVariableForParameterVariableCallback;
+ cc.getParameterVariableForIncomingVariable = GetParameterVariableForIncomingVariableCallback;
AddRefForRegistration();
m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc);
@@ -189,6 +191,24 @@ void CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, B
}
+void CallingConvention::GetIncomingVariableForParameterVariableCallback(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ *result = cc->GetIncomingVariableForParameterVariable(*var,
+ func ? new Function(BNNewFunctionReference(func)) : nullptr);
+}
+
+
+void CallingConvention::GetParameterVariableForIncomingVariableCallback(void* ctxt, const BNVariable* var,
+ BNFunction* func, BNVariable* result)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ *result = cc->GetParameterVariableForIncomingVariable(*var,
+ func ? new Function(BNNewFunctionReference(func)) : nullptr);
+}
+
+
Ref<Architecture> CallingConvention::GetArchitecture() const
{
return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object));
@@ -284,6 +304,18 @@ RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*)
}
+Variable CallingConvention::GetIncomingVariableForParameterVariable(const Variable& var, Function*)
+{
+ return BNGetDefaultIncomingVariableForParameterVariable(m_object, &var);
+}
+
+
+Variable CallingConvention::GetParameterVariableForIncomingVariable(const Variable& var, Function*)
+{
+ return BNGetDefaultParameterVariableForIncomingVariable(m_object, &var);
+}
+
+
CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc)
{
}
@@ -385,3 +417,15 @@ RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Functio
{
return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr));
}
+
+
+Variable CoreCallingConvention::GetIncomingVariableForParameterVariable(const Variable& var, Function* func)
+{
+ return BNGetIncomingVariableForParameterVariable(m_object, &var, func ? func->GetObject() : nullptr);
+}
+
+
+Variable CoreCallingConvention::GetParameterVariableForIncomingVariable(const Variable& var, Function* func)
+{
+ return BNGetParameterVariableForIncomingVariable(m_object, &var, func ? func->GetObject() : nullptr);
+}
diff --git a/function.cpp b/function.cpp
index 2d8db04c..879c7156 100644
--- a/function.cpp
+++ b/function.cpp
@@ -530,6 +530,18 @@ Confidence<size_t> Function::GetStackAdjustment() const
}
+map<uint32_t, Confidence<int32_t>> Function::GetRegisterStackAdjustments() const
+{
+ size_t count;
+ BNRegisterStackAdjustment* regStackAdjust = BNGetFunctionRegisterStackAdjustments(m_object, &count);
+ map<uint32_t, Confidence<int32_t>> result;
+ for (size_t i = 0; i < count; i++)
+ result[regStackAdjust[i].regStack] = Confidence<int32_t>(regStackAdjust[i].adjustment, regStackAdjust[i].confidence);
+ BNFreeRegisterStackAdjustments(regStackAdjust);
+ return result;
+}
+
+
Confidence<set<uint32_t>> Function::GetClobberedRegisters() const
{
BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object);
@@ -611,6 +623,22 @@ void Function::SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust)
}
+void Function::SetAutoRegisterStackAdjustments(const map<uint32_t, Confidence<int32_t>>& regStackAdjust)
+{
+ BNRegisterStackAdjustment* adjust = new BNRegisterStackAdjustment[regStackAdjust.size()];
+ size_t i = 0;
+ for (auto& j : regStackAdjust)
+ {
+ adjust[i].regStack = j.first;
+ adjust[i].adjustment = j.second.GetValue();
+ adjust[i].confidence = j.second.GetConfidence();
+ i++;
+ }
+ BNSetAutoFunctionRegisterStackAdjustments(m_object, adjust, regStackAdjust.size());
+ delete[] adjust;
+}
+
+
void Function::SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered)
{
BNRegisterSetWithConfidence regs;
@@ -694,6 +722,22 @@ void Function::SetStackAdjustment(const Confidence<size_t>& stackAdjust)
}
+void Function::SetRegisterStackAdjustments(const map<uint32_t, Confidence<int32_t>>& regStackAdjust)
+{
+ BNRegisterStackAdjustment* adjust = new BNRegisterStackAdjustment[regStackAdjust.size()];
+ size_t i = 0;
+ for (auto& j : regStackAdjust)
+ {
+ adjust[i].regStack = j.first;
+ adjust[i].adjustment = j.second.GetValue();
+ adjust[i].confidence = j.second.GetConfidence();
+ i++;
+ }
+ BNSetUserFunctionRegisterStackAdjustments(m_object, adjust, regStackAdjust.size());
+ delete[] adjust;
+}
+
+
void Function::SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered)
{
BNRegisterSetWithConfidence regs;
@@ -743,7 +787,7 @@ map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout()
result[vars[i].var.storage].push_back(var);
}
- BNFreeVariableList(vars, count);
+ BNFreeVariableNameAndTypeList(vars, count);
return result;
}
@@ -811,7 +855,7 @@ map<Variable, VariableNameAndType> Function::GetVariables()
result[vars[i].var] = var;
}
- BNFreeVariableList(vars, count);
+ BNFreeVariableNameAndTypeList(vars, count);
return result;
}
diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp
index 91af36b1..8259426a 100644
--- a/lowlevelilinstruction.cpp
+++ b/lowlevelilinstruction.cpp
@@ -74,12 +74,13 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType>
{FlagConditionLowLevelOperandUsage, FlagConditionLowLevelOperand},
{OutputSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
{OutputMemoryVersionLowLevelOperandUsage, IndexLowLevelOperand},
- {ParameterSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
+ {ParameterExprsLowLevelOperandUsage, ExprListLowLevelOperand},
{SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand},
{SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand},
{SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand},
{SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand},
- {TargetListLowLevelOperandUsage, IndexListLowLevelOperand}
+ {TargetListLowLevelOperandUsage, IndexListLowLevelOperand},
+ {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand}
};
@@ -133,7 +134,8 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{LLIL_JUMP, {DestExprLowLevelOperandUsage}},
{LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}},
{LLIL_CALL, {DestExprLowLevelOperandUsage}},
- {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage}},
+ {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage,
+ RegisterStackAdjustmentsLowLevelOperandUsage}},
{LLIL_RET, {DestExprLowLevelOperandUsage}},
{LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage,
FalseTargetLowLevelOperandUsage}},
@@ -142,10 +144,10 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>>
{LLIL_TRAP, {VectorLowLevelOperandUsage}},
{LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage,
DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage,
- StackMemoryVersionLowLevelOperandUsage, ParameterSSARegistersLowLevelOperandUsage}},
+ StackMemoryVersionLowLevelOperandUsage, ParameterExprsLowLevelOperandUsage}},
{LLIL_SYSCALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage,
StackSSARegisterLowLevelOperandUsage, StackMemoryVersionLowLevelOperandUsage,
- ParameterSSARegistersLowLevelOperandUsage}},
+ ParameterExprsLowLevelOperandUsage}},
{LLIL_REG_PHI, {DestSSARegisterLowLevelOperandUsage, SourceSSARegistersLowLevelOperandUsage}},
{LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}},
{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}},
@@ -239,7 +241,7 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage
// Represented as subexpression, so only takes one slot even though it is an SSA register
operand++;
break;
- case ParameterSSARegistersLowLevelOperandUsage:
+ case ParameterExprsLowLevelOperandUsage:
// Represented as subexpression, so only takes one slot even though it is a list
operand++;
break;
@@ -262,6 +264,7 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage
case SSARegisterListLowLevelOperand:
case SSARegisterStackListLowLevelOperand:
case SSAFlagListLowLevelOperand:
+ case RegisterStackAdjustmentsLowLevelOperand:
// SSA registers/flags and lists take two operand slots
operand += 2;
break;
@@ -580,6 +583,64 @@ LowLevelILIndexList::operator vector<size_t>() const
}
+const LowLevelILInstruction LowLevelILInstructionList::ListIterator::operator*()
+{
+ return LowLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos),
+ (size_t)*pos, instructionIndex);
+}
+
+
+LowLevelILInstructionList::LowLevelILInstructionList(LowLevelILFunction* func,
+ const BNLowLevelILInstruction& instr, size_t count, size_t instrIndex):
+ m_list(func, instr, count), m_instructionIndex(instrIndex)
+{
+}
+
+
+LowLevelILInstructionList::const_iterator LowLevelILInstructionList::begin() const
+{
+ const_iterator result;
+ result.pos = m_list.begin();
+ result.instructionIndex = m_instructionIndex;
+ return result;
+}
+
+
+LowLevelILInstructionList::const_iterator LowLevelILInstructionList::end() const
+{
+ const_iterator result;
+ result.pos = m_list.end();
+ result.instructionIndex = m_instructionIndex;
+ return result;
+}
+
+
+size_t LowLevelILInstructionList::size() const
+{
+ return m_list.size();
+}
+
+
+const LowLevelILInstruction LowLevelILInstructionList::operator[](size_t i) const
+{
+ if (i >= size())
+ throw LowLevelILInstructionAccessException();
+ auto iter = begin();
+ for (size_t j = 0; j < i; j++)
+ ++iter;
+ return *iter;
+}
+
+
+LowLevelILInstructionList::operator vector<LowLevelILInstruction>() const
+{
+ vector<LowLevelILInstruction> result;
+ for (auto i : *this)
+ result.push_back(i);
+ return result;
+}
+
+
const SSARegister LowLevelILSSARegisterList::ListIterator::operator*()
{
LowLevelILIntegerList::const_iterator cur = pos;
@@ -864,14 +925,20 @@ LowLevelILIndexList LowLevelILOperand::GetIndexList() const
}
+LowLevelILInstructionList LowLevelILOperand::GetExprList() const
+{
+ if (m_type != ExprListLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsExprList(0);
+}
+
+
LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const
{
if (m_type != SSARegisterListLowLevelOperand)
throw LowLevelILInstructionAccessException();
if (m_usage == OutputSSARegistersLowLevelOperandUsage)
return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(1);
- if (m_usage == ParameterSSARegistersLowLevelOperandUsage)
- return m_instr.GetRawOperandAsExpr(m_operandIndex).GetRawOperandAsSSARegisterList(0);
return m_instr.GetRawOperandAsSSARegisterList(m_operandIndex);
}
@@ -892,6 +959,14 @@ LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const
}
+map<uint32_t, int32_t> LowLevelILOperand::GetRegisterStackAdjustments() const
+{
+ if (m_type != RegisterStackAdjustmentsLowLevelOperand)
+ throw LowLevelILInstructionAccessException();
+ return m_instr.GetRawOperandAsRegisterStackAdjustments(m_operandIndex);
+}
+
+
const LowLevelILOperand LowLevelILOperandList::ListIterator::operator*()
{
LowLevelILOperandUsage usage = *pos;
@@ -1073,6 +1148,13 @@ LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t o
}
+LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const
+{
+ return LowLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand],
+ instructionIndex);
+}
+
+
LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const
{
return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
@@ -1091,6 +1173,24 @@ LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size
}
+map<uint32_t, int32_t> LowLevelILInstructionBase::GetRawOperandAsRegisterStackAdjustments(size_t operand) const
+{
+ LowLevelILIntegerList list(function, function->GetRawExpr(operands[operand + 1]), operands[operand]);
+ map<uint32_t, int32_t> result;
+ for (auto i = list.begin(); i != list.end(); )
+ {
+ uint32_t regStack = (uint32_t)*i;
+ ++i;
+ if (i == list.end())
+ break;
+ int32_t adjust = (int32_t)*i;
+ ++i;
+ result[regStack] = adjust;
+ }
+ return result;
+}
+
+
void LowLevelILInstructionBase::UpdateRawOperand(size_t operandIndex, ExprId value)
{
operands[operandIndex] = value;
@@ -1385,6 +1485,12 @@ void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelIL
break;
case LLIL_CALL_SSA:
GetDestExpr<LLIL_CALL_SSA>().VisitExprs(func);
+ for (auto& i : GetParameterExprs<LLIL_CALL_SSA>())
+ i.VisitExprs(func);
+ break;
+ case LLIL_SYSCALL_SSA:
+ for (auto& i : GetParameterExprs<LLIL_CALL_SSA>())
+ i.VisitExprs(func);
break;
case LLIL_RET:
GetDestExpr<LLIL_RET>().VisitExprs(func);
@@ -1478,6 +1584,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const
{
vector<BNLowLevelILLabel*> labelList;
+ vector<ExprId> params;
BNLowLevelILLabel* labelA;
BNLowLevelILLabel* labelB;
switch (operation)
@@ -1576,7 +1683,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
return dest->Call(subExprHandler(GetDestExpr<LLIL_CALL>()), *this);
case LLIL_CALL_STACK_ADJUST:
return dest->CallStackAdjust(subExprHandler(GetDestExpr<LLIL_CALL_STACK_ADJUST>()),
- GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), *this);
+ GetStackAdjustment<LLIL_CALL_STACK_ADJUST>(), GetRegisterStackAdjustments<LLIL_CALL_STACK_ADJUST>(), *this);
case LLIL_RET:
return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this);
case LLIL_JUMP_TO:
@@ -1607,13 +1714,17 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest,
case LLIL_TRAP:
return dest->Trap(GetVector<LLIL_TRAP>(), *this);
case LLIL_CALL_SSA:
+ for (auto& i : GetParameterExprs<LLIL_CALL_SSA>())
+ params.push_back(subExprHandler(i));
return dest->CallSSA(GetOutputSSARegisters<LLIL_CALL_SSA>(), subExprHandler(GetDestExpr<LLIL_CALL_SSA>()),
- GetParameterSSARegisters<LLIL_CALL_SSA>(), GetStackSSARegister<LLIL_CALL_SSA>(),
- GetDestMemoryVersion<LLIL_CALL_SSA>(), GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this);
+ params, GetStackSSARegister<LLIL_CALL_SSA>(), GetDestMemoryVersion<LLIL_CALL_SSA>(),
+ GetSourceMemoryVersion<LLIL_CALL_SSA>(), *this);
case LLIL_SYSCALL_SSA:
+ for (auto& i : GetParameterExprs<LLIL_SYSCALL_SSA>())
+ params.push_back(subExprHandler(i));
return dest->SystemCallSSA(GetOutputSSARegisters<LLIL_SYSCALL_SSA>(),
- GetParameterSSARegisters<LLIL_SYSCALL_SSA>(), GetStackSSARegister<LLIL_SYSCALL_SSA>(),
- GetDestMemoryVersion<LLIL_SYSCALL_SSA>(), GetSourceMemoryVersion<LLIL_SYSCALL_SSA>(), *this);
+ params, GetStackSSARegister<LLIL_SYSCALL_SSA>(), 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:
@@ -2055,11 +2166,11 @@ LowLevelILSSARegisterList LowLevelILInstruction::GetOutputSSARegisters() const
}
-LowLevelILSSARegisterList LowLevelILInstruction::GetParameterSSARegisters() const
+LowLevelILInstructionList LowLevelILInstruction::GetParameterExprs() const
{
size_t operandIndex;
- if (GetOperandIndexForUsage(ParameterSSARegistersLowLevelOperandUsage, operandIndex))
- return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSARegisterList(0);
+ if (GetOperandIndexForUsage(ParameterExprsLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsExpr(operandIndex).GetRawOperandAsExprList(0);
throw LowLevelILInstructionAccessException();
}
@@ -2109,6 +2220,15 @@ LowLevelILIndexList LowLevelILInstruction::GetTargetList() const
}
+map<uint32_t, int32_t> LowLevelILInstruction::GetRegisterStackAdjustments() const
+{
+ size_t operandIndex;
+ if (GetOperandIndexForUsage(RegisterStackAdjustmentsLowLevelOperandUsage, operandIndex))
+ return GetRawOperandAsRegisterStackAdjustments(operandIndex);
+ throw LowLevelILInstructionAccessException();
+}
+
+
ExprId LowLevelILFunction::Nop(const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_NOP, loc, 0, 0);
@@ -2578,13 +2698,21 @@ ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc)
}
-ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, const ILSourceLocation& loc)
+ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust,
+ const std::map<uint32_t, int32_t>& regStackAdjust, const ILSourceLocation& loc)
{
- return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust);
+ vector<size_t> list;
+ for (auto& i : regStackAdjust)
+ {
+ list.push_back(i.first);
+ list.push_back(i.second);
+ }
+ return AddExprWithLocation(LLIL_CALL_STACK_ADJUST, loc, 0, 0, dest, adjust, list.size(),
+ AddIndexList(list));
}
-ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<SSARegister>& params,
+ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId dest, const vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_CALL_SSA, loc, 0, 0,
@@ -2592,11 +2720,11 @@ ExprId LowLevelILFunction::CallSSA(const vector<SSARegister>& output, ExprId des
output.size() * 2, AddSSARegisterList(output)), dest,
AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer),
AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0,
- params.size() * 2, AddSSARegisterList(params)));
+ params.size(), AddOperandList(params)));
}
-ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<SSARegister>& params,
+ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, const vector<ExprId>& params,
const SSARegister& stack, size_t newMemoryVer, size_t prevMemoryVer, const ILSourceLocation& loc)
{
return AddExprWithLocation(LLIL_SYSCALL_SSA, loc, 0, 0,
@@ -2604,7 +2732,7 @@ ExprId LowLevelILFunction::SystemCallSSA(const vector<SSARegister>& output, cons
output.size() * 2, AddSSARegisterList(output)),
AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer),
AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0,
- params.size() * 2, AddSSARegisterList(params)));
+ params.size(), AddOperandList(params)));
}
diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h
index 4e02632e..cfc7e2d7 100644
--- a/lowlevelilinstruction.h
+++ b/lowlevelilinstruction.h
@@ -112,9 +112,11 @@ namespace BinaryNinja
SSARegisterStackLowLevelOperand,
SSAFlagLowLevelOperand,
IndexListLowLevelOperand,
+ ExprListLowLevelOperand,
SSARegisterListLowLevelOperand,
SSARegisterStackListLowLevelOperand,
- SSAFlagListLowLevelOperand
+ SSAFlagListLowLevelOperand,
+ RegisterStackAdjustmentsLowLevelOperand
};
enum LowLevelILOperandUsage
@@ -158,12 +160,13 @@ namespace BinaryNinja
FlagConditionLowLevelOperandUsage,
OutputSSARegistersLowLevelOperandUsage,
OutputMemoryVersionLowLevelOperandUsage,
- ParameterSSARegistersLowLevelOperandUsage,
+ ParameterExprsLowLevelOperandUsage,
SourceSSARegistersLowLevelOperandUsage,
SourceSSARegisterStacksLowLevelOperandUsage,
SourceSSAFlagsLowLevelOperandUsage,
SourceMemoryVersionsLowLevelOperandUsage,
- TargetListLowLevelOperandUsage
+ TargetListLowLevelOperandUsage,
+ RegisterStackAdjustmentsLowLevelOperandUsage
};
}
@@ -328,6 +331,36 @@ namespace BinaryNinja
operator std::vector<size_t>() const;
};
+ class LowLevelILInstructionList
+ {
+ struct ListIterator
+ {
+ LowLevelILIntegerList::const_iterator pos;
+ size_t instructionIndex;
+ bool operator==(const ListIterator& a) const { return pos == a.pos; }
+ bool operator!=(const ListIterator& a) const { return pos != a.pos; }
+ bool operator<(const ListIterator& a) const { return pos < a.pos; }
+ ListIterator& operator++() { ++pos; return *this; }
+ const LowLevelILInstruction operator*();
+ };
+
+ LowLevelILIntegerList m_list;
+ size_t m_instructionIndex;
+
+ public:
+ typedef ListIterator const_iterator;
+
+ LowLevelILInstructionList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr,
+ size_t count, size_t instrIndex);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+ size_t size() const;
+ const LowLevelILInstruction operator[](size_t i) const;
+
+ operator std::vector<LowLevelILInstruction>() const;
+ };
+
class LowLevelILSSARegisterList
{
struct ListIterator
@@ -436,9 +469,11 @@ namespace BinaryNinja
SSARegisterStack GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const;
SSAFlag GetRawOperandAsSSAFlag(size_t operand) const;
LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const;
+ LowLevelILInstructionList GetRawOperandAsExprList(size_t operand) const;
LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const;
LowLevelILSSARegisterStackList GetRawOperandAsSSARegisterStackList(size_t operand) const;
LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const;
+ std::map<uint32_t, int32_t> GetRawOperandAsRegisterStackAdjustments(size_t operand) const;
void UpdateRawOperand(size_t operandIndex, ExprId value);
void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector<SSARegister>& regs);
@@ -574,12 +609,13 @@ namespace BinaryNinja
template <BNLowLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); }
template <BNLowLevelILOperation N> BNLowLevelILFlagCondition GetFlagCondition() const { return As<N>().GetFlagCondition(); }
template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetOutputSSARegisters() const { return As<N>().GetOutputSSARegisters(); }
- template <BNLowLevelILOperation N> LowLevelILSSARegisterList GetParameterSSARegisters() const { return As<N>().GetParameterSSARegisters(); }
+ template <BNLowLevelILOperation N> LowLevelILInstructionList GetParameterExprs() const { return As<N>().GetParameterExprs(); }
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(); }
+ template <BNLowLevelILOperation N> std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const { return As<N>().GetRegisterStackAdjustments(); }
template <BNLowLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); }
template <BNLowLevelILOperation N> void SetSourceSSAVersion(size_t version) { As<N>().SetSourceSSAVersion(version); }
@@ -590,7 +626,6 @@ namespace BinaryNinja
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); }
- template <BNLowLevelILOperation N> void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { As<N>().SetParameterSSARegisters(regs); }
bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const;
@@ -632,12 +667,13 @@ namespace BinaryNinja
size_t GetDestMemoryVersion() const;
BNLowLevelILFlagCondition GetFlagCondition() const;
LowLevelILSSARegisterList GetOutputSSARegisters() const;
- LowLevelILSSARegisterList GetParameterSSARegisters() const;
+ LowLevelILInstructionList GetParameterExprs() const;
LowLevelILSSARegisterList GetSourceSSARegisters() const;
LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const;
LowLevelILSSAFlagList GetSourceSSAFlags() const;
LowLevelILIndexList GetSourceMemoryVersions() const;
LowLevelILIndexList GetTargetList() const;
+ std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const;
};
class LowLevelILOperand
@@ -665,9 +701,11 @@ namespace BinaryNinja
SSARegisterStack GetSSARegisterStack() const;
SSAFlag GetSSAFlag() const;
LowLevelILIndexList GetIndexList() const;
+ LowLevelILInstructionList GetExprList() const;
LowLevelILSSARegisterList GetSSARegisterList() const;
LowLevelILSSARegisterStackList GetSSARegisterStackList() const;
LowLevelILSSAFlagList GetSSAFlagList() const;
+ std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const;
};
class LowLevelILOperandList
@@ -915,6 +953,7 @@ namespace BinaryNinja
{
LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); }
size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); }
+ std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const { return GetRawOperandAsRegisterStackAdjustments(2); }
};
template <> struct LowLevelILInstructionAccessor<LLIL_RET>: public LowLevelILInstructionBase
{
@@ -949,12 +988,11 @@ namespace BinaryNinja
LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(1); }
SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegister(0); }
size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(2).GetRawOperandAsIndex(2); }
- LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(3).GetRawOperandAsSSARegisterList(0); }
+ LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); }
void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); }
void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(2, version); }
void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(2).UpdateRawOperand(1, version); }
void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); }
- void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(3).UpdateRawOperandAsSSARegisterList(0, regs); }
};
template <> struct LowLevelILInstructionAccessor<LLIL_SYSCALL_SSA>: public LowLevelILInstructionBase
{
@@ -962,12 +1000,11 @@ namespace BinaryNinja
size_t GetDestMemoryVersion() const { return GetRawOperandAsExpr(0).GetRawOperandAsIndex(0); }
SSARegister GetStackSSARegister() const { return GetRawOperandAsExpr(1).GetRawOperandAsSSARegister(0); }
size_t GetSourceMemoryVersion() const { return GetRawOperandAsExpr(1).GetRawOperandAsIndex(2); }
- LowLevelILSSARegisterList GetParameterSSARegisters() const { return GetRawOperandAsExpr(2).GetRawOperandAsSSARegisterList(0); }
+ LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(2).GetRawOperandAsExprList(0); }
void SetDestMemoryVersion(size_t version) { GetRawOperandAsExpr(0).UpdateRawOperand(0, version); }
void SetSourceMemoryVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(2, version); }
void SetStackSSAVersion(size_t version) { GetRawOperandAsExpr(1).UpdateRawOperand(1, version); }
void SetOutputSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); }
- void SetParameterSSARegisters(const std::vector<SSARegister>& regs) { GetRawOperandAsExpr(2).UpdateRawOperandAsSSARegisterList(0, regs); }
};
template <> struct LowLevelILInstructionAccessor<LLIL_REG_PHI>: public LowLevelILInstructionBase
diff --git a/python/architecture.py b/python/architecture.py
index 04179e7f..c4179b00 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -231,7 +231,7 @@ class Architecture(object):
for j in xrange(0, info.topRelativeCount):
top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j))
top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg)
- self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top)
+ self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i])
core.BNFreeRegisterList(regs)
else:
startup._init_plugins()
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 18662fc5..5aad3317 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -28,6 +28,7 @@ import log
import types
import function
import binaryview
+from enums import VariableSourceType
class CallingConvention(object):
@@ -68,6 +69,8 @@ class CallingConvention(object):
self._cb.getImplicitlyDefinedRegisters = self._cb.getImplicitlyDefinedRegisters.__class__(self._get_implicitly_defined_regs)
self._cb.getIncomingRegisterValue = self._cb.getIncomingRegisterValue.__class__(self._get_incoming_reg_value)
self._cb.getIncomingFlagValue = self._cb.getIncomingFlagValue.__class__(self._get_incoming_flag_value)
+ self._cb.getIncomingVariableForParameterVariable = self._cb.getIncomingVariableForParameterVariable.__class__(self._get_incoming_var_for_parameter_var)
+ self._cb.getParameterVariableForIncomingVariable = self._cb.getParameterVariableForIncomingVariable.__class__(self._get_parameter_var_for_incoming_var)
self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb)
self.__class__._registered_calling_conventions.append(self)
else:
@@ -301,6 +304,42 @@ class CallingConvention(object):
result[0].state = api_obj.state
result[0].value = api_obj.value
+ def _get_incoming_var_for_parameter_var(self, ctxt, in_var, func, result):
+ try:
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ out_var = self.perform_get_incoming_var_for_parameter_var(in_var_obj, func_obj)
+ result[0].type = out_var.source_type
+ result[0].index = out_var.index
+ result[0].storage = out_var.storage
+ except:
+ log.log_error(traceback.format_exc())
+ result[0].type = in_var[0].type
+ result[0].index = in_var[0].index
+ result[0].storage = in_var[0].storage
+
+ def _get_parameter_var_for_incoming_var(self, ctxt, in_var, func, result):
+ try:
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ out_var = self.perform_get_parameter_var_for_incoming_var(in_var_obj, func_obj)
+ result[0].type = out_var.source_type
+ result[0].index = out_var.index
+ result[0].storage = out_var.storage
+ except:
+ log.log_error(traceback.format_exc())
+ result[0].type = in_var[0].type
+ result[0].index = in_var[0].index
+ result[0].storage = in_var[0].storage
+
def __repr__(self):
return "<calling convention: %s %s>" % (self.arch.name, self.name)
@@ -317,6 +356,25 @@ class CallingConvention(object):
def perform_get_incoming_flag_value(self, reg, func):
return function.RegisterValue()
+ def perform_get_incoming_var_for_parameter_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ out_var = core.BNGetDefaultIncomingVariableForParameterVariable(self.handle, in_buf)
+ name = None
+ if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
+ name = func.arch.get_reg_name(out_var.storage)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+
+ def perform_get_parameter_var_for_incoming_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_buf)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage)
+
def with_confidence(self, confidence):
return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle),
confidence = confidence)
@@ -334,3 +392,30 @@ class CallingConvention(object):
if func is not None:
func_handle = func.handle
return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle))
+
+ def get_incoming_var_for_parameter_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = func.handle
+ out_var = core.BNGetIncomingVariableForParameterVariable(self.handle, in_buf, func_obj)
+ name = None
+ if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
+ name = func.arch.get_reg_name(out_var.storage)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+
+ def get_parameter_var_for_incoming_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = func.handle
+ out_var = core.BNGetParameterVariableForIncomingVariable(self.handle, in_buf, func_obj)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage)
diff --git a/python/function.py b/python/function.py
index ba00147e..eabf86b3 100644
--- a/python/function.py
+++ b/python/function.py
@@ -263,14 +263,15 @@ class Variable(object):
var.storage = storage
self.identifier = core.BNToVariableIdentifier(var)
- if name is None:
- name = core.BNGetVariableName(func.handle, var)
- if var_type is None:
- var_type_conf = core.BNGetVariableType(func.handle, var)
- if var_type_conf.type:
- var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence)
- else:
- var_type = None
+ if func is not None:
+ if name is None:
+ name = core.BNGetVariableName(func.handle, var)
+ if var_type is None:
+ var_type_conf = core.BNGetVariableType(func.handle, var)
+ if var_type_conf.type:
+ var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence)
+ else:
+ var_type = None
self.name = name
self.type = var_type
@@ -519,7 +520,7 @@ class Function(object):
result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence)))
result.sort(key = lambda x: x.identifier)
- core.BNFreeVariableList(v, count.value)
+ core.BNFreeVariableNameAndTypeList(v, count.value)
return result
@property
@@ -532,7 +533,7 @@ class Function(object):
result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence)))
result.sort(key = lambda x: x.identifier)
- core.BNFreeVariableList(v, count.value)
+ core.BNFreeVariableNameAndTypeList(v, count.value)
return result
@property
@@ -675,6 +676,35 @@ class Function(object):
core.BNSetUserFunctionStackAdjustment(self.handle, sc)
@property
+ def reg_stack_adjustments(self):
+ """Number of entries removed from each register stack after return"""
+ count = ctypes.c_ulonglong()
+ adjust = core.BNGetFunctionRegisterStackAdjustments(self.handle, count)
+ result = {}
+ for i in xrange(0, count.value):
+ name = self.arch.get_reg_stack_name(adjust[i].regStack)
+ value = types.RegisterStackAdjustmentWithConfidence(adjust[i].adjustment,
+ confidence = adjust[i].confidence)
+ result[name] = value
+ core.BNFreeRegisterStackAdjustments(adjust)
+ return result
+
+ @reg_stack_adjustments.setter
+ def reg_stack_adjustments(self, value):
+ adjust = (core.BNRegisterStackAdjustment * len(value))()
+ i = 0
+ for reg_stack in value.keys():
+ adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack)
+ if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence):
+ adjust[i].adjustment = value[reg_stack].value
+ adjust[i].confidence = value[reg_stack].confidence
+ else:
+ adjust[i].adjustment = value[reg_stack]
+ adjust[i].confidence = types.max_confidence
+ i += 1
+ core.BNSetUserFunctionRegisterStackAdjustments(self.handle, adjust, len(value))
+
+ @property
def clobbered_regs(self):
"""Registers that are modified by this function"""
result = core.BNGetFunctionClobberedRegisters(self.handle)
@@ -1099,6 +1129,20 @@ class Function(object):
sc.confidence = types.max_confidence
core.BNSetAutoFunctionStackAdjustment(self.handle, sc)
+ def set_auto_reg_stack_adjustments(self, value):
+ adjust = (core.BNRegisterStackAdjustment * len(value))()
+ i = 0
+ for reg_stack in value.keys():
+ adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack)
+ if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence):
+ adjust[i].adjustment = value[reg_stack].value
+ adjust[i].confidence = value[reg_stack].confidence
+ else:
+ adjust[i].adjustment = value[reg_stack]
+ adjust[i].confidence = types.max_confidence
+ i += 1
+ core.BNSetAutoFunctionRegisterStackAdjustments(self.handle, adjust, len(value))
+
def set_auto_clobbered_regs(self, value):
regs = core.BNRegisterSetWithConfidence()
regs.regs = (ctypes.c_uint * len(value))()
@@ -1727,10 +1771,11 @@ class RegisterInfo(object):
class RegisterStackInfo(object):
- def __init__(self, storage_regs, top_relative_regs, stack_top_reg):
+ def __init__(self, storage_regs, top_relative_regs, stack_top_reg, index=None):
self.storage_regs = storage_regs
self.top_relative_regs = top_relative_regs
self.stack_top_reg = stack_top_reg
+ self.index = index
def __repr__(self):
return "<reg stack: %d regs, stack top in %s>" % (len(self.storage_regs), self.stack_top_reg)
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index f5a39b7e..3810e742 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -197,7 +197,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_JUMP: [("dest", "expr")],
LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")],
LowLevelILOperation.LLIL_CALL: [("dest", "expr")],
- LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")],
+ LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")],
LowLevelILOperation.LLIL_RET: [("dest", "expr")],
LowLevelILOperation.LLIL_NORET: [],
LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")],
@@ -258,7 +258,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")],
LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")],
LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")],
- LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "expr_list")],
LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")],
@@ -334,6 +334,14 @@ class LowLevelILInstruction(object):
for i in xrange(count.value):
value.append(operand_list[i])
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "expr_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):
+ value.append(LowLevelILInstruction(func, operand_list[i]))
+ core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "reg_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
@@ -364,6 +372,18 @@ class LowLevelILInstruction(object):
flag_version = operand_list[(i * 2) + 1]
value.append(SSAFlag(ILFlag(func.arch, flag), flag_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_stack_adjust":
+ 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]
+ adjust = operand_list[(i * 2) + 1]
+ if adjust & 0x80000000:
+ adjust |= ~0x80000000
+ value[func.arch.get_reg_stack_name(reg_stack)] = adjust
+ core.BNLowLevelILFreeOperandList(operand_list)
self.operands.append(value)
self.__dict__[name] = value
i += 1
diff --git a/python/types.py b/python/types.py
index 2557db2c..d44cc736 100644
--- a/python/types.py
+++ b/python/types.py
@@ -680,6 +680,21 @@ class SizeWithConfidence(object):
return self.value
+class RegisterStackAdjustmentWithConfidence(object):
+ def __init__(self, value, confidence = max_confidence):
+ self.value = value
+ self.confidence = confidence
+
+ def __str__(self):
+ return str(self.value)
+
+ def __repr__(self):
+ return repr(self.value)
+
+ def __int__(self):
+ return self.value
+
+
class RegisterSet(object):
def __init__(self, reg_list, confidence = max_confidence):
self.regs = reg_list