summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-08-23 01:04:47 -0400
committerRusty Wagner <rusty@vector35.com>2017-08-23 17:01:33 -0400
commit0d88336e22cf85a917729fe0f814c1e63736fca0 (patch)
tree246a7cf34d3f3919770cfbb2cf5f357adb1771e1
parent7f3efa01f053e19549c480a770728085900c2131 (diff)
Added APIs for clobbered registers, global pointers, and function exit data flow info
-rw-r--r--binaryninjaapi.h13
-rw-r--r--binaryninjacore.h36
-rw-r--r--callingconvention.cpp20
-rw-r--r--function.cpp79
-rw-r--r--mediumlevelil.cpp26
-rw-r--r--python/binaryview.py6
-rw-r--r--python/callingconvention.py10
-rw-r--r--python/function.py79
-rw-r--r--python/types.py37
9 files changed, 297 insertions, 9 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index e16679cc..f5f51908 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2185,6 +2185,8 @@ namespace BinaryNinja
Confidence<Ref<CallingConvention>> GetCallingConvention() const;
Confidence<std::vector<Variable>> GetParameterVariables() const;
Confidence<bool> HasVariableArguments() const;
+ Confidence<size_t> GetStackAdjustment() const;
+ Confidence<std::set<uint32_t>> GetClobberedRegisters() const;
void SetAutoType(Type* type);
void SetAutoReturnType(const Confidence<Ref<Type>>& type);
@@ -2192,6 +2194,8 @@ namespace BinaryNinja
void SetAutoParameterVariables(const Confidence<std::vector<Variable>>& vars);
void SetAutoHasVariableArguments(const Confidence<bool>& varArgs);
void SetAutoCanReturn(const Confidence<bool>& returns);
+ void SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust);
+ void SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered);
void SetUserType(Type* type);
void SetReturnType(const Confidence<Ref<Type>>& type);
@@ -2199,6 +2203,8 @@ namespace BinaryNinja
void SetParameterVariables(const Confidence<std::vector<Variable>>& vars);
void SetHasVariableArguments(const Confidence<bool>& varArgs);
void SetCanReturn(const Confidence<bool>& returns);
+ void SetStackAdjustment(const Confidence<size_t>& stackAdjust);
+ void SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered);
void ApplyImportedTypes(Symbol* sym);
void ApplyAutoDiscoveredType(Type* type);
@@ -2260,6 +2266,9 @@ namespace BinaryNinja
std::map<std::string, double> GetAnalysisPerformanceInfo();
std::vector<DisassemblyTextLine> GetTypeTokens(DisassemblySettings* settings = nullptr);
+
+ Confidence<RegisterValue> GetGlobalPointerValue() const;
+ Confidence<RegisterValue> GetRegisterValueAtExit(uint32_t reg) const;
};
class AdvancedFunctionAnalysisDataRequestor
@@ -2856,6 +2865,7 @@ namespace BinaryNinja
void Finalize();
void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true,
+ const std::set<Variable>& knownNotAliases = std::set<Variable>(),
const std::set<Variable>& knownAliases = std::set<Variable>());
bool GetExprText(Architecture* arch, ExprId expr, std::vector<InstructionTextToken>& tokens);
@@ -3069,6 +3079,7 @@ namespace BinaryNinja
static bool AreArgumentRegistersSharedIndexCallback(void* ctxt);
static bool IsStackReservedForArgumentRegistersCallback(void* ctxt);
+ static bool IsStackAdjustedOnReturnCallback(void* ctxt);
static uint32_t GetIntegerReturnValueRegisterCallback(void* ctxt);
static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt);
@@ -3089,6 +3100,7 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetFloatArgumentRegisters();
virtual bool AreArgumentRegistersSharedIndex();
virtual bool IsStackReservedForArgumentRegisters();
+ virtual bool IsStackAdjustedOnReturn();
virtual uint32_t GetIntegerReturnValueRegister() = 0;
virtual uint32_t GetHighIntegerReturnValueRegister();
@@ -3111,6 +3123,7 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetFloatArgumentRegisters() override;
virtual bool AreArgumentRegistersSharedIndex() override;
virtual bool IsStackReservedForArgumentRegisters() override;
+ virtual bool IsStackAdjustedOnReturn() override;
virtual uint32_t GetIntegerReturnValueRegister() override;
virtual uint32_t GetHighIntegerReturnValueRegister() override;
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 0ee5c4d7..6ba7fda4 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -694,6 +694,12 @@ extern "C"
int64_t value;
};
+ struct BNRegisterValueWithConfidence
+ {
+ BNRegisterValue value;
+ uint8_t confidence;
+ };
+
struct BNValueRange
{
uint64_t start, end, step;
@@ -1113,6 +1119,12 @@ extern "C"
uint8_t confidence;
};
+ struct BNSizeWithConfidence
+ {
+ size_t value;
+ uint8_t confidence;
+ };
+
struct BNMemberScopeWithConfidence
{
BNMemberScope value;
@@ -1132,6 +1144,13 @@ extern "C"
uint8_t confidence;
};
+ struct BNRegisterSetWithConfidence
+ {
+ uint32_t* regs;
+ size_t count;
+ uint8_t confidence;
+ };
+
struct BNFunctionParameter
{
char* name;
@@ -1243,6 +1262,7 @@ extern "C"
bool (*areArgumentRegistersSharedIndex)(void* ctxt);
bool (*isStackReservedForArgumentRegisters)(void* ctxt);
+ bool (*isStackAdjustedOnReturn)(void* ctxt);
uint32_t (*getIntegerReturnValueRegister)(void* ctxt);
uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt);
@@ -1806,6 +1826,8 @@ extern "C"
BINARYNINJACOREAPI BNAddressRange* BNGetAllocatedRanges(BNBinaryView* view, size_t* count);
BINARYNINJACOREAPI void BNFreeAddressRanges(BNAddressRange* ranges);
+ BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetGlobalPointerValue(BNBinaryView* view);
+
// Raw binary data view
BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataView(BNFileMetadata* file);
BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataViewFromBuffer(BNFileMetadata* file, BNDataBuffer* buf);
@@ -2073,18 +2095,25 @@ extern "C"
BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func);
BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars);
BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func);
+ BINARYNINJACOREAPI BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func);
+ BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func);
+ BINARYNINJACOREAPI void BNFreeClobberedRegisters(BNRegisterSetWithConfidence* regs);
BINARYNINJACOREAPI void BNSetAutoFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type);
BINARYNINJACOREAPI void BNSetAutoFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention);
BINARYNINJACOREAPI void BNSetAutoFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars);
BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs);
BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns);
+ BINARYNINJACOREAPI void BNSetAutoFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust);
+ BINARYNINJACOREAPI void BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs);
BINARYNINJACOREAPI void BNSetUserFunctionReturnType(BNFunction* func, BNTypeWithConfidence* type);
BINARYNINJACOREAPI void BNSetUserFunctionCallingConvention(BNFunction* func, BNCallingConventionWithConfidence* convention);
BINARYNINJACOREAPI void BNSetUserFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars);
BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs);
BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns);
+ BINARYNINJACOREAPI void BNSetUserFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust);
+ BINARYNINJACOREAPI void BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs);
BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym);
BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type);
@@ -2093,6 +2122,9 @@ extern "C"
BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetFunctionTypeTokens(BNFunction* func,
BNDisassemblySettings* settings, size_t* count);
+ BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionGlobalPointerValue(BNFunction* func);
+ BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionRegisterValueAtExit(BNFunction* func, uint32_t reg);
+
BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block);
BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block);
BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block);
@@ -2492,7 +2524,8 @@ extern "C"
BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label);
BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func);
BINARYNINJACOREAPI void BNGenerateMediumLevelILSSAForm(BNMediumLevelILFunction* func,
- bool analyzeConditionals, bool handleAliases, BNVariable* knownAliases, size_t knownAliasCount);
+ bool analyzeConditionals, bool handleAliases, BNVariable* knownNotAliases, size_t knownNotAliasCount,
+ BNVariable* knownAliases, size_t knownAliasCount);
BINARYNINJACOREAPI void BNPrepareToCopyMediumLevelILFunction(BNMediumLevelILFunction* func,
BNMediumLevelILFunction* src);
@@ -2795,6 +2828,7 @@ extern "C"
BINARYNINJACOREAPI uint32_t* BNGetFloatArgumentRegisters(BNCallingConvention* cc, size_t* count);
BINARYNINJACOREAPI bool BNAreArgumentRegistersSharedIndex(BNCallingConvention* cc);
BINARYNINJACOREAPI bool BNIsStackReservedForArgumentRegisters(BNCallingConvention* cc);
+ BINARYNINJACOREAPI bool BNIsStackAdjustedOnReturn(BNCallingConvention* cc);
BINARYNINJACOREAPI uint32_t BNGetIntegerReturnValueRegister(BNCallingConvention* cc);
BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc);
diff --git a/callingconvention.cpp b/callingconvention.cpp
index 0a7d349c..945ba25f 100644
--- a/callingconvention.cpp
+++ b/callingconvention.cpp
@@ -41,6 +41,7 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
cc.freeRegisterList = FreeRegisterListCallback;
cc.areArgumentRegistersSharedIndex = AreArgumentRegistersSharedIndexCallback;
cc.isStackReservedForArgumentRegisters = IsStackReservedForArgumentRegistersCallback;
+ cc.isStackAdjustedOnReturn = IsStackAdjustedOnReturnCallback;
cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback;
cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback;
cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback;
@@ -120,6 +121,13 @@ bool CallingConvention::IsStackReservedForArgumentRegistersCallback(void* ctxt)
}
+bool CallingConvention::IsStackAdjustedOnReturnCallback(void* ctxt)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ return cc->IsStackAdjustedOnReturn();
+}
+
+
uint32_t CallingConvention::GetIntegerReturnValueRegisterCallback(void* ctxt)
{
CallingConvention* cc = (CallingConvention*)ctxt;
@@ -226,6 +234,12 @@ bool CallingConvention::IsStackReservedForArgumentRegisters()
}
+bool CallingConvention::IsStackAdjustedOnReturn()
+{
+ return false;
+}
+
+
uint32_t CallingConvention::GetHighIntegerReturnValueRegister()
{
return BN_INVALID_REGISTER;
@@ -312,6 +326,12 @@ bool CoreCallingConvention::IsStackReservedForArgumentRegisters()
}
+bool CoreCallingConvention::IsStackAdjustedOnReturn()
+{
+ return BNIsStackAdjustedOnReturn(m_object);
+}
+
+
uint32_t CoreCallingConvention::GetIntegerReturnValueRegister()
{
return BNGetIntegerReturnValueRegister(m_object);
diff --git a/function.cpp b/function.cpp
index 976d73d2..550691d0 100644
--- a/function.cpp
+++ b/function.cpp
@@ -508,6 +508,25 @@ Confidence<bool> Function::HasVariableArguments() const
}
+Confidence<size_t> Function::GetStackAdjustment() const
+{
+ BNSizeWithConfidence sc = BNGetFunctionStackAdjustment(m_object);
+ return Confidence<size_t>(sc.value, sc.confidence);
+}
+
+
+Confidence<set<uint32_t>> Function::GetClobberedRegisters() const
+{
+ BNRegisterSetWithConfidence regs = BNGetFunctionClobberedRegisters(m_object);
+ set<uint32_t> regSet;
+ for (size_t i = 0; i < regs.count; i++)
+ regSet.insert(regs.regs[i]);
+ Confidence<set<uint32_t>> result(regSet, regs.confidence);
+ BNFreeClobberedRegisters(&regs);
+ return result;
+}
+
+
void Function::SetAutoType(Type* type)
{
BNSetFunctionAutoType(m_object, type->GetObject());
@@ -568,6 +587,29 @@ void Function::SetAutoCanReturn(const Confidence<bool>& returns)
}
+void Function::SetAutoStackAdjustment(const Confidence<size_t>& stackAdjust)
+{
+ BNSizeWithConfidence sc;
+ sc.value = stackAdjust.GetValue();
+ sc.confidence = stackAdjust.GetConfidence();
+ BNSetAutoFunctionStackAdjustment(m_object, &sc);
+}
+
+
+void Function::SetAutoClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered)
+{
+ BNRegisterSetWithConfidence regs;
+ regs.regs = new uint32_t[clobbered.GetValue().size()];
+ regs.count = clobbered.GetValue().size();
+ size_t i = 0;
+ for (auto reg : clobbered.GetValue())
+ regs.regs[i++] = reg;
+ regs.confidence = clobbered.GetConfidence();
+ BNSetAutoFunctionClobberedRegisters(m_object, &regs);
+ delete[] regs.regs;
+}
+
+
void Function::SetUserType(Type* type)
{
BNSetFunctionUserType(m_object, type->GetObject());
@@ -628,6 +670,29 @@ void Function::SetCanReturn(const Confidence<bool>& returns)
}
+void Function::SetStackAdjustment(const Confidence<size_t>& stackAdjust)
+{
+ BNSizeWithConfidence sc;
+ sc.value = stackAdjust.GetValue();
+ sc.confidence = stackAdjust.GetConfidence();
+ BNSetUserFunctionStackAdjustment(m_object, &sc);
+}
+
+
+void Function::SetClobberedRegisters(const Confidence<std::set<uint32_t>>& clobbered)
+{
+ BNRegisterSetWithConfidence regs;
+ regs.regs = new uint32_t[clobbered.GetValue().size()];
+ regs.count = clobbered.GetValue().size();
+ size_t i = 0;
+ for (auto reg : clobbered.GetValue())
+ regs.regs[i++] = reg;
+ regs.confidence = clobbered.GetConfidence();
+ BNSetUserFunctionClobberedRegisters(m_object, &regs);
+ delete[] regs.regs;
+}
+
+
void Function::ApplyImportedTypes(Symbol* sym)
{
BNApplyImportedTypes(m_object, sym->GetObject());
@@ -1014,6 +1079,20 @@ void Function::SetUserInstructionHighlight(Architecture* arch, uint64_t addr, ui
}
+Confidence<RegisterValue> Function::GetGlobalPointerValue() const
+{
+ BNRegisterValueWithConfidence value = BNGetFunctionGlobalPointerValue(m_object);
+ return Confidence<RegisterValue>(RegisterValue::FromAPIObject(value.value), value.confidence);
+}
+
+
+Confidence<RegisterValue> Function::GetRegisterValueAtExit(uint32_t reg) const
+{
+ BNRegisterValueWithConfidence value = BNGetFunctionRegisterValueAtExit(m_object, reg);
+ return Confidence<RegisterValue>(RegisterValue::FromAPIObject(value.value), value.confidence);
+}
+
+
void Function::Reanalyze()
{
BNReanalyzeFunction(m_object);
diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp
index f978f681..04a7341f 100644
--- a/mediumlevelil.cpp
+++ b/mediumlevelil.cpp
@@ -302,19 +302,31 @@ void MediumLevelILFunction::Finalize()
void MediumLevelILFunction::GenerateSSAForm(bool analyzeConditionals, bool handleAliases,
- const set<Variable>& knownAliases)
+ const set<Variable>& knownNotAliases, const set<Variable>& knownAliases)
{
- BNVariable* vars = new BNVariable[knownAliases.size()];
+ BNVariable* knownNotAlias = new BNVariable[knownNotAliases.size()];
+ BNVariable* knownAlias = new BNVariable[knownAliases.size()];
+
size_t i = 0;
+ for (auto& j : knownNotAliases)
+ {
+ knownNotAlias[i].type = j.type;
+ knownNotAlias[i].index = j.index;
+ knownNotAlias[i].storage = j.storage;
+ }
+
+ i = 0;
for (auto& j : knownAliases)
{
- vars[i].type = j.type;
- vars[i].index = j.index;
- vars[i].storage = j.storage;
+ knownAlias[i].type = j.type;
+ knownAlias[i].index = j.index;
+ knownAlias[i].storage = j.storage;
}
- BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, vars, knownAliases.size());
- delete[] vars;
+ BNGenerateMediumLevelILSSAForm(m_object, analyzeConditionals, handleAliases, knownNotAlias, knownNotAliases.size(),
+ knownAlias, knownAliases.size());
+ delete[] knownNotAlias;
+ delete[] knownAlias;
}
diff --git a/python/binaryview.py b/python/binaryview.py
index d977de50..bf8a87e0 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -927,6 +927,12 @@ class BinaryView(object):
else:
return BinaryView._associated_data[handle.value]
+ @property
+ def global_pointer_value(self):
+ """Discovered value of the global pointer register, if the binary uses one (read-only)"""
+ result = core.BNGetGlobalPointerValue(self.handle)
+ return function.RegisterValue(self.arch, result.value, confidence = result.confidence)
+
def __len__(self):
return int(core.BNGetViewLength(self.handle))
diff --git a/python/callingconvention.py b/python/callingconvention.py
index bd8bbeee..e72475c9 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -37,6 +37,7 @@ class CallingConvention(object):
float_arg_regs = []
arg_regs_share_index = False
stack_reserved_for_arg_regs = False
+ stack_adjusted_on_return = False
int_return_reg = None
high_int_return_reg = None
float_return_reg = None
@@ -59,6 +60,7 @@ class CallingConvention(object):
self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list)
self._cb.areArgumentRegistersSharedIndex = self._cb.areArgumentRegistersSharedIndex.__class__(self._arg_regs_share_index)
self._cb.isStackReservedForArgumentRegisters = self._cb.isStackReservedForArgumentRegisters.__class__(self._stack_reserved_for_arg_regs)
+ self._cb.isStackAdjustedOnReturn = self._cb.isStackAdjustedOnReturn.__class__(self._stack_adjusted_on_return)
self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg)
self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg)
self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg)
@@ -74,6 +76,7 @@ class CallingConvention(object):
self.__dict__["name"] = core.BNGetCallingConventionName(self.handle)
self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle)
self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle)
+ self.__dict__["stack_adjusted_on_return"] = core.BNIsStackAdjustedOnReturn(self.handle)
count = ctypes.c_ulonglong()
regs = core.BNGetCallerSavedRegisters(self.handle, count)
@@ -218,6 +221,13 @@ class CallingConvention(object):
log.log_error(traceback.format_exc())
return False
+ def _stack_adjusted_on_return(self, ctxt):
+ try:
+ return self.__class__.stack_adjusted_on_return
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
def _get_int_return_reg(self, ctxt):
try:
return self.arch.regs[self.__class__.int_return_reg].index
diff --git a/python/function.py b/python/function.py
index 55151e16..553b156f 100644
--- a/python/function.py
+++ b/python/function.py
@@ -50,11 +50,12 @@ class LookupTableEntry(object):
class RegisterValue(object):
- def __init__(self, arch = None, value = None):
+ def __init__(self, arch = None, value = None, confidence = types.max_confidence):
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:
@@ -63,8 +64,10 @@ class RegisterValue(object):
self.reg = value.value
elif (value.state == RegisterValueType.ConstantValue) or (value.state == RegisterValueType.ConstantPointerValue):
self.value = value.value
+ self.is_constant = True
elif value.state == RegisterValueType.StackFrameOffset:
self.offset = value.value
+ self.confidence = confidence
def __repr__(self):
if self.type == RegisterValueType.EntryValue:
@@ -280,6 +283,9 @@ class ParameterVariables(object):
def __getitem__(self, idx):
return self.vars[idx]
+ def __len__(self):
+ return len(self.vars)
+
def with_confidence(self, confidence):
return ParameterVariables(list(self.vars), confidence = confidence)
@@ -598,6 +604,52 @@ class Function(object):
bc.confidence = types.max_confidence
core.BNSetUserFunctionHasVariableArguments(self.handle, bc)
+ @property
+ def stack_adjustment(self):
+ """Number of bytes removed from the stack after return"""
+ result = core.BNGetFunctionStackAdjustment(self.handle)
+ return types.SizeWithConfidence(result.value, confidence = result.confidence)
+
+ @stack_adjustment.setter
+ def stack_adjustment(self, value):
+ sc = core.BNSizeWithConfidence()
+ sc.value = int(value)
+ if hasattr(value, 'confidence'):
+ sc.confidence = value.confidence
+ else:
+ sc.confidence = types.max_confidence
+ core.BNSetUserFunctionStackAdjustment(self.handle, sc)
+
+ @property
+ def clobbered_regs(self):
+ """Registers that are modified by this function"""
+ result = core.BNGetFunctionClobberedRegisters(self.handle)
+ reg_set = []
+ for i in xrange(0, result.count):
+ reg_set.append(self.arch.get_reg_name(result.regs[i]))
+ regs = types.RegisterSet(reg_set, confidence = result.confidence)
+ core.BNFreeClobberedRegisters(result)
+ return regs
+
+ @clobbered_regs.setter
+ def clobbered_regs(self, value):
+ regs = core.BNRegisterSetWithConfidence()
+ regs.regs = (ctypes.c_uint * len(value))()
+ regs.count = len(value)
+ for i in xrange(0, len(value)):
+ regs.regs[i] = self.arch.get_reg_index(value[i])
+ if hasattr(value, 'confidence'):
+ regs.confidence = value.confidence
+ else:
+ regs.confidence = types.max_confidence
+ core.BNSetUserFunctionClobberedRegisters(self.handle, regs)
+
+ @property
+ def global_pointer_value(self):
+ """Discovered value of the global pointer register, if the function uses one (read-only)"""
+ result = core.BNGetFunctionGlobalPointerValue(self.handle)
+ return RegisterValue(self.arch, result.value, confidence = result.confidence)
+
def __iter__(self):
count = ctypes.c_ulonglong()
blocks = core.BNGetFunctionBasicBlockList(self.handle, count)
@@ -963,6 +1015,27 @@ class Function(object):
bc.confidence = types.max_confidence
core.BNSetAutoFunctionCanReturn(self.handle, bc)
+ def set_auto_stack_adjustment(self, value):
+ sc = core.BNSizeWithConfidence()
+ sc.value = int(value)
+ if hasattr(value, 'confidence'):
+ sc.confidence = value.confidence
+ else:
+ sc.confidence = types.max_confidence
+ core.BNSetAutoFunctionStackAdjustment(self.handle, sc)
+
+ def set_auto_clobbered_regs(self, value):
+ regs = core.BNRegisterSetWithConfidence()
+ regs.regs = (ctypes.c_uint * len(value))()
+ regs.count = len(value)
+ for i in xrange(0, len(value)):
+ regs.regs[i] = self.arch.get_reg_index(value[i])
+ if hasattr(value, 'confidence'):
+ regs.confidence = value.confidence
+ else:
+ regs.confidence = types.max_confidence
+ core.BNSetAutoFunctionClobberedRegisters(self.handle, regs)
+
def get_int_display_type(self, instr_addr, value, operand, arch=None):
if arch is None:
arch = self.arch
@@ -1160,6 +1233,10 @@ class Function(object):
core.BNFreeDisassemblyTextLines(lines, count.value)
return result
+ def get_reg_value_at_exit(self, reg):
+ result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg))
+ return RegisterValue(self.arch, result.value, confidence = result.confidence)
+
class AdvancedFunctionAnalysisDataRequestor(object):
def __init__(self, func = None):
diff --git a/python/types.py b/python/types.py
index fd2ee27e..bf4a7b74 100644
--- a/python/types.py
+++ b/python/types.py
@@ -650,6 +650,43 @@ class BoolWithConfidence(object):
return self.value
+class SizeWithConfidence(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
+ self.confidence = confidence
+
+ def __repr__(self):
+ return repr(self.regs)
+
+ def __iter__(self):
+ for reg in self.regs:
+ yield reg
+
+ def __getitem__(self, idx):
+ return self.regs[idx]
+
+ def __len__(self):
+ return len(self.regs)
+
+ def with_confidence(self, confidence):
+ return RegisterSet(list(self.regs), confidence = confidence)
+
+
class ReferenceTypeWithConfidence(object):
def __init__(self, value, confidence = max_confidence):
self.value = value