@@ -48,6 +48,37 @@ static bool IsReturnAddressRegisterExpr(LowLevelILInstruction expr, const set<ui
4848}
4949
5050
51+ static void RemoveWrittenReturnAddressRegisters (LowLevelILInstruction instr, set<uint32_t >& returnAddressRegisters)
52+ {
53+ switch (instr.operation )
54+ {
55+ case LLIL_SET_REG :
56+ returnAddressRegisters.erase (instr.GetDestRegister <LLIL_SET_REG >());
57+ break ;
58+ case LLIL_SET_REG_SPLIT :
59+ returnAddressRegisters.erase (instr.GetHighRegister <LLIL_SET_REG_SPLIT >());
60+ returnAddressRegisters.erase (instr.GetLowRegister <LLIL_SET_REG_SPLIT >());
61+ break ;
62+ default :
63+ break ;
64+ }
65+ }
66+
67+
68+ static bool IsReturnAddressRegisterJumpOrReturn (LowLevelILInstruction instr, const set<uint32_t >& returnAddressRegisters)
69+ {
70+ switch (instr.operation )
71+ {
72+ case LLIL_JUMP :
73+ return IsReturnAddressRegisterExpr (instr.GetDestExpr <LLIL_JUMP >(), returnAddressRegisters);
74+ case LLIL_RET :
75+ return IsReturnAddressRegisterExpr (instr.GetDestExpr <LLIL_RET >(), returnAddressRegisters);
76+ default :
77+ return false ;
78+ }
79+ }
80+
81+
5182void Architecture::DefaultAnalyzeBasicBlocks (Function* function, BasicBlockAnalysisContext& context)
5283{
5384 auto data = function->GetView ();
@@ -1033,11 +1064,34 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10331064 if (IsConstantPointer (instr.GetSourceExpr <LLIL_SET_REG >(), addr))
10341065 returnAddressRegisters.insert (instr.GetDestRegister <LLIL_SET_REG >());
10351066 }
1067+ bool hasCallSemantics = lastInstr.operation == LLIL_CALL
1068+ || (lastInstr.operation == LLIL_JUMP && !returnAddressRegisters.empty ());
10361069
1037- if (lastInstr.operation == LLIL_CALL && returnAddressRegisters.empty ())
1070+ // Copy the inlined code from the target function
1071+ Ref<Architecture> callArch = block->GetArchitecture ();
1072+ auto blocks = PrepareToCopyForeignFunction (targetIL);
1073+ auto unresolvedIndirectBranches = targetFunc->GetUnresolvedIndirectBranches ();
1074+ auto sourceLocation = inlineDuringAnalysis == InlineUsingCallAddress ? ILSourceLocation (lastInstr) : ILSourceLocation ();
1075+ set<uint32_t > unmodifiedReturnAddressRegisters = returnAddressRegisters;
1076+ bool calleeReturnsThroughCallerReturnAddressRegister = false ;
1077+ for (auto & block : blocks)
1078+ {
1079+ for (size_t instrIndex = block->GetStart (); instrIndex < block->GetEnd (); instrIndex++)
1080+ RemoveWrittenReturnAddressRegisters (targetIL->GetInstruction (instrIndex), unmodifiedReturnAddressRegisters);
1081+ }
1082+ for (auto & block : blocks)
1083+ {
1084+ for (size_t instrIndex = block->GetStart (); instrIndex < block->GetEnd (); instrIndex++)
1085+ {
1086+ if (IsReturnAddressRegisterJumpOrReturn (
1087+ targetIL->GetInstruction (instrIndex), unmodifiedReturnAddressRegisters))
1088+ calleeReturnsThroughCallerReturnAddressRegister = true ;
1089+ }
1090+ }
1091+
1092+ if (hasCallSemantics && !calleeReturnsThroughCallerReturnAddressRegister)
10381093 {
10391094 // Set up return address according to the architecture
1040- // TODO: Handle architectures that use a nonstandard way of calling functions
10411095 uint32_t linkReg = m_platform->GetArchitecture ()->GetLinkRegister ();
10421096 if (linkReg == BN_INVALID_REGISTER )
10431097 {
@@ -1056,20 +1110,14 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10561110
10571111 uint64_t addrToSet = addr;
10581112 if (block->GetArchitecture ()->GetName () == " thumb2" )
1059- addrToSet |= 1 ; // XXX: hack moved here from lowlevelilfunction.cpp
1113+ addrToSet |= 1 ;
10601114
10611115 ExprId linkExpr = m_function->SetRegister (
10621116 regInfo.size , linkReg, m_function->ConstPointer (regInfo.size , addrToSet, lastInstr), 0 , lastInstr);
10631117 m_function->SetExprAttributes (linkExpr, ILAllowDeadStoreElimination);
10641118 m_function->AddInstruction (linkExpr);
10651119 }
10661120 }
1067-
1068- // Copy the inlined code from the target function
1069- Ref<Architecture> callArch = block->GetArchitecture ();
1070- auto blocks = PrepareToCopyForeignFunction (targetIL);
1071- auto unresolvedIndirectBranches = targetFunc->GetUnresolvedIndirectBranches ();
1072- auto sourceLocation = inlineDuringAnalysis == InlineUsingCallAddress ? ILSourceLocation (lastInstr) : ILSourceLocation ();
10731121 for (auto & block : blocks)
10741122 {
10751123 m_function->PrepareToCopyBlock (block);
@@ -1078,7 +1126,7 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10781126 LowLevelILInstruction instr = targetIL->GetInstruction (instrIndex);
10791127 ArchAndAddr loc (block->GetArchitecture (), instr.address );
10801128
1081- if (lastInstr. operation == LLIL_CALL && instr.operation == LLIL_RET )
1129+ if (hasCallSemantics && instr.operation == LLIL_RET )
10821130 {
10831131 // If the instruction is a return, emit the computation of the target
10841132 // location (it may affect the stack pointer) but go directly to the
@@ -1089,14 +1137,15 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10891137 m_function->AddInstruction (instr.GetDestExpr <LLIL_RET >().CopyTo (m_function, sourceLocation));
10901138 m_function->AddInstruction (m_function->Goto (end, sourceLocation));
10911139 }
1092- else if (lastInstr. operation == LLIL_CALL && instr.operation == LLIL_JUMP
1140+ else if (hasCallSemantics && instr.operation == LLIL_JUMP
10931141 && (block->GetArchitecture () == callArch)
10941142 && (IsConstantPointer (instr.GetDestExpr <LLIL_JUMP >(), addr)
1095- || IsReturnAddressRegisterExpr (instr.GetDestExpr <LLIL_JUMP >(), returnAddressRegisters)))
1143+ || IsReturnAddressRegisterExpr (instr.GetDestExpr <LLIL_JUMP >(),
1144+ unmodifiedReturnAddressRegisters)))
10961145 {
10971146 m_function->AddInstruction (m_function->Goto (end, sourceLocation));
10981147 }
1099- else if (lastInstr. operation == LLIL_CALL && instr.operation == LLIL_JUMP
1148+ else if (hasCallSemantics && instr.operation == LLIL_JUMP
11001149 && block->GetOutgoingEdges ().empty () && (unresolvedIndirectBranches.count (loc) == 0 ))
11011150 {
11021151 // Jump without outgoing edges in the graph, and it is not marked as having
0 commit comments