summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Smith <couleeapps@gmail.com>2019-05-28 13:47:14 -0400
committerGlenn Smith <glenn@vector35.com>2019-08-01 18:36:03 -0400
commit087fdd83b85dd894d5b895557a378bb01828d0ff (patch)
tree8f9846be65885fa97cf934aa2e7dbd22cf150765
parent9bb1a15b800da0ac5b60c40e3b10321e4efc5a1b (diff)
Tags
-rw-r--r--architecture.cpp45
-rw-r--r--basicblock.cpp1
-rw-r--r--binaryninjaapi.h135
-rw-r--r--binaryninjacore.h97
-rw-r--r--binaryview.cpp459
-rw-r--r--datarenderer.cpp4
-rw-r--r--flowgraphnode.cpp2
-rw-r--r--function.cpp232
-rw-r--r--python/binaryview.py297
-rw-r--r--python/function.py250
-rw-r--r--ui/action.h12
-rw-r--r--ui/flowgraphwidget.h5
-rw-r--r--ui/linearview.h5
-rw-r--r--ui/taglist.h231
-rw-r--r--ui/tagtypelist.h142
-rw-r--r--ui/uitypes.h2
-rw-r--r--ui/viewframe.h5
17 files changed, 1905 insertions, 19 deletions
diff --git a/architecture.cpp b/architecture.cpp
index ae665e08..cd84dd05 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -49,38 +49,54 @@ void InstructionInfo::AddBranch(BNBranchType type, uint64_t target, Architecture
}
-InstructionTextToken::InstructionTextToken(): type(TextToken), value(0), confidence(BN_FULL_CONFIDENCE)
+InstructionTextToken::InstructionTextToken(): type(TextToken), value(0), width(WidthIsByteCount), confidence(BN_FULL_CONFIDENCE)
{
+ if (width == WidthIsByteCount)
+ {
+ width = text.size();
+ }
}
InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, const std::string& txt, uint64_t val,
- size_t s, size_t o, uint8_t c, const vector<string>& n) : type(t), text(txt), value(val), size(s), operand(o), context(NoTokenContext),
- confidence(c), address(0), typeNames(n)
+ size_t s, size_t o, uint8_t c, const vector<string>& n, uint64_t w) : type(t), text(txt), value(val), width(w), size(s), operand(o),
+ context(NoTokenContext), confidence(c), address(0), typeNames(n)
{
+ if (width == WidthIsByteCount)
+ {
+ width = text.size();
+ }
}
InstructionTextToken::InstructionTextToken(BNInstructionTextTokenType t, BNInstructionTextTokenContext ctxt,
- const string& txt, uint64_t a, uint64_t val, size_t s, size_t o, uint8_t c, const vector<string>& n):
- type(t), text(txt), value(val), size(s), operand(o), context(ctxt), confidence(c), address(a), typeNames(n)
+ const string& txt, uint64_t a, uint64_t val, size_t s, size_t o, uint8_t c, const vector<string>& n, uint64_t w):
+ type(t), text(txt), value(val), width(w), size(s), operand(o), context(ctxt), confidence(c), address(a), typeNames(n)
{
+ if (width == WidthIsByteCount)
+ {
+ width = text.size();
+ }
}
InstructionTextToken::InstructionTextToken(const BNInstructionTextToken& token):
- type(token.type), text(token.text), value(token.value), size(token.size), operand(token.operand),
- context(token.context), confidence(token.confidence), address(token.address)
+ type(token.type), text(token.text), value(token.value), width(token.width), size(token.size),
+ operand(token.operand), context(token.context), confidence(token.confidence), address(token.address)
{
typeNames.reserve(token.namesCount);
for (size_t j = 0; j < token.namesCount; j++)
typeNames.push_back(token.typeNames[j]);
+ if (width == WidthIsByteCount)
+ {
+ width = text.size();
+ }
}
InstructionTextToken InstructionTextToken::WithConfidence(uint8_t conf)
{
- return InstructionTextToken(type, context, text, address, value, size, operand, conf, typeNames);
+ return InstructionTextToken(type, context, text, address, value, size, operand, conf, typeNames, width);
}
@@ -89,6 +105,7 @@ static void ConvertInstructionTextToken(const InstructionTextToken& token, BNIns
result->type = token.type;
result->text = BNAllocString(token.text.c_str());
result->value = token.value;
+ result->width = token.width;
result->size = token.size;
result->operand = token.operand;
result->context = token.context;
@@ -2322,6 +2339,7 @@ bool DisassemblyTextRenderer::GetDisassemblyText(uint64_t addr, size_t& len, vec
line.instrIndex = result[i].instrIndex;
line.highlight = result[i].highlight;
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(result[i].tokens, result[i].count);
+ line.tags = Tag::ConvertAndFreeTagList(result[i].tags, result[i].tagCount);
lines.push_back(line);
}
@@ -2405,6 +2423,7 @@ void DisassemblyTextRenderer::WrapComment(DisassemblyTextLine& line, vector<Disa
inLine.highlight = line.highlight;
inLine.count = line.tokens.size();
inLine.tokens = InstructionTextToken::CreateInstructionTextTokenList(line.tokens);
+ inLine.tags = Tag::CreateTagList(line.tags, &inLine.tagCount);
size_t count = 0;
BNDisassemblyTextLine* result = BNDisassemblyTextRendererWrapComment(m_object, &inLine, &count,
@@ -2417,16 +2436,10 @@ void DisassemblyTextRenderer::WrapComment(DisassemblyTextLine& line, vector<Disa
line.instrIndex = result[i].instrIndex;
line.highlight = result[i].highlight;
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(result[i].tokens, result[i].count);
+ line.tags = Tag::ConvertAndFreeTagList(result[i].tags, result[i].tagCount);
lines.push_back(line);
}
BNFreeDisassemblyTextLines(result, count);
- for (size_t i = 0; i < inLine.count; i++)
- {
- BNFreeString(inLine.tokens[i].text);
- for (size_t j = 0; j < inLine.tokens[j].namesCount; j++)
- BNFreeString(inLine.tokens[i].typeNames[j]);
- delete[] inLine.tokens[i].typeNames;
- }
- delete[] inLine.tokens;
+ BNFreeInstructionText(inLine.tokens, inLine.count);
}
diff --git a/basicblock.cpp b/basicblock.cpp
index c34a4bb7..03a2386f 100644
--- a/basicblock.cpp
+++ b/basicblock.cpp
@@ -296,6 +296,7 @@ vector<DisassemblyTextLine> BasicBlock::GetDisassemblyText(DisassemblySettings*
line.instrIndex = lines[i].instrIndex;
line.highlight = lines[i].highlight;
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(lines[i].tokens, lines[i].count);
+ line.tags = Tag::ConvertAndFreeTagList(lines[i].tags, lines[i].tagCount);
result.push_back(line);
}
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 25c32b1c..02dc26c2 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -881,6 +881,7 @@ namespace BinaryNinja
class Function;
struct DataVariable;
class Symbol;
+ class Tag;
class BinaryDataNotification
{
@@ -1090,9 +1091,15 @@ namespace BinaryNinja
struct InstructionTextToken
{
+ enum
+ {
+ WidthIsByteCount = 0
+ };
+
BNInstructionTextTokenType type;
std::string text;
uint64_t value;
+ uint64_t width;
size_t size, operand;
BNInstructionTextTokenContext context;
uint8_t confidence;
@@ -1103,10 +1110,10 @@ namespace BinaryNinja
InstructionTextToken(uint8_t confidence, BNInstructionTextTokenType t, const std::string& txt);
InstructionTextToken(BNInstructionTextTokenType type, const std::string& text, uint64_t value = 0,
size_t size = 0, size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE,
- const std::vector<std::string>& typeName={});
+ const std::vector<std::string>& typeName={}, uint64_t width = WidthIsByteCount);
InstructionTextToken(BNInstructionTextTokenType type, BNInstructionTextTokenContext context,
const std::string& text, uint64_t address, uint64_t value = 0, size_t size = 0,
- size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE, const std::vector<std::string>& typeName={});
+ size_t operand = BN_INVALID_OPERAND, uint8_t confidence = BN_FULL_CONFIDENCE, const std::vector<std::string>& typeName={}, uint64_t width = WidthIsByteCount);
InstructionTextToken(const BNInstructionTextToken& token);
InstructionTextToken WithConfidence(uint8_t conf);
@@ -1116,12 +1123,14 @@ namespace BinaryNinja
};
+ class Tag;
struct DisassemblyTextLine
{
uint64_t addr;
size_t instrIndex;
std::vector<InstructionTextToken> tokens;
BNHighlightColor highlight;
+ std::vector<Ref<Tag>> tags;
DisassemblyTextLine();
};
@@ -1187,6 +1196,67 @@ namespace BinaryNinja
bool autoDiscovered;
};
+ class TagType: public CoreRefCountObject<BNTagType, BNNewTagTypeReference, BNFreeTagType>
+ {
+ public:
+ typedef BNTagTypeType Type;
+
+ TagType(BNTagType* tagType);
+ TagType(BinaryView* view);
+ TagType(BinaryView* view, const std::string& name, const std::string& icon, bool visible = true, Type type = UserTagType);
+
+ BinaryView* GetView() const;
+ std::string GetName() const;
+ void SetName(const std::string& name);
+ std::string GetIcon() const;
+ void SetIcon(const std::string& icon);
+ bool GetVisible() const;
+ void SetVisible(bool visible);
+ Type GetType() const;
+ void SetType(Type type);
+ };
+
+ class Tag: public CoreRefCountObject<BNTag, BNNewTagReference, BNFreeTag>
+ {
+ public:
+ Tag(BNTag* tag);
+ Tag(Ref<TagType> type, const std::string& data = "");
+
+ Ref<TagType> GetType() const;
+ std::string GetData() const;
+ void SetData(const std::string& data);
+
+ static BNTag** CreateTagList(const std::vector<Ref<Tag>>& tags, size_t* count);
+ static std::vector<Ref<Tag>> ConvertTagList(BNTag** tags, size_t count);
+ static std::vector<Ref<Tag>> ConvertAndFreeTagList(BNTag** tags, size_t count);
+ };
+
+ class Architecture;
+ class Function;
+ struct TagReference
+ {
+ typedef BNTagReferenceType RefType;
+
+ RefType refType;
+ bool autoDefined;
+ Ref<Tag> tag;
+ Ref<Architecture> arch;
+ Ref<Function> func;
+ uint64_t addr;
+
+ TagReference();
+ TagReference(const BNTagReference& ref);
+
+ bool operator==(const TagReference& other) const;
+ bool operator!=(const TagReference& other) const;
+
+ operator BNTagReference() const;
+
+ static BNTagReference* CreateTagReferenceList(const std::vector<TagReference>& tags, size_t* count);
+ static std::vector<TagReference> ConvertTagReferenceList(BNTagReference* tags, size_t count);
+ static std::vector<TagReference> ConvertAndFreeTagReferenceList(BNTagReference* tags, size_t count);
+ };
+
class Relocation;
class Segment: public CoreRefCountObject<BNSegment, BNNewSegmentReference, BNFreeSegment>
{
@@ -1456,6 +1526,38 @@ namespace BinaryNinja
void DefineImportedFunction(Ref<Symbol> importAddressSym, Ref<Function> func);
+ void AddTagType(Ref<TagType> tagType);
+ void RemoveTagType(Ref<TagType> tagType);
+ Ref<TagType> GetTagType(const std::string& name);
+ Ref<TagType> GetTagType(const std::string& name, TagType::Type type);
+ std::vector<Ref<TagType>> GetTagTypes();
+
+ void AddTag(Ref<Tag> tag);
+ void RemoveTag(Ref<Tag> tag);
+ Ref<Tag> GetTag(uint64_t tagId);
+
+ std::vector<TagReference> GetAllTagReferences();
+ std::vector<TagReference> GetAllAddressTagReferences();
+ std::vector<TagReference> GetAllFunctionTagReferences();
+ std::vector<TagReference> GetAllTagReferencesOfType(Ref<TagType> tagType);
+ std::vector<TagReference> GetTagReferencesOfType(Ref<TagType> tagType);
+
+ std::vector<TagReference> GetDataTagReferences();
+ std::vector<Ref<Tag>> GetDataTags(uint64_t addr);
+ std::vector<Ref<Tag>> GetDataTagsOfType(uint64_t addr, Ref<TagType> tagType);
+ std::vector<Ref<Tag>> GetDataTagsInRange(uint64_t start, uint64_t end);
+ void AddAutoDataTag(uint64_t addr, Ref<Tag> tag);
+ void RemoveAutoDataTag(uint64_t addr, Ref<Tag> tag);
+ void AddUserDataTag(uint64_t addr, Ref<Tag> tag);
+ void RemoveUserDataTag(uint64_t addr, Ref<Tag> tag);
+ void RemoveTagReference(const TagReference& ref);
+
+ Ref<Tag> CreateAutoDataTag(uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserDataTag(uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique = false);
+
+ Ref<Tag> CreateAutoDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
+
bool IsNeverBranchPatchAvailable(Architecture* arch, uint64_t addr);
bool IsAlwaysBranchPatchAvailable(Architecture* arch, uint64_t addr);
bool IsInvertBranchPatchAvailable(Architecture* arch, uint64_t addr);
@@ -2748,6 +2850,35 @@ namespace BinaryNinja
void SetUserInstructionHighlight(Architecture* arch, uint64_t addr, uint8_t r, uint8_t g, uint8_t b,
uint8_t alpha = 255);
+ std::vector<TagReference> GetAllTagReferences();
+ std::vector<TagReference> GetTagReferencesOfType(Ref<TagType> tagType);
+
+ std::vector<TagReference> GetAddressTagReferences();
+ std::vector<Ref<Tag>> GetAddressTags(Architecture* arch, uint64_t addr);
+ std::vector<Ref<Tag>> GetAddressTagsOfType(Architecture* arch, uint64_t addr, Ref<TagType> tagType);
+ void AddAutoAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag);
+ void RemoveAutoAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag);
+ void AddUserAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag);
+ void RemoveUserAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag);
+
+ std::vector<TagReference> GetFunctionTagReferences();
+ std::vector<Ref<Tag>> GetFunctionTags();
+ std::vector<Ref<Tag>> GetFunctionTagsOfType(Ref<TagType> tagType);
+ void AddAutoFunctionTag(Ref<Tag> tag);
+ void RemoveAutoFunctionTag(Ref<Tag> tag);
+ void AddUserFunctionTag(Ref<Tag> tag);
+ void RemoveUserFunctionTag(Ref<Tag> tag);
+
+ Ref<Tag> CreateAutoAddressTag(Architecture* arch, uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserAddressTag(Architecture* arch, uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique = false);
+ Ref<Tag> CreateAutoFunctionTag(const std::string& tagTypeName, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserFunctionTag(const std::string& tagTypeName, const std::string& data, bool unique = false);
+
+ Ref<Tag> CreateAutoAddressTag(Architecture* arch, uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserAddressTag(Architecture* arch, uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
+ Ref<Tag> CreateAutoFunctionTag(Ref<TagType> tagType, const std::string& data, bool unique = false);
+ Ref<Tag> CreateUserFunctionTag(Ref<TagType> tagType, const std::string& data, bool unique = false);
+
void Reanalyze();
void RequestAdvancedAnalysisData();
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 903e6a45..7dc1f8c2 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -136,6 +136,8 @@ extern "C"
struct BNMediumLevelILFunction;
struct BNType;
struct BNStructure;
+ struct BNTagType;
+ struct BNTag;
struct BNNamedTypeReference;
struct BNEnumeration;
struct BNCallingConvention;
@@ -238,6 +240,7 @@ extern "C"
FieldNameToken = 21,
NameSpaceToken = 22,
NameSpaceSeparatorToken = 23,
+ TagToken = 24,
// The following are output by the analysis system automatically, these should
// not be used directly by the architecture plugins
CodeSymbolToken = 64,
@@ -1198,6 +1201,7 @@ extern "C"
BNInstructionTextTokenType type;
char* text;
uint64_t value;
+ uint64_t width;
size_t size, operand;
BNInstructionTextTokenContext context;
uint8_t confidence;
@@ -1361,6 +1365,8 @@ extern "C"
BNInstructionTextToken* tokens;
size_t count;
BNHighlightColor highlight;
+ BNTag** tags;
+ size_t tagCount;
};
struct BNLinearDisassemblyLine
@@ -1386,6 +1392,30 @@ extern "C"
uint64_t addr;
};
+ enum BNTagTypeType
+ {
+ UserTagType,
+ NotificationTagType,
+ BookmarksTagType
+ };
+
+ enum BNTagReferenceType
+ {
+ AddressTagReference,
+ FunctionTagReference,
+ DataTagReference
+ };
+
+ struct BNTagReference
+ {
+ BNTagReferenceType refType;
+ bool autoDefined;
+ BNTag* tag;
+ BNArchitecture* arch;
+ BNFunction* func;
+ uint64_t addr;
+ };
+
struct BNUndoAction
{
BNActionType type;
@@ -2902,6 +2932,73 @@ extern "C"
BINARYNINJACOREAPI void BNSetAutoBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color);
BINARYNINJACOREAPI void BNSetUserBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color);
+ BINARYNINJACOREAPI BNTagType* BNCreateTagType(BNBinaryView* view);
+ BINARYNINJACOREAPI BNTagType* BNNewTagTypeReference(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNFreeTagType(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNFreeTagTypeList(BNTagType** tagTypes, size_t count);
+ BINARYNINJACOREAPI BNBinaryView* BNTagTypeGetView(BNTagType* tagType);
+ BINARYNINJACOREAPI char* BNTagTypeGetName(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNTagTypeSetName(BNTagType* tagType, const char* name);
+ BINARYNINJACOREAPI char* BNTagTypeGetIcon(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNTagTypeSetIcon(BNTagType* tagType, const char* icon);
+ BINARYNINJACOREAPI bool BNTagTypeGetVisible(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNTagTypeSetVisible(BNTagType* tagType, bool visible);
+ BINARYNINJACOREAPI BNTagTypeType BNTagTypeGetType(BNTagType* tagType);
+ BINARYNINJACOREAPI void BNTagTypeSetType(BNTagType* tagType, BNTagTypeType type);
+
+ BINARYNINJACOREAPI BNTag* BNCreateTag(BNTagType* type, const char* data);
+ BINARYNINJACOREAPI BNTag* BNNewTagReference(BNTag* tag);
+ BINARYNINJACOREAPI void BNFreeTag(BNTag* tag);
+ BINARYNINJACOREAPI void BNFreeTagList(BNTag** tags, size_t count);
+ BINARYNINJACOREAPI BNTagType* BNTagGetType(BNTag* tag);
+ BINARYNINJACOREAPI char* BNTagGetData(BNTag* tag);
+ BINARYNINJACOREAPI void BNTagSetData(BNTag* tag, const char* data);
+
+ BINARYNINJACOREAPI void BNAddTagType(BNBinaryView* view, BNTagType* tagType);
+ BINARYNINJACOREAPI void BNRemoveTagType(BNBinaryView* view, BNTagType* tagType);
+ BINARYNINJACOREAPI BNTagType* BNGetTagType(BNBinaryView* view, const char* name);
+ BINARYNINJACOREAPI BNTagType* BNGetTagTypeWithType(BNBinaryView* view, const char* name, BNTagTypeType type);
+ BINARYNINJACOREAPI BNTagType** BNGetTagTypes(BNBinaryView* view, size_t* count);
+
+ BINARYNINJACOREAPI void BNAddTag(BNBinaryView* view, BNTag* tag);
+ BINARYNINJACOREAPI BNTag* BNGetTag(BNBinaryView* view, uint64_t tagId);
+ BINARYNINJACOREAPI void BNRemoveTag(BNBinaryView* view, BNTag* tag);
+
+ BINARYNINJACOREAPI BNTagReference* BNGetAllTagReferences(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetAllAddressTagReferences(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetAllFunctionTagReferences(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetAllTagReferencesOfType(BNBinaryView* view, BNTagType* tagType, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetTagReferencesOfType(BNBinaryView* view, BNTagType* tagType, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetDataTagReferences(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI void BNFreeTagReferences(BNTagReference* refs, size_t count);
+ BINARYNINJACOREAPI BNTag** BNGetDataTags(BNBinaryView* view, uint64_t addr, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetDataTagsOfType(BNBinaryView* view, uint64_t addr, BNTagType* tagType, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetDataTagsInRange(BNBinaryView* view, uint64_t start, uint64_t end, size_t* count);
+ BINARYNINJACOREAPI void BNAddAutoDataTag(BNBinaryView* view, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveAutoDataTag(BNBinaryView* view, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNAddUserDataTag(BNBinaryView* view, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveUserDataTag(BNBinaryView* view, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveTagReference(BNBinaryView* view, BNTagReference ref);
+
+ BINARYNINJACOREAPI BNTagReference* BNGetFunctionAllTagReferences(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNTagReference* BNGetFunctionTagReferencesOfType(BNFunction* func, BNTagType* tagType, size_t* count);
+
+ BINARYNINJACOREAPI BNTagReference* BNGetAddressTagReferences(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetAddressTags(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetAddressTagsOfType(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNTagType* tagType, size_t* count);
+ BINARYNINJACOREAPI void BNAddAutoAddressTag(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveAutoAddressTag(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNAddUserAddressTag(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveUserAddressTag(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNTag* tag);
+
+ BINARYNINJACOREAPI BNTagReference* BNGetFunctionTagReferences(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetFunctionTags(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNTag** BNGetFunctionTagsOfType(BNFunction* func, BNTagType* tagType, size_t* count);
+ BINARYNINJACOREAPI void BNAddAutoFunctionTag(BNFunction* func, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveAutoFunctionTag(BNFunction* func, BNTag* tag);
+ BINARYNINJACOREAPI void BNAddUserFunctionTag(BNFunction* func, BNTag* tag);
+ BINARYNINJACOREAPI void BNRemoveUserFunctionTag(BNFunction* func, BNTag* tag);
+
BINARYNINJACOREAPI BNPerformanceInfo* BNGetFunctionAnalysisPerformanceInfo(BNFunction* func, size_t* count);
BINARYNINJACOREAPI void BNFreeAnalysisPerformanceInfo(BNPerformanceInfo* info, size_t count);
diff --git a/binaryview.cpp b/binaryview.cpp
index fd93b340..553ce251 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -342,6 +342,230 @@ void AnalysisCompletionEvent::Cancel()
}
+TagType::TagType(BNTagType* tagType)
+{
+ m_object = tagType;
+}
+
+
+TagType::TagType(BinaryView* view)
+{
+ m_object = BNCreateTagType(view->GetObject());
+}
+
+
+TagType::TagType(BinaryView* view, const std::string& name, const std::string& icon, bool visible, TagType::Type type)
+{
+ m_object = BNCreateTagType(view->GetObject());
+ SetName(name);
+ SetIcon(icon);
+ SetVisible(visible);
+ SetType(type);
+}
+
+
+BinaryView* TagType::GetView() const
+{
+ return new BinaryView(BNTagTypeGetView(m_object));
+}
+
+
+std::string TagType::GetName() const
+{
+ return BNTagTypeGetName(m_object);
+}
+
+
+void TagType::SetName(const std::string& name)
+{
+ BNTagTypeSetName(m_object, name.c_str());
+}
+
+
+std::string TagType::GetIcon() const
+{
+ return BNTagTypeGetIcon(m_object);
+}
+
+
+void TagType::SetIcon(const std::string& icon)
+{
+ BNTagTypeSetIcon(m_object, icon.c_str());
+}
+
+
+bool TagType::GetVisible() const
+{
+ return BNTagTypeGetVisible(m_object);
+}
+
+
+void TagType::SetVisible(bool visible)
+{
+ BNTagTypeSetVisible(m_object, visible);
+}
+
+
+TagType::Type TagType::GetType() const
+{
+ return BNTagTypeGetType(m_object);
+}
+
+
+void TagType::SetType(TagType::Type type)
+{
+ BNTagTypeSetType(m_object, type);
+}
+
+
+Tag::Tag(BNTag* tag)
+{
+ m_object = tag;
+}
+
+
+Tag::Tag(Ref<TagType> type, const std::string& data)
+{
+ m_object = BNCreateTag(type->GetObject(), data.c_str());
+}
+
+
+Ref<TagType> Tag::GetType() const
+{
+ return new TagType(BNTagGetType(m_object));
+}
+
+
+std::string Tag::GetData() const
+{
+ return BNTagGetData(m_object);
+}
+
+
+void Tag::SetData(const std::string& data)
+{
+ BNTagSetData(m_object, data.c_str());
+}
+
+
+BNTag** Tag::CreateTagList(const std::vector<Ref<Tag>>& tags, size_t* count)
+{
+ *count = tags.size();
+ BNTag** result = new BNTag*[tags.size()];
+ for (size_t i = 0; i < tags.size(); i++)
+ result[i] = tags[i]->GetObject();
+ return result;
+}
+
+
+std::vector<Ref<Tag>> Tag::ConvertTagList(BNTag** tags, size_t count)
+{
+ std::vector<Ref<Tag>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(new Tag(BNNewTagReference(tags[i])));
+ return result;
+}
+
+
+std::vector<Ref<Tag>> Tag::ConvertAndFreeTagList(BNTag** tags, size_t count)
+{
+ auto result = ConvertTagList(tags, count);
+ BNFreeTagList(tags, count);
+ return result;
+}
+
+
+TagReference::TagReference()
+{
+}
+
+
+TagReference::TagReference(const BNTagReference& ref)
+{
+ refType = ref.refType;
+ autoDefined = ref.autoDefined;
+ tag = ref.tag ? new Tag(BNNewTagReference(ref.tag)) : nullptr;
+ arch = ref.arch ? new CoreArchitecture(ref.arch) : nullptr;
+ func = ref.func ? new Function(BNNewFunctionReference(ref.func)) : nullptr;
+ addr = ref.addr;
+}
+
+
+bool TagReference::operator==(const TagReference& other) const
+{
+ if (refType != other.refType)
+ return false;
+ if (autoDefined != other.autoDefined)
+ return false;
+ if (tag != other.tag)
+ return false;
+ switch (refType)
+ {
+ case AddressTagReference:
+ return func == other.func && arch == other.arch && addr == other.addr;
+ case FunctionTagReference:
+ return func == other.func;
+ case DataTagReference:
+ return addr == other.addr;
+ }
+}
+
+
+bool TagReference::operator!=(const TagReference& other) const
+{
+ return !((*this) == other);
+}
+
+
+TagReference::operator BNTagReference() const
+{
+ BNTagReference ret;
+ ret.refType = refType;
+ ret.autoDefined = autoDefined;
+ ret.tag = tag->GetObject();
+ ret.arch = arch ? arch->GetObject() : nullptr;
+ ret.func = func ? func->GetObject() : nullptr;
+ ret.addr = addr;
+ return ret;
+}
+
+
+BNTagReference* TagReference::CreateTagReferenceList(const std::vector<TagReference>& tags, size_t* count)
+{
+ *count = tags.size();
+
+ BNTagReference* refs = new BNTagReference[*count];
+
+ for (size_t i = 0; i < *count; i ++)
+ {
+ refs[i] = tags[i];
+ }
+
+ return refs;
+}
+
+
+std::vector<TagReference> TagReference::ConvertTagReferenceList(BNTagReference* tags, size_t count)
+{
+ std::vector<TagReference> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i ++)
+ {
+ result.emplace_back(tags[i]);
+ }
+ return result;
+}
+
+
+std::vector<TagReference> TagReference::ConvertAndFreeTagReferenceList(BNTagReference* tags, size_t count)
+{
+ auto result = ConvertTagReferenceList(tags, count);
+ BNFreeTagReferences(tags, count);
+ return result;
+}
+
+
Segment::Segment(BNSegment* seg)
{
m_object = seg;
@@ -1757,6 +1981,239 @@ void BinaryView::DefineImportedFunction(Ref<Symbol> importAddressSym, Ref<Functi
}
+void BinaryView::AddTagType(Ref<TagType> tagType)
+{
+ BNAddTagType(m_object, tagType->GetObject());
+}
+
+
+void BinaryView::RemoveTagType(Ref<TagType> tagType)
+{
+ BNRemoveTagType(m_object, tagType->GetObject());
+}
+
+
+Ref<TagType> BinaryView::GetTagType(const std::string& name)
+{
+ BNTagType* tagType = BNGetTagType(m_object, name.c_str());
+ if (!tagType)
+ return nullptr;
+
+ return Ref<TagType>(new TagType(tagType));
+}
+
+
+Ref<TagType> BinaryView::GetTagType(const std::string& name, TagType::Type type)
+{
+ BNTagType* tagType = BNGetTagTypeWithType(m_object, name.c_str(), type);
+ if (!tagType)
+ return nullptr;
+
+ return Ref<TagType>(new TagType(tagType));
+}
+
+
+std::vector<Ref<TagType>> BinaryView::GetTagTypes()
+{
+ size_t count;
+ BNTagType** tagTypes = BNGetTagTypes(m_object, &count);
+
+ std::vector<Ref<TagType>> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i ++)
+ {
+ result.push_back(new TagType(BNNewTagTypeReference(tagTypes[i])));
+ }
+ BNFreeTagTypeList(tagTypes, count);
+
+ return result;
+}
+
+
+void BinaryView::AddTag(Ref<Tag> tag)
+{
+ BNAddTag(m_object, tag->GetObject());
+}
+
+
+void BinaryView::RemoveTag(Ref<Tag> tag)
+{
+ BNRemoveTag(m_object, tag->GetObject());
+}
+
+
+Ref<Tag> BinaryView::GetTag(uint64_t tagId)
+{
+ BNTag* tag = BNGetTag(m_object, tagId);
+ if (!tag)
+ return nullptr;
+
+ return Ref<Tag>(new Tag(tag));
+}
+
+
+std::vector<TagReference> BinaryView::GetAllTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetAllTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> BinaryView::GetAllAddressTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetAllAddressTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> BinaryView::GetAllFunctionTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetAllFunctionTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> BinaryView::GetAllTagReferencesOfType(Ref<TagType> tagType)
+{
+ size_t count;
+ BNTagReference* refs = BNGetAllTagReferencesOfType(m_object, tagType->GetObject(), &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> BinaryView::GetTagReferencesOfType(Ref<TagType> tagType)
+{
+ size_t count;
+ BNTagReference* refs = BNGetTagReferencesOfType(m_object, tagType->GetObject(), &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> BinaryView::GetDataTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetDataTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<Ref<Tag>> BinaryView::GetDataTags(uint64_t addr)
+{
+ size_t count;
+ BNTag** tags = BNGetDataTags(m_object, addr, &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+std::vector<Ref<Tag>> BinaryView::GetDataTagsOfType(uint64_t addr, Ref<TagType> tagType)
+{
+ size_t count;
+ BNTag** tags = BNGetDataTagsOfType(m_object, addr, tagType->GetObject(), &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+std::vector<Ref<Tag>> BinaryView::GetDataTagsInRange(uint64_t start, uint64_t end)
+{
+ size_t count;
+ BNTag** tags = BNGetDataTagsInRange(m_object, start, end, &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+void BinaryView::AddAutoDataTag(uint64_t addr, Ref<Tag> tag)
+{
+ BNAddAutoDataTag(m_object, addr, tag->GetObject());
+}
+
+
+void BinaryView::RemoveAutoDataTag(uint64_t addr, Ref<Tag> tag)
+{
+ BNRemoveAutoDataTag(m_object, addr, tag->GetObject());
+}
+
+
+void BinaryView::AddUserDataTag(uint64_t addr, Ref<Tag> tag)
+{
+ BNAddUserDataTag(m_object, addr, tag->GetObject());
+}
+
+
+void BinaryView::RemoveUserDataTag(uint64_t addr, Ref<Tag> tag)
+{
+ BNRemoveUserDataTag(m_object, addr, tag->GetObject());
+}
+
+
+void BinaryView::RemoveTagReference(const TagReference& ref)
+{
+ BNRemoveTagReference(m_object, (BNTagReference)ref);
+}
+
+
+Ref<Tag> BinaryView::CreateAutoDataTag(uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateAutoDataTag(addr, tagType, data, unique);
+}
+
+
+Ref<Tag> BinaryView::CreateUserDataTag(uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateUserDataTag(addr, tagType, data, unique);
+}
+
+
+Ref<Tag> BinaryView::CreateAutoDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetDataTags(addr);
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+
+ Ref<Tag> tag = new Tag(tagType, data);
+ AddTag(tag);
+
+ AddAutoDataTag(addr, tag);
+ return tag;
+}
+
+
+Ref<Tag> BinaryView::CreateUserDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetDataTags(addr);
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+
+ Ref<Tag> tag = new Tag(tagType, data);
+ AddTag(tag);
+
+ AddUserDataTag(addr, tag);
+ return tag;
+}
+
+
bool BinaryView::IsNeverBranchPatchAvailable(Architecture* arch, uint64_t addr)
{
return BNIsNeverBranchPatchAvailable(m_object, arch->GetObject(), addr);
@@ -1957,6 +2414,7 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line
line.contents.instrIndex = lines[i].contents.instrIndex;
line.contents.highlight = lines[i].contents.highlight;
line.contents.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].contents.tokens, lines[i].contents.count);
+ line.contents.tags = Tag::ConvertTagList(lines[i].contents.tags, lines[i].contents.tagCount);
result.push_back(line);
}
@@ -1994,6 +2452,7 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi
line.contents.instrIndex = lines[i].contents.instrIndex;
line.contents.highlight = lines[i].contents.highlight;
line.contents.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].contents.tokens, lines[i].contents.count);
+ line.contents.tags = Tag::ConvertTagList(lines[i].contents.tags, lines[i].contents.tagCount);
result.push_back(line);
}
diff --git a/datarenderer.cpp b/datarenderer.cpp
index c0536a6a..4004b7d4 100644
--- a/datarenderer.cpp
+++ b/datarenderer.cpp
@@ -76,6 +76,7 @@ BNDisassemblyTextLine* DataRenderer::GetLinesForDataCallback(void* ctxt, BNBinar
buf[i].highlight = line.highlight;
buf[i].tokens = InstructionTextToken::CreateInstructionTextTokenList(line.tokens);
buf[i].count = line.tokens.size();
+ buf[i].tags = Tag::CreateTagList(line.tags, &(buf[i].tagCount));
}
return buf;
}
@@ -130,6 +131,7 @@ vector<DisassemblyTextLine> DataRenderer::GetLinesForData(BinaryView* data, uint
line.instrIndex = lines[i].instrIndex;
line.highlight = lines[i].highlight;
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(lines[i].tokens, lines[i].count);
+ line.tags = Tag::ConvertAndFreeTagList(lines[i].tags, lines[i].tagCount);
result.push_back(line);
}
return result;
@@ -145,4 +147,4 @@ void DataRendererContainer::RegisterGenericDataRenderer(DataRenderer* renderer)
void DataRendererContainer::RegisterTypeSpecificDataRenderer(DataRenderer* renderer)
{
BNRegisterTypeSpecificDataRenderer(BNGetDataRendererContainer(), renderer->GetObject());
-} \ No newline at end of file
+}
diff --git a/flowgraphnode.cpp b/flowgraphnode.cpp
index 4a1729ff..2457ebb9 100644
--- a/flowgraphnode.cpp
+++ b/flowgraphnode.cpp
@@ -107,6 +107,7 @@ const vector<DisassemblyTextLine>& FlowGraphNode::GetLines()
line.instrIndex = lines[i].instrIndex;
line.highlight = lines[i].highlight;
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].tokens, lines[i].count);
+ line.tags = Tag::ConvertTagList(lines[i].tags, lines[i].tagCount);
result.push_back(line);
}
@@ -126,6 +127,7 @@ void FlowGraphNode::SetLines(const vector<DisassemblyTextLine>& lines)
buf[i].highlight = lines[i].highlight;
buf[i].tokens = InstructionTextToken::CreateInstructionTextTokenList(lines[i].tokens);
buf[i].count = lines[i].tokens.size();
+ buf[i].tags = Tag::CreateTagList(lines[i].tags, &(buf[i].tagCount));
}
BNSetFlowGraphNodeLines(m_object, buf, lines.size());
diff --git a/function.cpp b/function.cpp
index 752d0bd1..0d5cb2ba 100644
--- a/function.cpp
+++ b/function.cpp
@@ -1300,6 +1300,237 @@ void Function::SetUserInstructionHighlight(Architecture* arch, uint64_t addr, ui
}
+std::vector<TagReference> Function::GetAllTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetFunctionAllTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> Function::GetTagReferencesOfType(Ref<TagType> tagType)
+{
+ size_t count;
+ BNTagReference* refs = BNGetFunctionTagReferencesOfType(m_object, tagType->GetObject(), &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<TagReference> Function::GetAddressTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetAddressTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<Ref<Tag>> Function::GetAddressTags(Architecture* arch, uint64_t addr)
+{
+ size_t count;
+ BNTag** tags = BNGetAddressTags(m_object, arch->GetObject(), addr, &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+std::vector<Ref<Tag>> Function::GetAddressTagsOfType(Architecture* arch, uint64_t addr, Ref<TagType> tagType)
+{
+ size_t count;
+ BNTag** tags = BNGetAddressTagsOfType(m_object, arch->GetObject(), addr, tagType->GetObject(), &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+void Function::AddAutoAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag)
+{
+ BNAddAutoAddressTag(m_object, arch->GetObject(), addr, tag->GetObject());
+}
+
+
+void Function::RemoveAutoAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag)
+{
+ BNRemoveAutoAddressTag(m_object, arch->GetObject(), addr, tag->GetObject());
+}
+
+
+void Function::AddUserAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag)
+{
+ BNAddUserAddressTag(m_object, arch->GetObject(), addr, tag->GetObject());
+}
+
+
+void Function::RemoveUserAddressTag(Architecture* arch, uint64_t addr, Ref<Tag> tag)
+{
+ BNRemoveUserAddressTag(m_object, arch->GetObject(), addr, tag->GetObject());
+}
+
+
+std::vector<TagReference> Function::GetFunctionTagReferences()
+{
+ size_t count;
+ BNTagReference* refs = BNGetFunctionTagReferences(m_object, &count);
+ return TagReference::ConvertAndFreeTagReferenceList(refs, count);
+}
+
+
+std::vector<Ref<Tag>> Function::GetFunctionTags()
+{
+ size_t count;
+ BNTag** tags = BNGetFunctionTags(m_object, &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+std::vector<Ref<Tag>> Function::GetFunctionTagsOfType(Ref<TagType> tagType)
+{
+ size_t count;
+ BNTag** tags = BNGetFunctionTagsOfType(m_object, tagType->GetObject(), &count);
+ return Tag::ConvertAndFreeTagList(tags, count);
+}
+
+
+void Function::AddAutoFunctionTag(Ref<Tag> tag)
+{
+ BNAddAutoFunctionTag(m_object, tag->GetObject());
+}
+
+
+void Function::RemoveAutoFunctionTag(Ref<Tag> tag)
+{
+ BNRemoveAutoFunctionTag(m_object, tag->GetObject());
+}
+
+
+void Function::AddUserFunctionTag(Ref<Tag> tag)
+{
+ BNAddUserFunctionTag(m_object, tag->GetObject());
+}
+
+
+void Function::RemoveUserFunctionTag(Ref<Tag> tag)
+{
+ BNRemoveUserFunctionTag(m_object, tag->GetObject());
+}
+
+
+Ref<Tag> Function::CreateAutoAddressTag(Architecture* arch, uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetView()->GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateAutoAddressTag(arch, addr, tagType, data, unique);
+}
+
+
+Ref<Tag> Function::CreateAutoAddressTag(Architecture* arch, uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetAddressTags(arch, addr);
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+
+ Ref<Tag> tag = new Tag(tagType, data);
+ GetView()->AddTag(tag);
+
+ AddAutoAddressTag(arch, addr, tag);
+ return tag;
+}
+
+
+Ref<Tag> Function::CreateUserAddressTag(Architecture* arch, uint64_t addr, const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetView()->GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateUserAddressTag(arch, addr, tagType, data, unique);
+}
+
+
+Ref<Tag> Function::CreateUserAddressTag(Architecture* arch, uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetAddressTags(arch, addr);
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+ Ref<Tag> tag = new Tag(tagType, data);
+ GetView()->AddTag(tag);
+
+ AddUserAddressTag(arch, addr, tag);
+ return tag;
+}
+
+
+Ref<Tag> Function::CreateAutoFunctionTag(const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetView()->GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateAutoFunctionTag(tagType, data, unique);
+}
+
+
+Ref<Tag> Function::CreateAutoFunctionTag(Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetFunctionTags();
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+
+ Ref<Tag> tag = new Tag(tagType, data);
+ GetView()->AddTag(tag);
+
+ AddAutoFunctionTag(tag);
+ return tag;
+}
+
+
+Ref<Tag> Function::CreateUserFunctionTag(const std::string& tagTypeName, const std::string& data, bool unique)
+{
+ Ref<TagType> tagType = GetView()->GetTagType(tagTypeName);
+ if (!tagType)
+ return nullptr;
+
+ return CreateUserFunctionTag(tagType, data, unique);
+}
+
+
+Ref<Tag> Function::CreateUserFunctionTag(Ref<TagType> tagType, const std::string& data, bool unique)
+{
+ if (unique)
+ {
+ auto tags = GetFunctionTags();
+ for (const auto& tag : tags)
+ {
+ if (tag->GetType() == tagType && tag->GetData() == data)
+ return nullptr;
+ }
+ }
+
+ Ref<Tag> tag = new Tag(tagType, data);
+ GetView()->AddTag(tag);
+
+ AddUserFunctionTag(tag);
+ return tag;
+}
+
+
Confidence<RegisterValue> Function::GetGlobalPointerValue() const
{
BNRegisterValueWithConfidence value = BNGetFunctionGlobalPointerValue(m_object);
@@ -1370,6 +1601,7 @@ vector<DisassemblyTextLine> Function::GetTypeTokens(DisassemblySettings* setting
line.instrIndex = lines[i].instrIndex;
line.highlight = lines[i].highlight;
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].tokens, lines[i].count);
+ line.tags = Tag::ConvertTagList(lines[i].tags, lines[i].tagCount);
result.push_back(line);
}
diff --git a/python/binaryview.py b/python/binaryview.py
index c197e585..fe8fde76 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -1,3 +1,4 @@
+# coding=utf-8
# Copyright (c) 2015-2019 Vector 35 Inc
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -900,6 +901,98 @@ class AddressRange(object):
self._end = value
+class TagType(object):
+ def __init__(self, handle):
+ self.handle = core.handle_of_type(handle, core.BNTagType)
+
+ @property
+ def name(self):
+ return core.BNTagTypeGetName(self.handle)
+
+ @name.setter
+ def name(self, value):
+ core.BNTagTypeSetName(self.handle, value)
+
+ @property
+ def icon(self):
+ return core.BNTagTypeGetIcon(self.handle)
+
+ @icon.setter
+ def icon(self, value):
+ core.BNTagTypeSetIcon(self.handle, value)
+
+ @property
+ def visible(self):
+ return core.BNTagTypeGetVisible(self.handle)
+
+ @visible.setter
+ def visible(self, value):
+ core.BNTagTypeSetVisible(self.handle, value)
+
+ @property
+ def type(self):
+ return core.BNTagTypeGetType(self.handle)
+
+ @type.setter
+ def type(self, value):
+ core.BNTagTypeSetType(self.handle, value)
+
+ def __del__(self):
+ core.BNFreeTagType(self.handle)
+
+ def __eq__(self, other):
+ if not isinstance(other, TagType):
+ return False
+ return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents)
+
+ def __ne__(self, other):
+ if not isinstance(other, TagType):
+ return False
+ return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents)
+
+ def __hash__(self):
+ return hash(self.handle.contents)
+
+ def __repr__(self):
+ return "<tag type %s: %s>" % (self.name, self.icon)
+
+
+class Tag(object):
+ def __init__(self, handle):
+ self.handle = core.handle_of_type(handle, core.BNTag)
+
+ @property
+ def type(self):
+ return TagType(core.BNTagGetType(self.handle))
+
+ @property
+ def data(self):
+ return core.BNTagGetData(self.handle)
+
+ @data.setter
+ def data(self, value):
+ core.BNTagSetData(self.handle, value)
+
+ def __del__(self):
+ core.BNFreeTag(self.handle)
+
+ def __eq__(self, other):
+ if not isinstance(other, Tag):
+ return False
+ return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents)
+
+ def __ne__(self, other):
+ if not isinstance(other, Tag):
+ return False
+ return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents)
+
+ def __hash__(self):
+ return hash(self.handle.contents)
+
+ def __repr__(self):
+ return "<tag %s %s: %s>" % (self.type.icon, self.type.name, self.data)
+
+
class _BinaryViewAssociatedDataStore(associateddatastore._AssociatedDataStore):
_defaults = {}
@@ -3223,6 +3316,210 @@ class BinaryView(object):
"""
core.BNDefineImportedFunction(self.handle, import_addr_sym.handle, func.handle)
+ def create_tag_type(self, name, icon):
+ """
+ ``create_tag_type`` creates a new Tag Type and adds it to the view
+
+ :param str name: The name for the tag
+ :param str icon: The icon (recommended 1 emoji or 2 chars) for the tag
+ :return The created tag type
+ :rtype TagType
+ :Example:
+
+ >>> tt = bv.create_tag_type("Crabby Functions", "🦀")
+ >>> current_function.create_user_address_tag(here, tt, "Get Crabbed")
+ >>>
+ """
+ tag_type = TagType(core.BNCreateTagType(self.handle, name, icon))
+ tag_type.name = name
+ tag_type.icon = icon
+ core.BNAddTagType(self.handle, tag_type.handle)
+ return tag_type
+
+ def remove_tag_type(self, tag_type):
+ """
+ ``remove_tag_type`` removes a new Tag Type and all tags that use it
+
+ :param TagType tag_type: The Tag Type to remove
+ :rtype None
+ """
+ core.BNRemoveTagType(self.handle, tag_type.handle)
+
+ @property
+ def tag_types(self):
+ """
+ ``tag_types`` gets a dictionary of all Tag Types present for the view,
+ structured as {Tag Type Name => Tag Type}.
+
+ :type {str => TagType}
+ """
+ count = ctypes.c_ulonglong(0)
+ types = core.BNGetTagTypes(self.handle, count)
+ result = {}
+ for i in range(0, count.value):
+ tag = TagType(core.BNNewTagTypeReference(types[i]))
+ if tag.name in result:
+ result[tag.name] = [result[tag.name], tag]
+ else:
+ result[tag.name] = tag
+ core.BNFreeTagTypeList(types, count.value)
+ return result
+
+ def create_tag(self, type, data):
+ """
+ ``create_tag`` creates a new Tag object but does not add it anywhere
+
+ :param TagType type: The Tag Type for this Tag
+ :param str data: Additional data for the Tag
+ :return The created Tag
+ :rtype Tag
+ :Example:
+
+ >>> tt = bv.tag_types["Crabby Functions"]
+ >>> tag = bv.create_tag(tt, "Get Crabbed")
+ >>> bv.add_user_data_tag(here, tag)
+ >>>
+ """
+ tag = Tag(core.BNCreateTag(type.handle, data))
+ core.BNAddTag(self.handle, tag.handle)
+ return tag
+
+ @property
+ def data_tags(self):
+ """
+ ``data_tags`` gets a list of all data Tags in the view.
+ Tags are returned as a list of (address, Tag) pairs.
+
+ :type [(int, Tag)]
+ """
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetDataTagReferences(self.handle, count)
+ result = []
+ for i in range(0, count.value):
+ tag = Tag(core.BNNewTagReference(tags[i].tag))
+ result.append((tags[i].addr, tag))
+ core.BNFreeTagReferences(tags, count.value)
+ return result
+
+ def get_data_tags_at(self, addr):
+ """
+ ``get_data_tags_at`` gets a list of all Tags for a data address.
+
+ :param int addr: Address to get tags at
+ :return A list of data Tags
+ :rtype [Tag]
+ """
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetDataTags(self.handle, addr, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(Tag(core.BNNewTagReference(tags[i])))
+ core.BNFreeTagList(tags, count.value)
+ return result
+
+ def get_data_tags_in_range(self, range):
+ """
+ ``get_data_tags_in_range`` gets a list of all data Tags in a given range.
+ Range is inclusive at the start, exclusive at the end.
+
+ :param AddressRange range: Address range from which to get tags
+ :return A list of data Tags
+ :rtype [Tag]
+ """
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetDataTagsInRange(self.handle, range.start, range.end, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(Tag(core.BNNewTagReference(tags[i])))
+ core.BNFreeTagList(tags, count.value)
+ return result
+
+ def add_user_data_tag(self, addr, tag):
+ """
+ ``add_user_data_tag`` adds an already-created Tag object at a data address.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNAddUserDataTag(self.handle, addr, tag.handle)
+
+ def create_user_data_tag(self, addr, type, data, unique=False):
+ """
+ ``create_user_data_tag`` creates and adds a Tag object at a data address.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists at this location with this data, don't add another
+ :return The created Tag
+ :rtype Tag
+ """
+ if unique:
+ tags = self.get_data_tags_at(addr)
+ for tag in tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddUserDataTag(self.handle, addr, tag.handle)
+ return tag
+
+ def remove_user_data_tag(self, addr, tag):
+ """
+ ``remove_user_data_tag`` removes a Tag object at a data address.
+ Since this removes a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNRemoveUserDataTag(self.handle, addr, tag.handle)
+
+ def add_auto_data_tag(self, addr, tag):
+ """
+ ``add_auto_data_tag`` adds an already-created Tag object at a data address.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNAddAutoDataTag(self.handle, addr, tag.handle)
+
+ def create_auto_data_tag(self, addr, type, data, unique=False):
+ """
+ ``create_auto_data_tag`` creates and adds a Tag object at a data address.
+
+ :param int addr: Address at which to add the tag
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists at this location with this data, don't add another
+ :return The created Tag
+ :rtype Tag
+ """
+ if unique:
+ tags = self.get_data_tags_at(addr)
+ for tag in tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddAutoDataTag(self.handle, addr, tag.handle)
+ return tag
+
+ def remove_auto_data_tag(self, addr, tag):
+ """
+ ``remove_auto_data_tag`` removes a Tag object at a data address.
+ Since this removes a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNRemoveAutoDataTag(self.handle, addr, tag.handle)
+
def is_never_branch_patch_available(self, addr, arch=None):
"""
``is_never_branch_patch_available`` queries the architecture plugin to determine if the instruction at the
diff --git a/python/function.py b/python/function.py
index d7b03cf8..58565838 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1,3 +1,4 @@
+# coding=utf-8
# Copyright (c) 2015-2019 Vector 35 Inc
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -908,6 +909,255 @@ class Function(object):
core.BNFreeAddressList(addrs)
return result
+ def create_tag(self, type, data):
+ """
+ ``create_tag`` creates a new Tag object but does not add it anywhere
+
+ :param TagType type: The Tag Type for this Tag
+ :param str data: Additional data for the Tag
+ :return The created Tag
+ :rtype Tag
+ :Example:
+
+ >>> tt = bv.tag_types["Crabby Functions"]
+ >>> tag = current_function.create_tag(tt, "Get Crabbed")
+ >>> current_function.add_user_address_tag(here, tag)
+ >>>
+ """
+ return self.view.create_tag(type, data)
+
+ @property
+ def address_tags(self):
+ """
+ ``address_tags`` gets a list of all address Tags in the function.
+ Tags are returned as a list of (arch, address, Tag) tuples.
+
+ :type [(Architecture, int, Tag)]
+ """
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetAddressTagReferences(self.handle, count)
+ result = []
+ for i in range(0, count.value):
+ arch = binaryninja.architecture.CoreArchitecture(tags[i].arch)
+ tag = binaryninja.binaryview.Tag(core.BNNewTagReference(tags[i].tag))
+ result.append((arch, tags[i].addr, tag))
+ core.BNFreeTagReferences(tags, count.value)
+ return result
+
+ def get_address_tags_at(self, addr, arch=None):
+ """
+ ``get_address_tags_at`` gets a list of all Tags in the function at a given address.
+
+ :param int addr: Address to get tags at
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :return A list of Tags
+ :rtype [Tag]
+ """
+ if arch is None:
+ arch = self.arch
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetAddressTags(self.handle, arch.handle, addr, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(binaryninja.binaryview.Tag(core.BNNewTagReference(tags[i])))
+ core.BNFreeTagList(tags, count.value)
+ return result
+
+ def add_user_address_tag(self, addr, tag, arch=None):
+ """
+ ``add_user_address_tag`` adds an already-created Tag object at a given address.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :rtype None
+ """
+ if arch is None:
+ arch = self.arch
+ core.BNAddUserAddressTag(self.handle, arch.handle, addr, tag.handle)
+
+ def create_user_address_tag(self, addr, type, data, unique=False, arch=None):
+ """
+ ``create_user_address_tag`` creates and adds a Tag object at a given address.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists at this location with this data, don't add another
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :return The created Tag
+ :rtype Tag
+ """
+ if arch is None:
+ arch = self.arch
+ if unique:
+ tags = self.get_address_tags_at(addr, arch)
+ for tag in tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddUserAddressTag(self.handle, arch.handle, addr, tag.handle)
+ return tag
+
+ def remove_user_address_tag(self, addr, tag, arch=None):
+ """
+ ``remove_user_address_tag`` removes a Tag object at a given address.
+ Since this removes a user tag, it will be added to the current undo buffer.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :rtype None
+ """
+ if arch is None:
+ arch = self.arch
+ core.BNRemoveUserAddressTag(self.handle, arch.handle, addr, tag.handle)
+
+ def add_auto_address_tag(self, addr, tag, arch=None):
+ """
+ ``add_auto_address_tag`` adds an already-created Tag object at a given address.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :rtype None
+ """
+ if arch is None:
+ arch = self.arch
+ core.BNAddAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
+
+ def create_auto_address_tag(self, addr, type, data, unique=False, arch=None):
+ """
+ ``create_auto_address_tag`` creates and adds a Tag object at a given address.
+
+ :param int addr: Address at which to add the tag
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists at this location with this data, don't add another
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :return The created Tag
+ :rtype Tag
+ """
+ if arch is None:
+ arch = self.arch
+ if unique:
+ tags = self.get_address_tags_at(addr, arch)
+ for tag in tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
+ return tag
+
+ def remove_auto_address_tag(self, addr, tag, arch=None):
+ """
+ ``remove_auto_address_tag`` removes a Tag object at a given address.
+
+ :param int addr: Address at which to add the tag
+ :param Tag tag: Tag object to be added
+ :param Architecture arch: Architecture for the block in which the Tag is added (optional)
+ :rtype None
+ """
+ if arch is None:
+ arch = self.arch
+ core.BNRemoveAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
+
+ @property
+ def function_tags(self):
+ """
+ ``function_tags`` gets a list of all function Tags for the function.
+
+ :type [Tag]
+ """
+ count = ctypes.c_ulonglong()
+ tags = core.BNGetFunctionTags(self.handle, count)
+ result = []
+ for i in range(0, count.value):
+ result.append(binaryninja.binaryview.Tag(core.BNNewTagReference(tags[i])))
+ core.BNFreeTagList(tags, count.value)
+ return result
+
+ def add_user_function_tag(self, tag):
+ """
+ ``add_user_function_tag`` adds an already-created Tag object as a function tag.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNAddUserFunctionTag(self.handle, tag.handle)
+
+ def create_user_function_tag(self, type, data, unique=False):
+ """
+ ``add_user_function_tag`` creates and adds a Tag object as a function tag.
+ Since this adds a user tag, it will be added to the current undo buffer.
+
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists with this data, don't add another
+ :return The created Tag
+ :rtype Tag
+ """
+ if unique:
+ for tag in self.function_tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddUserFunctionTag(self.handle, tag.handle)
+ return tag
+
+ def remove_user_function_tag(self, tag):
+ """
+ ``remove_user_function_tag`` removes a Tag object as a function tag.
+ Since this removes a user tag, it will be added to the current undo buffer.
+
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNRemoveUserFunctionTag(self.handle, tag.handle)
+
+ def add_auto_function_tag(self, tag):
+ """
+ ``add_user_function_tag`` adds an already-created Tag object as a function tag.
+
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNAddAutoFunctionTag(self.handle, tag.handle)
+
+ def create_auto_function_tag(self, type, data, unique=False):
+ """
+ ``add_user_function_tag`` creates and adds a Tag object as a function tag.
+
+ :param TagType type: Tag Type for the Tag that is created
+ :param str data: Additional data for the Tag
+ :param bool unique: If a tag already exists with this data, don't add another
+ :return The created Tag
+ :rtype Tag
+ """
+ if unique:
+ for tag in self.function_tags:
+ if tag.type == type and tag.data == data:
+ return
+
+ tag = self.create_tag(type, data)
+ core.BNAddAutoFunctionTag(self.handle, tag.handle)
+ return tag
+
+ def remove_auto_function_tag(self, tag):
+ """
+ ``remove_user_function_tag`` removes a Tag object as a function tag.
+
+ :param Tag tag: Tag object to be added
+ :rtype None
+ """
+ core.BNRemoveAutoFunctionTag(self.handle, tag.handle)
+
@property
def low_level_il(self):
"""Deprecated property provided for compatibility. Use llil instead."""
diff --git a/ui/action.h b/ui/action.h
index 7770a016..8559e887 100644
--- a/ui/action.h
+++ b/ui/action.h
@@ -81,6 +81,7 @@ struct BINARYNINJAUIAPI UIAction
static void registerPluginCommandActions();
static void registerPluginCommandActions(const QString& prefix);
static void registerHighlightColorActions(const QString& prefix);
+ static void registerBookmarkActions(const QString& prefix);
static void setActionDisplayName(const QString& registeredName, const QString& displayName);
static void setActionDisplayName(const QString& registeredName, const std::function<QString()>& displayNameFunc);
@@ -139,6 +140,14 @@ struct BINARYNINJAUIAPI UIHighlightColorAction
UIHighlightColorAction(const UIHighlightColorAction& other);
};
+struct BINARYNINJAUIAPI UIBookmarkAction
+{
+ std::function<void (const UIActionContext& context, int index)> activate;
+ std::function<bool (const UIActionContext& context, int index)> isValid;
+
+ UIBookmarkAction(const std::function<void (const UIActionContext& context, int index)>& activate, const std::function<bool (const UIActionContext& context, int index)>& isValid);
+};
+
enum ActionPriority
{
LowActionPriority,
@@ -203,6 +212,9 @@ public:
void bindHighlightColorActions(const QString& prefix, const UIHighlightColorAction& action);
void unbindHighlightColorActions(const QString& prefix);
+ void bindBookmarkActions(const QString& prefix, const UIBookmarkAction& action);
+ void unbindBookmarkActions(const QString& prefix);
+
void setActionDisplayName(const QString& registeredName, const QString& displayName);
void setActionDisplayName(const QString& registeredName, const std::function<QString()>& displayNameFunc);
void setActionDisplayName(const QString& registeredName, const std::function<QString(const UIActionContext&)>& displayNameFunc);
diff --git a/ui/flowgraphwidget.h b/ui/flowgraphwidget.h
index a519ed97..3ec61019 100644
--- a/ui/flowgraphwidget.h
+++ b/ui/flowgraphwidget.h
@@ -288,6 +288,11 @@ private Q_SLOTS:
void functionComment();
void commentAccepted();
void functionCommentAccepted();
+ void bookmarkAddress();
+ void unbookmarkAddress();
+ void tagAddress();
+ void tagAddressAccepted(TagTypeRef tt);
+ void manageAddressTags();
void convertToNop();
void alwaysBranch();
diff --git a/ui/linearview.h b/ui/linearview.h
index 85586ca8..486b2326 100644
--- a/ui/linearview.h
+++ b/ui/linearview.h
@@ -142,6 +142,11 @@ private Q_SLOTS:
void comment();
void commentAccepted();
void addUserXref();
+ void bookmarkAddress();
+ void unbookmarkAddress();
+ void tagAddress();
+ void tagAddressAccepted(TagTypeRef tt);
+ void manageAddressTags();
void convertToNop();
void alwaysBranch();
diff --git a/ui/taglist.h b/ui/taglist.h
new file mode 100644
index 00000000..c2a5bd8a
--- /dev/null
+++ b/ui/taglist.h
@@ -0,0 +1,231 @@
+#pragma once
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QItemSelectionModel>
+#include <QtWidgets/QTableView>
+#include <QtWidgets/QTabWidget>
+#include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QDialog>
+#include "binaryninjaapi.h"
+#include "dockhandler.h"
+#include "viewframe.h"
+#include "filter.h"
+#include "tagtypelist.h"
+
+
+class BINARYNINJAUIAPI TagListModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+protected:
+ QWidget* m_owner;
+ BinaryViewRef m_data;
+ std::vector<BinaryNinja::TagReference> m_refs;
+ DisassemblySettingsRef m_settings;
+
+private:
+ void AddDisassemblyTokens(QList<QVariant>& line, std::vector<BinaryNinja::InstructionTextToken> tokens) const;
+
+ void TrimLeadingWhitespace(QList<QVariant>& line) const;
+
+ QVariant GetIconColumn(const BinaryNinja::TagReference& ref) const;
+ QVariant GetLocationColumn(const BinaryNinja::TagReference& ref) const;
+ QVariant GetDataColumn(const BinaryNinja::TagReference& ref) const;
+ QVariant GetPreviewColumn(const BinaryNinja::TagReference& ref) const;
+
+public:
+ TagListModel(QWidget* parent, BinaryViewRef data);
+
+ BinaryNinja::TagReference& GetRef(int index) { return m_refs[index]; }
+ const BinaryNinja::TagReference& GetRef(int index) const { return m_refs[index]; }
+
+ virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override;
+ virtual QModelIndex parent(const QModelIndex& i) const override;
+ virtual bool hasChildren(const QModelIndex& parent) const override;
+ virtual int rowCount(const QModelIndex& parent) const override;
+ virtual int columnCount(const QModelIndex& parent) const override;
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ virtual QVariant data(const QModelIndex& i, int role) const override;
+ virtual bool setData(const QModelIndex& i, const QVariant& value, int role = Qt::EditRole) override;
+ virtual Qt::ItemFlags flags(const QModelIndex& i) const override;
+ virtual void sort(int column, Qt::SortOrder order) override;
+
+ bool setModelData(const std::vector<BinaryNinja::TagReference>& refs, QItemSelectionModel* selectionModel, int sortColumn, Qt::SortOrder sortOrder, bool& selectionUpdated);
+};
+
+
+class BINARYNINJAUIAPI BookmarkListModel: public TagListModel
+{
+public:
+ BookmarkListModel(QWidget* parent, BinaryViewRef data);
+
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ virtual void sort(int column, Qt::SortOrder order) override;
+};
+
+
+class BINARYNINJAUIAPI TagItemDelegate: public QStyledItemDelegate
+{
+ Q_OBJECT
+
+protected:
+ QFont m_font;
+ int m_baseline, m_charWidth, m_charHeight, m_charOffset;
+
+ void initFont();
+
+public:
+ TagItemDelegate(QWidget* parent);
+
+ void updateFonts();
+
+ virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+ virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+ virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override;
+};
+
+
+class BINARYNINJAUIAPI BookmarkListItemDelegate: public TagItemDelegate
+{
+public:
+ BookmarkListItemDelegate(QWidget* parent);
+
+ virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+};
+
+
+class BINARYNINJAUIAPI TagList: public QTableView,
+ public BinaryNinja::BinaryDataNotification, public FilterTarget
+{
+ Q_OBJECT
+
+ ViewFrame* m_view;
+ TagListModel* m_list;
+ TagItemDelegate* m_itemDelegate;
+ BinaryViewRef m_data;
+ UIActionHandler* m_handler;
+ UIActionHandler m_actionHandler;
+ ContextMenuManager* m_contextMenuManager;
+ FilteredView* m_filterView;
+ Menu* m_menu;
+
+public:
+ typedef std::function<bool(const BinaryNinja::TagReference&)> FilterFn;
+
+private:
+ bool m_hasFilter;
+ FilterFn m_filter;
+ std::string m_searchFilter;
+
+ QTimer* m_hoverTimer;
+ QTimer* m_updateTimer;
+ QPoint m_hoverPos;
+
+ uint64_t m_curRefTarget = 0;
+ bool m_needsUpdate;
+ bool m_navToNextOrPrevStarted = false;
+
+protected:
+ virtual void contextMenuEvent(QContextMenuEvent* event) override;
+ virtual void keyPressEvent(QKeyEvent* e) override;
+ virtual void mouseMoveEvent(QMouseEvent* e) override;
+ virtual void mousePressEvent(QMouseEvent* e) override;
+ virtual void wheelEvent(QWheelEvent* e) override;
+ virtual void resizeEvent(QResizeEvent *event) override;
+ void goToReference(const QModelIndex& idx);
+
+ void setFilter(const std::string& filter) override;
+ void scrollToFirstItem() override;
+ void scrollToCurrentItem() override;
+ void selectFirstItem() override;
+ void activateFirstItem() override;
+
+ virtual void OnDataMetadataUpdated(BinaryNinja::BinaryView*, uint64_t) override;
+
+private Q_SLOTS:
+ void hoverTimerEvent();
+ void updateTimerEvent();
+ void referenceActivated(const QModelIndex& idx);
+
+public:
+ TagList(QWidget* parent, ViewFrame* view, BinaryViewRef data, TagListModel* model = nullptr, Menu* menu = nullptr);
+ virtual ~TagList();
+
+ static void registerActions();
+ virtual void setModel(QAbstractItemModel* model) override;
+
+ void notifyFontChanged();
+ void removeSelection();
+
+ void clearFilter();
+ void setFilter(FilterFn filter);
+ void setFilterView(FilteredView* filterView) { m_filterView = filterView; }
+
+ void updateTags();
+
+ bool hasSelection();
+ void navigateToNext();
+ void navigateToPrev();
+};
+
+
+class BINARYNINJAUIAPI TagListWidget: public QWidget, public DockContextHandler
+{
+ Q_OBJECT
+ Q_INTERFACES(DockContextHandler)
+
+ ViewFrame* m_view;
+ QTabWidget* m_tabs;
+
+ TagList* m_bookmarkList;
+ FilteredView* m_bookmarkFilter;
+
+ TagList* m_notificationList;
+ FilteredView* m_notificationFilter;
+
+ TagTypeList* m_typeList;
+
+ BinaryViewRef m_data;
+ UIActionHandler* m_handler;
+
+protected:
+ virtual void notifyFontChanged() override;
+
+private Q_SLOTS:
+ void bookmarkListUpdate();
+
+public:
+ TagList* GetList();
+ void editTag(TagRef tag);
+
+ TagListWidget(QWidget* parent, ViewFrame* view, BinaryViewRef data);
+ virtual ~TagListWidget();
+};
+
+
+class BINARYNINJAUIAPI TagListDialog: public QDialog
+{
+ Q_OBJECT
+
+public:
+ typedef std::function<void(const TagRef&)> AddFn;
+
+private:
+ BinaryViewRef m_data;
+ TagList* m_list;
+ FilteredView* m_filter;
+
+ AddFn m_addFn;
+
+ QPushButton* m_removeButton;
+
+public:
+ TagListDialog(QWidget* parent, ViewFrame* frame, BinaryViewRef data, AddFn addFn);
+ void setFilter(TagList::FilterFn filter);
+
+private Q_SLOTS:
+ void updateActive(const QItemSelection&, const QItemSelection&);
+ void createTag();
+ void createTagAccept(TagTypeRef tt);
+ void removeTag();
+};
diff --git a/ui/tagtypelist.h b/ui/tagtypelist.h
new file mode 100644
index 00000000..cc7015a9
--- /dev/null
+++ b/ui/tagtypelist.h
@@ -0,0 +1,142 @@
+#pragma once
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QItemSelectionModel>
+#include <QtWidgets/QTableView>
+#include <QtWidgets/QItemDelegate>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QComboBox>
+#include "binaryninjaapi.h"
+#include "dockhandler.h"
+#include "viewframe.h"
+
+
+class BINARYNINJAUIAPI TagTypeListModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+ QWidget* m_owner;
+ BinaryViewRef m_data;
+ std::vector<TagTypeRef> m_refs;
+
+public:
+ TagTypeListModel(QWidget* parent, BinaryViewRef data);
+
+ TagTypeRef& GetRef(int index) { return m_refs[index]; }
+ const TagTypeRef& GetRef(int index) const { return m_refs[index]; }
+
+ virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override;
+ virtual QModelIndex parent(const QModelIndex& i) const override;
+ virtual bool hasChildren(const QModelIndex& parent) const override;
+ virtual int rowCount(const QModelIndex& parent) const override;
+ virtual int columnCount(const QModelIndex& parent) const override;
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ virtual QVariant data(const QModelIndex& i, int role) const override;
+ virtual bool setData(const QModelIndex& i, const QVariant& value, int role = Qt::EditRole) override;
+ virtual void sort(int column, Qt::SortOrder order) override;
+ virtual Qt::ItemFlags flags(const QModelIndex& i) const override;
+
+ bool setModelData(const std::vector<TagTypeRef>& refs, QItemSelectionModel* selectionModel, int sortColumn, Qt::SortOrder sortOrder, bool& selectionUpdated);
+};
+
+
+class BINARYNINJAUIAPI TagTypeItemDelegate: public QItemDelegate
+{
+ Q_OBJECT
+
+ QFont m_font;
+ int m_baseline, m_charWidth, m_charHeight, m_charOffset;
+
+ void initFont();
+
+public:
+ TagTypeItemDelegate(QWidget* parent);
+
+ void updateFonts();
+
+ virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+ virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const override;
+ virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override;
+ virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
+};
+
+
+class BINARYNINJAUIAPI TagTypeList: public QTableView, public DockContextHandler, public BinaryNinja::BinaryDataNotification
+{
+ Q_OBJECT
+ Q_INTERFACES(DockContextHandler)
+
+ ViewFrame* m_view;
+ TagTypeListModel* m_list;
+ TagTypeItemDelegate* m_itemDelegate;
+ BinaryViewRef m_data;
+ UIActionHandler* m_handler;
+ UIActionHandler m_actionHandler;
+ ContextMenuManager* m_contextMenuManager;
+ Menu* m_menu;
+
+ QTimer* m_updateTimer;
+ bool m_needsUpdate;
+
+protected:
+ virtual void contextMenuEvent(QContextMenuEvent* event) override;
+
+ virtual void OnDataMetadataUpdated(BinaryNinja::BinaryView*, uint64_t) override;
+
+private:
+ void createTagType();
+ void removeTagType();
+
+private Q_SLOTS:
+ void updateTimerEvent();
+
+public:
+ TagTypeList(QWidget* parent, ViewFrame* view, BinaryViewRef data, Menu* menu = nullptr);
+ virtual ~TagTypeList();
+ virtual void notifyFontChanged() override;
+
+ static void registerActions();
+
+ void updateData();
+ bool hasSelection();
+};
+
+class BINARYNINJAUIAPI TagTypeDialogModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+ QWidget* m_owner;
+ BinaryViewRef m_data;
+ std::vector<TagTypeRef> m_refs;
+
+public:
+ TagTypeDialogModel(QWidget* parent, BinaryViewRef data);
+
+ TagTypeRef& GetRef(int index) { return m_refs[index]; }
+ const TagTypeRef& GetRef(int index) const { return m_refs[index]; }
+
+ virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override;
+ virtual QModelIndex parent(const QModelIndex& i) const override;
+ virtual bool hasChildren(const QModelIndex& parent) const override;
+ virtual int rowCount(const QModelIndex& parent) const override;
+ virtual int columnCount(const QModelIndex& parent) const override;
+ virtual QVariant data(const QModelIndex& i, int role) const override;
+};
+
+class BINARYNINJAUIAPI TagTypeSelectDialog: public QDialog
+{
+ Q_OBJECT
+
+ BinaryViewRef m_data;
+ TagTypeDialogModel* m_model;
+ QComboBox* m_tagTypeList;
+
+private Q_SLOTS:
+ void select();
+
+public:
+ TagTypeSelectDialog(QWidget* parent, BinaryViewRef data);
+
+Q_SIGNALS:
+ void selected(TagTypeRef tagType);
+};
diff --git a/ui/uitypes.h b/ui/uitypes.h
index 557063f3..9859cdb2 100644
--- a/ui/uitypes.h
+++ b/ui/uitypes.h
@@ -55,6 +55,8 @@ typedef BinaryNinja::Ref<BinaryNinja::Section> SectionRef;
typedef BinaryNinja::Ref<BinaryNinja::Segment> SegmentRef;
typedef BinaryNinja::Ref<BinaryNinja::Structure> StructureRef;
typedef BinaryNinja::Ref<BinaryNinja::Symbol> SymbolRef;
+typedef BinaryNinja::Ref<BinaryNinja::Tag> TagRef;
+typedef BinaryNinja::Ref<BinaryNinja::TagType> TagTypeRef;
typedef BinaryNinja::Ref<BinaryNinja::TemporaryFile> TemporaryFileRef;
typedef BinaryNinja::Ref<BinaryNinja::Transform> TransformRef;
typedef BinaryNinja::Ref<BinaryNinja::Type> TypeRef;
diff --git a/ui/viewframe.h b/ui/viewframe.h
index 0a73ad89..fefc72d2 100644
--- a/ui/viewframe.h
+++ b/ui/viewframe.h
@@ -246,6 +246,11 @@ public:
void nextCrossReference();
void prevCrossReference();
+ void showTags();
+ void editTag(TagRef tag);
+ void nextTag();
+ void prevTag();
+
virtual UIActionContext actionContext();
void bindActions();
static void registerActions();