Skip to content

Commit df2691a

Browse files
committed
abb: minor refactor
1 parent b079d1a commit df2691a

File tree

5 files changed

+394
-201
lines changed

5 files changed

+394
-201
lines changed

architecture.cpp

Lines changed: 235 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,235 @@ vector<InstructionTextToken> InstructionTextToken::ConvertInstructionTextTokenLi
204204
return result;
205205
}
206206

207+
BasicBlockAnalysisContext::BasicBlockAnalysisContext(BNBasicBlockAnalysisContext* context)
208+
{
209+
m_context = context;
210+
}
211+
212+
const std::map<ArchAndAddr, std::set<ArchAndAddr>> BasicBlockAnalysisContext::GetIndirectBranches()
213+
{
214+
if (!m_indirectBranches)
215+
{
216+
auto& indirectBranches = m_indirectBranches.emplace();
217+
218+
for (size_t i = 0; i < m_context->indirectBranchesCount; i++)
219+
{
220+
ArchAndAddr src(new CoreArchitecture(m_context->indirectBranches[i].sourceArch), m_context->indirectBranches[i].sourceAddr);
221+
ArchAndAddr dst(new CoreArchitecture(m_context->indirectBranches[i].destArch), m_context->indirectBranches[i].destAddr);
222+
223+
indirectBranches[src].insert(dst);
224+
}
225+
}
226+
227+
return *m_indirectBranches;
228+
}
229+
230+
231+
const std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetIndirectNoReturnCalls()
232+
{
233+
if (!m_indirectNoReturnCalls)
234+
{
235+
auto& indirectNoReturnCalls = m_indirectNoReturnCalls.emplace();
236+
237+
for (size_t i = 0; i < m_context->indirectNoReturnCallsCount; i++)
238+
{
239+
ArchAndAddr addr(new CoreArchitecture(m_context->indirectNoReturnCalls[i].arch), m_context->indirectNoReturnCalls[i].address);
240+
indirectNoReturnCalls.insert(addr);
241+
}
242+
}
243+
244+
return *m_indirectNoReturnCalls;
245+
}
246+
247+
248+
std::map<ArchAndAddr, bool>& BasicBlockAnalysisContext::GetContextualReturns()
249+
{
250+
if (!m_contextualReturns)
251+
{
252+
auto& contextualReturns = m_contextualReturns.emplace();
253+
254+
for (size_t i = 0; i < m_context->contextualFunctionReturnCount; i++)
255+
{
256+
ArchAndAddr addr(new CoreArchitecture(m_context->contextualFunctionReturnLocations[i].arch), m_context->contextualFunctionReturnLocations[i].address);
257+
contextualReturns[addr] = m_context->contextualFunctionReturnValues[i];
258+
}
259+
}
260+
261+
return *m_contextualReturns;
262+
}
263+
264+
265+
std::map<uint64_t, std::set<ArchAndAddr>>& BasicBlockAnalysisContext::GetDirectCodeReferences()
266+
{
267+
if (!m_directCodeReferences)
268+
{
269+
auto& directCodeReferences = m_directCodeReferences.emplace();
270+
271+
for (size_t i = 0; i < m_context->directRefCount; i++)
272+
{
273+
ArchAndAddr src(new CoreArchitecture(m_context->directRefSources[i].arch), m_context->directRefSources[i].address);
274+
275+
directCodeReferences[m_context->directRefTargets[i]].insert(src);
276+
}
277+
}
278+
279+
return *m_directCodeReferences;
280+
}
281+
282+
283+
std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetDirectNoReturnCalls()
284+
{
285+
if (!m_directNoReturnCalls)
286+
m_directNoReturnCalls.emplace();
287+
288+
return *m_directNoReturnCalls;
289+
}
290+
291+
292+
std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetHaltedDisassemblyAddresses()
293+
{
294+
if (!m_haltedDisassemblyAddresses)
295+
m_haltedDisassemblyAddresses.emplace();
296+
297+
return *m_haltedDisassemblyAddresses;
298+
}
299+
300+
301+
void BasicBlockAnalysisContext::AddTempOutgoingReference(Function* targetFunc)
302+
{
303+
BNAnalyzeBasicBlocksContextAddTempReference(m_context, targetFunc->m_object);
304+
}
305+
306+
307+
Ref<BasicBlock> BasicBlockAnalysisContext::CreateBasicBlock(Architecture* arch, uint64_t start)
308+
{
309+
BNBasicBlock* block = BNAnalyzeBasicBlocksContextCreateBasicBlock(m_context, arch->GetObject(), start);
310+
if (!block)
311+
return nullptr;
312+
return new BasicBlock(block);
313+
}
314+
315+
316+
void BasicBlockAnalysisContext::AddFunctionBasicBlock(BasicBlock* block)
317+
{
318+
BNAnalyzeBasicBlocksContextAddBasicBlockToFunction(m_context, block->GetObject());
319+
}
320+
321+
322+
void BasicBlockAnalysisContext::Finalize()
323+
{
324+
if (m_directCodeReferences)
325+
{
326+
auto& directRefs = *m_directCodeReferences;
327+
328+
size_t total = 0;
329+
for (auto& pair : directRefs)
330+
total += pair.second.size();
331+
332+
BNArchitectureAndAddress* sources = new BNArchitectureAndAddress[total];
333+
uint64_t* targets = new uint64_t[total];
334+
335+
size_t i = 0;
336+
for (auto& pair : directRefs)
337+
{
338+
for (auto& src : pair.second)
339+
{
340+
sources[i].arch = src.arch->GetObject();
341+
sources[i].address = src.address;
342+
targets[i] = pair.first;
343+
i++;
344+
}
345+
}
346+
347+
BNAnalyzeBasicBlocksContextSetDirectCodeReferences(m_context, sources, targets, total);
348+
349+
delete[] sources;
350+
delete[] targets;
351+
}
352+
353+
if (m_directNoReturnCalls)
354+
{
355+
auto& directNoReturnCalls = *m_directNoReturnCalls;
356+
357+
BNArchitectureAndAddress* noRets = new BNArchitectureAndAddress[directNoReturnCalls.size()];
358+
359+
size_t i = 0;
360+
for (auto& addr : directNoReturnCalls)
361+
{
362+
noRets[i].arch = addr.arch->GetObject();
363+
noRets[i].address = addr.address;
364+
i++;
365+
}
366+
367+
BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls(m_context, noRets, directNoReturnCalls.size());
368+
delete[] noRets;
369+
}
370+
371+
if (m_haltedDisassemblyAddresses)
372+
{
373+
auto& haltedDisassemblyAddresses = *m_haltedDisassemblyAddresses;
374+
375+
BNArchitectureAndAddress* haltedAddresses = new BNArchitectureAndAddress[haltedDisassemblyAddresses.size()];
376+
377+
size_t i = 0;
378+
for (auto& addr : haltedDisassemblyAddresses)
379+
{
380+
haltedAddresses[i].arch = addr.arch->GetObject();
381+
haltedAddresses[i].address = addr.address;
382+
i++;
383+
}
384+
385+
BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses(m_context, haltedAddresses, haltedDisassemblyAddresses.size());
386+
delete[] haltedAddresses;
387+
}
388+
389+
if (m_contextualReturns)
390+
{
391+
auto& contextualReturns = *m_contextualReturns;
392+
393+
bool dirty = contextualReturns.size() != m_context->contextualFunctionReturnCount;
394+
395+
if (!dirty)
396+
{
397+
size_t i = 0;
398+
for (auto& pair : contextualReturns)
399+
{
400+
if (pair.first.arch->GetObject() != m_context->contextualFunctionReturnLocations[i].arch
401+
|| pair.first.address != m_context->contextualFunctionReturnLocations[i].address
402+
|| pair.second != m_context->contextualFunctionReturnValues[i])
403+
{
404+
dirty = true;
405+
break;
406+
}
407+
408+
i++;
409+
}
410+
}
411+
412+
if (dirty)
413+
{
414+
BNArchitectureAndAddress* returns = new BNArchitectureAndAddress[contextualReturns.size()];
415+
bool* values = new bool[contextualReturns.size()];
416+
417+
size_t i = 0;
418+
for (auto& pair : contextualReturns)
419+
{
420+
returns[i].arch = pair.first.arch->GetObject();
421+
returns[i].address = pair.first.address;
422+
values[i] = pair.second;
423+
i++;
424+
}
425+
426+
BNAnalyzeBasicBlocksContextSetContextualFunctionReturns(m_context, returns, values, contextualReturns.size());
427+
428+
delete[] returns;
429+
delete[] values;
430+
}
431+
}
432+
433+
BNAnalyzeBasicBlocksContextFinalize(m_context);
434+
}
435+
207436

