Example #1
0
/* Returns PID */
R_API int r_debug_wait(RDebug *dbg) {
	int ret = 0;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	if (dbg && dbg->h && dbg->h->wait) {
		dbg->reason = R_DBG_REASON_UNKNOWN;
		ret = dbg->h->wait (dbg, dbg->pid);
		dbg->reason = ret;
		dbg->newstate = 1;
		if (ret == -1) {
			eprintf ("\n==> Process finished\n\n");
			r_debug_select (dbg, -1, -1);
		}
		//eprintf ("wait = %d\n", ret);
		if (dbg->trace->enabled)
			r_debug_trace_pc (dbg);
		if (ret == R_DBG_REASON_SIGNAL && dbg->signum != -1) {
			/* handle signal on continuations here */
			int what = r_debug_signal_what (dbg, dbg->signum);
			const char *name = r_debug_signal_resolve_i (dbg, dbg->signum);
			if (strcmp ("SIGTRAP", name))
				r_cons_printf ("[+] signal %d aka %s received\n",
					dbg->signum, name);
			if (what & R_DBG_SIGNAL_SKIP) {
				dbg->signum = 0;
				// TODO: use ptrace-setsiginfo to ignore signal
			}
			if (what & R_DBG_SIGNAL_CONT) {
				// XXX: support step, steptrace, continue_until_foo, etc..
				r_debug_continue (dbg);
			}
		}
	}
	return ret;
}
Example #2
0
/* Returns PID */
R_API int r_debug_wait(RDebug *dbg) {
	int ret = 0;
	if (!dbg)
		return R_FALSE;
	dbg->reason.type = R_DEBUG_REASON_UNKNOWN;
	if (r_debug_is_dead (dbg)) {
		return dbg->reason.type = R_DEBUG_REASON_DEAD;
	}
	if (dbg->h && dbg->h->wait) {
		dbg->reason.type = R_DEBUG_REASON_UNKNOWN;
		ret = dbg->h->wait (dbg, dbg->pid);
		dbg->newstate = 1;
		if (ret == -1) {
			eprintf ("\n==> Process finished\n\n");
			r_debug_select (dbg, -1, -1);
		}
		//eprintf ("wait = %d\n", ret);
		if (dbg->trace->enabled)
			r_debug_trace_pc (dbg);
		if (ret == R_DEBUG_REASON_SIGNAL && dbg->reason.signum != -1) {
			/* handle signal on continuations here */
			int what = r_debug_signal_what (dbg, dbg->reason.signum);
			const char *name = r_debug_signal_resolve_i (dbg, dbg->reason.signum);
			if (name && strcmp ("SIGTRAP", name))
				r_cons_printf ("[+] signal %d aka %s received %d\n",
						dbg->reason.signum, name, what);
		}
	}
	return ret;
}
Example #3
0
R_API int r_debug_attach(RDebug *dbg, int pid) {
	int ret = false;
	if (dbg && dbg->h && dbg->h->attach) {
		ret = dbg->h->attach (dbg, pid);
		if (ret != -1) {
			//eprintf ("Attached debugger to pid = %d, tid = %d\n", pid, ret);
			r_debug_select (dbg, pid, ret); //dbg->pid, dbg->tid);
		}
	}
	return ret;
}
Example #4
0
static int config_cfgdebug_callback(void *user, void *data) {
	RCore *core = (RCore*) user;
	RConfigNode *node = (RConfigNode*) data;
	if (!core) return R_FALSE;
	if (core->io)
		core->io->debug = node->i_value;
	if (core->dbg && node->i_value) {
		const char *dbgbackend = r_config_get (core->config, "dbg.backend");
		r_debug_use (core->dbg, dbgbackend);
		if (!strcmp (dbgbackend, "bf"))
			r_config_set (core->config, "asm.arch", "bf");
		if (core->file) {
			r_debug_select (core->dbg, core->file->fd->fd, core->file->fd->fd);
		}
	} else r_debug_use (core->dbg, NULL);
	return R_TRUE;
}
Example #5
0
R_API int r_debug_attach(RDebug *dbg, int pid) {
	int ret = R_FALSE;
	if (dbg && dbg->h && dbg->h->attach) {
		ret = dbg->h->attach (dbg, pid);
		if (ret != -1) {
			eprintf ("Attached debugger to pid = %d, tid = %d\n", pid, ret);
			// TODO: get arch and set io pid
			//int arch = dbg->h->arch;
			//r_reg_set(dbg->reg->nregs, arch); //R_DBG_ARCH_X86);
			// dbg->bp->iob->system("pid %d", pid);
			//dbg->pid = pid;
			//dbg->tid = ret;
			r_debug_select (dbg, pid, ret); //dbg->pid, dbg->tid);
		}// else if (pid != -1)
		//	eprintf ("Cannot attach to this pid %d\n", pid);
	}// else eprintf ("dbg->attach = NULL\n");
	return ret;
}
Example #6
0
/* Returns PID */
R_API int r_debug_wait(RDebug *dbg) {
	int ret = 0;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	if (dbg && dbg->h && dbg->h->wait) {
		dbg->reason = R_DBG_REASON_UNKNOWN;
		ret = dbg->h->wait (dbg, dbg->pid);
		dbg->reason = ret;
		dbg->newstate = 1;
		if (ret == -1) {
			eprintf ("\n==> Process finished\n\n");
			r_debug_select (dbg, -1, -1); //dbg->pid = -1;
		}
		//eprintf ("wait = %d\n", ret);
		if (dbg->trace->enabled)
			r_debug_trace_pc (dbg);
	}
	return ret;
}
Example #7
0
R_API int r_debug_continue_kill(RDebug *dbg, int sig) {
	int ret = R_FALSE;
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	if (dbg && dbg->h && dbg->h->cont) {
		r_bp_restore (dbg->bp, R_FALSE); // set sw breakpoints
		ret = dbg->h->cont (dbg, dbg->pid, dbg->tid, sig);
		r_debug_wait (dbg);
		r_bp_restore (dbg->bp, R_TRUE); // unset sw breakpoints
		r_debug_recoil (dbg);
#if 0
#if __UNIX__
		/* XXX Uh? */
		if (dbg->stop_all_threads && dbg->pid>0)
			r_sandbox_kill (dbg->pid, SIGSTOP);
#endif
#endif
		r_debug_select (dbg, dbg->pid, ret);
	}
	return ret;
}
Example #8
0
R_API int r_debug_continue_kill(RDebug *dbg, int sig) {
	ut64 pc;
	int retwait, ret = R_FALSE;
	if (!dbg)
		return R_FALSE;
#if __WINDOWS__
	r_cons_break(w32_break_process, dbg);
#endif
repeat:
	if (r_debug_is_dead (dbg))
		return R_FALSE;
	if (dbg->h && dbg->h->cont) {
		r_bp_restore (dbg->bp, R_TRUE); // set sw breakpoints
		ret = dbg->h->cont (dbg, dbg->pid, dbg->tid, sig);
		dbg->reason.signum = 0;
		retwait = r_debug_wait (dbg);
#if __WINDOWS__
		if (retwait != R_DEBUG_REASON_DEAD) {
			ret = dbg->tid;
		}
#endif
		r_bp_restore (dbg->bp, R_FALSE); // unset sw breakpoints
		//r_debug_recoil (dbg);
		if (r_debug_recoil (dbg) || (dbg->reason.type == R_DEBUG_REASON_BREAKPOINT)) {
			/* check if cur bp demands tracing or not */
			pc = r_debug_reg_get (dbg, dbg->reg->name[R_REG_NAME_PC]);
			RBreakpointItem *b = r_bp_get_at (dbg->bp, pc);
			if (b) {
				/* check if cur bp demands tracing or not */
				if (b->trace) {
					eprintf("hit tracepoit at: %"PFMT64x"\n",pc);
				} else {
					eprintf("hit breakpoint at: %"PFMT64x"\n",pc);
				}
				if (dbg->trace->enabled)
					r_debug_trace_pc (dbg);
				// TODO: delegate this to RCore.bphit(RCore, RBreakopintItem)
				if (dbg->corebind.core && dbg->corebind.bphit) {
					dbg->corebind.bphit (dbg->corebind.core, b);
				}
				if (b->trace) {
					r_debug_step (dbg, 1);
					goto repeat;
				}
			}
		}
#if 0
#if __UNIX__
		/* XXX Uh? */
		if (dbg->stop_all_threads && dbg->pid>0)
			r_sandbox_kill (dbg->pid, SIGSTOP);
#endif
#endif
		r_debug_select (dbg, dbg->pid, ret);
		sig = 0; // clear continuation after signal if needed
		if (retwait == R_DEBUG_REASON_SIGNAL && dbg->reason.signum != -1) {
			int what = r_debug_signal_what (dbg, dbg->reason.signum);
			if (what & R_DBG_SIGNAL_CONT) {
				sig = dbg->reason.signum;
				eprintf ("Continue into the signal %d handler\n", sig);
				goto repeat;
			} else if (what & R_DBG_SIGNAL_SKIP) {
				// skip signal. requires skipping one instruction
				ut8 buf[64];
				RAnalOp op = {0};
				ut64 pc = r_debug_reg_get (dbg, "pc");
				dbg->iob.read_at (dbg->iob.io, pc, buf, sizeof (buf));
				r_anal_op (dbg->anal, &op, pc, buf, sizeof (buf));
				if (op.size>0) {
					const char *signame = r_debug_signal_resolve_i (dbg, dbg->reason.signum);
					r_debug_reg_set (dbg, "pc", pc+op.size);
					eprintf ("Skip signal %d handler %s\n",
						dbg->reason.signum, signame);
					goto repeat;
				} else  {
					ut64 pc = r_debug_reg_get (dbg, "pc");
					eprintf ("Stalled with an exception at 0x%08"PFMT64x"\n", pc);
				}
			}
		}
	}
	return ret;
}
Example #9
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;
}
Example #10
0
R_API int r_core_file_reopen(RCore *core, const char *args, int perm, int loadbin) {
	int isdebug = r_config_get_i (core->config, "cfg.debug");
	char *path;
	ut64 laddr = r_config_get_i (core->config, "bin.laddr");
	RCoreFile *file = NULL;
	RCoreFile *ofile = core->file;
	RBinFile *bf = ofile ? r_bin_file_find_by_fd (core->bin, ofile->fd)
		: NULL;
	RIODesc *odesc = (core->io && ofile) ? r_io_desc_get (core->io, ofile->fd) : NULL;
	char *ofilepath = NULL, *obinfilepath = (bf && bf->file)? strdup (bf->file): NULL;
	int ret = false;
	ut64 origoff = core->offset;
	if (odesc) {
		if (odesc->referer) {
			ofilepath = odesc->referer;
		} else if (odesc->uri) {
			ofilepath = odesc->uri;
		}
	}

	if (r_sandbox_enable (0)) {
		eprintf ("Cannot reopen in sandbox\n");
		free (obinfilepath);
		return false;
	}
	if (!core->file) {
		eprintf ("No file opened to reopen\n");
		free (ofilepath);
		free (obinfilepath);
		return false;
	}
	int newpid = odesc? odesc->fd: -1;

	if (isdebug) {
		r_debug_kill (core->dbg, core->dbg->pid, core->dbg->tid, 9); // KILL
		perm = 7;
	} else {
		if (!perm) {
			perm = 4; //R_IO_READ;
		}
	}
	if (!ofilepath) {
		eprintf ("Unknown file path");
		free (obinfilepath);
		return false;
	}

	// HACK: move last mapped address to higher place
	// XXX - why does this hack work?
	// when the new memory maps are created.
	path = strdup (ofilepath);
	free (obinfilepath);
	obinfilepath = strdup (ofilepath);

	// r_str_trim (path);
	file = r_core_file_open (core, path, perm, laddr);
	if (file) {
		bool had_rbin_info = false;

		if (ofile) {
			if (r_bin_file_delete (core->bin, ofile->fd)) {
				had_rbin_info = true;
			}
		}
		r_core_file_close (core, ofile);
		r_core_file_set_by_file (core, file);
		ofile = NULL;
		odesc = NULL;
		//	core->file = file;
		eprintf ("File %s reopened in %s mode\n", path,
			(perm & R_IO_WRITE)? "read-write": "read-only");

		if (loadbin && (loadbin == 2 || had_rbin_info)) {
			ut64 baddr = r_config_get_i (core->config, "bin.baddr");
			ret = r_core_bin_load (core, obinfilepath, baddr);
			r_core_bin_update_arch_bits (core);
			if (!ret) {
				eprintf ("Error: Failed to reload rbin for: %s", path);
			}
		}

		if (core->bin->cur && core->io && r_io_desc_get (core->io, file->fd) && !loadbin) {
			//force here NULL because is causing uaf look this better in future XXX @alvarofe
			core->bin->cur = NULL;
		}
		// close old file
	} else if (ofile) {
		eprintf ("r_core_file_reopen: Cannot reopen file: %s with perms 0x%04x,"
			" attempting to open read-only.\n", path, perm);
		// lower it down back
		//ofile = r_core_file_open (core, path, R_IO_READ, addr);
		r_core_file_set_by_file (core, ofile);
	} else {
		eprintf ("Cannot reopen\n");
	}
	if (isdebug) {
		int newtid = newpid;
		// XXX - select the right backend
		if (core->file) {
			newpid = r_io_fd_get_pid (core->io, core->file->fd);
			newtid = r_io_fd_get_tid (core->io, core->file->fd);
#if __linux__
			core->dbg->main_pid = newpid;
			newtid = newpid;
#endif
#pragma message ("fix debugger-concept in core")
#if __WINDOWS__
			r_debug_select (core->dbg, newpid, newtid);
			core->dbg->reason.type = R_DEBUG_REASON_NONE;
#endif
		}
		//reopen and attach
		r_core_setup_debugger (core, "native", true);
		r_debug_select (core->dbg, newpid, newtid);
	}
	if (core->file) {
		r_io_use_fd (core->io, core->file->fd);
		core->switch_file_view = 1;
		r_core_block_read (core);
#if 0
		else {