| 969 | |
| 970 | |
| 971 | DebugStopReason DebuggerController::EmulateStepOverAndWait() |
| 972 | { |
| 973 | uint64_t remoteIP = m_state->IP(); |
| 974 | |
| 975 | // TODO: support the case where we cannot determined the remote arch |
| 976 | ArchitectureRef remoteArch = m_state->GetRemoteArchitecture(); |
| 977 | if (!remoteArch) |
| 978 | return InternalError; |
| 979 | |
| 980 | size_t size = remoteArch->GetMaxInstructionLength(); |
| 981 | DataBuffer buffer = m_adapter->ReadMemory(remoteIP, size); |
| 982 | size_t bytesRead = buffer.GetLength(); |
| 983 | |
| 984 | Ref<LowLevelILFunction> ilFunc = new LowLevelILFunction(remoteArch, nullptr); |
| 985 | ilFunc->SetCurrentAddress(remoteArch, remoteIP); |
| 986 | remoteArch->GetInstructionLowLevelIL((const uint8_t*)buffer.GetData(), remoteIP, bytesRead, *ilFunc); |
| 987 | |
| 988 | const auto& instr = (*ilFunc)[0]; |
| 989 | if (instr.operation != LLIL_CALL) |
| 990 | { |
| 991 | return StepIntoAndWaitInternal(); |
| 992 | } |
| 993 | else |
| 994 | { |
| 995 | InstructionInfo info; |
| 996 | if (!remoteArch->GetInstructionInfo((const uint8_t*)buffer.GetData(), remoteIP, bytesRead, info)) |
| 997 | { |
| 998 | // Whenever there is a failure, we fail back to step into |
| 999 | return StepIntoAndWaitInternal(); |
| 1000 | } |
| 1001 | |
| 1002 | if (info.length == 0) |
| 1003 | { |
| 1004 | return StepIntoAndWaitInternal(); |
| 1005 | } |
| 1006 | |
| 1007 | uint64_t remoteIPNext = remoteIP + info.length; |
| 1008 | return RunToAndWaitInternal({remoteIPNext}); |
| 1009 | } |
| 1010 | } |
| 1011 | |
| 1012 | |
| 1013 | DebugStopReason DebuggerController::StepOverAndWaitInternal() |
nothing calls this directly
no test coverage detected