208437
Architecture::Architecture(BNArchitecture* arch)
209438
{
@@ -332,8 +561,10 @@ void Architecture::AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function,
332561
BNBasicBlockAnalysisContext* context)
333562
{
334563
CallbackRef<Architecture> arch(ctxt);
564+
BasicBlockAnalysisContext abbc(context);
335565
Ref<Function> func(new Function(BNNewFunctionReference(function)));
336-
arch->AnalyzeBasicBlocks(*func, *context);
566+
567+
arch->AnalyzeBasicBlocks(func, abbc);
337568
}
338569

339570

@@ -956,7 +1187,7 @@ bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, L
9561187
}
9571188

9581189

959-
void Architecture::AnalyzeBasicBlocks(Function& function, BasicBlockAnalysisContext& context)
1190+
void Architecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context)
9601191
{
9611192
DefaultAnalyzeBasicBlocks(function, context);
9621193
}
@@ -1522,9 +1753,9 @@ bool CoreArchitecture::GetInstructionLowLevelIL(const uint8_t* data, uint64_t ad
15221753
}
15231754

15241755

1525-
void CoreArchitecture::AnalyzeBasicBlocks(Function& function, BasicBlockAnalysisContext& context)
1756+
void CoreArchitecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context)
15261757
{
1527-
BNArchitectureAnalyzeBasicBlocks(m_object, function.GetObject(), &context);
1758+
BNArchitectureAnalyzeBasicBlocks(m_object, function->GetObject(), context.m_context);
15281759
}
15291760

