Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 75 additions & 2 deletions architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,15 @@ std::map<ArchAndAddr, ArchAndAddr>& BasicBlockAnalysisContext::GetInlinedUnresol
}


bool BasicBlockAnalysisContext::SetFunctionArchContextRaw(void* p)
{
if (m_context->functionArchContext)
return false;
m_context->functionArchContext = p;
return true;
}


void BasicBlockAnalysisContext::AddTempOutgoingReference(Function* targetFunc)
{
BNAnalyzeBasicBlocksContextAddTempReference(m_context, targetFunc->m_object);
Expand Down Expand Up @@ -461,8 +470,6 @@ void BasicBlockAnalysisContext::Finalize()
delete[] values;
}
}

BNAnalyzeBasicBlocksContextFinalize(m_context);
}


Expand Down Expand Up @@ -518,6 +525,7 @@ FunctionLifterContext::FunctionLifterContext(LowLevelILFunction* func, BNFunctio
m_inlinedCalls.insert(context->inlinedCalls[i]);
}

m_functionArchContext = context->functionArchContext;
m_containsInlinedFunctions = context->containsInlinedFunctions;
}

Expand Down Expand Up @@ -730,6 +738,26 @@ bool Architecture::GetInstructionTextCallback(
}


bool Architecture::GetInstructionTextWithContextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
void* context, BNInstructionTextToken** result, size_t* count)
{
CallbackRef<Architecture> arch(ctxt);

vector<InstructionTextToken> tokens;
bool ok = arch->GetInstructionTextWithContext(data, addr, *len, context, tokens);
if (!ok)
{
*result = nullptr;
*count = 0;
return false;
}

*count = tokens.size();
*result = InstructionTextToken::CreateInstructionTextTokenList(tokens);
return true;
}


void Architecture::FreeInstructionTextCallback(BNInstructionTextToken* tokens, size_t count)
{
for (size_t i = 0; i < count; i++)
Expand Down Expand Up @@ -772,6 +800,13 @@ bool Architecture::LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* functi
}


void Architecture::FreeFunctionArchContextCallback(void* ctxt, void* context)
{
CallbackRef<Architecture> arch(ctxt);
arch->FreeFunctionArchContext(context);
}


