summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-08-15 00:24:03 -0400
committerRusty Wagner <rusty@vector35.com>2017-08-15 18:30:13 -0400
commitec2d882e1a165b703e8fedaa81246dcdd91f50f3 (patch)
treea6d9f2aebca1618db3aea5faf14ea6ddb60b7002
parent6bcb7bd30e5e6a8e69c875841f04245b8c3a0d7a (diff)
Add APIs to access and update portions of the function type, and added new APIs for global registers and implicit incoming state in calling conventions
-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);
}