summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp40
-rw-r--r--binaryninjaapi.h66
-rw-r--r--binaryninjacore.h57
-rw-r--r--callingconvention.cpp97
-rw-r--r--function.cpp202
-rw-r--r--mediumlevelilinstruction.h3
-rw-r--r--python/architecture.py25
-rw-r--r--python/callingconvention.py87
-rw-r--r--python/function.py247
-rw-r--r--python/types.py18
-rw-r--r--type.cpp15
11 files changed, 822 insertions, 35 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 3e82ffd3..8fd38de2 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -346,6 +346,19 @@ uint32_t Architecture::GetLinkRegisterCallback(void* ctxt)
}
+uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<uint32_t> regs = arch->GetGlobalRegisters();
+ *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;
+}
+
+
bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors)
{
Architecture* arch = (Architecture*)ctxt;
@@ -453,6 +466,7 @@ void Architecture::Register(Architecture* arch)
callbacks.getRegisterInfo = GetRegisterInfoCallback;
callbacks.getStackPointerRegister = GetStackPointerRegisterCallback;
callbacks.getLinkRegister = GetLinkRegisterCallback;
+ callbacks.getGlobalRegisters = GetGlobalRegistersCallback;
callbacks.assemble = AssembleCallback;
callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback;
callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback;
@@ -656,6 +670,18 @@ uint32_t Architecture::GetLinkRegister()
}
+vector<uint32_t> Architecture::GetGlobalRegisters()
+{
+ return vector<uint32_t>();
+}
+
+
+bool Architecture::IsGlobalRegister(uint32_t reg)
+{
+ return BNIsArchitectureGlobalRegister(m_object, reg);
+}
+
+
vector<uint32_t> Architecture::GetModifiedRegistersOnWrite(uint32_t reg)
{
size_t count;
@@ -1161,6 +1187,20 @@ uint32_t CoreArchitecture::GetLinkRegister()
}
+vector<uint32_t> CoreArchitecture::GetGlobalRegisters()
+{
+ size_t count;
+ uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count);
+
+ vector<uint32_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(regs[i]);
+
+ BNFreeRegisterList(regs);
+ return result;
+}
+
+
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 9a61a9cb..63cab888 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -300,7 +300,17 @@ namespace BinaryNinja
{
}
+ static uint8_t Combine(uint8_t a, uint8_t b)
+ {
+ uint8_t result = (uint8_t)(((uint32_t)a * (uint32_t)b) / BN_FULL_CONFIDENCE);
+ if ((a >= BN_MINIMUM_CONFIDENCE) && (b >= BN_MINIMUM_CONFIDENCE) &&
+ (result < BN_MINIMUM_CONFIDENCE))
+ result = BN_MINIMUM_CONFIDENCE;
+ return result;
+ }
+
uint8_t GetConfidence() const { return m_confidence; }
+ uint8_t GetCombinedConfidence(uint8_t base) const { return Combine(m_confidence, base); }
void SetConfidence(uint8_t conf) { m_confidence = conf; }
bool IsUnknown() const { return m_confidence == 0; }
};
@@ -331,8 +341,12 @@ namespace BinaryNinja
T* operator->() { return &m_value; }
const T* operator->() const { return &m_value; }
- T& GetValue() { return m_value; }
- const T& GetValue() const { return m_value; }
+ // This MUST be a copy. There are subtle compiler scoping bugs that will cause nondeterministic failures
+ // when using one of these objects as a temporary if a reference is returned here. Unfortunately, this has
+ // negative performance implications. Make a local copy first if the template argument is a complex
+ // object and it is needed repeatedly.
+ T GetValue() const { return m_value; }
+
void SetValue(const T& value) { m_value = value; }
Confidence<T>& operator=(const Confidence<T>& v)
@@ -1584,6 +1598,7 @@ namespace BinaryNinja
static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result);
static uint32_t GetStackPointerRegisterCallback(void* ctxt);
static uint32_t GetLinkRegisterCallback(void* ctxt);
+ static uint32_t* GetGlobalRegistersCallback(void* ctxt, size_t* count);
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);
@@ -1646,6 +1661,8 @@ namespace BinaryNinja
virtual BNRegisterInfo GetRegisterInfo(uint32_t reg);
virtual uint32_t GetStackPointerRegister();
virtual uint32_t GetLinkRegister();
+ virtual std::vector<uint32_t> GetGlobalRegisters();
+ bool IsGlobalRegister(uint32_t reg);
std::vector<uint32_t> GetModifiedRegistersOnWrite(uint32_t reg);
uint32_t GetRegisterByName(const std::string& name);
@@ -1784,6 +1801,7 @@ namespace BinaryNinja
virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override;
virtual uint32_t GetStackPointerRegister() override;
virtual uint32_t GetLinkRegister() override;
+ virtual std::vector<uint32_t> GetGlobalRegisters() override;
virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override;
@@ -1831,7 +1849,7 @@ namespace BinaryNinja
Confidence<Ref<Type>> GetChildType() const;
Confidence<Ref<CallingConvention>> GetCallingConvention() const;
std::vector<NameAndType> GetParameters() const;
- bool HasVariableArguments() const;
+ Confidence<bool> HasVariableArguments() const;
Confidence<bool> CanReturn() const;
Ref<Structure> GetStructure() const;
Ref<Enumeration> GetEnumeration() const;
@@ -1879,7 +1897,7 @@ namespace BinaryNinja
static Ref<Type> ArrayType(const Confidence<Ref<Type>>& type, uint64_t elem);
static Ref<Type> FunctionType(const Confidence<Ref<Type>>& returnValue,
const Confidence<Ref<CallingConvention>>& callingConvention,
- const std::vector<NameAndType>& params, bool varArg = false);
+ const std::vector<NameAndType>& params, const Confidence<bool>& varArg = Confidence<bool>(false, 0));
static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name);
static std::string GenerateAutoDemangledTypeId(const QualifiedName& name);
@@ -2097,7 +2115,9 @@ namespace BinaryNinja
BNRegisterValueType state;
int64_t value;
- static RegisterValue FromAPIObject(BNRegisterValue& value);
+ RegisterValue();
+ static RegisterValue FromAPIObject(const BNRegisterValue& value);
+ BNRegisterValue ToAPIObject();
};
struct PossibleValueSet
@@ -2127,7 +2147,7 @@ namespace BinaryNinja
uint64_t GetStart() const;
Ref<Symbol> GetSymbol() const;
bool WasAutomaticallyDiscovered() const;
- bool CanReturn() const;
+ Confidence<bool> CanReturn() const;
bool HasExplicitlyDefinedType() const;
bool NeedsUpdate() const;
@@ -2163,8 +2183,25 @@ namespace BinaryNinja
Ref<MediumLevelILFunction> GetMediumLevelIL() const;
Ref<Type> GetType() const;
+ Confidence<Ref<Type>> GetReturnType() const;
+ Confidence<Ref<CallingConvention>> GetCallingConvention() const;
+ Confidence<std::vector<Variable>> GetParameterVariables() const;
+ Confidence<bool> HasVariableArguments() const;
+
void SetAutoType(Type* type);
+ void SetAutoReturnType(const Confidence<Ref<Type>>& type);
+ void SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention);
+ void SetAutoParameterVariables(const Confidence<std::vector<Variable>>& vars);
+ void SetAutoHasVariableArguments(const Confidence<bool>& varArgs);
+ void SetAutoCanReturn(const Confidence<bool>& returns);
+
void SetUserType(Type* type);
+ void SetReturnType(const Confidence<Ref<Type>>& type);
+ void SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention);
+ void SetParameterVariables(const Confidence<std::vector<Variable>>& vars);
+ void SetHasVariableArguments(const Confidence<bool>& varArgs);
+ void SetCanReturn(const Confidence<bool>& returns);
+
void ApplyImportedTypes(Symbol* sym);
void ApplyAutoDiscoveredType(Type* type);
@@ -2223,6 +2260,8 @@ namespace BinaryNinja
void ReleaseAdvancedAnalysisData(size_t count);
std::map<std::string, double> GetAnalysisPerformanceInfo();
+
+ std::vector<DisassemblyTextLine> GetTypeTokens(DisassemblySettings* settings = nullptr);
};
class AdvancedFunctionAnalysisDataRequestor
@@ -3036,6 +3075,11 @@ namespace BinaryNinja
static uint32_t GetIntegerReturnValueRegisterCallback(void* ctxt);
static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt);
static uint32_t GetFloatReturnValueRegisterCallback(void* ctxt);
+ static uint32_t GetGlobalPointerRegisterCallback(void* ctxt);
+
+ static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count);
+ static BNRegisterValue GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func);
+ static BNRegisterValue GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func);
public:
Ref<Architecture> GetArchitecture() const;
@@ -3051,6 +3095,11 @@ namespace BinaryNinja
virtual uint32_t GetIntegerReturnValueRegister() = 0;
virtual uint32_t GetHighIntegerReturnValueRegister();
virtual uint32_t GetFloatReturnValueRegister();
+ virtual uint32_t GetGlobalPointerRegister();
+
+ virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters();
+ virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func);
+ virtual RegisterValue GetIncomingFlagValue(uint32_t flag, Function* func);
};
class CoreCallingConvention: public CallingConvention
@@ -3068,6 +3117,11 @@ namespace BinaryNinja
virtual uint32_t GetIntegerReturnValueRegister() override;
virtual uint32_t GetHighIntegerReturnValueRegister() override;
virtual uint32_t GetFloatReturnValueRegister() override;
+ virtual uint32_t GetGlobalPointerRegister() override;
+
+ 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;
};
/*!
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 22980067..6b5d5acc 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -92,7 +92,9 @@
#define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL
#define BN_MAX_VARIABLE_INDEX 0xfffff
-#define BN_FULL_CONFIDENCE 255
+#define BN_FULL_CONFIDENCE 255
+#define BN_MINIMUM_CONFIDENCE 1
+#define BN_HEURISTIC_CONFIDENCE 192
#ifdef __cplusplus
extern "C"
@@ -230,8 +232,7 @@ extern "C"
NoTokenContext = 0,
LocalVariableTokenContext = 1,
DataVariableTokenContext = 2,
- FunctionReturnTokenContext = 3,
- ArgumentTokenContext = 4
+ FunctionReturnTokenContext = 3
};
enum BNLinearDisassemblyLineType
@@ -419,6 +420,7 @@ extern "C"
ShowVariablesAtTopOfGraph = 3,
ShowVariableTypesWhenAssigned = 4,
ShowDefaultRegisterTypes = 5,
+ ShowCallParameterNames = 6,
// Linear disassembly options
GroupLinearDisassemblyFunctions = 64,
@@ -1015,6 +1017,7 @@ extern "C"
void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result);
uint32_t (*getStackPointerRegister)(void* ctxt);
uint32_t (*getLinkRegister)(void* ctxt);
+ uint32_t* (*getGlobalRegisters)(void* ctxt, size_t* count);
bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
@@ -1122,6 +1125,13 @@ extern "C"
uint8_t confidence;
};
+ struct BNParameterVariablesWithConfidence
+ {
+ BNVariable* vars;
+ size_t count;
+ uint8_t confidence;
+ };
+
struct BNNameAndType
{
char* name;
@@ -1235,6 +1245,11 @@ extern "C"
uint32_t (*getIntegerReturnValueRegister)(void* ctxt);
uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt);
uint32_t (*getFloatReturnValueRegister)(void* ctxt);
+ uint32_t (*getGlobalPointerRegister)(void* ctxt);
+
+ uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count);
+ BNRegisterValue (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func);
+ BNRegisterValue (*getIncomingFlagValue)(void* ctxt, uint32_t flag, BNFunction* func);
};
struct BNVariableNameAndType
@@ -1922,6 +1937,8 @@ extern "C"
BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg);
BINARYNINJACOREAPI uint32_t BNGetArchitectureStackPointerRegister(BNArchitecture* arch);
BINARYNINJACOREAPI uint32_t BNGetArchitectureLinkRegister(BNArchitecture* arch);
+ BINARYNINJACOREAPI uint32_t* BNGetArchitectureGlobalRegisters(BNArchitecture* arch, size_t* count);
+ BINARYNINJACOREAPI bool BNIsArchitectureGlobalRegister(BNArchitecture* arch, uint32_t reg);
BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterByName(BNArchitecture* arch, const char* name);
BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors);
@@ -1982,7 +1999,7 @@ extern "C"
BINARYNINJACOREAPI uint64_t BNGetFunctionStart(BNFunction* func);
BINARYNINJACOREAPI BNSymbol* BNGetFunctionSymbol(BNFunction* func);
BINARYNINJACOREAPI bool BNWasFunctionAutomaticallyDiscovered(BNFunction* func);
- BINARYNINJACOREAPI bool BNCanFunctionReturn(BNFunction* func);
+ BINARYNINJACOREAPI BNBoolWithConfidence BNCanFunctionReturn(BNFunction* func);
BINARYNINJACOREAPI void BNSetFunctionAutoType(BNFunction* func, BNType* type);
BINARYNINJACOREAPI void BNSetFunctionUserType(BNFunction* func, BNType* type);
@@ -2038,10 +2055,31 @@ extern "C"
BINARYNINJACOREAPI uint32_t* BNGetFlagsWrittenByLiftedILInstruction(BNFunction* func, size_t i, size_t* count);
BINARYNINJACOREAPI BNType* BNGetFunctionType(BNFunction* func);
+ BINARYNINJACOREAPI BNTypeWithConfidence BNGetFunctionReturnType(BNFunction* func);
+ BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetFunctionCallingConvention(BNFunction* func);
+ BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func);
+ BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars);
+ BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func);
+
+ 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 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 BNApplyImportedTypes(BNFunction* func, BNSymbol* sym);
BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type);
BINARYNINJACOREAPI bool BNFunctionHasExplicitlyDefinedType(BNFunction* func);
+ BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetFunctionTypeTokens(BNFunction* func,
+ BNDisassemblySettings* settings, size_t* count);
+
BINARYNINJACOREAPI BNFunction* BNGetBasicBlockFunction(BNBasicBlock* block);
BINARYNINJACOREAPI BNArchitecture* BNGetBasicBlockArchitecture(BNBasicBlock* block);
BINARYNINJACOREAPI uint64_t BNGetBasicBlockStart(BNBasicBlock* block);
@@ -2565,7 +2603,7 @@ extern "C"
BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem);
BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue,
BNCallingConventionWithConfidence* callingConvention, BNNameAndType* params,
- size_t paramCount, bool varArg);
+ size_t paramCount, BNBoolWithConfidence* varArg);
BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type);
BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type);
BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name);
@@ -2584,14 +2622,14 @@ extern "C"
BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type);
BINARYNINJACOREAPI BNNameAndType* BNGetTypeParameters(BNType* type, size_t* count);
BINARYNINJACOREAPI void BNFreeTypeParameterList(BNNameAndType* types, size_t count);
- BINARYNINJACOREAPI bool BNTypeHasVariableArguments(BNType* type);
+ BINARYNINJACOREAPI BNBoolWithConfidence BNTypeHasVariableArguments(BNType* type);
BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionTypeCanReturn(BNType* type);
BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type);
BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type);
BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type);
BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type);
BINARYNINJACOREAPI uint64_t BNGetTypeOffset(BNType* type);
- BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, BNBoolWithConfidence* canReturn);
+ BINARYNINJACOREAPI void BNSetFunctionTypeCanReturn(BNType* type, BNBoolWithConfidence* canReturn);
BINARYNINJACOREAPI BNMemberScopeWithConfidence BNTypeGetMemberScope(BNType* type);
BINARYNINJACOREAPI void BNTypeSetMemberScope(BNType* type, BNMemberScopeWithConfidence* scope);
BINARYNINJACOREAPI BNMemberAccessWithConfidence BNTypeGetMemberAccess(BNType* type);
@@ -2745,6 +2783,11 @@ extern "C"
BINARYNINJACOREAPI uint32_t BNGetIntegerReturnValueRegister(BNCallingConvention* cc);
BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc);
BINARYNINJACOREAPI uint32_t BNGetFloatReturnValueRegister(BNCallingConvention* cc);
+ BINARYNINJACOREAPI uint32_t BNGetGlobalPointerRegister(BNCallingConvention* cc);
+
+ BINARYNINJACOREAPI uint32_t* BNGetImplicitlyDefinedRegisters(BNCallingConvention* cc, size_t* count);
+ BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func);
+ BINARYNINJACOREAPI BNRegisterValue BNGetIncomingFlagValue(BNCallingConvention* cc, uint32_t reg, BNFunction* func);
BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureDefaultCallingConvention(BNArchitecture* arch);
BINARYNINJACOREAPI BNCallingConvention* BNGetArchitectureCdeclCallingConvention(BNArchitecture* arch);
diff --git a/callingconvention.cpp b/callingconvention.cpp
index fb5ed73f..b0783ad6 100644
--- a/callingconvention.cpp
+++ b/callingconvention.cpp
@@ -44,6 +44,10 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
cc.getIntegerReturnValueRegister = GetIntegerReturnValueRegisterCallback;
cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback;
cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback;
+ cc.getGlobalPointerRegister = GetGlobalPointerRegisterCallback;
+ cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback;
+ cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback;
+ cc.getIncomingFlagValue = GetIncomingFlagValueCallback;
AddRefForRegistration();
m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc);
@@ -137,6 +141,46 @@ uint32_t CallingConvention::GetFloatReturnValueRegisterCallback(void* ctxt)
}
+uint32_t CallingConvention::GetGlobalPointerRegisterCallback(void* ctxt)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ return cc->GetGlobalPointerRegister();
+}
+
+
+uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ vector<uint32_t> regs = cc->GetImplicitlyDefinedRegisters();
+ *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;
+}
+
+
+BNRegisterValue CallingConvention::GetIncomingRegisterValueCallback(void* ctxt, uint32_t reg, BNFunction* func)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ Ref<Function> funcObj;
+ if (func)
+ funcObj = new Function(BNNewFunctionReference(func));
+ return cc->GetIncomingRegisterValue(reg, funcObj).ToAPIObject();
+}
+
+
+BNRegisterValue CallingConvention::GetIncomingFlagValueCallback(void* ctxt, uint32_t reg, BNFunction* func)
+{
+ CallingConvention* cc = (CallingConvention*)ctxt;
+ Ref<Function> funcObj;
+ if (func)
+ funcObj = new Function(BNNewFunctionReference(func));
+ return cc->GetIncomingFlagValue(reg, funcObj).ToAPIObject();
+}
+
+
Ref<Architecture> CallingConvention::GetArchitecture() const
{
return new CoreArchitecture(BNGetCallingConventionArchitecture(m_object));
@@ -194,6 +238,30 @@ uint32_t CallingConvention::GetFloatReturnValueRegister()
}
+uint32_t CallingConvention::GetGlobalPointerRegister()
+{
+ return BN_INVALID_REGISTER;
+}
+
+
+vector<uint32_t> CallingConvention::GetImplicitlyDefinedRegisters()
+{
+ return vector<uint32_t>();
+}
+
+
+RegisterValue CallingConvention::GetIncomingRegisterValue(uint32_t, Function*)
+{
+ return RegisterValue();
+}
+
+
+RegisterValue CallingConvention::GetIncomingFlagValue(uint32_t, Function*)
+{
+ return RegisterValue();
+}
+
+
CoreCallingConvention::CoreCallingConvention(BNCallingConvention* cc): CallingConvention(cc)
{
}
@@ -260,3 +328,32 @@ uint32_t CoreCallingConvention::GetFloatReturnValueRegister()
{
return BNGetFloatReturnValueRegister(m_object);
}
+
+
+uint32_t CoreCallingConvention::GetGlobalPointerRegister()
+{
+ return BNGetGlobalPointerRegister(m_object);
+}
+
+
+vector<uint32_t> CoreCallingConvention::GetImplicitlyDefinedRegisters()
+{
+ size_t count;
+ uint32_t* regs = BNGetImplicitlyDefinedRegisters(m_object, &count);
+ vector<uint32_t> result;
+ result.insert(result.end(), regs, &regs[count]);
+ BNFreeRegisterList(regs);
+ return result;
+}
+
+
+RegisterValue CoreCallingConvention::GetIncomingRegisterValue(uint32_t reg, Function* func)
+{
+ return RegisterValue::FromAPIObject(BNGetIncomingRegisterValue(m_object, reg, func ? func->GetObject() : nullptr));
+}
+
+
+RegisterValue CoreCallingConvention::GetIncomingFlagValue(uint32_t flag, Function* func)
+{
+ return RegisterValue::FromAPIObject(BNGetIncomingFlagValue(m_object, flag, func ? func->GetObject() : nullptr));
+}
diff --git a/function.cpp b/function.cpp
index 66b2aade..976d73d2 100644
--- a/function.cpp
+++ b/function.cpp
@@ -91,6 +91,20 @@ Variable Variable::FromIdentifier(uint64_t id)
}
+RegisterValue::RegisterValue(): state(UndeterminedValue), value(0)
+{
+}
+
+
+BNRegisterValue RegisterValue::ToAPIObject()
+{
+ BNRegisterValue result;
+ result.state = state;
+ result.value = value;
+ return result;
+}
+
+
Function::Function(BNFunction* func)
{
m_object = func;
@@ -135,9 +149,10 @@ bool Function::WasAutomaticallyDiscovered() const
}
-bool Function::CanReturn() const
+Confidence<bool> Function::CanReturn() const
{
- return BNCanFunctionReturn(m_object);
+ BNBoolWithConfidence bc = BNCanFunctionReturn(m_object);
+ return Confidence<bool>(bc.value, bc.confidence);
}
@@ -233,7 +248,7 @@ vector<size_t> Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui
}
-RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value)
+RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value)
{
RegisterValue result;
result.state = value.state;
@@ -452,18 +467,167 @@ Ref<Type> Function::GetType() const
}
+Confidence<Ref<Type>> Function::GetReturnType() const
+{
+ BNTypeWithConfidence tc = BNGetFunctionReturnType(m_object);
+ Ref<Type> type = tc.type ? new Type(tc.type) : nullptr;
+ return Confidence<Ref<Type>>(type, tc.confidence);
+}
+
+
+Confidence<Ref<CallingConvention>> Function::GetCallingConvention() const
+{
+ BNCallingConventionWithConfidence cc = BNGetFunctionCallingConvention(m_object);
+ Ref<CallingConvention> convention = cc.convention ? new CoreCallingConvention(cc.convention) : nullptr;
+ return Confidence<Ref<CallingConvention>>(convention, cc.confidence);
+}
+
+
+Confidence<vector<Variable>> Function::GetParameterVariables() const
+{
+ BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object);
+ vector<Variable> varList;
+ for (size_t i = 0; i < vars.count; i++)
+ {
+ Variable var;
+ var.type = vars.vars[i].type;
+ var.index = vars.vars[i].index;
+ var.storage = vars.vars[i].storage;
+ varList.push_back(var);
+ }
+ Confidence<vector<Variable>> result(varList, vars.confidence);
+ BNFreeParameterVariables(&vars);
+ return result;
+}
+
+
+Confidence<bool> Function::HasVariableArguments() const
+{
+ BNBoolWithConfidence bc = BNFunctionHasVariableArguments(m_object);
+ return Confidence<bool>(bc.value, bc.confidence);
+}
+
+
void Function::SetAutoType(Type* type)
{
BNSetFunctionAutoType(m_object, type->GetObject());
}
+void Function::SetAutoReturnType(const Confidence<Ref<Type>>& type)
+{
+ BNTypeWithConfidence tc;
+ tc.type = type ? type->GetObject() : nullptr;
+ tc.confidence = type.GetConfidence();
+ BNSetAutoFunctionReturnType(m_object, &tc);
+}
+
+
+void Function::SetAutoCallingConvention(const Confidence<Ref<CallingConvention>>& convention)
+{
+ BNCallingConventionWithConfidence cc;
+ cc.convention = convention ? convention->GetObject() : nullptr;
+ cc.confidence = convention.GetConfidence();
+ BNSetAutoFunctionCallingConvention(m_object, &cc);
+}
+
+
+void Function::SetAutoParameterVariables(const Confidence<vector<Variable>>& vars)
+{
+ BNParameterVariablesWithConfidence varConf;
+ varConf.vars = new BNVariable[vars.GetValue().size()];
+ varConf.count = vars.GetValue().size();
+ for (size_t i = 0; i < vars.GetValue().size(); i++)
+ {
+ varConf.vars[i].type = vars.GetValue()[i].type;
+ varConf.vars[i].index = vars.GetValue()[i].index;
+ varConf.vars[i].storage = vars.GetValue()[i].storage;
+ }
+ varConf.confidence = vars.GetConfidence();
+
+ BNSetAutoFunctionParameterVariables(m_object, &varConf);
+ delete[] varConf.vars;
+}
+
+
+void Function::SetAutoHasVariableArguments(const Confidence<bool>& varArgs)
+{
+ BNBoolWithConfidence bc;
+ bc.value = varArgs.GetValue();
+ bc.confidence = varArgs.GetConfidence();
+ BNSetAutoFunctionHasVariableArguments(m_object, &bc);
+}
+
+
+void Function::SetAutoCanReturn(const Confidence<bool>& returns)
+{
+ BNBoolWithConfidence bc;
+ bc.value = returns.GetValue();
+ bc.confidence = returns.GetConfidence();
+ BNSetAutoFunctionCanReturn(m_object, &bc);
+}
+
+
void Function::SetUserType(Type* type)
{
BNSetFunctionUserType(m_object, type->GetObject());
}
+void Function::SetReturnType(const Confidence<Ref<Type>>& type)
+{
+ BNTypeWithConfidence tc;
+ tc.type = type ? type->GetObject() : nullptr;
+ tc.confidence = type.GetConfidence();
+ BNSetUserFunctionReturnType(m_object, &tc);
+}
+
+
+void Function::SetCallingConvention(const Confidence<Ref<CallingConvention>>& convention)
+{
+ BNCallingConventionWithConfidence cc;
+ cc.convention = convention ? convention->GetObject() : nullptr;
+ cc.confidence = convention.GetConfidence();
+ BNSetUserFunctionCallingConvention(m_object, &cc);
+}
+
+
+void Function::SetParameterVariables(const Confidence<vector<Variable>>& vars)
+{
+ BNParameterVariablesWithConfidence varConf;
+ varConf.vars = new BNVariable[vars.GetValue().size()];
+ varConf.count = vars.GetValue().size();
+ for (size_t i = 0; i < vars.GetValue().size(); i++)
+ {
+ varConf.vars[i].type = vars.GetValue()[i].type;
+ varConf.vars[i].index = vars.GetValue()[i].index;
+ varConf.vars[i].storage = vars.GetValue()[i].storage;
+ }
+ varConf.confidence = vars.GetConfidence();
+
+ BNSetUserFunctionParameterVariables(m_object, &varConf);
+ delete[] varConf.vars;
+}
+
+
+void Function::SetHasVariableArguments(const Confidence<bool>& varArgs)
+{
+ BNBoolWithConfidence bc;
+ bc.value = varArgs.GetValue();
+ bc.confidence = varArgs.GetConfidence();
+ BNSetUserFunctionHasVariableArguments(m_object, &bc);
+}
+
+
+void Function::SetCanReturn(const Confidence<bool>& returns)
+{
+ BNBoolWithConfidence bc;
+ bc.value = returns.GetValue();
+ bc.confidence = returns.GetConfidence();
+ BNSetUserFunctionCanReturn(m_object, &bc);
+}
+
+
void Function::ApplyImportedTypes(Symbol* sym)
{
BNApplyImportedTypes(m_object, sym->GetObject());
@@ -891,6 +1055,38 @@ map<string, double> Function::GetAnalysisPerformanceInfo()
}
+vector<DisassemblyTextLine> Function::GetTypeTokens(DisassemblySettings* settings)
+{
+ size_t count;
+ BNDisassemblyTextLine* lines = BNGetFunctionTypeTokens(m_object,
+ settings ? settings->GetObject() : nullptr, &count);
+
+ vector<DisassemblyTextLine> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ DisassemblyTextLine line;
+ line.addr = lines[i].addr;
+ for (size_t j = 0; j < lines[i].count; j++)
+ {
+ InstructionTextToken token;
+ token.type = lines[i].tokens[j].type;
+ token.text = lines[i].tokens[j].text;
+ token.value = lines[i].tokens[j].value;
+ token.size = lines[i].tokens[j].size;
+ token.operand = lines[i].tokens[j].operand;
+ token.context = lines[i].tokens[j].context;
+ token.confidence = lines[i].tokens[j].confidence;
+ token.address = lines[i].tokens[j].address;
+ line.tokens.push_back(token);
+ }
+ result.push_back(line);
+ }
+
+ BNFreeDisassemblyTextLines(lines, count);
+ return result;
+}
+
+
AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func)
{
if (m_func)
diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h
index ef5e7567..066259eb 100644
--- a/mediumlevelilinstruction.h
+++ b/mediumlevelilinstruction.h
@@ -521,6 +521,8 @@ namespace BinaryNinja
template <BNMediumLevelILOperation N> void SetParameterSSAVariables(const std::vector<SSAVariable>& vars) { As<N>().SetParameterSSAVariables(vars); }
template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetParameterExprs(params); }
template <BNMediumLevelILOperation N> void SetParameterExprs(const std::vector<ExprId>& params) { As<N>().SetParameterExprs(params); }
+ template <BNMediumLevelILOperation N> void SetSourceExprs(const std::vector<MediumLevelILInstruction>& params) { As<N>().SetSourceExprs(params); }
+ template <BNMediumLevelILOperation N> void SetSourceExprs(const std::vector<ExprId>& params) { As<N>().SetSourceExprs(params); }
bool GetOperandIndexForUsage(MediumLevelILOperandUsage usage, size_t& operandIndex) const;
@@ -894,6 +896,7 @@ namespace BinaryNinja
template <> struct MediumLevelILInstructionAccessor<MLIL_RET>: public MediumLevelILInstructionBase
{
MediumLevelILInstructionList GetSourceExprs() const { return GetRawOperandAsExprList(0); }
+ void SetSourceExprs(const std::vector<ExprId>& exprs) { UpdateRawOperandAsExprList(0, exprs); }
};
template <> struct MediumLevelILInstructionAccessor<MLIL_IF>: public MediumLevelILInstructionBase
diff --git a/python/architecture.py b/python/architecture.py
index b5f56767..61559934 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -116,6 +116,7 @@ class Architecture(object):
regs = {}
stack_pointer = None
link_reg = None
+ global_regs = []
flags = []
flag_write_types = []
flag_roles = {}
@@ -208,6 +209,13 @@ class Architecture(object):
core.BNFreeRegisterList(flags)
self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes
self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetArchitectureGlobalRegisters(self.handle, count)
+ self.__dict__["global_regs"] = []
+ for i in xrange(0, count.value):
+ self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i]))
+ core.BNFreeRegisterList(regs)
else:
startup._init_plugins()
@@ -250,6 +258,7 @@ class Architecture(object):
self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__(
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.assemble = self._cb.assemble.__class__(self._assemble)
self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
self._is_never_branch_patch_available)
@@ -330,6 +339,8 @@ class Architecture(object):
flags.append(self._flags[flag])
self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags
+ self.__dict__["global_regs"] = self.__class__.global_regs
+
self._pending_reg_lists = {}
self._pending_token_lists = {}
@@ -719,6 +730,20 @@ class Architecture(object):
log.log_error(traceback.format_exc())
return 0
+ def _get_global_registers(self, ctxt, count):
+ try:
+ count[0] = len(self.__class__.global_regs)
+ reg_buf = (ctypes.c_uint * len(self.__class__.global_regs))()
+ for i in xrange(0, len(self.__class__.global_regs)):
+ reg_buf[i] = self._all_regs[self.__class__.global_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 _assemble(self, ctxt, code, addr, result, errors):
try:
data, error_str = self.perform_assemble(code, addr)
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 21c8c95a..609c71b0 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -26,6 +26,8 @@ import _binaryninjacore as core
import architecture
import log
import types
+import function
+import binaryview
class CallingConvention(object):
@@ -38,6 +40,8 @@ class CallingConvention(object):
int_return_reg = None
high_int_return_reg = None
float_return_reg = None
+ global_pointer_reg = None
+ implicitly_defined_regs = []
_registered_calling_conventions = []
@@ -58,6 +62,10 @@ class CallingConvention(object):
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)
+ self._cb.getGlobalPointerRegister = self._cb.getGlobalPointerRegister.__class__(self._get_global_pointer_reg)
+ 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.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb)
self.__class__._registered_calling_conventions.append(self)
else:
@@ -112,6 +120,21 @@ class CallingConvention(object):
else:
self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg)
+ reg = core.BNGetGlobalPointerRegister(self.handle)
+ if reg == 0xffffffff:
+ self.__dict__["global_pointer_reg"] = None
+ else:
+ self.__dict__["global_pointer_reg"] = self.arch.get_reg_name(reg)
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetImplicitlyDefinedRegisters(self.handle, count)
+ result = []
+ arch = self.arch
+ for i in xrange(0, count.value):
+ result.append(arch.get_reg_name(regs[i]))
+ core.BNFreeRegisterList(regs, count.value)
+ self.__dict__["implicitly_defined_regs"] = result
+
self.confidence = confidence
def __del__(self):
@@ -220,12 +243,76 @@ class CallingConvention(object):
log.log_error(traceback.format_exc())
return False
+ def _get_global_pointer_reg(self, ctxt):
+ try:
+ if self.__class__.global_pointer_reg is None:
+ return 0xffffffff
+ return self.arch.regs[self.__class__.global_pointer_reg].index
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ def _get_implicitly_defined_regs(self, ctxt, count):
+ try:
+ regs = self.__class__.implicitly_defined_regs
+ count[0] = len(regs)
+ reg_buf = (ctypes.c_uint * len(regs))()
+ for i in xrange(0, len(regs)):
+ reg_buf[i] = self.arch.regs[regs[i]].index
+ result = ctypes.cast(reg_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, reg_buf)
+ return result.value
+ except:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_incoming_reg_value(self, ctxt, reg, func):
+ try:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ reg_name = self.arch.get_reg_name(reg)
+ return self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object()
+ except:
+ log.log_error(traceback.format_exc())
+ return function.RegisterValue()._to_api_object()
+
+ def _get_incoming_flag_value(self, ctxt, reg, func):
+ try:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ reg_name = self.arch.get_reg_name(reg)
+ return self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object()
+ except:
+ log.log_error(traceback.format_exc())
+ return function.RegisterValue()._to_api_object()
+
def __repr__(self):
return "<calling convention: %s %s>" % (self.arch.name, self.name)
def __str__(self):
return self.name
+ def perform_get_incoming_reg_value(self, reg, func):
+ return function.RegisterValue()
+
+ def perform_get_incoming_flag_value(self, reg, func):
+ return function.RegisterValue()
+
def with_confidence(self, confidence):
return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle),
confidence = confidence)
+
+ def get_incoming_reg_value(self, reg, func):
+ reg_num = self.arch.get_reg_index(reg)
+ func_handle = None
+ if func is not None:
+ func_handle = func.handle
+ return function.RegisterValue(self.arch, core.BNGetIncomingRegisterValue(self.handle, reg_num, func_handle))
+
+ def get_incoming_flag_value(self, flag, func):
+ reg_num = self.arch.get_flag_index(flag)
+ func_handle = None
+ if func is not None:
+ func_handle = func.handle
+ return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle))
diff --git a/python/function.py b/python/function.py
index b14ba53e..cf9bd759 100644
--- a/python/function.py
+++ b/python/function.py
@@ -37,6 +37,7 @@ import lowlevelil
import mediumlevelil
import binaryview
import log
+import callingconvention
class LookupTableEntry(object):
@@ -49,26 +50,50 @@ class LookupTableEntry(object):
class RegisterValue(object):
- def __init__(self, arch, value):
- self.type = RegisterValueType(value.state)
- if value.state == RegisterValueType.EntryValue:
- self.reg = arch.get_reg_name(value.value)
- elif value.state == RegisterValueType.ConstantValue:
- self.value = value.value
- elif value.state == RegisterValueType.StackFrameOffset:
- self.offset = value.value
+ def __init__(self, arch = None, value = None):
+ if value is None:
+ self.type = RegisterValueType.UndeterminedValue
+ else:
+ self.type = RegisterValueType(value.state)
+ if value.state == RegisterValueType.EntryValue:
+ self.arch = arch
+ if arch is not None:
+ self.reg = arch.get_reg_name(value.value)
+ else:
+ self.reg = value.value
+ elif (value.state == RegisterValueType.ConstantValue) or (value.state == RegisterValueType.ConstantPointerValue):
+ self.value = value.value
+ elif value.state == RegisterValueType.StackFrameOffset:
+ self.offset = value.value
def __repr__(self):
if self.type == RegisterValueType.EntryValue:
return "<entry %s>" % self.reg
if self.type == RegisterValueType.ConstantValue:
return "<const %#x>" % self.value
+ if self.type == RegisterValueType.ConstantPointerValue:
+ return "<const ptr %#x>" % self.value
if self.type == RegisterValueType.StackFrameOffset:
return "<stack frame offset %#x>" % self.offset
if self.type == RegisterValueType.ReturnAddressValue:
return "<return address>"
return "<undetermined>"
+ def _to_api_object(self):
+ result = core.BNRegisterValue()
+ result.state = self.type
+ result.value = 0
+ if self.type == RegisterValueType.EntryValue:
+ if self.arch is not None:
+ result.value = self.arch.get_reg_index(self.reg)
+ else:
+ result.value = self.reg
+ elif (self.type == RegisterValueType.ConstantValue) or (self.type == RegisterValueType.ConstantPointerValue):
+ result.value = self.value
+ elif self.type == RegisterValueType.StackFrameOffset:
+ result.value = self.offset
+ return result
+
class ValueRange(object):
def __init__(self, start, end, step):
@@ -240,6 +265,25 @@ class IndirectBranchInfo(object):
return "<branch %s:%#x -> %s:%#x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr)
+class ParameterVariables(object):
+ def __init__(self, var_list, confidence = types.max_confidence):
+ self.vars = var_list
+ self.confidence = confidence
+
+ def __repr__(self):
+ return repr(self.vars)
+
+ def __iter__(self):
+ for var in self.vars:
+ yield var
+
+ def __getitem__(self, idx):
+ return self.vars[idx]
+
+ def with_confidence(self, confidence):
+ return ParameterVariables(list(self.vars), confidence = confidence)
+
+
class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore):
_defaults = {}
@@ -335,8 +379,19 @@ class Function(object):
@property
def can_return(self):
- """Whether function can return (read-only)"""
- return core.BNCanFunctionReturn(self.handle)
+ """Whether function can return"""
+ result = core.BNCanFunctionReturn(self.handle)
+ return types.BoolWithConfidence(result.value, confidence = result.confidence)
+
+ @can_return.setter
+ def can_return(self, value):
+ bc = core.BNBoolWithConfidence()
+ bc.value = bool(value)
+ if hasattr(value, 'confidence'):
+ bc.confidence = value.confidence
+ else:
+ bc.confidence = types.max_confidence
+ core.BNSetUserFunctionCanReturn(self.handle, bc)
@property
def explicitly_defined_type(self):
@@ -452,6 +507,97 @@ class Function(object):
core.BNFreeAnalysisPerformanceInfo(info, count.value)
return result
+ @property
+ def type_tokens(self):
+ """Text tokens for this function's prototype"""
+ return self.get_type_tokens()[0].tokens
+
+ @property
+ def return_type(self):
+ """Return type of the function"""
+ result = core.BNGetFunctionReturnType(self.handle)
+ if not result.type:
+ return None
+ return types.Type(result.type, confidence = result.confidence)
+
+ @return_type.setter
+ def return_type(self, value):
+ type_conf = core.BNTypeWithConfidence()
+ if value is None:
+ type_conf.type = None
+ type_conf.confidence = 0
+ else:
+ type_conf.type = value.handle
+ type_conf.confidence = value.confidence
+ core.BNSetUserFunctionReturnType(self.handle, type_conf)
+
+ @property
+ def calling_convention(self):
+ """Calling convention used by the function"""
+ result = core.BNGetFunctionCallingConvention(self.handle)
+ if not result.convention:
+ return None
+ return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence)
+
+ @calling_convention.setter
+ def calling_convention(self, value):
+ conv_conf = core.BNCallingConventionWithConfidence()
+ if value is None:
+ conv_conf.convention = None
+ conv_conf.confidence = 0
+ else:
+ conv_conf.convention = value.handle
+ conv_conf.confidence = value.confidence
+ core.BNSetUserFunctionCallingConvention(self.handle, conv_conf)
+
+ @property
+ def parameter_vars(self):
+ """List of variables for the incoming function parameters"""
+ result = core.BNGetFunctionParameterVariables(self.handle)
+ var_list = []
+ for i in xrange(0, result.count):
+ var_list.append(Variable(self, result.vars[i].type, result.vars[i].index, result.vars[i].storage))
+ confidence = result.confidence
+ core.BNFreeParameterVariables(result)
+ return ParameterVariables(var_list, confidence = confidence)
+
+ @parameter_vars.setter
+ def parameter_vars(self, value):
+ if value is None:
+ var_list = []
+ else:
+ var_list = list(value)
+ var_conf = core.BNParameterVariablesWithConfidence()
+ var_conf.vars = (core.BNVariable * len(var_list))()
+ var_conf.count = len(var_list)
+ for i in xrange(0, len(var_list)):
+ var_conf.vars[i].type = var_list[i].source_type
+ var_conf.vars[i].index = var_list[i].index
+ var_conf.vars[i].storage = var_list[i].storage
+ if value is None:
+ var_conf.confidence = 0
+ elif hasattr(value, 'confidence'):
+ var_conf.confidence = value.confidence
+ else:
+ var_conf.confidence = types.max_confidence
+ core.BNSetUserFunctionParameterVariables(self.handle, var_conf)
+
+ @property
+ def has_variable_arguments(self):
+ """Whether the function takes a variable number of arguments"""
+ result = core.BNFunctionHasVariableArguments(self.handle)
+ return types.BoolWithConfidence(result.value, confidence = result.confidence)
+
+ @has_variable_arguments.setter
+ def has_variable_arguments(self, value):
+ bc = core.BNBoolWithConfidence()
+ bc.value = bool(value)
+ if hasattr(value, 'confidence'):
+ bc.confidence = value.confidence
+ else:
+ bc.confidence = types.max_confidence
+ core.BNSetUserFunctionHasVariableArguments(self.handle, bc)
+
def __iter__(self):
count = ctypes.c_ulonglong()
blocks = core.BNGetFunctionBasicBlockList(self.handle, count)
@@ -759,6 +905,64 @@ class Function(object):
def set_user_type(self, value):
core.BNSetFunctionUserType(self.handle, value.handle)
+ def set_auto_return_type(self, value):
+ type_conf = core.BNTypeWithConfidence()
+ if value is None:
+ type_conf.type = None
+ type_conf.confidence = 0
+ else:
+ type_conf.type = value.handle
+ type_conf.confidence = value.confidence
+ core.BNSetAutoFunctionReturnType(self.handle, type_conf)
+
+ def set_auto_calling_convention(self, value):
+ conv_conf = core.BNCallingConventionWithConfidence()
+ if value is None:
+ conv_conf.convention = None
+ conv_conf.confidence = 0
+ else:
+ conv_conf.convention = value.handle
+ conv_conf.confidence = value.confidence
+ core.BNSetAutoFunctionCallingConvention(self.handle, conv_conf)
+
+ def set_auto_parameter_vars(self, value):
+ if value is None:
+ var_list = []
+ else:
+ var_list = list(value)
+ var_conf = core.BNParameterVariablesWithConfidence()
+ var_conf.vars = (core.BNVariable * len(var_list))()
+ var_conf.count = len(var_list)
+ for i in xrange(0, len(var_list)):
+ var_conf.vars[i].type = var_list[i].source_type
+ var_conf.vars[i].index = var_list[i].index
+ var_conf.vars[i].storage = var_list[i].storage
+ if value is None:
+ var_conf.confidence = 0
+ elif hasattr(value, 'confidence'):
+ var_conf.confidence = value.confidence
+ else:
+ var_conf.confidence = types.max_confidence
+ core.BNSetAutoFunctionParameterVariables(self.handle, var_conf)
+
+ def set_auto_has_variable_arguments(self, value):
+ bc = core.BNBoolWithConfidence()
+ bc.value = bool(value)
+ if hasattr(value, 'confidence'):
+ bc.confidence = value.confidence
+ else:
+ bc.confidence = types.max_confidence
+ core.BNSetAutoFunctionHasVariableArguments(self.handle, bc)
+
+ def set_auto_can_return(self, value):
+ bc = core.BNBoolWithConfidence()
+ bc.value = bool(value)
+ if hasattr(value, 'confidence'):
+ bc.confidence = value.confidence
+ else:
+ bc.confidence = types.max_confidence
+ core.BNSetAutoFunctionCanReturn(self.handle, bc)
+
def get_int_display_type(self, instr_addr, value, operand, arch=None):
if arch is None:
arch = self.arch
@@ -932,6 +1136,29 @@ class Function(object):
core.BNFreeVariableNameAndType(found_var)
return result
+ def get_type_tokens(self, settings=None):
+ if settings is not None:
+ settings = settings.handle
+ count = ctypes.c_ulonglong()
+ lines = core.BNGetFunctionTypeTokens(self.handle, settings, count)
+ result = []
+ for i in xrange(0, count.value):
+ addr = lines[i].addr
+ tokens = []
+ for j in xrange(0, lines[i].count):
+ token_type = InstructionTextTokenType(lines[i].tokens[j].type)
+ text = lines[i].tokens[j].text
+ value = lines[i].tokens[j].value
+ size = lines[i].tokens[j].size
+ operand = lines[i].tokens[j].operand
+ context = lines[i].tokens[j].context
+ confidence = lines[i].tokens[j].confidence
+ address = lines[i].tokens[j].address
+ tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
+ result.append(DisassemblyTextLine(addr, tokens))
+ core.BNFreeDisassemblyTextLines(lines, count.value)
+ return result
+
class AdvancedFunctionAnalysisDataRequestor(object):
def __init__(self, func = None):
diff --git a/python/types.py b/python/types.py
index 47d99bee..e297ddd2 100644
--- a/python/types.py
+++ b/python/types.py
@@ -279,7 +279,7 @@ class Type(object):
result = core.BNGetTypeCallingConvention(self.handle)
if not result.convention:
return None
- return callingconvention.CallingConvention(None, handle = result, confidence = result.confidence)
+ return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence)
@property
def parameters(self):
@@ -295,7 +295,8 @@ class Type(object):
@property
def has_variable_arguments(self):
"""Whether type has variable arguments (read-only)"""
- return core.BNTypeHasVariableArguments(self.handle)
+ result = core.BNTypeHasVariableArguments(self.handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
@property
def can_return(self):
@@ -505,7 +506,7 @@ class Type(object):
return Type(core.BNCreateArrayType(type_conf, count))
@classmethod
- def function(self, ret, params, calling_convention=None, variable_arguments=False):
+ def function(self, ret, params, calling_convention=None, variable_arguments=None):
"""
``function`` class method for creating an function Type.
@@ -537,8 +538,17 @@ class Type(object):
conv_conf.convention = calling_convention.handle
conv_conf.confidence = calling_convention.confidence
+ if variable_arguments is None:
+ variable_arguments = BoolWithConfidence(False, confidence = 0)
+ elif not isinstance(variable_arguments, BoolWithConfidence):
+ variable_arguments = BoolWithConfidence(variable_arguments)
+
+ vararg_conf = core.BNBoolWithConfidence()
+ vararg_conf.value = variable_arguments.value
+ vararg_conf.confidence = variable_arguments.confidence
+
return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params),
- variable_arguments))
+ vararg_conf))
@classmethod
def generate_auto_type_id(self, source, name):
diff --git a/type.cpp b/type.cpp
index 19624cdd..398a7216 100644
--- a/type.cpp
+++ b/type.cpp
@@ -368,9 +368,10 @@ vector<NameAndType> Type::GetParameters() const
}
-bool Type::HasVariableArguments() const
+Confidence<bool> Type::HasVariableArguments() const
{
- return BNTypeHasVariableArguments(m_object);
+ BNBoolWithConfidence result = BNTypeHasVariableArguments(m_object);
+ return Confidence<bool>(result.value, result.confidence);
}
@@ -655,7 +656,7 @@ Ref<Type> Type::ArrayType(const Confidence<Ref<Type>>& type, uint64_t elem)
Ref<Type> Type::FunctionType(const Confidence<Ref<Type>>& returnValue,
const Confidence<Ref<CallingConvention>>& callingConvention,
- const std::vector<NameAndType>& params, bool varArg)
+ const std::vector<NameAndType>& params, const Confidence<bool>& varArg)
{
BNTypeWithConfidence returnValueConf;
returnValueConf.type = returnValue->GetObject();
@@ -673,8 +674,12 @@ Ref<Type> Type::FunctionType(const Confidence<Ref<Type>>& returnValue,
paramArray[i].typeConfidence = params[i].type.GetConfidence();
}
+ BNBoolWithConfidence varArgConf;
+ varArgConf.value = varArg.GetValue();
+ varArgConf.confidence = varArg.GetConfidence();
+
Type* type = new Type(BNCreateFunctionType(&returnValueConf, &callingConventionConf,
- paramArray, params.size(), varArg));
+ paramArray, params.size(), &varArgConf));
delete[] paramArray;
return type;
}
@@ -685,7 +690,7 @@ void Type::SetFunctionCanReturn(const Confidence<bool>& canReturn)
BNBoolWithConfidence bc;
bc.value = canReturn.GetValue();
bc.confidence = canReturn.GetConfidence();
- BNSetFunctionCanReturn(m_object, &bc);
+ BNSetFunctionTypeCanReturn(m_object, &bc);
}