Skip to content

Commit 5b545dd

Browse files
committed
Perform function lifting and inlining in arch plugins
This change allows architecture plugins to override the LiftFunction callback to iterate a function's basic block list and lift entire functions at once. This is required for architectures such as TMS320 C6x, which have non-traditional "delay slots" in that branches, loads, and other instructions take multiple cycles to complete, and branch instructions can reside within the delay slots of other branches.
1 parent 6e50ced commit 5b545dd

File tree

14 files changed

+1050
-30
lines changed

14 files changed

+1050
-30
lines changed

architecture.cpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,169 @@ void BasicBlockAnalysisContext::Finalize()
466466
}
467467

468468

469+
FunctionLifterContext::FunctionLifterContext(LowLevelILFunction* func, BNFunctionLifterContext* context)
470+
{
471+
m_context = context;
472+
m_view = func->GetFunction()->GetView();
473+
m_function = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func->GetObject()));
474+
m_platform = new Platform(BNNewPlatformReference(context->platform));
475+
m_logger = new Logger(BNNewLoggerReference(context->logger));
476+
m_blocks.reserve(context->basicBlockCount);
477+
for (size_t i = 0; i < context->basicBlockCount; i++)
478+
{
479+
m_blocks.emplace_back(new BasicBlock(context->basicBlocks[i]));
480+
}
481+
482+
for (size_t i = 0; i < context->noReturnCallsCount; i++)
483+
{
484+
ArchAndAddr addr(new CoreArchitecture(context->noReturnCalls[i].arch), context->noReturnCalls[i].address);
485+
m_noReturnCalls.insert(addr);
486+
}
487+
488+
for (size_t i = 0; i < context->contextualFunctionReturnCount; i++)
489+
{
490+
ArchAndAddr addr(new CoreArchitecture(context->contextualFunctionReturnLocations[i].arch),
491+
context->contextualFunctionReturnLocations[i].address);
492+
m_contextualReturns[addr] = context->contextualFunctionReturnValues[i];
493+
}
494+
495+
for (size_t i = 0; i < context->inlinedRemappingEntryCount; i++)
496+
{
497+
ArchAndAddr key(
498+
new CoreArchitecture(context->inlinedRemappingKeys[i].arch), context->inlinedRemappingKeys[i].address);
499+
ArchAndAddr value(
500+
new CoreArchitecture(context->inlinedRemappingValues[i].arch), context->inlinedRemappingValues[i].address);
501+
m_inlinedRemapping[key] = value;
502+
}
503+
504+
for (size_t i = 0; i < context->indirectBranchesCount; i++)
505+
{
506+
ArchAndAddr src(
507+
new CoreArchitecture(context->indirectBranches[i].sourceArch), context->indirectBranches[i].sourceAddr);
508+
ArchAndAddr dest(
509+
new CoreArchitecture(context->indirectBranches[i].destArch), context->indirectBranches[i].destAddr);
510+
if (context->indirectBranches[i].autoDefined)
511+
m_autoIndirectBranches[src].insert(dest);
512+
else
513+
m_userIndirectBranches[src].insert(dest);
514+
}
515+
516+
for (size_t i = 0; i < context->inlinedCallsCount; i++)
517+
{
518+
m_inlinedCalls.insert(context->inlinedCalls[i]);
519+
}
520+
521+
m_containsInlinedFunctions = context->containsInlinedFunctions;
522+
}
523+
524+
525+
Ref<BinaryView>& FunctionLifterContext::GetView()
526+
{
527+
return m_view;
528+
}
529+
530+
531+
Ref<Platform>& FunctionLifterContext::GetPlatform()
532+
{
533+
return m_platform;
534+
}
535+
536+
537+
std::map<ArchAndAddr, ArchAndAddr>& FunctionLifterContext::GetInlinedRemapping()
538+
{
539+
return m_inlinedRemapping;
540+
}
541+
542+
543+
std::map<ArchAndAddr, std::set<ArchAndAddr>>& FunctionLifterContext::GetUserIndirectBranches()
544+
{
545+
return m_userIndirectBranches;
546+
}
547+
548+
549+
std::map<ArchAndAddr, std::set<ArchAndAddr>>& FunctionLifterContext::GetAutoIndirectBranches()
550+
{
551+
return m_autoIndirectBranches;
552+
}
553+
554+
555+
Ref<Logger>& FunctionLifterContext::GetLogger()
556+
{
557+
return m_logger;
558+
}
559+
560+
561+
vector<Ref<BasicBlock>>& FunctionLifterContext::GetBasicBlocks()
562+
{
563+
return m_blocks;
564+
}
565+
566+
567+
std::set<ArchAndAddr>& FunctionLifterContext::GetNoReturnCalls()
568+
{
569+
return m_noReturnCalls;
570+
}
571+
572+
573+
std::map<ArchAndAddr, bool>& FunctionLifterContext::GetContextualReturns()
574+
{
575+
return m_contextualReturns;
576+
}
577+
578+
579+
std::set<uint64_t>& FunctionLifterContext::GetInlinedCalls()
580+
{
581+
return m_inlinedCalls;
582+
}
583+
584+
585+
void FunctionLifterContext::SetContainsInlinedFunctions(bool value)
586+
{
587+
*m_containsInlinedFunctions = value;
588+
}
589+
590+
591+
void FunctionLifterContext::PrepareBlockTranslation(LowLevelILFunction* function, Architecture* arch, uint64_t addr)
592+
{
593+
BNPrepareBlockTranslation(function->GetObject(), arch->GetObject(), addr);
594+
}
595+
596+
597+
std::vector<Ref<BasicBlock>> FunctionLifterContext::PrepareToCopyForeignFunction(LowLevelILFunction* function)
598+
{
599+
size_t blockCount = 0;
600+
BNBasicBlock** bnBlocks =
601+
BNPrepareToCopyForeignFunction(m_function->GetObject(), function->GetObject(), &blockCount);
602+
std::vector<Ref<BasicBlock>> blocks;
603+
blocks.reserve(blockCount);
604+
for (size_t i = 0; i < blockCount; i++)
605+
blocks.emplace_back(new BasicBlock(BNNewBasicBlockReference(bnBlocks[i])));
606+
607+
BNFreeBasicBlockList(bnBlocks, blockCount);
608+
return blocks;
609+
}
610+
611+
612+
Ref<LowLevelILFunction> FunctionLifterContext::GetForeignFunctionLiftedIL(Ref<Function> func)
613+
{
614+
size_t inlinedCallsCount = m_inlinedCalls.size();
615+
uint64_t* inlinedCalls = nullptr;
616+
if (inlinedCallsCount)
617+
inlinedCalls = new uint64_t[inlinedCallsCount];
618+
619+
BNLowLevelILFunction* il =
620+
BNGetForeignFunctionLiftedIL(func->GetObject(), m_logger->GetObject(), inlinedCallsCount, inlinedCalls);
621+
622+
if (inlinedCalls)
623+
delete[] inlinedCalls;
624+
625+
if (!il)
626+
return nullptr;
627+
628+
return new LowLevelILFunction(il);
629+
}
630+
631+
469632
Architecture::Architecture(BNArchitecture* arch)
470633
{
471634
m_object = arch;
@@ -600,6 +763,15 @@ void Architecture::AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function,
600763
}
601764

