diff options
| author | Rusty Wagner <rusty@vector35.com> | 2020-04-10 22:04:08 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2020-04-17 14:20:25 -0400 |
| commit | 9c1577c370d76b1797d55176cb59a10666b6ef2f (patch) | |
| tree | 4b4ee97e205557c98d48be0c9abbd94bf24b95b1 | |
| parent | 111a17fe65435ccf96b66d7c55a33d3642c68b9a (diff) | |
Initial implementation of new linear view API
| -rw-r--r-- | binaryninjaapi.h | 78 | ||||
| -rw-r--r-- | binaryninjacore.h | 74 | ||||
| -rw-r--r-- | binaryview.cpp | 2 | ||||
| -rw-r--r-- | linearviewcursor.cpp | 228 | ||||
| -rw-r--r-- | linearviewobject.cpp | 206 | ||||
| -rw-r--r-- | python/binaryview.py | 2 | ||||
| -rw-r--r-- | python/lineardisassembly.py | 393 | ||||
| -rw-r--r-- | ui/linearview.h | 69 |
8 files changed, 1026 insertions, 26 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8267cbb8..e48fb33d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1210,7 +1210,6 @@ __attribute__ ((format (printf, 1, 2))) BNLinearDisassemblyLineType type; Ref<Function> function; Ref<BasicBlock> block; - size_t lineOffset; DisassemblyTextLine contents; }; @@ -4963,4 +4962,81 @@ __attribute__ ((format (printf, 1, 2))) bool hasAutoAnnotations, const std::string& leadingSpaces=" "); }; + + struct LinearViewObjectIdentifier + { + std::string name; + BNLinearViewObjectIdentifierType type; + uint64_t start, end; + + LinearViewObjectIdentifier(); + LinearViewObjectIdentifier(const std::string& name); + LinearViewObjectIdentifier(const std::string& name, uint64_t addr); + LinearViewObjectIdentifier(const std::string& name, uint64_t start, uint64_t end); + LinearViewObjectIdentifier(const LinearViewObjectIdentifier& other); + }; + + class LinearViewObject: public CoreRefCountObject<BNLinearViewObject, + BNNewLinearViewObjectReference, BNFreeLinearViewObject> + { + public: + LinearViewObject(BNLinearViewObject* obj); + + Ref<LinearViewObject> GetFirstChild(); + Ref<LinearViewObject> GetLastChild(); + Ref<LinearViewObject> GetPreviousChild(LinearViewObject* obj); + Ref<LinearViewObject> GetNextChild(LinearViewObject* obj); + + Ref<LinearViewObject> GetChildForAddress(uint64_t addr); + Ref<LinearViewObject> GetChildForIdentifier(const LinearViewObjectIdentifier& id); + int CompareChildren(LinearViewObject* a, LinearViewObject* b); + + std::vector<LinearDisassemblyLine> GetLines(LinearViewObject* prev, LinearViewObject* next); + + uint64_t GetStart() const; + uint64_t GetEnd() const; + + LinearViewObjectIdentifier GetIdentifier() const; + + uint64_t GetOrderingIndexTotal() const; + uint64_t GetOrderingIndexForChild(LinearViewObject* obj) const; + Ref<LinearViewObject> GetChildForOrderingIndex(uint64_t idx); + + static Ref<LinearViewObject> CreateDisassemblyByBlock(BinaryView* view, DisassemblySettings* settings); + }; + + class LinearViewCursor: public CoreRefCountObject<BNLinearViewCursor, + BNNewLinearViewCursorReference, BNFreeLinearViewCursor> + { + public: + LinearViewCursor(LinearViewObject* root); + LinearViewCursor(BNLinearViewCursor* cursor); + + bool IsBeforeBegin() const; + bool IsAfterEnd() const; + bool IsValid() const; + + Ref<LinearViewObject> GetCurrentObject() const; + std::vector<LinearViewObjectIdentifier> GetPath() const; + std::vector<Ref<LinearViewObject>> GetPathObjects() const; + BNAddressRange GetOrderingIndex() const; + uint64_t GetOrderingIndexTotal() const; + + void SeekToBegin(); + void SeekToEnd(); + void SeekToAddress(uint64_t addr); + bool SeekToPath(const std::vector<LinearViewObjectIdentifier>& path); + bool SeekToPath(const std::vector<LinearViewObjectIdentifier>& path, uint64_t addr); + bool SeekToPath(LinearViewCursor* cursor); + bool SeekToPath(LinearViewCursor* cursor, uint64_t addr); + void SeekToOrderingIndex(uint64_t idx); + bool Next(); + bool Previous(); + + std::vector<LinearDisassemblyLine> GetLines(); + + Ref<LinearViewCursor> Duplicate(); + + static int Compare(LinearViewCursor* a, LinearViewCursor* b); + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index bb872f8d..e58144ff 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -169,6 +169,8 @@ extern "C" struct BNDataRenderer; struct BNDataRendererContainer; struct BNDisassemblyTextRenderer; + struct BNLinearViewObject; + struct BNLinearViewCursor; typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, bool force, void* ctx); @@ -1395,7 +1397,6 @@ extern "C" BNLinearDisassemblyLineType type; BNFunction* function; BNBasicBlock* block; - size_t lineOffset; BNDisassemblyTextLine contents; }; @@ -2089,6 +2090,20 @@ extern "C" SettingsContextScope = 0x10 }; + enum BNLinearViewObjectIdentifierType + { + SingleLinearViewObject, + AddressLinearViewObject, + AddressRangeLinearViewObject + }; + + struct BNLinearViewObjectIdentifier + { + char* name; + BNLinearViewObjectIdentifierType type; + uint64_t start, end; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -2972,6 +2987,63 @@ __attribute__ ((format (printf, 1, 2))) BNLinearDisassemblyPosition* pos, BNDisassemblySettings* settings, size_t* count); BINARYNINJACOREAPI void BNFreeLinearDisassemblyLines(BNLinearDisassemblyLine* lines, size_t count); + BINARYNINJACOREAPI BNLinearViewObject* BNCreateLinearViewDisassemblyByBlock(BNBinaryView* view, + BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNLinearViewObject* BNNewLinearViewObjectReference(BNLinearViewObject* obj); + BINARYNINJACOREAPI void BNFreeLinearViewObject(BNLinearViewObject* obj); + BINARYNINJACOREAPI BNLinearViewObject* BNGetFirstLinearViewObjectChild(BNLinearViewObject* obj); + BINARYNINJACOREAPI BNLinearViewObject* BNGetLastLinearViewObjectChild(BNLinearViewObject* obj); + BINARYNINJACOREAPI BNLinearViewObject* BNGetPreviousLinearViewObjectChild(BNLinearViewObject* parent, + BNLinearViewObject* child); + BINARYNINJACOREAPI BNLinearViewObject* BNGetNextLinearViewObjectChild(BNLinearViewObject* parent, + BNLinearViewObject* child); + BINARYNINJACOREAPI BNLinearViewObject* BNGetLinearViewObjectChildForAddress(BNLinearViewObject* parent, + uint64_t addr); + BINARYNINJACOREAPI BNLinearViewObject* BNGetLinearViewObjectChildForIdentifier(BNLinearViewObject* parent, + BNLinearViewObjectIdentifier* id); + BINARYNINJACOREAPI BNLinearDisassemblyLine* BNGetLinearViewObjectLines(BNLinearViewObject* obj, + BNLinearViewObject* prev, BNLinearViewObject* next, size_t* count); + BINARYNINJACOREAPI uint64_t BNGetLinearViewObjectStart(BNLinearViewObject* obj); + BINARYNINJACOREAPI uint64_t BNGetLinearViewObjectEnd(BNLinearViewObject* obj); + BINARYNINJACOREAPI BNLinearViewObjectIdentifier BNGetLinearViewObjectIdentifier(BNLinearViewObject* obj); + BINARYNINJACOREAPI void BNFreeLinearViewObjectIdentifier(BNLinearViewObjectIdentifier* id); + BINARYNINJACOREAPI int BNCompareLinearViewObjectChildren(BNLinearViewObject* obj, + BNLinearViewObject* a, BNLinearViewObject* b); + BINARYNINJACOREAPI uint64_t BNGetLinearViewObjectOrderingIndexTotal(BNLinearViewObject* obj); + BINARYNINJACOREAPI uint64_t BNGetLinearViewObjectOrderingIndexForChild(BNLinearViewObject* parent, + BNLinearViewObject* child); + BINARYNINJACOREAPI BNLinearViewObject* BNGetLinearViewObjectChildForOrderingIndex(BNLinearViewObject* parent, + uint64_t idx); + + BINARYNINJACOREAPI BNLinearViewCursor* BNCreateLinearViewCursor(BNLinearViewObject* root); + BINARYNINJACOREAPI BNLinearViewCursor* BNDuplicateLinearViewCursor(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI BNLinearViewCursor* BNNewLinearViewCursorReference(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI void BNFreeLinearViewCursor(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI bool BNIsLinearViewCursorBeforeBegin(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI bool BNIsLinearViewCursorAfterEnd(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI BNLinearViewObject* BNGetLinearViewCursorCurrentObject(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI BNLinearViewObjectIdentifier* BNGetLinearViewCursorPath(BNLinearViewCursor* cursor, size_t* count); + BINARYNINJACOREAPI void BNFreeLinearViewCursorPath(BNLinearViewObjectIdentifier* objs, size_t count); + BINARYNINJACOREAPI BNLinearViewObject** BNGetLinearViewCursorPathObjects(BNLinearViewCursor* cursor, size_t* count); + BINARYNINJACOREAPI void BNFreeLinearViewCursorPathObjects(BNLinearViewObject** objs, size_t count); + BINARYNINJACOREAPI BNAddressRange BNGetLinearViewCursorOrderingIndex(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI uint64_t BNGetLinearViewCursorOrderingIndexTotal(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI void BNSeekLinearViewCursorToBegin(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI void BNSeekLinearViewCursorToEnd(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI void BNSeekLinearViewCursorToAddress(BNLinearViewCursor* cursor, uint64_t addr); + BINARYNINJACOREAPI bool BNSeekLinearViewCursorToPath(BNLinearViewCursor* cursor, + BNLinearViewObjectIdentifier* ids, size_t count); + BINARYNINJACOREAPI bool BNSeekLinearViewCursorToPathAndAddress(BNLinearViewCursor* cursor, + BNLinearViewObjectIdentifier* ids, size_t count, uint64_t addr); + BINARYNINJACOREAPI bool BNSeekLinearViewCursorToCursorPath(BNLinearViewCursor* cursor, BNLinearViewCursor* path); + BINARYNINJACOREAPI bool BNSeekLinearViewCursorToCursorPathAndAddress(BNLinearViewCursor* cursor, + BNLinearViewCursor* path, uint64_t addr); + BINARYNINJACOREAPI void BNSeekLinearViewCursorToOrderingIndex(BNLinearViewCursor* cursor, uint64_t idx); + BINARYNINJACOREAPI bool BNLinearViewCursorNext(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI bool BNLinearViewCursorPrevious(BNLinearViewCursor* cursor); + BINARYNINJACOREAPI BNLinearDisassemblyLine* BNGetLinearViewCursorLines(BNLinearViewCursor* cursor, size_t* count); + BINARYNINJACOREAPI int BNCompareLinearViewCursors(BNLinearViewCursor* a, BNLinearViewCursor* b); + BINARYNINJACOREAPI void BNDefineDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); BINARYNINJACOREAPI void BNDefineUserDataVariable(BNBinaryView* view, uint64_t addr, BNTypeWithConfidence* type); BINARYNINJACOREAPI void BNUndefineDataVariable(BNBinaryView* view, uint64_t addr); diff --git a/binaryview.cpp b/binaryview.cpp index d1c44e97..32cc688d 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -2480,7 +2480,6 @@ vector<LinearDisassemblyLine> BinaryView::GetPreviousLinearDisassemblyLines(Line line.type = lines[i].type; line.function = lines[i].function ? new Function(BNNewFunctionReference(lines[i].function)) : nullptr; line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; - line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; line.contents.instrIndex = lines[i].contents.instrIndex; line.contents.highlight = lines[i].contents.highlight; @@ -2518,7 +2517,6 @@ vector<LinearDisassemblyLine> BinaryView::GetNextLinearDisassemblyLines(LinearDi line.type = lines[i].type; line.function = lines[i].function ? new Function(BNNewFunctionReference(lines[i].function)) : nullptr; line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; - line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; line.contents.instrIndex = lines[i].contents.instrIndex; line.contents.highlight = lines[i].contents.highlight; diff --git a/linearviewcursor.cpp b/linearviewcursor.cpp new file mode 100644 index 00000000..41356c47 --- /dev/null +++ b/linearviewcursor.cpp @@ -0,0 +1,228 @@ +// Copyright (c) 2020 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace std; +using namespace BinaryNinja; + + +LinearViewCursor::LinearViewCursor(LinearViewObject* root) +{ + m_object = BNCreateLinearViewCursor(root->GetObject()); +} + + +LinearViewCursor::LinearViewCursor(BNLinearViewCursor* cursor) +{ + m_object = cursor; +} + + +bool LinearViewCursor::IsBeforeBegin() const +{ + return BNIsLinearViewCursorBeforeBegin(m_object); +} + + +bool LinearViewCursor::IsAfterEnd() const +{ + return BNIsLinearViewCursorAfterEnd(m_object); +} + + +bool LinearViewCursor::IsValid() const +{ + return !(IsBeforeBegin() || IsAfterEnd()); +} + + +Ref<LinearViewObject> LinearViewCursor::GetCurrentObject() const +{ + BNLinearViewObject* result = BNGetLinearViewCursorCurrentObject(m_object); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +vector<LinearViewObjectIdentifier> LinearViewCursor::GetPath() const +{ + size_t count; + BNLinearViewObjectIdentifier* path = BNGetLinearViewCursorPath(m_object, &count); + vector<LinearViewObjectIdentifier> result; + for (size_t i = 0; i < count; i++) + { + LinearViewObjectIdentifier id; + id.name = path[i].name; + id.type = path[i].type; + id.start = path[i].start; + id.end = path[i].end; + result.push_back(id); + } + BNFreeLinearViewCursorPath(path, count); + return result; +} + + +vector<Ref<LinearViewObject>> LinearViewCursor::GetPathObjects() const +{ + size_t count; + BNLinearViewObject** path = BNGetLinearViewCursorPathObjects(m_object, &count); + vector<Ref<LinearViewObject>> result; + for (size_t i = 0; i < count; i++) + result.push_back(new LinearViewObject(BNNewLinearViewObjectReference(path[i]))); + BNFreeLinearViewCursorPathObjects(path, count); + return result; +} + + +BNAddressRange LinearViewCursor::GetOrderingIndex() const +{ + return BNGetLinearViewCursorOrderingIndex(m_object); +} + + +uint64_t LinearViewCursor::GetOrderingIndexTotal() const +{ + return BNGetLinearViewCursorOrderingIndexTotal(m_object); +} + + +void LinearViewCursor::SeekToBegin() +{ + BNSeekLinearViewCursorToBegin(m_object); +} + + +void LinearViewCursor::SeekToEnd() +{ + BNSeekLinearViewCursorToEnd(m_object); +} + + +void LinearViewCursor::SeekToAddress(uint64_t addr) +{ + BNSeekLinearViewCursorToAddress(m_object, addr); +} + + +bool LinearViewCursor::SeekToPath(const vector<LinearViewObjectIdentifier>& path) +{ + BNLinearViewObjectIdentifier* ids = new BNLinearViewObjectIdentifier[path.size()]; + for (size_t i = 0; i < path.size(); i++) + { + ids[i].name = BNAllocString(path[i].name.c_str()); + ids[i].type = path[i].type; + ids[i].start = path[i].start; + ids[i].end = path[i].end; + } + bool result = BNSeekLinearViewCursorToPath(m_object, ids, path.size()); + for (size_t i = 0; i < path.size(); i++) + BNFreeString(ids[i].name); + delete[] ids; + return result; +} + + +bool LinearViewCursor::SeekToPath(const vector<LinearViewObjectIdentifier>& path, uint64_t addr) +{ + BNLinearViewObjectIdentifier* ids = new BNLinearViewObjectIdentifier[path.size()]; + for (size_t i = 0; i < path.size(); i++) + { + ids[i].name = BNAllocString(path[i].name.c_str()); + ids[i].type = path[i].type; + ids[i].start = path[i].start; + ids[i].end = path[i].end; + } + bool result = BNSeekLinearViewCursorToPathAndAddress(m_object, ids, path.size(), addr); + for (size_t i = 0; i < path.size(); i++) + BNFreeString(ids[i].name); + delete[] ids; + return result; +} + + +bool LinearViewCursor::SeekToPath(LinearViewCursor* cursor) +{ + return BNSeekLinearViewCursorToCursorPath(m_object, cursor->GetObject()); +} + + +bool LinearViewCursor::SeekToPath(LinearViewCursor* cursor, uint64_t addr) +{ + return BNSeekLinearViewCursorToCursorPathAndAddress(m_object, cursor->GetObject(), addr); +} + + +void LinearViewCursor::SeekToOrderingIndex(uint64_t idx) +{ + BNSeekLinearViewCursorToOrderingIndex(m_object, idx); +} + + +bool LinearViewCursor::Next() +{ + return BNLinearViewCursorNext(m_object); +} + + +bool LinearViewCursor::Previous() +{ + return BNLinearViewCursorPrevious(m_object); +} + + +vector<LinearDisassemblyLine> LinearViewCursor::GetLines() +{ + size_t count; + BNLinearDisassemblyLine* lines = BNGetLinearViewCursorLines(m_object, &count); + + vector<LinearDisassemblyLine> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + LinearDisassemblyLine line; + line.type = lines[i].type; + line.function = lines[i].function ? new Function(BNNewFunctionReference(lines[i].function)) : nullptr; + line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; + line.contents.addr = lines[i].contents.addr; + 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); + } + + BNFreeLinearDisassemblyLines(lines, count); + return result; +} + + +Ref<LinearViewCursor> LinearViewCursor::Duplicate() +{ + return new LinearViewCursor(BNDuplicateLinearViewCursor(m_object)); +} + + +int LinearViewCursor::Compare(LinearViewCursor* a, LinearViewCursor* b) +{ + return BNCompareLinearViewCursors(a->GetObject(), b->GetObject()); +} diff --git a/linearviewobject.cpp b/linearviewobject.cpp new file mode 100644 index 00000000..8f4fc22e --- /dev/null +++ b/linearviewobject.cpp @@ -0,0 +1,206 @@ +// Copyright (c) 2020 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace std; +using namespace BinaryNinja; + + +LinearViewObjectIdentifier::LinearViewObjectIdentifier(): + type(SingleLinearViewObject), start(0), end(0) +{ +} + + +LinearViewObjectIdentifier::LinearViewObjectIdentifier(const string& _name): + name(_name), type(SingleLinearViewObject), start(0), end(0) +{ +} + + +LinearViewObjectIdentifier::LinearViewObjectIdentifier(const string& _name, uint64_t addr): + name(_name), type(AddressLinearViewObject), start(addr), end(addr) +{ +} + + +LinearViewObjectIdentifier::LinearViewObjectIdentifier(const string& _name, uint64_t _start, uint64_t _end): + name(_name), type(AddressRangeLinearViewObject), start(_start), end(_end) +{ +} + + +LinearViewObjectIdentifier::LinearViewObjectIdentifier(const LinearViewObjectIdentifier& other): + name(other.name), type(other.type), start(other.start), end(other.end) +{ +} + + +LinearViewObject::LinearViewObject(BNLinearViewObject* obj) +{ + m_object = obj; +} + + +Ref<LinearViewObject> LinearViewObject::GetFirstChild() +{ + BNLinearViewObject* result = BNGetFirstLinearViewObjectChild(m_object); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::GetLastChild() +{ + BNLinearViewObject* result = BNGetLastLinearViewObjectChild(m_object); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::GetPreviousChild(LinearViewObject* obj) +{ + BNLinearViewObject* result = BNGetPreviousLinearViewObjectChild(m_object, obj->GetObject()); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::GetNextChild(LinearViewObject* obj) +{ + BNLinearViewObject* result = BNGetNextLinearViewObjectChild(m_object, obj->GetObject()); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::GetChildForAddress(uint64_t addr) +{ + BNLinearViewObject* result = BNGetLinearViewObjectChildForAddress(m_object, addr); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::GetChildForIdentifier(const LinearViewObjectIdentifier& id) +{ + BNLinearViewObjectIdentifier lvid; + lvid.name = BNAllocString(id.name.c_str()); + lvid.type = id.type; + lvid.start = id.start; + lvid.end = id.end; + BNLinearViewObject* result = BNGetLinearViewObjectChildForIdentifier(m_object, &lvid); + BNFreeString(lvid.name); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +int LinearViewObject::CompareChildren(LinearViewObject* a, LinearViewObject* b) +{ + return BNCompareLinearViewObjectChildren(m_object, a->GetObject(), b->GetObject()); +} + + +vector<LinearDisassemblyLine> LinearViewObject::GetLines(LinearViewObject* prev, LinearViewObject* next) +{ + size_t count; + BNLinearDisassemblyLine* lines = BNGetLinearViewObjectLines(m_object, prev ? prev->GetObject() : nullptr, + next ? next->GetObject() : nullptr, &count); + + vector<LinearDisassemblyLine> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + LinearDisassemblyLine line; + line.type = lines[i].type; + line.function = lines[i].function ? new Function(BNNewFunctionReference(lines[i].function)) : nullptr; + line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; + line.contents.addr = lines[i].contents.addr; + 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); + } + + BNFreeLinearDisassemblyLines(lines, count); + return result; +} + + +uint64_t LinearViewObject::GetStart() const +{ + return BNGetLinearViewObjectStart(m_object); +} + + +uint64_t LinearViewObject::GetEnd() const +{ + return BNGetLinearViewObjectEnd(m_object); +} + + +LinearViewObjectIdentifier LinearViewObject::GetIdentifier() const +{ + BNLinearViewObjectIdentifier id = BNGetLinearViewObjectIdentifier(m_object); + LinearViewObjectIdentifier result; + result.name = id.name; + result.type = id.type; + result.start = id.start; + result.end = id.end; + BNFreeLinearViewObjectIdentifier(&id); + return result; +} + + +uint64_t LinearViewObject::GetOrderingIndexTotal() const +{ + return BNGetLinearViewObjectOrderingIndexTotal(m_object); +} + + +uint64_t LinearViewObject::GetOrderingIndexForChild(LinearViewObject* obj) const +{ + return BNGetLinearViewObjectOrderingIndexForChild(m_object, obj->GetObject()); +} + + +Ref<LinearViewObject> LinearViewObject::GetChildForOrderingIndex(uint64_t idx) +{ + BNLinearViewObject* result = BNGetLinearViewObjectChildForOrderingIndex(m_object, idx); + if (result) + return new LinearViewObject(result); + return nullptr; +} + + +Ref<LinearViewObject> LinearViewObject::CreateDisassemblyByBlock(BinaryView* view, DisassemblySettings* settings) +{ + return new LinearViewObject(BNCreateLinearViewDisassemblyByBlock(view->GetObject(), + settings ? settings->GetObject() : nullptr)); +} diff --git a/python/binaryview.py b/python/binaryview.py index 1aba8b84..e9a8cca8 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -4469,7 +4469,7 @@ class BinaryView(object): addr = lines[i].contents.addr tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].contents.tokens, lines[i].contents.count) contents = binaryninja.function.DisassemblyTextLine(tokens, addr, color = color) - result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) + result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, contents)) func = None block = None diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 92679917..24574e48 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -18,6 +18,15 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +import ctypes + +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja import highlight +from binaryninja import function +from binaryninja import basicblock +from binaryninja.enums import LinearViewObjectIdentifierType + class LinearDisassemblyPosition(object): """ @@ -60,11 +69,10 @@ class LinearDisassemblyPosition(object): class LinearDisassemblyLine(object): - def __init__(self, line_type, func, block, line_offset, contents): + def __init__(self, line_type, func, block, contents): self.type = line_type self.function = func self.block = block - self.line_offset = line_offset self.contents = contents def __str__(self): @@ -72,3 +80,384 @@ class LinearDisassemblyLine(object): def __repr__(self): return repr(self.contents) + + +class LinearViewObjectIdentifier(object): + def __init__(self, name, start = None, end = None): + self._name = name + self._start = start + self._end = end + + @property + def name(self): + return self._name + + @property + def address(self): + return self._start + + @property + def start(self): + return self._start + + @property + def end(self): + return self._end + + @property + def has_address(self): + return self._start is not None + + @property + def has_range(self): + return self._start is not None and self._end is not None + + def __str__(self): + if not self.has_address: + return self._name + if self.has_range: + return "%s 0x%x-0x%x" % (self._name, self._start, self._end) + return "%s 0x%x" % (self._name, self._start) + + def __repr__(self): + return "<LinearViewObjectIdentifier: " + str(self) + ">" + + def _to_api_object(self, obj = None): + if obj is None: + result = core.BNLinearViewObjectIdentifier() + else: + result = obj + result.name = self.name + if self.has_range: + result.type = LinearViewObjectIdentifierType.AddressRangeLinearViewObject + result.start = self.start + result.end = self.end + elif self.has_address: + result.type = LinearViewObjectIdentifierType.AddressLinearViewObject + result.start = self.start + result.end = self.start + else: + result.type = LinearViewObjectIdentifierType.SingleLinearViewObject + result.start = 0 + result.end = 0 + return result + + @classmethod + def _from_api_object(cls, obj): + if obj.type == LinearViewObjectIdentifierType.AddressLinearViewObject: + result = LinearViewObjectIdentifier(obj.name, obj.start) + elif obj.type == LinearViewObjectIdentifierType.AddressRangeLinearViewObject: + result = LinearViewObjectIdentifier(obj.name, obj.start, obj.end) + else: + result = LinearViewObjectIdentifier(obj.name) + return result + + +class LinearViewObject(object): + def __init__(self, handle, parent = None): + self.handle = handle + self._parent = parent + + def __del__(self): + core.BNFreeLinearViewObject(self.handle) + + @property + def first_child(self): + result = core.BNGetFirstLinearViewObjectChild(self.handle) + if not result: + return None + return LinearViewObject(result, self) + + @property + def last_child(self): + result = core.BNGetLastLinearViewObjectChild(self.handle) + if not result: + return None + return LinearViewObject(result, self) + + @property + def previous(self): + if parent is None: + return None + result = core.BNGetPreviousLinearViewObjectChild(self._parent.handle, self.handle) + if not result: + return None + return LinearViewObject(result, self._parent) + + @property + def next(self): + if parent is None: + return None + result = core.BNGetNextLinearViewObjectChild(self._parent.handle, self.handle) + if not result: + return None + return LinearViewObject(result, self._parent) + + @property + def start(self): + return core.BNGetLinearViewObjectStart(self.handle) + + @property + def end(self): + return core.BNGetLinearViewObjectEnd(self.handle) + + @property + def parent(self): + return self._parent + + @property + def identifier(self): + ident = core.BNGetLinearViewObjectIdentifier(self.handle) + result = LinearViewObjectIdentifier._from_api_object(ident) + core.BNFreeLinearViewObjectIdentifier(ident) + return result + + @property + def cursor(self): + root = self + while root.parent is not None: + root = root.parent + return LinearViewCursor(root) + + @property + def ordering_index(self): + if self.parent is None: + return 0 + return self.parent.ordering_index_for_child(self) + + @property + def ordering_index_total(self): + return core.BNGetLinearViewObjectOrderingIndexTotal(self.handle) + + def __len__(self): + return self.end - self.start + + def __str__(self): + result = str(self.identifier) + if self._parent is not None: + result = str(self._parent) + "/" + result + return result + + def __repr__(self): + return "<LinearViewObject: " + str(self) + ">" + + def child_for_address(self, addr): + result = core.BNGetLinearViewObjectChildForAddress(self.handle, addr) + if not result: + return None + return LinearViewObject(result, self) + + def child_for_identifier(self, ident): + ident_obj = ident._to_api_object() + result = core.BNGetLinearViewObjectChildForIdentifier(self.handle, ident_obj) + if not result: + return None + return LinearViewObject(result, self) + + def child_for_ordering_index(self, idx): + result = core.BNGetLinearViewObjectChildForOrderingIndex(self.handle, idx) + if not result: + return None + return LinearViewObject(result, self) + + def compare_children(self, a, b): + return core.BNCompareLinearViewObjectChildren(self.handle, a.handle, b.handle) + + def get_lines(self, prev_obj, next_obj): + if prev_obj is not None: + prev_obj = prev_obj.handle + if next_obj is not None: + next_obj = next_obj.handle + + count = ctypes.c_ulonglong(0) + lines = core.BNGetLinearViewObjectLines(self.handle, prev_obj, next_obj, count) + + result = [] + for i in range(0, count.value): + func = None + block = None + if lines[i].function: + func = binaryninja.function.Function(self, core.BNNewFunctionReference(lines[i].function)) + if lines[i].block: + block = binaryninja.basicblock.BasicBlock(core.BNNewBasicBlockReference(lines[i].block), self) + color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) + addr = lines[i].contents.addr + tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].contents.tokens, lines[i].contents.count) + contents = binaryninja.function.DisassemblyTextLine(tokens, addr, color = color) + result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) + + core.BNFreeLinearDisassemblyLines(lines, count.value) + return result + + def ordering_index_for_child(self, child): + return core.BNGetLinearViewObjectOrderingIndexForChild(self.handle, child.handle) + + @classmethod + def disassembly_by_block(cls, view, settings = None): + if settings is not None: + settings = settings.handle + return LinearViewObject(core.BNCreateLinearViewDisassemblyByBlock(view.handle, settings)) + + +class LinearViewCursor(object): + def __init__(self, root_object, handle = None): + if handle is not None: + self.handle = handle + else: + self.handle = core.BNCreateLinearViewCursor(root_object.handle) + + def __del__(self): + core.BNFreeLinearViewCursor(self.handle) + + @property + def before_begin(self): + return core.BNIsLinearViewCursorBeforeBegin(self.handle) + + @property + def after_end(self): + return core.BNIsLinearViewCursorAfterEnd(self.handle) + + @property + def valid(self): + return not (self.before_begin or self.after_end) + + @property + def current_object(self): + count = ctypes.c_ulonglong(0) + path = core.BNGetLinearViewCursorPathObjects(self.handle, count) + result = None + for i in range(0, count.value): + result = LinearViewObject(core.BNNewLinearViewObjectReference(path[i]), result) + core.BNFreeLinearViewCursorPathObjects(path, count.value) + return result + + @property + def path(self): + count = ctypes.c_ulonglong(0) + path = core.BNGetLinearViewCursorPath(self.handle, count) + result = [] + for i in range(0, count.value): + result.append(LinearViewObjectIdentifier._from_api_object(path[i])) + core.BNFreeLinearViewCursorPath(path, count.value) + return result + + @property + def path_objects(self): + count = ctypes.c_ulonglong(0) + path = core.BNGetLinearViewCursorPathObjects(self.handle, count) + result = [] + parent = None + for i in range(0, count.value): + obj = LinearViewObject(core.BNNewLinearViewObjectReference(path[i]), parent) + result.append(obj) + parent = obj + core.BNFreeLinearViewCursorPathObjects(path, count.value) + return result + + @property + def ordering_index(self): + return core.BNGetLinearViewCursorOrderingIndex(self.handle) + + @property + def ordering_index_total(self): + return core.BNGetLinearViewCursorOrderingIndexTotal(self.handle) + + def seek_to_begin(self): + core.BNSeekLinearViewCursorToBegin(self.handle) + + def seek_to_end(self): + core.BNSeekLinearViewCursorToEnd(self.handle) + + def seek_to_address(self, addr): + core.BNSeekLinearViewCursorToAddress(self.handle, addr) + + def seek_to_path(self, path, addr = None): + if isinstance(path, LinearViewCursor): + if addr is None: + return core.BNSeekLinearViewCursorToCursorPath(self.handle, path.handle) + return core.BNSeekLinearViewCursorToCursorPathAndAddress(self.handle, path.handle, addr) + path_objs = (core.BNLinearViewObjectIdentifier * len(path))() + for i in range(0, len(path)): + path[i]._to_api_object(path_objs[i]) + if addr is None: + return core.BNSeekLinearViewCursorToPath(self.handle, path_objs, len(path)) + return core.BNSeekLinearViewCursorToPathAndAddress(self.handle, path_objs, len(path), addr) + + def seek_to_ordering_index(self, idx): + core.BNSeekLinearViewCursorToOrderingIndex(self.handle, idx) + + def previous(self): + return core.BNLinearViewCursorPrevious(self.handle) + + def next(self): + return core.BNLinearViewCursorNext(self.handle) + + @property + def lines(self): + count = ctypes.c_ulonglong(0) + lines = core.BNGetLinearViewCursorLines(self.handle, count) + + result = [] + for i in range(0, count.value): + func = None + block = None + if lines[i].function: + func = binaryninja.function.Function(self, core.BNNewFunctionReference(lines[i].function)) + if lines[i].block: + block = binaryninja.basicblock.BasicBlock(core.BNNewBasicBlockReference(lines[i].block), self) + color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) + addr = lines[i].contents.addr + tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].contents.tokens, lines[i].contents.count) + contents = binaryninja.function.DisassemblyTextLine(tokens, addr, color = color) + result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) + + core.BNFreeLinearDisassemblyLines(lines, count.value) + return result + + def duplicate(self): + return LinearViewCursor(None, handle = core.BNDuplicateLinearViewCursor(self.handle)) + + def __str__(self): + return str(self.current_object) + + def __repr__(self): + return "<LinearViewCursor: " + str(self.current_object) + ">" + + def __eq__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) == 0 + return False + + def __ne__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) != 0 + return True + + def __lt__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) < 0 + return False + + def __le__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) <= 0 + return False + + def __gt__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) > 0 + return False + + def __ge__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) >= 0 + return False + + def __cmp__(self, other): + if isinstance(other, LinearViewCursor): + return LinearViewCursor.compare(self, other) + return 0 + + @classmethod + def compare(cls, a, b): + return core.BNCompareLinearViewCursors(a.handle, b.handle) diff --git a/ui/linearview.h b/ui/linearview.h index 62bb3dad..f8f85439 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -13,34 +13,59 @@ #define LINEAR_VIEW_UPDATE_CHECK_INTERVAL 200 #define MAX_STRING_TYPE_LENGTH 1048576 +struct BINARYNINJAUIAPI LinearViewLine: public BinaryNinja::LinearDisassemblyLine +{ + BinaryNinja::Ref<BinaryNinja::LinearViewCursor> cursor; + size_t lineIndex; +}; + struct BINARYNINJAUIAPI LinearViewCursorPosition: public BinaryNinja::LinearDisassemblyPosition { - uint64_t lineAddress; - size_t lineIndexForAddress; + BinaryNinja::Ref<BinaryNinja::LinearViewCursor> cursor; + size_t lineIndex; size_t tokenIndex; LinearViewCursorPosition(); LinearViewCursorPosition(const LinearViewCursorPosition& pos); LinearViewCursorPosition(const BinaryNinja::LinearDisassemblyPosition& pos); + LinearViewCursorPosition(const LinearViewLine& line); LinearViewCursorPosition& operator=(const LinearViewCursorPosition& pos); + + bool operator==(const LinearViewCursorPosition& other) const; + bool operator!=(const LinearViewCursorPosition& other) const; + bool operator<(const LinearViewCursorPosition& other) const; + bool operator<=(const LinearViewCursorPosition& other) const; + bool operator>=(const LinearViewCursorPosition& other) const; + bool operator>(const LinearViewCursorPosition& other) const; + + LinearViewCursorPosition AsLine() const; }; class BINARYNINJAUIAPI LinearViewHistoryEntry: public HistoryEntry { - BinaryNinja::LinearDisassemblyPosition m_topPosition; - LinearViewCursorPosition m_cursorPosition; - size_t m_topLineOffset; + std::vector<BinaryNinja::LinearViewObjectIdentifier> m_topPath; + size_t m_topLineIndex; + uint64_t m_topAddr; + std::vector<BinaryNinja::LinearViewObjectIdentifier> m_cursorPath; + size_t m_cursorLineIndex; + uint64_t m_cursorAddr; HighlightTokenState m_highlight; public: - const BinaryNinja::LinearDisassemblyPosition& getTopPosition() const { return m_topPosition; } - const LinearViewCursorPosition& getCursorPosition() const { return m_cursorPosition; } - size_t getTopLineOffset() const { return m_topLineOffset; } + const std::vector<BinaryNinja::LinearViewObjectIdentifier>& getTopPath() const { return m_topPath; } + size_t getTopLineIndex() const { return m_topLineIndex; } + uint64_t getTopAddress() const { return m_topAddr; } + const std::vector<BinaryNinja::LinearViewObjectIdentifier>& getCursorPath() const { return m_cursorPath; } + size_t getCursorLineIndex() const { return m_cursorLineIndex; } + uint64_t getCursorAddress() const { return m_cursorAddr; } const HighlightTokenState& getHighlightTokenState() const { return m_highlight; } - void setTopPosition(const BinaryNinja::LinearDisassemblyPosition& pos) { m_topPosition = pos; } - void setCursorPosition(const LinearViewCursorPosition& pos) { m_cursorPosition = pos; } - void setTopLineOffset(size_t offset) { m_topLineOffset = offset; } + void setTopPath(const std::vector<BinaryNinja::LinearViewObjectIdentifier>& path) { m_topPath = path; } + void setTopLineIndex(size_t offset) { m_topLineIndex = offset; } + void setTopAddress(uint64_t addr) { m_topAddr = addr; } + void setCursorPath(const std::vector<BinaryNinja::LinearViewObjectIdentifier>& path) { m_cursorPath = path; } + void setCursorLineIndex(size_t offset) { m_cursorLineIndex = offset; } + void setCursorAddress(uint64_t addr) { m_cursorAddr = addr; } void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; } }; @@ -73,7 +98,6 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ BinaryViewRef m_data; ViewFrame* m_view; - std::vector<BNAddressRange> m_ranges; uint64_t m_allocatedLength; RenderContext m_render; @@ -83,7 +107,7 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ bool m_updatingScrollBar; bool m_updatesRequired; - bool m_updateBounds, m_updateBlockRef; + bool m_updateBounds; LinearViewCursorPosition m_cursorPosition, m_selectionStartPos; bool m_tokenSelection = false; @@ -93,8 +117,8 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ DisassemblySettingsRef m_settings; - BinaryNinja::LinearDisassemblyPosition m_topPosition, m_bottomPosition; - std::vector<BinaryNinja::LinearDisassemblyLine> m_lines; + BinaryNinja::Ref<BinaryNinja::LinearViewCursor> m_topPosition, m_bottomPosition; + std::vector<LinearViewLine> m_lines; size_t m_topLine; QTimer* m_updateTimer; @@ -104,13 +128,11 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ void adjustSize(int width, int height); - uint64_t getContiguousOffsetForAddress(uint64_t addr); - uint64_t getAddressForContiguousOffset(uint64_t offset); - void setTopToAddress(uint64_t addr); + void setTopToOrderingIndex(uint64_t idx); void refreshLines(size_t lineOffset = 0, bool refreshUIContext = true); bool cachePreviousLines(); - bool cacheNextLines(size_t& topLineAdjustment); + bool cacheNextLines(); void updateCache(); void refreshAtCurrentLocation(); bool navigateToAddress(uint64_t addr, bool center, bool updateHighlight, bool navByRef = false); @@ -138,6 +160,15 @@ class BINARYNINJAUIAPI LinearView: public QAbstractScrollArea, public View, publ TypeRef getPointerTypeAndName(ArchitectureRef arch, uint64_t addr, std::string& name); std::string getVariableName(uint64_t addr); + BinaryNinja::Ref<BinaryNinja::LinearViewObject> createLinearViewObject(); + LinearViewCursorPosition getPositionForCursor(BinaryNinja::LinearViewCursor* cursor); + bool updateCursor(LinearViewCursorPosition& cursorToUpdate, BinaryNinja::LinearViewCursor* matched, bool fullMatch); + bool updateCursor(LinearViewCursorPosition& cursorToUpdate, BinaryNinja::LinearViewCursor* newCursor); + bool updateCursor(LinearViewCursorPosition& cursorToUpdate, + const std::vector<BinaryNinja::LinearViewObjectIdentifier>& path, + BinaryNinja::LinearViewCursor* newCursor); + uint64_t getOrderingIndexForLine(const LinearViewLine& line); + private Q_SLOTS: void viewInHexEditor(); void viewInGraph(); |
