@@ -470,25 +470,47 @@ static unsigned char syscall_buf32[] = {
470470
471471#endif
472472
473+ pid_t waitpid_debug (pid_t pid, int *stat_loc, int options, const char *callsite = " " ) {
474+ pid_t ret = waitpid (pid, stat_loc, options);
475+ // printf("Waitpid %s returned pid %d status %x\n", callsite, ret, *stat_loc);
476+ return ret;
477+ }
478+
473479void Debugger::RemoteSyscall () {
480+ // disable watchdog when doing remore syscalls
481+ // we still might get stopped by the watchdog
482+ // but at least it won't happen repeatedly
483+ bool saved_watchdog_state = watchdog_enabled;
484+ watchdog_enabled = false ;
485+
474486 SetRegister (ARCH_PC, syscall_address);
475487
476488 uint64_t rsp = GetRegister (ARCH_SP);
477489
478490 ptrace_check (PTRACE_SINGLESTEP, current_pid, nullptr , nullptr );
479491
480- int status = 0 ;
481- int wait_ret = waitpid (current_pid, &status, __WALL);
482- if (wait_ret != current_pid) {
483- FATAL (" Unexpected wait result after syscall" );
492+ while (true ) {
493+ int status = 0 ;
494+ int wait_ret = waitpid_debug (current_pid, &status, __WALL, " remote syscall" );
495+ if (WIFSTOPPED (status) && (WSTOPSIG (status) == SIGSTOP)) {
496+ // possible race with watchdog but we don't want to break in the middle of syscall
497+ ptrace (ptrace_continue_request, current_pid, 0 , 0 );
498+ continue ;
499+ }
500+ if (wait_ret != current_pid) {
501+ FATAL (" Unexpected wait result after syscall" );
502+ }
503+ break ;
484504 }
505+
485506 // printf("syscall status: %x\n", status);
486507
487508 // uint64_t rip = GetRegister(RIP);
488509 // printf("rip: %lx, syscall_address: %lx\n", rip, syscall_address);
489510
490511 if (rsp != GetRegister (ARCH_SP)) FATAL (" rsp mismatch %lx %lx" , rsp, GetRegister (ARCH_SP));
491512 // printf("Syscall status: %x\n", status);
513+ watchdog_enabled = saved_watchdog_state;
492514}
493515
494516void Debugger::SetSyscallArguments (uint64_t *args, size_t num_args) {
@@ -1819,7 +1841,7 @@ DebuggerStatus Debugger::HandleStopped(int status) {
18191841 if (trace_debug_events) printf (" Debugger: New thread, pid: %d\n " , new_thread_pid);
18201842 if (threads.find (new_thread_pid) == threads.end ()) {
18211843 int new_thread_status = 0 ;
1822- pid_t ret_pid = waitpid (new_thread_pid, &new_thread_status, __WALL);
1844+ pid_t ret_pid = waitpid_debug (new_thread_pid, &new_thread_status, __WALL, " thread " );
18231845 if (ret_pid != new_thread_pid) FATAL (" Unexpected waitpid result waiting for new thread\n " );
18241846 if (!WIFSTOPPED (new_thread_status)) FATAL (" Unexpected status from a new thread" );
18251847 SetThreadOptions (new_thread_pid);
@@ -1932,7 +1954,7 @@ DebuggerStatus Debugger::DebugLoop(uint32_t timeout) {
19321954 int status;
19331955 // printf("waiting...\n");
19341956 if (timeout != 0xFFFFFFFF ) watchdog_enabled = true ;
1935- current_pid = waitpid (-1 , &status, __WNOTHREAD);
1957+ current_pid = waitpid_debug (-1 , &status, __WNOTHREAD, " debugloop " );
19361958
19371959 // printf("done, %d %d\n", current_pid, main_pid);
19381960 // printf("RIP: %lx\n", GetRegister(RIP));
@@ -1944,7 +1966,7 @@ DebuggerStatus Debugger::DebugLoop(uint32_t timeout) {
19441966
19451967 watchdog_mutex.lock ();
19461968 watchdog_enabled = false ;
1947- if (killed_by_watchdog) {
1969+ if (killed_by_watchdog && WIFSTOPPED (status) && ( WSTOPSIG (status) == SIGSTOP) ) {
19481970 watchdog_mutex.unlock ();
19491971 return DEBUGGER_HANGED;
19501972 }
@@ -2021,7 +2043,7 @@ DebuggerStatus Debugger::Run(int argc, char **argv, uint32_t timeout) {
20212043 }
20222044
20232045 int status;
2024- pid_t ret = waitpid (child_pid, &status, 0 );
2046+ pid_t ret = waitpid_debug (child_pid, &status, 0 , " run " );
20252047 if ((ret != child_pid) || !WIFSTOPPED (status) || (WSTOPSIG (status) != SIGTRAP)) {
20262048 FATAL (" Child process didn't start correctly" );
20272049 }
@@ -2100,7 +2122,7 @@ DebuggerStatus Debugger::Attach(unsigned int pid, uint32_t timeout) {
21002122 for (auto iter = threads.begin (); iter != threads.end (); ++iter) {
21012123 // printf("waiting for %d\n", *iter);
21022124 int new_thread_status = 0 ;
2103- pid_t ret_pid = waitpid (*iter, &new_thread_status, __WALL);
2125+ pid_t ret_pid = waitpid_debug (*iter, &new_thread_status, __WALL, " attach " );
21042126 if (ret_pid != *iter) FATAL (" Unexpected waitpid result waiting for new thread\n " );
21052127 // printf("status: %x\n", new_thread_status);
21062128 if (!WIFSTOPPED (new_thread_status)) FATAL (" Unexpected status from a new thread" );
0 commit comments