static int r_debug_native_wait (RDebug *dbg, int pid) { int status = -1; #if __WINDOWS__ && !__CYGWIN__ int mode = 0; status = w32_dbg_wait (dbg, pid); if (status == R_DEBUG_REASON_NEW_LIB) { mode = 'l'; } else if (status == R_DEBUG_REASON_EXIT_LIB) { mode = 'u'; } else { mode = 0; } if (mode) { RDebugInfo *r = r_debug_native_info (dbg, ""); if (r && r->lib) { if (tracelib (dbg, mode=='l'? "load":"unload", r->lib)) status=R_DEBUG_REASON_TRAP; } else { eprintf ("%soading unknown library.\n", mode?"L":"Unl"); } r_debug_info_free (r); } #else if (pid == -1) { status = R_DEBUG_REASON_UNKNOWN; } else { #if __APPLE__ // eprintf ("No waitpid here :D\n"); status = xnu_wait (dbg, pid); #else // XXX: this is blocking, ^C will be ignored int ret = waitpid (pid, &status, 0); if (ret == -1) { status = R_DEBUG_REASON_ERROR; } else { //printf ("status=%d (return=%d)\n", status, ret); // TODO: switch status and handle reasons here r_debug_handle_signals (dbg); if (WIFSTOPPED (status)) { dbg->reason.signum = WSTOPSIG (status); status = R_DEBUG_REASON_SIGNAL; } else if (status == 0 || ret == -1) { status = R_DEBUG_REASON_DEAD; } else { if (ret != pid) status = R_DEBUG_REASON_NEW_PID; else status = R_DEBUG_REASON_UNKNOWN; } } #endif } #endif dbg->reason.tid = pid; dbg->reason.type = status; return status; }
/* * wait for an event and start trying to figure out what to do with it. * * Returns R_DEBUG_REASON_* */ static RDebugReasonType r_debug_native_wait (RDebug *dbg, int pid) { int status = -1; RDebugReasonType reason = R_DEBUG_REASON_UNKNOWN; #if __WINDOWS__ && !__CYGWIN__ int mode = 0; reason = w32_dbg_wait (dbg, pid); if (reason == R_DEBUG_REASON_NEW_LIB) { mode = 'l'; } else if (reason == R_DEBUG_REASON_EXIT_LIB) { mode = 'u'; } else { mode = 0; } if (mode) { RDebugInfo *r = r_debug_native_info (dbg, ""); if (r && r->lib) { if (tracelib (dbg, mode=='l'? "load":"unload", r->lib)) reason = R_DEBUG_REASON_TRAP; } else { eprintf ("%soading unknown library.\n", mode?"L":"Unl"); } r_debug_info_free (r); } #else if (pid == -1) { eprintf ("r_debug_native_wait called with -1 pid!\n"); return R_DEBUG_REASON_ERROR; } #if __APPLE__ // eprintf ("No waitpid here :D\n"); reason = xnu_wait (dbg, pid); status = reason? 1: 0; #else // XXX: this is blocking, ^C will be ignored #ifdef WAIT_ON_ALL_CHILDREN //eprintf ("waiting on all children ...\n"); int ret = waitpid (-1, &status, WAITPID_FLAGS); #else //eprintf ("waiting on pid %d ...\n", pid); int ret = waitpid (pid, &status, WAITPID_FLAGS); #endif // WAIT_ON_ALL_CHILDREN if (ret == -1) { r_sys_perror ("waitpid"); return R_DEBUG_REASON_ERROR; } //eprintf ("r_debug_native_wait: status=%d (0x%x) (return=%d)\n", status, status, ret); #ifdef WAIT_ON_ALL_CHILDREN if (ret != pid) { reason = R_DEBUG_REASON_NEW_PID; eprintf ("switching to pid %d\n", ret); r_debug_select(dbg, ret, ret); } #endif // WAIT_ON_ALL_CHILDREN // TODO: switch status and handle reasons here #if __linux__ && defined(PT_GETEVENTMSG) reason = linux_ptrace_event (dbg, pid, status); #endif // __linux__ /* propagate errors */ if (reason == R_DEBUG_REASON_ERROR) { return reason; } /* we don't know what to do yet, let's try harder to figure it out. */ if (reason == R_DEBUG_REASON_UNKNOWN) { if (WIFEXITED (status)) { eprintf ("child exited with status %d\n", WEXITSTATUS (status)); reason = R_DEBUG_REASON_DEAD; } else if (WIFSIGNALED (status)) { eprintf ("child received signal %d\n", WTERMSIG (status)); reason = R_DEBUG_REASON_SIGNAL; } else if (WIFSTOPPED (status)) { if (WSTOPSIG (status) != SIGTRAP) { eprintf ("child stopped with signal %d\n", WSTOPSIG (status)); } /* this one might be good enough... */ dbg->reason.signum = WSTOPSIG (status); /* the ptrace documentation says GETSIGINFO is only necessary for * differentiating the various stops. * * this might modify dbg->reason.signum */ if (!r_debug_handle_signals (dbg)) return R_DEBUG_REASON_ERROR; reason = dbg->reason.type; } else if (WIFCONTINUED (status)) { eprintf ("child continued...\n"); reason = R_DEBUG_REASON_NONE; } else if (status == 1) { /* XXX(jjd): does this actually happen? */ eprintf ("EEK DEAD DEBUGEE!\n"); reason = R_DEBUG_REASON_DEAD; } else if (status == 0) { /* XXX(jjd): does this actually happen? */ eprintf ("STATUS=0?!?!?!?\n"); reason = R_DEBUG_REASON_DEAD; } else { if (ret != pid) { reason = R_DEBUG_REASON_NEW_PID; } else { /* ugh. still don't know :-/ */ eprintf ("CRAP. returning from wait without knowing why...\n"); } } } /* if we still don't know what to do, we have a problem... */ if (reason == R_DEBUG_REASON_UNKNOWN) { eprintf ("%s: no idea what happened... wtf?!?!\n", __func__); reason = R_DEBUG_REASON_ERROR; } #endif // __APPLE__ #endif // __WINDOWS__ && !__CYGWIN__ dbg->reason.tid = pid; dbg->reason.type = reason; return reason; }
static int r_debug_native_wait (RDebug *dbg, int pid) { int status = -1; #if __WINDOWS__ && !__CYGWIN__ int mode = 0; status = w32_dbg_wait (dbg, pid); if (status == R_DEBUG_REASON_NEW_LIB) { mode = 'l'; } else if (status == R_DEBUG_REASON_EXIT_LIB) { mode = 'u'; } else { mode = 0; } if (mode) { RDebugInfo *r = r_debug_native_info (dbg, ""); if (r && r->lib) { if (tracelib (dbg, mode=='l'? "load":"unload", r->lib)) status=R_DEBUG_REASON_TRAP; } else { eprintf ("%soading unknown library.\n", mode?"L":"Unl"); } r_debug_info_free (r); } #else if (pid == -1) { status = R_DEBUG_REASON_UNKNOWN; } else { #if __APPLE__ // eprintf ("No waitpid here :D\n"); status = xnu_wait (dbg, pid); #else // XXX: this is blocking, ^C will be ignored int ret = waitpid (pid, &status, 0); if (ret == -1) { r_sys_perror ("waitpid"); status = R_DEBUG_REASON_ERROR; } else { //printf ("r_debug_native_wait: status=%d (return=%d)\n", status, ret); // TODO: switch status and handle reasons here #if __linux__ && defined(PT_GETEVENTMSG) // Handle PTRACE_EVENT_* if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) { ut32 pt_evt = status >> 16; ut32 data; switch (pt_evt) { case 0: // Normal trap? break; case PTRACE_EVENT_FORK: if (dbg->trace_forks) { if (ptrace (PTRACE_GETEVENTMSG, pid, 0, &data) == -1) { r_sys_perror ("ptrace GETEVENTMSG"); } else { eprintf ("PTRACE_EVENT_FORK new_pid=%d\n", data); dbg->forked_pid = data; // TODO: more handling here? } } break; case PTRACE_EVENT_EXIT: if (ptrace (PTRACE_GETEVENTMSG, pid, 0, &data) == -1) { r_sys_perror ("ptrace GETEVENTMSG"); } else { eprintf ("PTRACE_EVENT_EXIT pid=%d, status=%d\n", pid, data); } break; default: eprintf ("Unknown PTRACE_EVENT encountered: %d\n", pt_evt); break; } } #endif r_debug_handle_signals (dbg); if (WIFSTOPPED (status)) { dbg->reason.signum = WSTOPSIG (status); status = R_DEBUG_REASON_SIGNAL; } else if (status == 0 || ret == -1) { status = R_DEBUG_REASON_DEAD; } else { if (ret != pid) status = R_DEBUG_REASON_NEW_PID; else status = R_DEBUG_REASON_UNKNOWN; } } #endif }