602765

766+
bool Architecture::LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* function, BNFunctionLifterContext* context)
767+
{
768+
CallbackRef<Architecture> arch(ctxt);
769+
Ref func(new LowLevelILFunction(BNNewLowLevelILFunctionReference(function)));
770+
FunctionLifterContext flc(func, context);
771+
return arch->LiftFunction(func, flc);
772+
}
773+
774+
603775
char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg)
604776
{
605777
CallbackRef<Architecture> arch(ctxt);
@@ -1091,6 +1263,7 @@ void Architecture::Register(Architecture* arch)
10911263
callbacks.freeInstructionText = FreeInstructionTextCallback;
10921264
callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback;
10931265
callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback;
1266+
callbacks.liftFunction = LiftFunctionCallback;
10941267
callbacks.getRegisterName = GetRegisterNameCallback;
10951268
callbacks.getFlagName = GetFlagNameCallback;
10961269
callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback;
@@ -1225,6 +1398,12 @@ void Architecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisCont
12251398
}
12261399

12271400

1401+
bool Architecture::LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context)
1402+
{
1403+
return DefaultLiftFunction(function, context);
1404+
}
1405+
1406+
12281407
string Architecture::GetRegisterName(uint32_t reg)
12291408
{
12301409
return fmt::format("r{}", reg);
@@ -1792,6 +1971,12 @@ void CoreArchitecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysis
17921971
}
17931972

17941973

1974+
bool CoreArchitecture::LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context)
1975+
{
1976+
return BNArchitectureLiftFunction(m_object, function->GetObject(), context.m_context);
1977+
}
1978+
1979+
17951980
string CoreArchitecture::GetRegisterName(uint32_t reg)
17961981
{
17971982
char* name = BNGetArchitectureRegisterName(m_object, reg);

basicblock.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,12 @@ void BasicBlock::SetUndeterminedOutgoingEdges(bool value)
454454
}
455455

456456

457+
bool BasicBlock::HasInstructionData() const
458+
{
459+
return BNBasicBlockHasInstructionData(m_object);
460+
}
461+
462+
457463
const uint8_t* BasicBlock::GetInstructionData(uint64_t addr, size_t* len) const
458464
{
459465
return BNBasicBlockGetInstructionData(m_object, addr, len);

0 commit comments

Comments
 (0)