Skip to content

Commit e8a3449

Browse files
appleflyerv3zznop
authored andcommitted
defaultarch: handle caller-set return addresses when inlining calls
detect registers that are set to the caller's next addr before a call is inlined, and therefore treat the jumps to those regs in the callee IL as returns to the call label.
1 parent 01ab3ad commit e8a3449

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

defaultarch.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

2051
void 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

Comments
 (0)