char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg)
{
CallbackRef<Architecture> arch(ctxt);
Expand Down Expand Up @@ -1260,10 +1295,12 @@ void Architecture::Register(Architecture* arch)
callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback;
callbacks.getInstructionInfo = GetInstructionInfoCallback;
callbacks.getInstructionText = GetInstructionTextCallback;
callbacks.getInstructionTextWithContext = GetInstructionTextWithContextCallback;
callbacks.freeInstructionText = FreeInstructionTextCallback;
callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback;
callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback;
callbacks.liftFunction = LiftFunctionCallback;
callbacks.freeFunctionArchContext = FreeFunctionArchContextCallback;
callbacks.getRegisterName = GetRegisterNameCallback;
callbacks.getFlagName = GetFlagNameCallback;
callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback;
Expand Down Expand Up @@ -1404,6 +1441,16 @@ bool Architecture::LiftFunction(LowLevelILFunction* function, FunctionLifterCont
}


bool Architecture::GetInstructionTextWithContext(
const uint8_t* data, uint64_t addr, size_t& len, void* context, std::vector<InstructionTextToken>& result)
{
return GetInstructionText(data, addr, len, result);
}


void Architecture::FreeFunctionArchContext(void* context) {}


string Architecture::GetRegisterName(uint32_t reg)
{
return fmt::format("r{}", reg);
Expand Down Expand Up @@ -1959,6 +2006,19 @@ bool CoreArchitecture::GetInstructionText(
}


bool CoreArchitecture::GetInstructionTextWithContext(
const uint8_t* data, uint64_t addr, size_t& len, void* context, std::vector<InstructionTextToken>& result)
{
BNInstructionTextToken* tokens = nullptr;
size_t count = 0;
if (!BNGetInstructionTextWithContext(m_object, data, addr, &len, context, &tokens, &count))
return false;

result = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(tokens, count);
return true;
}


bool CoreArchitecture::GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il)
{
return BNGetInstructionLowLevelIL(m_object, data, addr, &len, il.GetObject());
Expand All @@ -1977,6 +2037,12 @@ bool CoreArchitecture::LiftFunction(LowLevelILFunction* function, FunctionLifter
}


void CoreArchitecture::FreeFunctionArchContext(void* context)
{
BNArchitectureFreeFunctionArchContext(m_object, context);
}


string CoreArchitecture::GetRegisterName(uint32_t reg)
{
char* name = BNGetArchitectureRegisterName(m_object, reg);
Expand Down Expand Up @@ -2487,6 +2553,13 @@ bool ArchitectureExtension::GetInstructionText(
}


bool ArchitectureExtension::GetInstructionTextWithContext(
const uint8_t* data, uint64_t addr, size_t& len, void* context, vector<InstructionTextToken>& result)
{
return m_base->GetInstructionTextWithContext(data, addr, len, context, result);
}


bool ArchitectureExtension::GetInstructionLowLevelIL(
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il)
{
Expand Down
102 changes: 102 additions & 0 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9400,6 +9400,21 @@ namespace BinaryNinja {
std::set<ArchAndAddr>& GetHaltedDisassemblyAddresses();
std::map<ArchAndAddr, ArchAndAddr>& GetInlinedUnresolvedIndirectBranches();

bool SetFunctionArchContextRaw(void* p);
void* GetFunctionArchContextRaw() const { return m_context->functionArchContext; }

template <class ArchT>
bool SetFunctionArchContext(const ArchT* arch, typename ArchT::FunctionArchContext* context)
{
return arch->SetFunctionArchContext(*this, context);
}

template <class ArchT>
typename ArchT::FunctionArchContext* GetFunctionArchContext(const ArchT* arch)
{
return arch->GetFunctionArchContext(*this);
}

void AddTempOutgoingReference(Function* targetFunc);

Ref<BasicBlock> CreateBasicBlock(Architecture* arch, uint64_t start);
Expand All @@ -9422,6 +9437,7 @@ namespace BinaryNinja {
std::map<ArchAndAddr, std::set<ArchAndAddr>> m_autoIndirectBranches;
std::set<uint64_t> m_inlinedCalls;
bool* m_containsInlinedFunctions;
void* m_functionArchContext;

public:
BNFunctionLifterContext* m_context;
Expand All @@ -9437,6 +9453,12 @@ namespace BinaryNinja {
std::map<ArchAndAddr, std::set<ArchAndAddr>>& GetAutoIndirectBranches();
std::set<uint64_t>& GetInlinedCalls();
void SetContainsInlinedFunctions(bool value);
void* GetFunctionArchContextRaw() const { return m_functionArchContext; }
template <class ArchT>
typename ArchT::FunctionArchContext* GetFunctionArchContext(const ArchT* arch)
{
return arch->GetFunctionArchContext(*this);
}

void CheckForInlinedCall(BasicBlock* block, size_t instrCountBefore, size_t instrCountAfter, uint64_t prevAddr,
uint64_t addr, const uint8_t* opcode, size_t len,
Expand Down Expand Up @@ -9470,11 +9492,14 @@ namespace BinaryNinja {
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,
BNInstructionTextToken** result, size_t* count);
static bool GetInstructionTextWithContextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
void* context, BNInstructionTextToken** result, size_t* count);
static void FreeInstructionTextCallback(BNInstructionTextToken* tokens, size_t count);
static bool GetInstructionLowLevelILCallback(
void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
static void AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function, BNBasicBlockAnalysisContext* context);
static bool LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* function, BNFunctionLifterContext* context);
static void FreeFunctionArchContextCallback(void* ctxt, void* context);
static char* GetRegisterNameCallback(void* ctxt, uint32_t reg);
static char* GetFlagNameCallback(void* ctxt, uint32_t flag);
static char* GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags);
Expand Down Expand Up @@ -9652,6 +9677,10 @@ namespace BinaryNinja {
virtual bool GetInstructionText(
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) = 0;

/* For use in architecture plugins that inherit from ArchitectureWithFunctionContext */
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
std::vector<InstructionTextToken>& result);

/*! Translates an instruction at addr and appends it onto the LowLevelILFunction& il.

\note Architecture subclasses should implement this method.
Expand All @@ -9678,6 +9707,9 @@ namespace BinaryNinja {
*/
virtual bool LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context);

/* For use in architecture plugins that inherit from ArchitectureWithFunctionContext */
virtual void FreeFunctionArchContext(void* context);

/*! Gets a register name from a register index.

\param reg Register index
Expand Down Expand Up @@ -10053,6 +10085,71 @@ namespace BinaryNinja {
void AddArchitectureRedirection(Architecture* from, Architecture* to);
};

/*! The ArchitectureWithFunctionContext class is to be inherited by architecture plugins that need to maintain a
* function context that is set during AnalyzeBasicBlocks and accessed in LiftFunction and/or
* GetInstructionTextWithContext.

\ingroup architectures
*/
template <class FnCtxT>
class ArchitectureWithFunctionContext : public Architecture
{
public:
using Architecture::Architecture;
using FunctionArchContext = FnCtxT;

/*! Set the function architecture context

\param bbac Basic block analysis context
\param ctx Function architecture context
\return True if the context was set successfully
*/
bool SetFunctionArchContext(BasicBlockAnalysisContext& bbac, FnCtxT* ctx) const
{
return bbac.SetFunctionArchContextRaw(static_cast<void*>(ctx));
}

/*! Get the function architecture context from the basic block analysis context

\param bbac Basic block analysis context
\return Function architecture context
*/
FnCtxT* GetFunctionArchContext(const BasicBlockAnalysisContext& bbac) const
{
return static_cast<FnCtxT*>(bbac.GetFunctionArchContextRaw());
}

/*! Free the function architecture context
\param context Function architecture context
*/
virtual void FreeFunctionArchContext(FnCtxT* context) {}
void FreeFunctionArchContext(void* context) override final
{
FreeFunctionArchContext(static_cast<FnCtxT*>(context));
}

/*! Get instruction text with function context

\param data Pointer to the instruction data to retrieve text for
\param addr Address of the instruction data to retrieve text for
\param len Will be written to with the length of the instruction data which was translated
\param context Context to use when retrieving instruction text
\param result Output vector of instruction text tokens
\return Whether instruction info was successfully retrieved.
*/
virtual bool GetInstructionTextWithContext(
const uint8_t* data, uint64_t addr, size_t& len, FnCtxT* context, std::vector<InstructionTextToken>& result)
{
return Architecture::GetInstructionTextWithContext(data, addr, len, static_cast<void*>(context), result);
}

bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
std::vector<InstructionTextToken>& result) override final
{
return GetInstructionTextWithContext(data, addr, len, static_cast<FnCtxT*>(context), result);
}
};

/*!

\ingroup architectures
Expand All @@ -10072,10 +10169,13 @@ namespace BinaryNinja {
const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
virtual bool GetInstructionText(
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) override;
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
std::vector<InstructionTextToken>& result) override;
virtual bool GetInstructionLowLevelIL(
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
virtual void AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context) override;
virtual bool LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context) override;
virtual void FreeFunctionArchContext(void* context) override;
virtual std::string GetRegisterName(uint32_t reg) override;
virtual std::string GetFlagName(uint32_t flag) override;
virtual std::string GetFlagWriteTypeName(uint32_t flags) override;
Expand Down Expand Up @@ -10159,6 +10259,8 @@ namespace BinaryNinja {
const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
virtual bool GetInstructionText(
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) override;
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
std::vector<InstructionTextToken>& result) override;
virtual bool GetInstructionLowLevelIL(
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
virtual std::string GetRegisterName(uint32_t reg) override;
Expand Down
11 changes: 10 additions & 1 deletion binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,8 @@ extern "C"

size_t inlinedUnresolvedIndirectBranchCount;
BNArchitectureAndAddress* inlinedUnresolvedIndirectBranches;

void* functionArchContext;
} BNBasicBlockAnalysisContext;

typedef struct BNFunctionLifterContext {
Expand All @@ -2075,6 +2077,8 @@ extern "C"
size_t inlinedCallsCount;
uint64_t* inlinedCalls;

void* functionArchContext;

// OUT
bool* containsInlinedFunctions;
} BNFunctionLifterContext;
Expand All @@ -2094,11 +2098,14 @@ extern "C"
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,
BNInstructionTextToken** result, size_t* count);
bool (*getInstructionTextWithContext)(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
void* context, BNInstructionTextToken** result, size_t* count);
void (*freeInstructionText)(BNInstructionTextToken* tokens, size_t count);
bool (*getInstructionLowLevelIL)(
void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
void (*analyzeBasicBlocks)(void* ctxt, BNFunction* function, BNBasicBlockAnalysisContext* context);
bool (*liftFunction)(void *ctext, BNLowLevelILFunction* function, BNFunctionLifterContext* context);
void (*freeFunctionArchContext)(void *ctxt, void* context);
char* (*getRegisterName)(void* ctxt, uint32_t reg);
char* (*getFlagName)(void* ctxt, uint32_t flag);
char* (*getFlagWriteTypeName)(void* ctxt, uint32_t flags);
Expand Down Expand Up @@ -4931,6 +4938,8 @@ extern "C"
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,
BNInstructionTextToken** result, size_t* count);
BINARYNINJACOREAPI bool BNGetInstructionTextWithContext(BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len,
void* context, BNInstructionTextToken** result, size_t* count);
BINARYNINJACOREAPI bool BNGetInstructionLowLevelIL(
BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
BINARYNINJACOREAPI void BNFreeInstructionText(BNInstructionTextToken* tokens, size_t count);
Expand All @@ -4942,6 +4951,7 @@ extern "C"
BINARYNINJACOREAPI bool BNArchitectureDefaultLiftFunction(BNLowLevelILFunction* function, BNFunctionLifterContext* context);
BINARYNINJACOREAPI bool BNArchitectureLiftFunction(BNArchitecture* arch, BNLowLevelILFunction* function,
BNFunctionLifterContext* context);
BINARYNINJACOREAPI void BNArchitectureFreeFunctionArchContext(BNArchitecture* arch, void* context);
BINARYNINJACOREAPI void BNFreeInstructionTextLines(BNInstructionTextLine* lines, size_t count);
BINARYNINJACOREAPI char* BNGetArchitectureRegisterName(BNArchitecture* arch, uint32_t reg);
BINARYNINJACOREAPI char* BNGetArchitectureFlagName(BNArchitecture* arch, uint32_t flag);
Expand Down Expand Up @@ -5591,7 +5601,6 @@ extern "C"
// BNAnalyzeBasicBlockContext operations
BINARYNINJACOREAPI BNBasicBlock* BNAnalyzeBasicBlocksContextCreateBasicBlock(BNBasicBlockAnalysisContext* abb, BNArchitecture* arch, uint64_t addr);
BINARYNINJACOREAPI void BNAnalyzeBasicBlocksContextAddBasicBlockToFunction(BNBasicBlockAnalysisContext* abb, BNBasicBlock* block);
BINARYNINJACOREAPI void BNAnalyzeBasicBlocksContextFinalize(BNBasicBlockAnalysisContext* abb);

BINARYNINJACOREAPI void BNAnalyzeBasicBlocksContextAddTempReference(BNBasicBlockAnalysisContext* abb, BNFunction* target);

Expand Down
Loading
Loading