summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2025-10-03 18:48:17 -0400
committerBrian Potchik <brian@vector35.com>2025-10-03 18:48:17 -0400
commit0fb07c24d8321bdec2d5d5a254acbb9ceaee807a (patch)
tree181ed447398789d8f4d31614ee3edb8d81ebb0af
parent183ef5e2f0ba6124efac98efba67757f1e8b2aa9 (diff)
Add zero-copy data pointer access for BinaryData objects for API-side container transforms.
-rw-r--r--binaryninjaapi.h12
-rw-r--r--binaryninjacore.h4
-rw-r--r--binaryview.cpp12
-rw-r--r--view/kernelcache/core/transformers/KernelCacheTransforms.cpp11
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;