From 5ccef726c0954116f8f4b5d6347e0acdbb0b6ce3 Mon Sep 17 00:00:00 2001 From: Brandon Miller Date: Tue, 27 Jan 2026 11:26:57 -0500 Subject: 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. --- architecture.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 64d3907c..1901438f 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -466,6 +466,169 @@ void BasicBlockAnalysisContext::Finalize() } +FunctionLifterContext::FunctionLifterContext(LowLevelILFunction* func, BNFunctionLifterContext* context) +{ + m_context = context; + m_view = func->GetFunction()->GetView(); + m_function = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func->GetObject())); + m_platform = new Platform(BNNewPlatformReference(context->platform)); + m_logger = new Logger(BNNewLoggerReference(context->logger)); + m_blocks.reserve(context->basicBlockCount); + for (size_t i = 0; i < context->basicBlockCount; i++) + { + m_blocks.emplace_back(new BasicBlock(context->basicBlocks[i])); + } + + for (size_t i = 0; i < context->noReturnCallsCount; i++) + { + ArchAndAddr addr(new CoreArchitecture(context->noReturnCalls[i].arch), context->noReturnCalls[i].address); + m_noReturnCalls.insert(addr); + } + + for (size_t i = 0; i < context->contextualFunctionReturnCount; i++) + { + ArchAndAddr addr(new CoreArchitecture(context->contextualFunctionReturnLocations[i].arch), + context->contextualFunctionReturnLocations[i].address); + m_contextualReturns[addr] = context->contextualFunctionReturnValues[i]; + } + + for (size_t i = 0; i < context->inlinedRemappingEntryCount; i++) + { + ArchAndAddr key( + new CoreArchitecture(context->inlinedRemappingKeys[i].arch), context->inlinedRemappingKeys[i].address); + ArchAndAddr value( + new CoreArchitecture(context->inlinedRemappingValues[i].arch), context->inlinedRemappingValues[i].address); + m_inlinedRemapping[key] = value; + } + + for (size_t i = 0; i < context->indirectBranchesCount; i++) + { + ArchAndAddr src( + new CoreArchitecture(context->indirectBranches[i].sourceArch), context->indirectBranches[i].sourceAddr); + ArchAndAddr dest( + new CoreArchitecture(context->indirectBranches[i].destArch), context->indirectBranches[i].destAddr); + if (context->indirectBranches[i].autoDefined) + m_autoIndirectBranches[src].insert(dest); + else + m_userIndirectBranches[src].insert(dest); + } + + for (size_t i = 0; i < context->inlinedCallsCount; i++) + { + m_inlinedCalls.insert(context->inlinedCalls[i]); + } + + m_containsInlinedFunctions = context->containsInlinedFunctions; +} + + +Ref& FunctionLifterContext::GetView() +{ + return m_view; +} + + +Ref& FunctionLifterContext::GetPlatform() +{ + return m_platform; +} + + +std::map& FunctionLifterContext::GetInlinedRemapping() +{ + return m_inlinedRemapping; +} + + +std::map>& FunctionLifterContext::GetUserIndirectBranches() +{ + return m_userIndirectBranches; +} + + +std::map>& FunctionLifterContext::GetAutoIndirectBranches() +{ + return m_autoIndirectBranches; +} + + +Ref& FunctionLifterContext::GetLogger() +{ + return m_logger; +} + + +vector>& FunctionLifterContext::GetBasicBlocks() +{ + return m_blocks; +} + + +std::set& FunctionLifterContext::GetNoReturnCalls() +{ + return m_noReturnCalls; +} + + +std::map& FunctionLifterContext::GetContextualReturns() +{ + return m_contextualReturns; +} + + +std::set& FunctionLifterContext::GetInlinedCalls() +{ + return m_inlinedCalls; +} + + +void FunctionLifterContext::SetContainsInlinedFunctions(bool value) +{ + *m_containsInlinedFunctions = value; +} + + +void FunctionLifterContext::PrepareBlockTranslation(LowLevelILFunction* function, Architecture* arch, uint64_t addr) +{ + BNPrepareBlockTranslation(function->GetObject(), arch->GetObject(), addr); +} + + +std::vector> FunctionLifterContext::PrepareToCopyForeignFunction(LowLevelILFunction* function) +{ + size_t blockCount = 0; + BNBasicBlock** bnBlocks = + BNPrepareToCopyForeignFunction(m_function->GetObject(), function->GetObject(), &blockCount); + std::vector> blocks; + blocks.reserve(blockCount); + for (size_t i = 0; i < blockCount; i++) + blocks.emplace_back(new BasicBlock(BNNewBasicBlockReference(bnBlocks[i]))); + + BNFreeBasicBlockList(bnBlocks, blockCount); + return blocks; +} + + +Ref FunctionLifterContext::GetForeignFunctionLiftedIL(Ref func) +{ + size_t inlinedCallsCount = m_inlinedCalls.size(); + uint64_t* inlinedCalls = nullptr; + if (inlinedCallsCount) + inlinedCalls = new uint64_t[inlinedCallsCount]; + + BNLowLevelILFunction* il = + BNGetForeignFunctionLiftedIL(func->GetObject(), m_logger->GetObject(), inlinedCallsCount, inlinedCalls); + + if (inlinedCalls) + delete[] inlinedCalls; + + if (!il) + return nullptr; + + return new LowLevelILFunction(il); +} + + Architecture::Architecture(BNArchitecture* arch) { m_object = arch; @@ -600,6 +763,15 @@ void Architecture::AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function, } +bool Architecture::LiftFunctionCallback(void* ctxt, BNLowLevelILFunction* function, BNFunctionLifterContext* context) +{ + CallbackRef arch(ctxt); + Ref func(new LowLevelILFunction(BNNewLowLevelILFunctionReference(function))); + FunctionLifterContext flc(func, context); + return arch->LiftFunction(func, flc); +} + + char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg) { CallbackRef arch(ctxt); @@ -1091,6 +1263,7 @@ void Architecture::Register(Architecture* arch) callbacks.freeInstructionText = FreeInstructionTextCallback; callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback; callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback; + callbacks.liftFunction = LiftFunctionCallback; callbacks.getRegisterName = GetRegisterNameCallback; callbacks.getFlagName = GetFlagNameCallback; callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback; @@ -1225,6 +1398,12 @@ void Architecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisCont } +bool Architecture::LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context) +{ + return DefaultLiftFunction(function, context); +} + + string Architecture::GetRegisterName(uint32_t reg) { return fmt::format("r{}", reg); @@ -1792,6 +1971,12 @@ void CoreArchitecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysis } +bool CoreArchitecture::LiftFunction(LowLevelILFunction* function, FunctionLifterContext& context) +{ + return BNArchitectureLiftFunction(m_object, function->GetObject(), context.m_context); +} + + string CoreArchitecture::GetRegisterName(uint32_t reg) { char* name = BNGetArchitectureRegisterName(m_object, reg); -- cgit v1.3.1