Skip to content

Commit 2a4c7d5

Browse files
committed
Share context between BB recovery, lifing, and disassembly
Adds a GetInstructionTextWithContext callback to the architecture class that can be used to pass data from AnalyzeBasicBlocks. This same context is also supplied to LiftFunction and allows for supplying shared function and/or binary view level information across basic block analysis, function lifting, and disassembly text rendering
1 parent c9dbb48 commit 2a4c7d5

6 files changed

Lines changed: 785 additions & 308 deletions

File tree

architecture.cpp

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,15 @@ std::map<ArchAndAddr, ArchAndAddr>& BasicBlockAnalysisContext::GetInlinedUnresol
307307
}
308308

309309

310+
bool BasicBlockAnalysisContext::SetFunctionArchContextRaw(void* p)
311+
{
312+
if (m_context->functionArchContext)
313+
return false;
314+
m_context->functionArchContext = p;
315+
return true;
316+
}
317+
318+
310319
void BasicBlockAnalysisContext::AddTempOutgoingReference(Function* targetFunc)
311320
{
312321
BNAnalyzeBasicBlocksContextAddTempReference(m_context, targetFunc->m_object);
@@ -461,8 +470,6 @@ void BasicBlockAnalysisContext::Finalize()
461470
delete[] values;
462471
}
463472
}
464-
465-
BNAnalyzeBasicBlocksContextFinalize(m_context);
466473
}
467474

468475

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

528+
m_functionArchContext = context->functionArchContext;
521529
m_containsInlinedFunctions = context->containsInlinedFunctions;
522530
}
523531

@@ -730,6 +738,26 @@ bool Architecture::GetInstructionTextCallback(
730738
}
731739

732740

741+
bool Architecture::GetInstructionTextWithContextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
742+
void* context, BNInstructionTextToken** result, size_t* count)
743+
{
744+
CallbackRef<Architecture> arch(ctxt);
745+
746+
vector<InstructionTextToken> tokens;
747+
bool ok = arch->GetInstructionTextWithContext(data, addr, *len, context, tokens);
748+
if (!ok)
749+
{
750+
*result = nullptr;
751+
*count = 0;
752+
return false;
753+
}
754+
755+
*count = tokens.size();
756+
*result = InstructionTextToken::CreateInstructionTextTokenList(tokens);
757+
return true;
758+
}
759+
760+
733761
void Architecture::FreeInstructionTextCallback(BNInstructionTextToken* tokens, size_t count)
734762
{
735763
for (size_t i = 0; i < count; i++)
@@ -772,6 +800,13 @@ bool Architecture::LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* functi
772800
}
773801

774802

