diff options
| author | Brian Potchik <brian@vector35.com> | 2025-10-03 18:48:17 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2025-10-03 18:48:17 -0400 |
| commit | 0fb07c24d8321bdec2d5d5a254acbb9ceaee807a (patch) | |
| tree | 181ed447398789d8f4d31614ee3edb8d81ebb0af | |
| parent | 183ef5e2f0ba6124efac98efba67757f1e8b2aa9 (diff) | |
Add zero-copy data pointer access for BinaryData objects for API-side container transforms.
| -rw-r--r-- | binaryninjaapi.h | 12 | ||||
| -rw-r--r-- | binaryninjacore.h | 4 | ||||
| -rw-r--r-- | binaryview.cpp | 12 | ||||
| -rw-r--r-- | view/kernelcache/core/transformers/KernelCacheTransforms.cpp | 11 |
4 files changed, 34 insertions, 5 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 99ba7044..f7896a45 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -5829,6 +5829,18 @@ namespace BinaryNinja { */ DataBuffer ReadBuffer(uint64_t offset, size_t len); + /*! GetDataPointer returns a pointer to the underlying data for zero-copy access + + \return pointer to data if available for zero-copy access, nullptr otherwise + */ + const uint8_t* GetDataPointer() const; + + /*! GetDataLength returns the length of the underlying data + + \return length of data if available for zero-copy access, 0 otherwise + */ + size_t GetDataLength() const; + /*! Write writes `len` bytes data at address `dest` to virtual address `offset` \param offset virtual address to write to diff --git a/binaryninjacore.h b/binaryninjacore.h index 67b17bc4..fb2e8ae8 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,7 +37,7 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 134 +#define BN_CURRENT_CORE_ABI_VERSION 135 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and @@ -4328,6 +4328,8 @@ extern "C" BINARYNINJACOREAPI size_t BNReadViewData(BNBinaryView* view, void* dest, uint64_t offset, size_t len); BINARYNINJACOREAPI BNDataBuffer* BNReadViewBuffer(BNBinaryView* view, uint64_t offset, size_t len); + BINARYNINJACOREAPI const uint8_t* BNGetViewDataPointer(BNBinaryView* view); + BINARYNINJACOREAPI size_t BNGetViewDataLength(BNBinaryView* view); BINARYNINJACOREAPI size_t BNWriteViewData(BNBinaryView* view, uint64_t offset, const void* data, size_t len); BINARYNINJACOREAPI size_t BNWriteViewBuffer(BNBinaryView* view, uint64_t offset, BNDataBuffer* data); diff --git a/binaryview.cpp b/binaryview.cpp index 21266886..66b7e77f 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1747,6 +1747,18 @@ DataBuffer BinaryView::ReadBuffer(uint64_t offset, size_t len) } +const uint8_t* BinaryView::GetDataPointer() const +{ + return BNGetViewDataPointer(m_object); +} + + +size_t BinaryView::GetDataLength() const +{ + return BNGetViewDataLength(m_object); +} + + size_t BinaryView::WriteBuffer(uint64_t offset, const DataBuffer& data) { return BNWriteViewBuffer(m_object, offset, data.GetBufferObject()); diff --git a/view/kernelcache/core/transformers/KernelCacheTransforms.cpp b/view/kernelcache/core/transformers/KernelCacheTransforms.cpp index 6158e7ad..be06ad9e 100644 --- a/view/kernelcache/core/transformers/KernelCacheTransforms.cpp +++ b/view/kernelcache/core/transformers/KernelCacheTransforms.cpp @@ -41,11 +41,14 @@ public: if (!context || !context->GetInput()) return false; - // TODO: DataBuffers are not zero-copy, so this is inefficient. Investigate a better way. - auto input = context->GetInput()->ReadBuffer(0, context->GetInput()->GetLength()); + const uint8_t* dataPtr = context->GetInput()->GetDataPointer(); + size_t dataLength = context->GetInput()->GetDataLength(); + if (!dataPtr || !dataLength) + return false; + DERItem item = {}; - item.data = (DERByte *)input.GetData(); - item.length = static_cast<DERSize>(std::min(input.GetLength(), (size_t)std::numeric_limits<DERSize>::max())); + item.data = (DERByte *)dataPtr; + item.length = static_cast<DERSize>(std::min(dataLength, (size_t)std::numeric_limits<DERSize>::max())); Img4Payload payload = {}; if (auto result = DERImg4DecodePayload(&item, &payload); (result != DR_Success) && (result != DR_DecodeError)) return false; |
