static int r_debug_native_kill (RDebug *dbg, int pid, int tid, int sig) { int ret = false; if (pid == 0) pid = dbg->pid; #if __WINDOWS__ && !__CYGWIN__ ret = w32_terminate_process (dbg, pid); #else #if 0 if (thread) { // XXX this is linux>2.5 specific..ugly if (dbg->tid>0 && (ret = tgkill (dbg->pid, dbg->tid, sig))) { if (ret != -1) ret = true; } } else { #endif if ((r_sandbox_kill (pid, sig) != -1)) ret = true; if (errno == 1) ret = -true; // EPERM #if 0 // } #endif #endif return ret; } struct r_debug_desc_plugin_t r_debug_desc_plugin_native; static int r_debug_native_init (RDebug *dbg) { dbg->h->desc = r_debug_desc_plugin_native; #if __WINDOWS__ && !__CYGWIN__ return w32_dbg_init (); #elif __APPLE__ return xnu_init (); #else return true; #endif }
R_API bool r_sys_stop () { if (enabled) { return false; } #if __UNIX__ return !r_sandbox_kill (0, SIGTSTP); #else return false; #endif }
R_API int r_sys_stop () { if (enabled) return R_FALSE; int pid = r_sys_getpid (); #ifndef SIGSTOP #define SIGSTOP 19 #endif if (!r_sandbox_kill (pid, SIGSTOP)) return R_TRUE; return R_FALSE; }
R_API int r_sys_stop () { int pid; if (enabled) { return false; } pid = r_sys_getpid (); #ifndef SIGSTOP #define SIGSTOP 19 #endif return (!r_sandbox_kill (pid, SIGSTOP)); }
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; }
static RList *r_debug_native_pids (int pid) { RList *list = r_list_new (); #if __WINDOWS__ && !__CYGWIN__ return w32_pids (pid, list); #elif __APPLE__ if (pid) { RDebugPid *p = xnu_get_pid (pid); if (p) r_list_append (list, p); } else { int i; for (i = 1; i < MAXPID; i++) { RDebugPid *p = xnu_get_pid (i); if (p) r_list_append (list, p); } } #else int i, fd; char *ptr, cmdline[1024]; list->free = (RListFree)&r_debug_pid_free; /* TODO */ if (pid) { r_list_append (list, r_debug_pid_new ("(current)", pid, 's', 0)); /* list parents */ DIR *dh; struct dirent *de; dh = opendir ("/proc"); if (dh == NULL) { r_list_free (list); return NULL; } //for (i=2; i<39999; i++) { while ((de = readdir (dh))) { i = atoi (de->d_name); if (!i) continue; snprintf (cmdline, sizeof (cmdline), "/proc/%d/status", i); fd = open (cmdline, O_RDONLY); if (fd == -1) continue; if (read (fd, cmdline, sizeof(cmdline)) == -1) { close (fd); continue; } cmdline[sizeof(cmdline) - 1] = '\0'; ptr = strstr (cmdline, "PPid:"); if (ptr) { int ret, ppid = atoi (ptr + 6); close (fd); if (i == pid) { //eprintf ("PPid: %d\n", ppid); r_list_append (list, r_debug_pid_new ( "(ppid)", ppid, 's', 0)); } if (ppid != pid) continue; snprintf (cmdline, sizeof(cmdline) - 1, "/proc/%d/cmdline", ppid); fd = open (cmdline, O_RDONLY); if (fd == -1) continue; ret = read (fd, cmdline, sizeof(cmdline)); if (ret > 0) { cmdline[ret - 1] = '\0'; r_list_append (list, r_debug_pid_new ( cmdline, i, 's', 0)); } } close (fd); } closedir (dh); } else for (i = 2; i < MAXPID; i++) { if (!r_sandbox_kill (i, 0)) { int ret; // TODO: Use slurp! snprintf (cmdline, sizeof(cmdline), "/proc/%d/cmdline", i); fd = open (cmdline, O_RDONLY); if (fd == -1) continue; cmdline[0] = '\0'; ret = read (fd, cmdline, sizeof(cmdline)); if (ret > 0) { cmdline[ret - 1] = '\0'; r_list_append (list, r_debug_pid_new ( cmdline, i, 's', 0)); } close (fd); } } #endif return list; }
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; }
static RList *r_debug_native_pids (int pid) { RList *list = r_list_new (); if (!list) return NULL; #if __WINDOWS__ && !__CYGWIN__ return w32_pids (pid, list); #elif __APPLE__ if (pid) { RDebugPid *p = xnu_get_pid (pid); if (p) r_list_append (list, p); } else { int i; for (i = 1; i < MAXPID; i++) { RDebugPid *p = xnu_get_pid (i); if (p) r_list_append (list, p); } } #elif __linux__ int i; char *ptr, buf[1024]; list->free = (RListFree)&r_debug_pid_free; if (pid) { DIR *dh; struct dirent *de; /* add the requested pid. should we do this? we don't even know if it's valid still.. */ r_list_append (list, r_debug_pid_new ("(current)", pid, 's', 0)); /* list parents */ dh = opendir ("/proc"); if (!dh) { r_sys_perror ("opendir /proc"); r_list_free (list); return NULL; } while ((de = readdir (dh))) { /* for each existing pid file... */ i = atoi (de->d_name); if (i <= 0) { continue; } /* try to read the status */ buf[0] = 0; if (procfs_pid_slurp (i, "status", buf, sizeof (buf)) == -1) { continue; } buf[sizeof (buf) - 1] = 0; /* look for the parent process id */ ptr = strstr (buf, "PPid:"); if (ptr) { int ppid = atoi (ptr + 6); /* if this is the requested process... */ if (i == pid) { //eprintf ("PPid: %d\n", ppid); /* append it to the list with parent */ r_list_append (list, r_debug_pid_new ( "(ppid)", ppid, 's', 0)); } /* ignore it if it is not one of our children */ if (ppid != pid) { continue; } /* it's a child of the requested pid, read it's command line and add it */ if (procfs_pid_slurp (ppid, "cmdline", buf, sizeof(buf)) == -1) { continue; } r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } closedir (dh); } else { /* try to bruteforce the processes * XXX(jjd): wouldn't listing the processes like before work better? */ for (i = 2; i < MAXPID; i++) { /* try to send signal 0, if it fails it must not be valid */ if (r_sandbox_kill (i, 0) == -1) continue; if (procfs_pid_slurp (i, "cmdline", buf, sizeof(buf)) == -1) continue; r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } #else /* rest is BSD */ #ifdef __NetBSD__ # define KVM_OPEN_FLAG KVM_NO_FILES # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getproc2 (kd, opt, arg, sizeof(struct kinfo_proc2), cntptr) # define KP_COMM(x) (x)->p_comm # define KP_PID(x) (x)->p_pid # define KP_PPID(x) (x)->p_ppid # define KINFO_PROC kinfo_proc2 #elif defined(__OpenBSD__) # define KVM_OPEN_FLAG KVM_NO_FILES # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getprocs (kd, opt, arg, sizeof(struct kinfo_proc), cntptr) # define KP_COMM(x) (x)->p_comm # define KP_PID(x) (x)->p_pid # define KP_PPID(x) (x)->p_ppid # define KINFO_PROC kinfo_proc #else # define KVM_OPEN_FLAG O_RDONLY # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getprocs (kd, opt, arg, cntptr) # define KP_COMM(x) (x)->ki_comm # define KP_PID(x) (x)->ki_pid # define KP_PPID(x) (x)->ki_ppid # define KINFO_PROC kinfo_proc #endif char errbuf[_POSIX2_LINE_MAX]; struct KINFO_PROC* kp; int cnt = 0; kvm_t* kd = kvm_openfiles (NULL, NULL, NULL, KVM_OPEN_FLAG, errbuf); if (!kd) { eprintf ("kvm_openfiles says %s\n", errbuf); return NULL; } if (pid) { kp = KVM_GETPROCS (kd, KERN_PROC_PID, pid, &cnt); if (cnt == 1) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp), pid, 's', 0); if (p) r_list_append (list, p); /* we got our process, now fetch the parent process */ kp = KVM_GETPROCS (kd, KERN_PROC_PID, KP_PPID(kp), &cnt); if (cnt == 1) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp), KP_PID(kp), 's', 0); if (p) r_list_append (list, p); } } } else { kp = KVM_GETPROCS (kd, KERN_PROC_UID, geteuid(), &cnt); int i; for (i = 0; i < cnt; i++) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp + i), KP_PID(kp + i), 's', 0); if (p) r_list_append (list, p); } } kvm_close(kd); #endif return list; }
R_API int r_debug_signal_send(RDebug *dbg, int num) { return r_sandbox_kill (dbg->pid, num); }
static RList *r_debug_native_pids (int pid) { RList *list = r_list_new (); if (!list) return NULL; #if __WINDOWS__ && !__CYGWIN__ return w32_pids (pid, list); #elif __APPLE__ if (pid) { RDebugPid *p = xnu_get_pid (pid); if (p) r_list_append (list, p); } else { int i; for (i = 1; i < MAXPID; i++) { RDebugPid *p = xnu_get_pid (i); if (p) r_list_append (list, p); } } #else int i; char *ptr, buf[1024]; list->free = (RListFree)&r_debug_pid_free; if (pid) { DIR *dh; struct dirent *de; /* add the requested pid. should we do this? we don't even know if it's valid still.. */ r_list_append (list, r_debug_pid_new ("(current)", pid, 's', 0)); /* list parents */ dh = opendir ("/proc"); if (dh == NULL) { r_sys_perror ("opendir /proc"); r_list_free (list); return NULL; } while ((de = readdir (dh))) { /* for each existing pid file... */ i = atoi (de->d_name); if (i <= 0) { continue; } /* try to read the status */ buf[0] = 0; if (procfs_pid_slurp (i, "status", buf, sizeof (buf)) == -1) { continue; } buf[sizeof (buf) - 1] = 0; /* look for the parent process id */ ptr = strstr (buf, "PPid:"); if (ptr) { int ppid = atoi (ptr + 6); /* if this is the requested process... */ if (i == pid) { //eprintf ("PPid: %d\n", ppid); /* append it to the list with parent */ r_list_append (list, r_debug_pid_new ( "(ppid)", ppid, 's', 0)); } /* ignore it if it is not one of our children */ if (ppid != pid) { continue; } /* it's a child of the requested pid, read it's command line and add it */ if (procfs_pid_slurp (ppid, "cmdline", buf, sizeof(buf)) == -1) { continue; } r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } closedir (dh); } else { /* try to bruteforce the processes * XXX(jjd): wouldn't listing the processes like before work better? */ for (i = 2; i < MAXPID; i++) { /* try to send signal 0, if it fails it must not be valid */ if (r_sandbox_kill (i, 0) == -1) continue; if (procfs_pid_slurp (i, "cmdline", buf, sizeof(buf)) == -1) continue; r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } #endif return list; }