From 23f2f93be93d1389df5ef6ad0d0d371f5517c0c7 Mon Sep 17 00:00:00 2001 From: Bradley Fernandez Date: Fri, 18 Sep 2026 13:29:24 -0400 Subject: [PATCH] Updated API to have an EncodeFunctionPointer() to replace manual address manipulation when handling function calls --- architecture.cpp | 26 ++++++++++++++++++++++++++ binaryninjaapi.h | 10 ++++++++++ binaryninjacore.h | 2 ++ rust/src/architecture.rs | 1 + 4 files changed, 39 insertions(+) diff --git a/architecture.cpp b/architecture.cpp index c185d0c131..3510f244c6 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -762,6 +762,13 @@ BNArchitecture* Architecture::GetAssociatedArchitectureByAddressCallback(void* c } +uint64_t Architecture::EncodeFunctionPointerCallback(void* ctxt, uint64_t* addr) +{ + CallbackRef arch(ctxt); + return arch->EncodeFunctionPointer(*addr); +} + + bool Architecture::GetInstructionInfoCallback( void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result) { @@ -1350,6 +1357,7 @@ void Architecture::Register(Architecture* arch) callbacks.getMaxInstructionLength = GetMaxInstructionLengthCallback; callbacks.getOpcodeDisplayLength = GetOpcodeDisplayLengthCallback; callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback; + callbacks.encodeFunctionPointer = EncodeFunctionPointerCallback; callbacks.getInstructionInfo = GetInstructionInfoCallback; callbacks.getInstructionText = GetInstructionTextCallback; callbacks.getInstructionTextWithContext = GetInstructionTextWithContextCallback; @@ -1493,6 +1501,12 @@ Ref Architecture::GetAssociatedArchitectureByAddress(uint64_t&) } +uint64_t Architecture::EncodeFunctionPointer(uint64_t& addr) +{ + return addr; +} + + bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, LowLevelILFunction& il) { il.AddInstruction(il.Undefined()); @@ -2070,6 +2084,12 @@ Ref CoreArchitecture::GetAssociatedArchitectureByAddress(uint64_t& } +uint64_t CoreArchitecture::EncodeFunctionPointer(uint64_t& addr) +{ + return BNArchitectureEncodeFunctionPointer(m_object, &addr); +} + + bool CoreArchitecture::GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) { return BNGetInstructionInfo(m_object, data, addr, maxLen, &result); @@ -2634,6 +2654,12 @@ Ref ArchitectureExtension::GetAssociatedArchitectureByAddress(uint } +uint64_t ArchitectureExtension::EncodeFunctionPointer(uint64_t& addr) +{ + return m_base->EncodeFunctionPointer(addr); +} + + bool ArchitectureExtension::GetInstructionInfo( const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) { diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b41c5873ae..73a51c3fa2 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -9844,6 +9844,7 @@ namespace BinaryNinja { static size_t GetMaxInstructionLengthCallback(void* ctxt); static size_t GetOpcodeDisplayLengthCallback(void* ctxt); static BNArchitecture* GetAssociatedArchitectureByAddressCallback(void* ctxt, uint64_t* addr); + static uint64_t EncodeFunctionPointerCallback(void* ctxt, uint64_t* addr); static bool GetInstructionInfoCallback( void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result); static bool GetInstructionTextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, @@ -10009,6 +10010,13 @@ namespace BinaryNinja { virtual Ref GetAssociatedArchitectureByAddress(uint64_t& addr); + /*! Encode a function pointer for this architecture, e.g. setting the LSB for Thumb functions + + \param addr Address of the function + \return The encoded function pointer + */ + virtual uint64_t EncodeFunctionPointer(uint64_t& addr); + /*! Retrieves an InstructionInfo struct for the instruction at the given virtual address \note Architecture subclasses should implement this method. @@ -10538,6 +10546,7 @@ namespace BinaryNinja { virtual size_t GetMaxInstructionLength() const override; virtual size_t GetOpcodeDisplayLength() const override; virtual Ref GetAssociatedArchitectureByAddress(uint64_t& addr) override; + virtual uint64_t EncodeFunctionPointer(uint64_t& addr) override; virtual bool GetInstructionInfo( const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override; virtual bool GetInstructionText( @@ -10630,6 +10639,7 @@ namespace BinaryNinja { virtual size_t GetMaxInstructionLength() const override; virtual size_t GetOpcodeDisplayLength() const override; virtual Ref GetAssociatedArchitectureByAddress(uint64_t& addr) override; + virtual uint64_t EncodeFunctionPointer(uint64_t& addr) override; virtual bool GetInstructionInfo( const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override; virtual bool GetInstructionText( diff --git a/binaryninjacore.h b/binaryninjacore.h index 446fdaccad..dfd7f4a6b8 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2250,6 +2250,7 @@ extern "C" size_t (*getMaxInstructionLength)(void* ctxt); size_t (*getOpcodeDisplayLength)(void* ctxt); BNArchitecture* (*getAssociatedArchitectureByAddress)(void* ctxt, uint64_t* addr); + uint64_t (*encodeFunctionPointer)(void* ctxt, uint64_t* addr); bool (*getInstructionInfo)( void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result); bool (*getInstructionText)(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, @@ -5792,6 +5793,7 @@ extern "C" BINARYNINJACOREAPI size_t BNGetArchitectureMaxInstructionLength(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureOpcodeDisplayLength(BNArchitecture* arch); BINARYNINJACOREAPI BNArchitecture* BNGetAssociatedArchitectureByAddress(BNArchitecture* arch, uint64_t* addr); + BINARYNINJACOREAPI uint64_t BNArchitectureEncodeFunctionPointer(BNArchitecture* arch, uint64_t* addr); BINARYNINJACOREAPI bool BNGetInstructionInfo( BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result); BINARYNINJACOREAPI bool BNGetInstructionText(BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len, diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index c8e6b7f103..58d531a8ea 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -2746,6 +2746,7 @@ where // TODO: Make getOpcodeDisplayLength optional. getOpcodeDisplayLength: Some(cb_opcode_display_len::), getAssociatedArchitectureByAddress: Some(cb_associated_arch_by_addr::), + encodeFunctionPointer: None, getInstructionInfo: Some(cb_instruction_info::), getInstructionText: Some(cb_get_instruction_text::), getInstructionTextWithContext: Some(cb_get_instruction_text_with_context::),