// Copyright (c) 2015-2026 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 BinaryNinja;
using namespace std;
BinaryReader::BinaryReader(BinaryView* data, BNEndianness endian) : m_view(data)
{
m_stream = BNCreateBinaryReader(data->GetObject());
BNSetBinaryReaderEndianness(m_stream, endian);
}
BinaryReader::~BinaryReader()
{
BNFreeBinaryReader(m_stream);
}
BNEndianness BinaryReader::GetEndianness() const
{
return BNGetBinaryReaderEndianness(m_stream);
}
void BinaryReader::SetEndianness(BNEndianness endian)
{
BNSetBinaryReaderEndianness(m_stream, endian);
}
void BinaryReader::Read(void* dest, size_t len)
{
if (!BNReadData(m_stream, dest, len))
throw ReadException();
}
DataBuffer BinaryReader::Read(size_t len)
{
DataBuffer result(len);
Read(result.GetData(), len);
return result;
}
string BinaryReader::ReadString(size_t len)
{
DataBuffer result = Read(len);
return string((const char*)result.GetData(), len);
}
uint8_t BinaryReader::Read8()
{
uint8_t result;
if (!BNRead8(m_stream, &result))
throw ReadException();
return result;
}
uint16_t BinaryReader::Read16()
{
uint16_t result;
if (!BNRead16(m_stream, &result))
throw ReadException();
return result;
}
uint32_t BinaryReader::Read32()
{
uint32_t result;
if (!BNRead32(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::Read64()
{
uint64_t result;
if (!BNRead64(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::ReadPointer()
{
size_t addressSize = m_view->GetAddressSize();
if (addressSize > 8 || addressSize == 0)
throw ReadException();
if (GetEndianness() == BigEndian)
return ReadBEPointer();
return ReadLEPointer();
}
uint16_t BinaryReader::ReadLE16()
{
uint16_t result;
if (!BNReadLE16(m_stream, &result))
throw ReadException();
return result;
}
uint32_t BinaryReader::ReadLE32()
{
uint32_t result;
if (!BNReadLE32(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::ReadLE64()
{
uint64_t result;
if (!BNReadLE64(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::ReadLEPointer()
{
uint64_t result;
size_t addressSize = m_view->GetAddressSize();
switch (addressSize)
{
case 1:
{
uint8_t r;
if (!BNRead8(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 2:
{
uint16_t r;
if (!BNReadLE16(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 4:
{
uint32_t r;
if (!BNReadLE32(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 8:
{
if (!BNReadLE64(m_stream, &result))
throw ReadException();
break;
}
default:
{
throw ReadException();
break;
}
}
return result;
}
uint16_t BinaryReader::ReadBE16()
{
uint16_t result;
if (!BNReadBE16(m_stream, &result))
throw ReadException();
return result;
}
uint32_t BinaryReader::ReadBE32()
{
uint32_t result;
if (!BNReadBE32(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::ReadBE64()
{
uint64_t result;
if (!BNReadBE64(m_stream, &result))
throw ReadException();
return result;
}
uint64_t BinaryReader::ReadBEPointer()
{
uint64_t result;
size_t addressSize = m_view->GetAddressSize();
switch (addressSize)
{
case 1:
{
uint8_t r;
if (!BNRead8(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 2:
{
uint16_t r;
if (!BNReadBE16(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 4:
{
uint32_t r;
if (!BNReadBE32(m_stream, &r))
throw ReadException();
result = r;
break;
}
case 8:
{
if (!BNReadBE64(m_stream, &result))
throw ReadException();
break;
}
default:
{
throw ReadException();
break;
}
}
return result;
}
bool BinaryReader::TryRead(void* dest, size_t len)
{
return BNReadData(m_stream, dest, len);
}
bool BinaryReader::TryRead(DataBuffer& dest, size_t len)
{
dest.SetSize(len);
return TryRead(dest.GetData(), len);
}
bool BinaryReader::TryReadString(string& dest, size_t len)
{
DataBuffer result(len);
if (!TryRead(result.GetData(), len))
return false;
dest = string((const char*)result.GetData(), len);
return true;
}
bool BinaryReader::TryRead8(uint8_t& result)
{
return BNRead8(m_stream, &result);
}
bool BinaryReader::TryRead16(uint16_t& result)
{
return BNRead16(m_stream, &result);
}
bool BinaryReader::TryRead32(uint32_t& result)
{
return BNRead32(m_stream, &result);
}
bool BinaryReader::TryRead64(uint64_t& result)
{
return BNRead64(m_stream, &result);
}
bool BinaryReader::TryReadPointer(uint64_t& result)
{
return BNReadPointer(m_view->GetObject(), m_stream, &result);
}
bool BinaryReader::TryReadLE16(uint16_t& result)
{
return BNReadLE16(m_stream, &result);
}
bool BinaryReader::TryReadLE32(uint32_t& result)
{
return BNReadLE32(m_stream, &result);
}
bool BinaryReader::TryReadLE64(uint64_t& result)
{
return BNReadLE64(m_stream, &result);
}
bool BinaryReader::TryReadLEPointer(uint64_t& result)
{
size_t addressSize = m_view->GetAddressSize();
switch (addressSize)
{
case 1:
{
uint8_t r;
if (!BNRead8(m_stream, &r))
return false;
result = r;
break;
}
case 2:
{
uint16_t r;
if (!BNReadLE16(m_stream, &r))
return false;
result = r;
break;
}
case 4:
{
uint32_t r;
if (!BNReadLE32(m_stream, &r))
return false;
result = r;
break;
}
case 8:
{
if (!BNReadLE64(m_stream, &result))
return false;
break;
}
default:
{
return false;
}
}
return true;
}
bool BinaryReader::TryReadBE16(uint16_t& result)
{
return BNReadBE16(m_stream, &result);
}
bool BinaryReader::TryReadBE32(uint32_t& result)
{
return BNReadBE32(m_stream, &result);
}
bool BinaryReader::TryReadBE64(uint64_t& result)
{
return BNReadBE64(m_stream, &result);
}
bool BinaryReader::TryReadBEPointer(uint64_t& result)
{
size_t addressSize = m_view->GetAddressSize();
switch (addressSize)
{
case 1:
{
uint8_t r;
if (!BNRead8(m_stream, &r))
return false;
result = r;
break;
}
case 2:
{
uint16_t r;
if (!BNReadBE16(m_stream, &r))
return false;
result = r;
break;
}
case 4:
{
uint32_t r;
if (!BNReadBE32(m_stream, &r))
return false;
result = r;
break;
}
case 8:
{
if (!BNReadBE64(m_stream, &result))
return false;
break;
}
default:
{
return false;
}
}
return true;
}
uint64_t BinaryReader::GetOffset() const
{
return BNGetReaderPosition(m_stream);
}
void BinaryReader::Seek(uint64_t offset)
{
BNSeekBinaryReader(m_stream, offset);
}
void BinaryReader::SeekRelative(int64_t offset)
{
BNSeekBinaryReaderRelative(m_stream, offset);
}
uint64_t BinaryReader::GetVirtualBase()
{
return BNGetBinaryReaderVirtualBase(m_stream);
}
void BinaryReader::SetVirtualBase(uint64_t base)
{
BNSetBinaryReaderVirtualBase(m_stream, base);
}
bool BinaryReader::IsEndOfFile() const
{
return BNIsEndOfFile(m_stream);
}
template