Пример #1
0
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__ && (__arm__ || __arm64__ || __aarch64__)
		// eprintf ("No waitpid here :D\n");
		status = R_DEBUG_REASON_UNKNOWN;
#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;
}
Пример #2
0
/*
 * 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;
}
Пример #3
0
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
	}