@@ -16,6 +16,37 @@ static bool GetNextFunctionAfterAddress(Ref<BinaryView> data, Ref<Platform> plat
1616 return nextFunc != nullptr ;
1717}
1818
19+ static bool IsZeroConstant (LowLevelILInstruction expr)
20+ {
21+ return ((expr.operation == LLIL_CONST ) || (expr.operation == LLIL_CONST_PTR )) && (expr.GetConstant () == 0 );
22+ }
23+
24+
25+ static bool IsConstantPointer (LowLevelILInstruction expr, uint64_t value)
26+ {
27+ return ((expr.operation == LLIL_CONST ) || (expr.operation == LLIL_CONST_PTR )) && ((uint64_t )expr.GetConstant () == value);
28+ }
29+
30+
31+ static bool IsReturnAddressRegisterExpr (LowLevelILInstruction expr, const set<uint32_t >& returnAddressRegisters)
32+ {
33+ switch (expr.operation )
34+ {
35+ case LLIL_REG :
36+ return returnAddressRegisters.count (expr.GetSourceRegister <LLIL_REG >()) != 0 ;
37+ case LLIL_ADD :
38+ return (IsReturnAddressRegisterExpr (expr.GetLeftExpr <LLIL_ADD >(), returnAddressRegisters)
39+ && IsZeroConstant (expr.GetRightExpr <LLIL_ADD >()))
40+ || (IsZeroConstant (expr.GetLeftExpr <LLIL_ADD >())
41+ && IsReturnAddressRegisterExpr (expr.GetRightExpr <LLIL_ADD >(), returnAddressRegisters));
42+ case LLIL_SUB :
43+ return IsReturnAddressRegisterExpr (expr.GetLeftExpr <LLIL_SUB >(), returnAddressRegisters)
44+ && IsZeroConstant (expr.GetRightExpr <LLIL_SUB >());
45+ default :
46+ return false ;
47+ }
48+ }
49+
1950
2051void Architecture::DefaultAnalyzeBasicBlocks (Function* function, BasicBlockAnalysisContext& context)
2152{
@@ -992,7 +1023,18 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
9921023 m_function->MarkLabel (start);
9931024 m_function->ReplaceExpr (lastInstr.exprIndex , m_function->Goto (start, lastInstr));
9941025
995- if (lastInstr.operation == LLIL_CALL )
1026+ set<uint32_t > returnAddressRegisters;
1027+ for (size_t instrIndex = instrCountBefore; instrIndex < instrCountAfter - 1 ; instrIndex++)
1028+ {
1029+ LowLevelILInstruction instr = m_function->GetInstruction (instrIndex);
1030+ if (instr.operation != LLIL_SET_REG )
1031+ continue ;
1032+
1033+ if (IsConstantPointer (instr.GetSourceExpr <LLIL_SET_REG >(), addr))
1034+ returnAddressRegisters.insert (instr.GetDestRegister <LLIL_SET_REG >());
1035+ }
1036+
1037+ if (lastInstr.operation == LLIL_CALL && returnAddressRegisters.empty ())
9961038 {
9971039 // Set up return address according to the architecture
9981040 // TODO: Handle architectures that use a nonstandard way of calling functions
@@ -1024,6 +1066,7 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10241066 }
10251067
10261068 // Copy the inlined code from the target function
1069+ Ref<Architecture> callArch = block->GetArchitecture ();
10271070 auto blocks = PrepareToCopyForeignFunction (targetIL);
10281071 auto unresolvedIndirectBranches = targetFunc->GetUnresolvedIndirectBranches ();
10291072 auto sourceLocation = inlineDuringAnalysis == InlineUsingCallAddress ? ILSourceLocation (lastInstr) : ILSourceLocation ();
@@ -1046,6 +1089,13 @@ void FunctionLifterContext::CheckForInlinedCall(BasicBlock* block, size_t instrC
10461089 m_function->AddInstruction (instr.GetDestExpr <LLIL_RET >().CopyTo (m_function, sourceLocation));
10471090 m_function->AddInstruction (m_function->Goto (end, sourceLocation));
10481091 }
1092+ else if (lastInstr.operation == LLIL_CALL && instr.operation == LLIL_JUMP
1093+ && (block->GetArchitecture () == callArch)
1094+ && (IsConstantPointer (instr.GetDestExpr <LLIL_JUMP >(), addr)
1095+ || IsReturnAddressRegisterExpr (instr.GetDestExpr <LLIL_JUMP >(), returnAddressRegisters)))
1096+ {
1097+ m_function->AddInstruction (m_function->Goto (end, sourceLocation));
1098+ }
10491099 else if (lastInstr.operation == LLIL_CALL && instr.operation == LLIL_JUMP
10501100 && block->GetOutgoingEdges ().empty () && (unresolvedIndirectBranches.count (loc) == 0 ))
10511101 {
0 commit comments