803+
void Architecture::FreeFunctionArchContextCallback(void* ctxt, void* context)
804+
{
805+
CallbackRef<Architecture> arch(ctxt);
806+
arch->FreeFunctionArchContext(context);
807+
}
808+
809+
775810
char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg)
776811
{
777812
CallbackRef<Architecture> arch(ctxt);
@@ -1260,10 +1295,12 @@ void Architecture::Register(Architecture* arch)
12601295
callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback;
12611296
callbacks.getInstructionInfo = GetInstructionInfoCallback;
12621297
callbacks.getInstructionText = GetInstructionTextCallback;
1298+
callbacks.getInstructionTextWithContext = GetInstructionTextWithContextCallback;
12631299
callbacks.freeInstructionText = FreeInstructionTextCallback;
12641300
callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback;
12651301
callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback;
12661302
callbacks.liftFunction = LiftFunctionCallback;
1303+
callbacks.freeFunctionArchContext = FreeFunctionArchContextCallback;
12671304
callbacks.getRegisterName = GetRegisterNameCallback;
12681305
callbacks.getFlagName = GetFlagNameCallback;
12691306
callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback;
@@ -1404,6 +1441,16 @@ bool Architecture::LiftFunction(LowLevelILFunction* function, FunctionLifterCont
14041441
}
14051442

14061443

1444+
bool Architecture::GetInstructionTextWithContext(
1445+
const uint8_t* data, uint64_t addr, size_t& len, void* context, std::vector<InstructionTextToken>& result)
1446+
{
1447+
return GetInstructionText(data, addr, len, result);
1448+
}
1449+
1450+
1451+
void Architecture::FreeFunctionArchContext(void* context) {}
1452+
1453+
14071454
string Architecture::GetRegisterName(uint32_t reg)
14081455
{
14091456
return fmt::format("r{}", reg);
@@ -1959,6 +2006,19 @@ bool CoreArchitecture::GetInstructionText(
19592006
}
19602007

19612008

2009+
bool CoreArchitecture::GetInstructionTextWithContext(
2010+
const uint8_t* data, uint64_t addr, size_t& len, void* context, std::vector<InstructionTextToken>& result)
2011+
{
2012+
BNInstructionTextToken* tokens = nullptr;
2013+
size_t count = 0;
2014+
if (!BNGetInstructionTextWithContext(m_object, data, addr, &len, context, &tokens, &count))
2015+
return false;
2016+
2017+
result = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(tokens, count);
2018+
return true;
2019+
}
2020+
2021+
19622022
bool CoreArchitecture::GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il)
19632023
{
19642024
return BNGetInstructionLowLevelIL(m_object, data, addr, &len, il.GetObject());
@@ -1977,6 +2037,12 @@ bool CoreArchitecture::LiftFunction(LowLevelILFunction* function, FunctionLifter
19772037
}
19782038

19792039

2040+
void CoreArchitecture::FreeFunctionArchContext(void* context)
2041+
{
2042+
BNArchitectureFreeFunctionArchContext(m_object, context);
2043+
}
2044+
2045+
19802046
string CoreArchitecture::GetRegisterName(uint32_t reg)
19812047
{
19822048
char* name = BNGetArchitectureRegisterName(m_object, reg);
@@ -2487,6 +2553,13 @@ bool ArchitectureExtension::GetInstructionText(
24872553
}
24882554

24892555

2556+
bool ArchitectureExtension::GetInstructionTextWithContext(
2557+
const uint8_t* data, uint64_t addr, size_t& len, void* context, vector<InstructionTextToken>& result)
2558+
{
2559+
return m_base->GetInstructionTextWithContext(data, addr, len, context, result);
2560+
}
2561+
2562+
24902563
bool ArchitectureExtension::GetInstructionLowLevelIL(
24912564
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il)
24922565
{

binaryninjaapi.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9414,6 +9414,21 @@ namespace BinaryNinja {
94149414
std::set<ArchAndAddr>& GetHaltedDisassemblyAddresses();
94159415
std::map<ArchAndAddr, ArchAndAddr>& GetInlinedUnresolvedIndirectBranches();
94169416

9417+
bool SetFunctionArchContextRaw(void* p);
9418+
void* GetFunctionArchContextRaw() const { return m_context->functionArchContext; }
9419+
9420+
template <class ArchT>
9421+
bool SetFunctionArchContext(const ArchT* arch, typename ArchT::FunctionArchContext* context)
9422+
{
9423+
return arch->SetFunctionArchContext(*this, context);
9424+
}
9425+
9426+
template <class ArchT>
9427+
typename ArchT::FunctionArchContext* GetFunctionArchContext(const ArchT* arch)
9428+
{
9429+
return arch->GetFunctionArchContext(*this);
9430+
}
9431+
94179432
void AddTempOutgoingReference(Function* targetFunc);
94189433

94199434
Ref<BasicBlock> CreateBasicBlock(Architecture* arch, uint64_t start);
@@ -9436,6 +9451,7 @@ namespace BinaryNinja {
94369451
std::map<ArchAndAddr, std::set<ArchAndAddr>> m_autoIndirectBranches;
94379452
std::set<uint64_t> m_inlinedCalls;
94389453
bool* m_containsInlinedFunctions;
9454+
void* m_functionArchContext;
94399455

94409456
public:
94419457
BNFunctionLifterContext* m_context;
@@ -9451,6 +9467,12 @@ namespace BinaryNinja {
94519467
std::map<ArchAndAddr, std::set<ArchAndAddr>>& GetAutoIndirectBranches();
94529468
std::set<uint64_t>& GetInlinedCalls();
94539469
void SetContainsInlinedFunctions(bool value);
9470+
void* GetFunctionArchContextRaw() const { return m_functionArchContext; }
9471+
template <class ArchT>
9472+
typename ArchT::FunctionArchContext* GetFunctionArchContext(const ArchT* arch)
9473+
{
9474+
return arch->GetFunctionArchContext(*this);
9475+
}
94549476

94559477
void CheckForInlinedCall(BasicBlock* block, size_t instrCountBefore, size_t instrCountAfter, uint64_t prevAddr,
94569478
uint64_t addr, const uint8_t* opcode, size_t len,
@@ -9484,11 +9506,14 @@ namespace BinaryNinja {
94849506
void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result);
94859507
static bool GetInstructionTextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
94869508
BNInstructionTextToken** result, size_t* count);
9509+
static bool GetInstructionTextWithContextCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
9510+
void* context, BNInstructionTextToken** result, size_t* count);
94879511
static void FreeInstructionTextCallback(BNInstructionTextToken* tokens, size_t count);
94889512
static bool GetInstructionLowLevelILCallback(
94899513
void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
94909514
static void AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function, BNBasicBlockAnalysisContext* context);
94919515
static bool LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* function, BNFunctionLifterContext* context);
9516+
static void FreeFunctionArchContextCallback(void* ctxt, void* context);
94929517
static char* GetRegisterNameCallback(void* ctxt, uint32_t reg);
94939518
static char* GetFlagNameCallback(void* ctxt, uint32_t flag);
94949519
static char* GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags);
@@ -9666,6 +9691,10 @@ namespace BinaryNinja {
96669691
virtual bool GetInstructionText(
96679692
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) = 0;
96689693

9694+
/* For use in architecture plugins that inherit from ArchitectureWithFunctionContext */
9695+
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
9696+
std::vector<InstructionTextToken>& result);
9697+
96699698
/*! Translates an instruction at addr and appends it onto the LowLevelILFunction& il.
96709699

96719700
\note Architecture subclasses should implement this method.
@@ -9692,6 +9721,9 @@ namespace BinaryNinja {
96929721
*/
96939722
virtual bool LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context);
96949723

9724+
/* For use in architecture plugins that inherit from ArchitectureWithFunctionContext */
9725+
virtual void FreeFunctionArchContext(void* context);
9726+
96959727
/*! Gets a register name from a register index.
96969728

96979729
\param reg Register index
@@ -10067,6 +10099,71 @@ namespace BinaryNinja {
1006710099
void AddArchitectureRedirection(Architecture* from, Architecture* to);
1006810100
};
1006910101

10102+
/*! The ArchitectureWithFunctionContext class is to be inherited by architecture plugins that need to maintain a
10103+
* function context that is set during AnalyzeBasicBlocks and accessed in LiftFunction and/or
10104+
* GetInstructionTextWithContext.
10105+
10106+
\ingroup architectures
10107+
*/
10108+
template <class FnCtxT>
10109+
class ArchitectureWithFunctionContext : public Architecture
10110+
{
10111+
public:
10112+
using Architecture::Architecture;
10113+
using FunctionArchContext = FnCtxT;
10114+
10115+
/*! Set the function architecture context
10116+
10117+
\param bbac Basic block analysis context
10118+
\param ctx Function architecture context
10119+
\return True if the context was set successfully
10120+
*/
10121+
bool SetFunctionArchContext(BasicBlockAnalysisContext& bbac, FnCtxT* ctx) const
10122+
{
10123+
return bbac.SetFunctionArchContextRaw(static_cast<void*>(ctx));
10124+
}
10125+
10126+
/*! Get the function architecture context from the basic block analysis context
10127+
10128+
\param bbac Basic block analysis context
10129+
\return Function architecture context
10130+
*/
10131+
FnCtxT* GetFunctionArchContext(const BasicBlockAnalysisContext& bbac) const
10132+
{
10133+
return static_cast<FnCtxT*>(bbac.GetFunctionArchContextRaw());
10134+
}
10135+
10136+
/*! Free the function architecture context
10137+
\param context Function architecture context
10138+
*/
10139+
virtual void FreeFunctionArchContext(FnCtxT* context) {}
10140+
void FreeFunctionArchContext(void* context) override final
10141+
{
10142+
FreeFunctionArchContext(static_cast<FnCtxT*>(context));
10143+
}
10144+
10145+
/*! Get instruction text with function context
10146+
10147+
\param data Pointer to the instruction data to retrieve text for
10148+
\param addr Address of the instruction data to retrieve text for
10149+
\param len Will be written to with the length of the instruction data which was translated
10150+
\param context Context to use when retrieving instruction text
10151+
\param result Output vector of instruction text tokens
10152+
\return Whether instruction info was successfully retrieved.
10153+
*/
10154+
virtual bool GetInstructionTextWithContext(
10155+
const uint8_t* data, uint64_t addr, size_t& len, FnCtxT* context, std::vector<InstructionTextToken>& result)
10156+
{
10157+
return Architecture::GetInstructionTextWithContext(data, addr, len, static_cast<void*>(context), result);
10158+
}
10159+
10160+
bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
10161+
std::vector<InstructionTextToken>& result) override final
10162+
{
10163+
return GetInstructionTextWithContext(data, addr, len, static_cast<FnCtxT*>(context), result);
10164+
}
10165+
};
10166+
1007010167
/*!
1007110168

1007210169
\ingroup architectures
@@ -10086,10 +10183,13 @@ namespace BinaryNinja {
1008610183
const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
1008710184
virtual bool GetInstructionText(
1008810185
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) override;
10186+
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
10187+
std::vector<InstructionTextToken>& result) override;
1008910188
virtual bool GetInstructionLowLevelIL(
1009010189
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
1009110190
virtual void AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context) override;
1009210191
virtual bool LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context) override;
10192+
virtual void FreeFunctionArchContext(void* context) override;
1009310193
virtual std::string GetRegisterName(uint32_t reg) override;
1009410194
virtual std::string GetFlagName(uint32_t flag) override;
1009510195
virtual std::string GetFlagWriteTypeName(uint32_t flags) override;
@@ -10173,6 +10273,8 @@ namespace BinaryNinja {
1017310273
const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
1017410274
virtual bool GetInstructionText(
1017510275
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) override;
10276+
virtual bool GetInstructionTextWithContext(const uint8_t* data, uint64_t addr, size_t& len, void* context,
10277+
std::vector<InstructionTextToken>& result) override;
1017610278
virtual bool GetInstructionLowLevelIL(
1017710279
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
1017810280
virtual std::string GetRegisterName(uint32_t reg) override;

binaryninjacore.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 156
40+
#define BN_CURRENT_CORE_ABI_VERSION 157
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
4444
// will require rebuilding. The minimum version is increased when there are
4545
// incompatible changes that break binary compatibility, such as changes to
4646
// existing types or functions.
47-
#define BN_MINIMUM_CORE_ABI_VERSION 155
47+
#define BN_MINIMUM_CORE_ABI_VERSION 157
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -2049,6 +2049,8 @@ extern "C"
20492049

20502050
size_t inlinedUnresolvedIndirectBranchCount;
20512051
BNArchitectureAndAddress* inlinedUnresolvedIndirectBranches;
2052+
2053+
void* functionArchContext;
20522054
} BNBasicBlockAnalysisContext;
20532055

20542056
typedef struct BNFunctionLifterContext {
@@ -2075,6 +2077,8 @@ extern "C"
20752077
size_t inlinedCallsCount;
20762078
uint64_t* inlinedCalls;
20772079

2080+
void* functionArchContext;
2081+
20782082
// OUT
20792083
bool* containsInlinedFunctions;
20802084
} BNFunctionLifterContext;
@@ -2094,11 +2098,14 @@ extern "C"
20942098
void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result);
20952099
bool (*getInstructionText)(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
20962100
BNInstructionTextToken** result, size_t* count);
2101+
bool (*getInstructionTextWithContext)(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
2102+
void* context, BNInstructionTextToken** result, size_t* count);
20972103
void (*freeInstructionText)(BNInstructionTextToken* tokens, size_t count);
20982104
bool (*getInstructionLowLevelIL)(
20992105
void* ctxt, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
21002106
void (*analyzeBasicBlocks)(void* ctxt, BNFunction* function, BNBasicBlockAnalysisContext* context);
21012107
bool (*liftFunction)(void *ctext, BNLowLevelILFunction* function, BNFunctionLifterContext* context);
2108+
void (*freeFunctionArchContext)(void *ctxt, void* context);
21022109
char* (*getRegisterName)(void* ctxt, uint32_t reg);
21032110
char* (*getFlagName)(void* ctxt, uint32_t flag);
21042111
char* (*getFlagWriteTypeName)(void* ctxt, uint32_t flags);
@@ -4934,6 +4941,8 @@ extern "C"
49344941
BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result);
49354942
BINARYNINJACOREAPI bool BNGetInstructionText(BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len,
49364943
BNInstructionTextToken** result, size_t* count);
4944+
BINARYNINJACOREAPI bool BNGetInstructionTextWithContext(BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len,
4945+
void* context, BNInstructionTextToken** result, size_t* count);
49374946
BINARYNINJACOREAPI bool BNGetInstructionLowLevelIL(
49384947
BNArchitecture* arch, const uint8_t* data, uint64_t addr, size_t* len, BNLowLevelILFunction* il);
49394948
BINARYNINJACOREAPI void BNFreeInstructionText(BNInstructionTextToken* tokens, size_t count);
@@ -4945,6 +4954,7 @@ extern "C"
49454954
BINARYNINJACOREAPI bool BNArchitectureDefaultLiftFunction(BNLowLevelILFunction* function, BNFunctionLifterContext* context);
49464955
BINARYNINJACOREAPI bool BNArchitectureLiftFunction(BNArchitecture* arch, BNLowLevelILFunction* function,
49474956
BNFunctionLifterContext* context);
4957+
BINARYNINJACOREAPI void BNArchitectureFreeFunctionArchContext(BNArchitecture* arch, void* context);
49484958
BINARYNINJACOREAPI void BNFreeInstructionTextLines(BNInstructionTextLine* lines, size_t count);
49494959
BINARYNINJACOREAPI char* BNGetArchitectureRegisterName(BNArchitecture* arch, uint32_t reg);
49504960
BINARYNINJACOREAPI char* BNGetArchitectureFlagName(BNArchitecture* arch, uint32_t flag);
@@ -5594,7 +5604,6 @@ extern "C"
55945604
// BNAnalyzeBasicBlockContext operations
55955605
BINARYNINJACOREAPI BNBasicBlock* BNAnalyzeBasicBlocksContextCreateBasicBlock(BNBasicBlockAnalysisContext* abb, BNArchitecture* arch, uint64_t addr);
55965606
BINARYNINJACOREAPI void BNAnalyzeBasicBlocksContextAddBasicBlockToFunction(BNBasicBlockAnalysisContext* abb, BNBasicBlock* block);
5597-
BINARYNINJACOREAPI void BNAnalyzeBasicBlocksContextFinalize(BNBasicBlockAnalysisContext* abb);
55985607

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

0 commit comments

Comments
 (0)