Skip to content

Commit 0262af3

Browse files
committed
Merge remote-tracking branch 'origin/dev' into test_homegrown_powerpc_vle
2 parents d902a6c + df2691a commit 0262af3

32 files changed

+2704
-12
lines changed

architecture.cpp

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <inttypes.h>
2525
#include <vector>
2626
#include "binaryninjaapi.h"
27+
#include "lowlevelilinstruction.h"
2728
#include "ffi.h"
2829

2930
using namespace BinaryNinja;
@@ -203,6 +204,235 @@ vector<InstructionTextToken> InstructionTextToken::ConvertInstructionTextTokenLi
203204
return result;
204205
}
205206

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+
206436

207437
Architecture::Architecture(BNArchitecture* arch)
208438
{
@@ -327,6 +557,17 @@ bool Architecture::GetInstructionLowLevelILCallback(
327557
}
328558

329559

560+
void Architecture::AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function,
561+
BNBasicBlockAnalysisContext* context)
562+
{
563+
CallbackRef<Architecture> arch(ctxt);
564+
BasicBlockAnalysisContext abbc(context);
565+
Ref<Function> func(new Function(BNNewFunctionReference(function)));
566+
567+
arch->AnalyzeBasicBlocks(func, abbc);
568+
}
569+
570+
330571
char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg)
331572
{
332573
CallbackRef<Architecture> arch(ctxt);
@@ -817,6 +1058,7 @@ void Architecture::Register(Architecture* arch)
8171058
callbacks.getInstructionText = GetInstructionTextCallback;
8181059
callbacks.freeInstructionText = FreeInstructionTextCallback;
8191060
callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback;
1061+
callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback;
8201062
callbacks.getRegisterName = GetRegisterNameCallback;
8211063
callbacks.getFlagName = GetFlagNameCallback;
8221064
callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback;
@@ -945,6 +1187,12 @@ bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, L
9451187
}
9461188

9471189

1190+
void Architecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context)
1191+
{
1192+
DefaultAnalyzeBasicBlocks(function, context);
1193+
}
1194+
1195+
9481196
string Architecture::GetRegisterName(uint32_t reg)
9491197
{
9501198
return fmt::format("r{}", reg);
@@ -1505,6 +1753,12 @@ bool CoreArchitecture::GetInstructionLowLevelIL(const uint8_t* data, uint64_t ad
15051753
}
15061754

15071755

1756+
void CoreArchitecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context)
1757+
{
1758+
BNArchitectureAnalyzeBasicBlocks(m_object, function->GetObject(), context.m_context);
1759+
}
1760+
1761+
15081762
string CoreArchitecture::GetRegisterName(uint32_t reg)
15091763
{
15101764
char* name = BNGetArchitectureRegisterName(m_object, reg);

basicblock.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ uint64_t BasicBlock::GetStart() const
317317
}
318318

319319

320+
void BasicBlock::SetEnd(uint64_t end)
321+
{
322+
BNSetBasicBlockEnd(m_object, end);
323+
}
324+
325+
320326
uint64_t BasicBlock::GetEnd() const
321327
{
322328
return BNGetBasicBlockEnd(m_object);
@@ -385,6 +391,81 @@ bool BasicBlock::HasUndeterminedOutgoingEdges() const
385391
}
386392

387393

394+
bool BasicBlock::HasInvalidInstructions() const
395+
{
396+
return BNBasicBlockHasInvalidInstructions(m_object);
397+
}
398+
399+
400+
void BasicBlock::SetHasInvalidInstructions(bool value)
401+
{
402+
BNBasicBlockSetHasInvalidInstructions(m_object, value);
403+
}
404+
405+
406+
void BasicBlock::AddPendingOutgoingEdge(BNBranchType type, uint64_t addr, Ref<Architecture> arch, bool fallThrough)
407+
{
408+
BNBasicBlockAddPendingOutgoingEdge(m_object, type, addr, arch ? arch->GetObject() : nullptr, fallThrough);
409+
}
410+
411+
412+
vector<PendingBasicBlockEdge> BasicBlock::GetPendingOutgoingEdges() const
413+
{
414+
size_t count;
415+
BNPendingBasicBlockEdge* edges = BNGetBasicBlockPendingOutgoingEdges(m_object, &count);
416+
vector<PendingBasicBlockEdge> result;
417+
result.reserve(count);
418+
for (size_t i = 0; i < count; i++)
419+
{
420+
PendingBasicBlockEdge edge;
421+
edge.type = edges[i].type;
422+
edge.arch = edges[i].arch ? new CoreArchitecture(edges[i].arch) : nullptr;
423+
edge.target = edges[i].target;
424+
edge.fallThrough = edges[i].fallThrough;
425+
result.push_back(edge);
426+
}
427+
428+
BNFreePendingBasicBlockEdgeList(edges);
429+
return result;
430+
}
431+
432+
433+
void BasicBlock::ClearPendingOutgoingEdges()
434+
{
435+
BNClearBasicBlockPendingOutgoingEdges(m_object);
436+
}
437+
438+
439+
void BasicBlock::SetUndeterminedOutgoingEdges(bool value)
440+
{
441+
BNBasicBlockSetUndeterminedOutgoingEdges(m_object, value);
442+
}
443+
444+
445+
const uint8_t* BasicBlock::GetInstructionData(uint64_t addr, size_t* len) const
446+
{
447+
return BNBasicBlockGetInstructionData(m_object, addr, len);
448+
}
449+
450+
451+
void BasicBlock::AddInstructionData(const void* data, size_t len)
452+
{
453+
BNBasicBlockAddInstructionData(m_object, data, len);
454+
}
455+
456+
457+
void BasicBlock::SetFallThroughToFunction(bool value)
458+
{
459+
BNBasicBlockSetFallThroughToFunction(m_object, value);
460+
}
461+
462+
463+
bool BasicBlock::IsFallThroughToFunction() const
464+
{
465+
return BNBasicBlockIsFallThroughToFunction(m_object);
466+
}
467+
468+
388469
bool BasicBlock::CanExit() const
389470
{
390471
return BNBasicBlockCanExit(m_object);

0 commit comments

Comments
 (0)