15301761

binaryninjaapi.h

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8073,7 +8073,52 @@ namespace BinaryNinja {
80738073
class RelocationHandler;
80748074

80758075
typedef size_t ExprId;
8076-
typedef BNBasicBlockAnalysisContext BasicBlockAnalysisContext;
8076+
8077+
class BasicBlockAnalysisContext
8078+
{
8079+
private:
8080+
// in
8081+
std::optional<std::map<ArchAndAddr, std::set<ArchAndAddr>>> m_indirectBranches;
8082+
std::optional<std::set<ArchAndAddr>> m_indirectNoReturnCalls;
8083+
8084+
// in/out
8085+
std::optional<std::map<ArchAndAddr, bool>> m_contextualReturns;
8086+
8087+
// out
8088+
std::optional<std::map<uint64_t, std::set<ArchAndAddr>>> m_directCodeReferences;
8089+
std::optional<std::set<ArchAndAddr>> m_directNoReturnCalls;
8090+
std::optional<std::set<ArchAndAddr>> m_haltedDisassemblyAddresses;
8091+
8092+
public:
8093+
BNBasicBlockAnalysisContext* m_context;
8094+
8095+
BasicBlockAnalysisContext(BNBasicBlockAnalysisContext* context);
8096+
8097+
BNFunctionAnalysisSkipOverride GetAnalysisSkipOverride() const { return m_context->analysisSkipOverride; }
8098+
bool GetTranslateTailCalls() const { return m_context->translateTailCalls; }
8099+
bool GetDisallowBranchToString() const { return m_context->disallowBranchToString; }
8100+
bool GetHaltOnInvalidInstructions() const { return m_context->haltOnInvalidInstructions; }
8101+
uint64_t GetMaxFunctionSize() const { return m_context->maxFunctionSize; }
8102+
8103+
bool GetMaxSizeReached() const { return m_context->maxSizeReached; }
8104+
void SetMaxSizeReached(bool reached) { m_context->maxSizeReached = reached; }
8105+
8106+
const std::map<ArchAndAddr, std::set<ArchAndAddr>> GetIndirectBranches();
8107+
const std::set<ArchAndAddr>& GetIndirectNoReturnCalls();
8108+
8109+
std::map<ArchAndAddr, bool>& GetContextualReturns();
8110+
8111+
std::map<uint64_t, std::set<ArchAndAddr>>& GetDirectCodeReferences();
8112+
std::set<ArchAndAddr>& GetDirectNoReturnCalls();
8113+
std::set<ArchAndAddr>& GetHaltedDisassemblyAddresses();
8114+
8115+
void AddTempOutgoingReference(Function* targetFunc);
8116+
8117+
Ref<BasicBlock> CreateBasicBlock(Architecture* arch, uint64_t start);
8118+
void AddFunctionBasicBlock(BasicBlock* block);
8119+
8120+
void Finalize();
8121+
};
80778122

80788123
/*! The Architecture class is the base class for all CPU architectures. This provides disassembly, assembly,
80798124
patching, and IL translation lifting for a given architecture.
@@ -8182,7 +8227,7 @@ namespace BinaryNinja {
81828227
\param function Function to analyze
81838228
\param context Context for the analysis
81848229
*/
8185-
static void DefaultAnalyzeBasicBlocks(Function& function, BasicBlockAnalysisContext& context);
8230+
static void DefaultAnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context);
81868231

81878232
/*! Get an Architecture by name
81888233

@@ -8287,7 +8332,7 @@ namespace BinaryNinja {
82878332
\param function Function to analyze
82888333
\param context Context for the analysis
82898334
*/
8290-
virtual void AnalyzeBasicBlocks(Function& function, BasicBlockAnalysisContext& context);
8335+
virtual void AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context);
82918336

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

@@ -8682,7 +8727,7 @@ namespace BinaryNinja {
86828727
const uint8_t* data, uint64_t addr, size_t& len, std::vector<InstructionTextToken>& result) override;
86838728
virtual bool GetInstructionLowLevelIL(
86848729
const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
8685-
virtual void AnalyzeBasicBlocks(Function& function, BasicBlockAnalysisContext& context) override;
8730+
virtual void AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context) override;
86868731
virtual std::string GetRegisterName(uint32_t reg) override;
86878732
virtual std::string GetFlagName(uint32_t flag) override;
86888733
virtual std::string GetFlagWriteTypeName(uint32_t flags) override;
@@ -11063,24 +11108,6 @@ namespace BinaryNinja {
1106311108
*/
1106411109
std::vector<Ref<BasicBlock>> GetBasicBlocks() const;
1106511110

11066-
/*! Create a new basic block for this function
11067-
11068-
\param arch Architecture for the basic block
11069-
\param addr Address of the basic block
11070-
\return The new BasicBlock
11071-
*/
11072-
Ref<BasicBlock> CreateBasicBlock(Architecture* arch, uint64_t addr);
11073-
11074-
/*! Add a basic block to the function analysis basic block list
11075-
11076-
\param block The BasicBlock to add
11077-
*/
11078-
void AddBasicBlock(Ref<BasicBlock> block);
11079-
11080-
/*! Finalize basic block list for this function
11081-
*/
11082-
void FinalizeBasicBlocks();
11083-
1108411111
/*! Get the basic block an address is located in
1108511112

1108611113
\param arch Architecture for the basic block
@@ -11411,16 +11438,7 @@ namespace BinaryNinja {
1141111438
std::vector<IndirectBranchInfo> GetIndirectBranches();
1141211439
std::vector<IndirectBranchInfo> GetIndirectBranchesAt(Architecture* arch, uint64_t addr);
1141311440

11414-
void AddDirectCodeReference(const ArchAndAddr& source, uint64_t target);
11415-
void AddDirectNoReturnCall(const ArchAndAddr& location);
11416-
bool LocationHasNoReturnCalls(const ArchAndAddr& location) const;
1141711441
Ref<Function> GetCalleeForAnalysis(Ref<Platform> platform, uint64_t addr, bool exact);
11418-
void AddTempOutgoingReference(Ref<Function> target);
11419-
bool HasTempOutgoingReference(Ref<Function> target) const;
11420-
void AddTempIncomingReference(Ref<Function> source);
11421-
11422-
bool GetContextualFunctionReturn(const ArchAndAddr& location, bool& value) const;
11423-
void SetContextualFunctionReturn(const ArchAndAddr& location, bool value);
1142411442

1142511443
std::vector<uint64_t> GetUnresolvedIndirectBranches();
1142611444
bool HasUnresolvedIndirectBranches();

0 commit comments

Comments
 (0)