int proc_bkptset(struct proc_handle *phdl, uintptr_t address, unsigned long *saved) { struct ptrace_io_desc piod; unsigned long paddr, caddr; int ret = 0; *saved = 0; if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD || phdl->status == PS_IDLE) { errno = ENOENT; return (-1); } DPRINTFX("adding breakpoint at 0x%lx", address); if (phdl->status != PS_STOP) if (proc_stop(phdl) != 0) return (-1); /* * Read the original instruction. */ caddr = address; paddr = 0; piod.piod_op = PIOD_READ_I; piod.piod_offs = (void *)caddr; piod.piod_addr = &paddr; piod.piod_len = BREAKPOINT_INSTR_SZ; if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) { DPRINTF("ERROR: couldn't read instruction at address 0x%" PRIuPTR, address); ret = -1; goto done; } *saved = paddr; /* * Write a breakpoint instruction to that address. */ caddr = address; paddr = BREAKPOINT_INSTR; piod.piod_op = PIOD_WRITE_I; piod.piod_offs = (void *)caddr; piod.piod_addr = &paddr; piod.piod_len = BREAKPOINT_INSTR_SZ; if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) { DPRINTF("ERROR: couldn't write instruction at address 0x%" PRIuPTR, address); ret = -1; goto done; } done: if (phdl->status != PS_STOP) /* Restart the process if we had to stop it. */ proc_cont(phdl); return (ret); }
void process_stoptrace(void) { struct lwp *l = curlwp; struct proc *p = l->l_proc, *pp; mutex_enter(proc_lock); mutex_enter(p->p_lock); pp = p->p_pptr; if (pp->p_pid == 1) { CLR(p->p_slflag, PSL_SYSCALL); /* XXXSMP */ mutex_exit(p->p_lock); mutex_exit(proc_lock); return; } p->p_xstat = SIGTRAP; proc_stop(p, 1, SIGSTOP); mutex_exit(proc_lock); /* * Call issignal() once only, to have it take care of the * pending stop. Signal processing will take place as usual * from userret(). */ KERNEL_UNLOCK_ALL(l, &l->l_biglocks); (void)issignal(l); mutex_exit(p->p_lock); KERNEL_LOCK(l->l_biglocks, l); }
u32 procwrap_stop(union trapped_args *args, void *pr_ctxt) { u32 ret; ret = proc_stop(((struct process_context *)pr_ctxt)->processor); return ret; }
/* ** atexit. */ static void quit_ftrace(int i) { tracer_quit = i = 1; if (!tracee.proc) exit(0); else if (tracee.status == RUN) { if (proc_stop(tracee.proc) == -1) errexit("ftrace: proc_stop, %s", ftrace_strerror(errno)); } }
int proc_bkptdel(struct proc_handle *phdl, uintptr_t address, unsigned long saved) { struct ptrace_io_desc piod; uintptr_t caddr; int ret = 0, stopped; instr_t instr; if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD || phdl->status == PS_IDLE) { errno = ENOENT; return (-1); } DPRINTFX("removing breakpoint at 0x%lx", address); stopped = 0; if (phdl->status != PS_STOP) { if (proc_stop(phdl) != 0) return (-1); stopped = 1; } /* * Overwrite the breakpoint instruction that we setup previously. */ caddr = address; instr = saved; piod.piod_op = PIOD_WRITE_I; piod.piod_offs = (void *)caddr; piod.piod_addr = &instr; piod.piod_len = BREAKPOINT_INSTR_SZ; if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) { DPRINTF("ERROR: couldn't write instruction at address 0x%" PRIuPTR, address); ret = -1; } if (stopped) /* Restart the process if we had to stop it. */ proc_continue(phdl); return (ret); }
static int tool_procedural_iter(goxel_t *goxel, const inputs_t *inputs, int state, const vec2_t *view_size, bool inside) { int snaped = 0; vec3_t pos, normal; box_t box; gox_proc_t *proc = &goxel->proc; const bool down = inputs->mouse_down[0]; if (proc->state == PROC_PARSE_ERROR) return 0; // XXX: duplicate code with tool_brush_iter. if (inside) snaped = goxel_unproject( goxel, view_size, &inputs->mouse_pos, goxel->painter.op == OP_ADD && !goxel->snap_offset, &pos, &normal); if (snaped) { if (goxel->tool == TOOL_BRUSH && goxel->snap_offset) vec3_iaddk(&pos, normal, goxel->snap_offset * goxel->tool_radius); pos.x = round(pos.x - 0.5) + 0.5; pos.y = round(pos.y - 0.5) + 0.5; pos.z = round(pos.z - 0.5) + 0.5; box = bbox_from_extents(pos, 0.5, 0.5, 0.5); render_box(&goxel->rend, &box, false, NULL, false); } if (state == STATE_IDLE) { if (snaped) state = STATE_SNAPED; } if (state == STATE_SNAPED) { if (!snaped) return STATE_IDLE; if (down) { image_history_push(goxel->image); proc_stop(proc); proc_start(proc, &box); state = STATE_PAINT; } } if (state == STATE_PAINT) { if (!down) state = STATE_IDLE; } return state; }
static void *get_executable_mappings(pid_t pid, unsigned int *size) { unsigned long long start; unsigned long long end; unsigned long long offset; char permr; char permw; char permx; char filename[PATH_MAX + 2]; char nl; FILE *in; struct xmap *xmap = NULL; void *xmap_base = NULL; unsigned int xmap_size = 0; proc_stop(pid); *size = 0; snprintf(filename, sizeof(filename)-1, "/proc/%d/maps", pid); in = fopen(filename, "r"); if (!in) return NULL; while(fscanf(in, "%llx-%llx %c%c%c%*c %llx %*x:%*x %*u%*64[ ]%c", &start, &end, &permr, &permw, &permx, &offset, filename) == 7) { size_t flen; size_t xmap_off; if (*filename != '\n') { if (fscanf(in, "%" STR(PATH_MAX) "[^\n]%c", filename + 1, &nl) != 2) break; if (nl != '\n') break; } else *filename = 0; if (*filename != '[' && *filename != 0) { struct stat statbuf; if (stat(filename, &statbuf) < 0) continue; if (S_ISCHR(statbuf.st_mode)) continue; flen = strlen(filename); } else flen = 0; if (permx != 'x' || permr != 'r' || permw == 'w') continue; xmap_off = (void *)xmap - xmap_base; if (xmap_off + XMAP_ALIGN(flen + 1) > xmap_size) { xmap_size += 4096 + XMAP_ALIGN(flen + 1); xmap_base = realloc(xmap_base, xmap_size); xmap = (struct xmap *)(xmap_base + xmap_off); } xmap->start = start; xmap->end = end; xmap->offset = offset; xmap->flen = flen; strncpy(xmap->fname, filename, flen); xmap->fname[flen] = 0; #if 0 fprintf(stderr, "start: %llx end: %llx offset: %llx flen: %u fname: %s\n", xmap->start, xmap->end, xmap->offset, xmap->flen, xmap->fname); #endif xmap = XMAP_NEXT(xmap, flen + 1); } fclose(in); *size = (void *)xmap - xmap_base; return xmap_base; }
static int procfs_control(struct proc *curp, struct lwp *lp, int op) { struct proc *p = lp->lwp_proc; int error; ASSERT_LWKT_TOKEN_HELD(&p->p_token); ASSERT_LWKT_TOKEN_HELD(&proc_token); /* Can't trace a process that's currently exec'ing. */ if ((p->p_flags & P_INEXEC) != 0) return EAGAIN; /* * Authorization check: rely on normal debugging protection, except * allow processes to disengage debugging on a process onto which * they have previously attached, but no longer have permission to * debug. */ if (op != PROCFS_CTL_DETACH) { if (securelevel > 0 && p->p_pid == 1) return (EPERM); if (!CHECKIO(curp, p) || p_trespass(curp->p_ucred, p->p_ucred)) return (EPERM); } /* * Attach - attaches the target process for debugging * by the calling process. */ if (op == PROCFS_CTL_ATTACH) { /* check whether already being traced */ if (p->p_flags & P_TRACED) return (EBUSY); /* can't trace yourself! */ if (p->p_pid == curp->p_pid) return (EINVAL); /* * Go ahead and set the trace flag. * Save the old parent (it's reset in * _DETACH, and also in kern_exit.c:wait4() * Reparent the process so that the tracing * proc gets to see all the action. * Stop the target. */ p->p_flags |= P_TRACED; faultin(p); p->p_xstat = 0; /* XXX ? */ if (p->p_pptr != curp) { p->p_oppid = p->p_pptr->p_pid; proc_reparent(p, curp); } proc_stop(p); return (0); } /* * Target process must be stopped, owned by (curp) and * be set up for tracing (P_TRACED flag set). * Allow DETACH to take place at any time for sanity. * Allow WAIT any time, of course. */ switch (op) { case PROCFS_CTL_DETACH: case PROCFS_CTL_WAIT: break; default: if (!TRACE_WAIT_P(curp, p)) return (EBUSY); } #ifdef FIX_SSTEP /* * do single-step fixup if needed */ FIX_SSTEP(lp); #endif /* * Don't deliver any signal by default. * To continue with a signal, just send * the signal name to the ctl file */ p->p_xstat = 0; switch (op) { /* * Detach. Cleans up the target process, reparent it if possible * and set it running once more. */ case PROCFS_CTL_DETACH: /* if not being traced, then this is a painless no-op */ if ((p->p_flags & P_TRACED) == 0) return (0); /* not being traced any more */ p->p_flags &= ~P_TRACED; /* remove pending SIGTRAP, else the process will die */ spin_lock(&lp->lwp_spin); lwp_delsig(lp, SIGTRAP); spin_unlock(&lp->lwp_spin); /* give process back to original parent */ if (p->p_oppid != p->p_pptr->p_pid) { struct proc *pp; pp = pfs_pfind(p->p_oppid); if (pp) { proc_reparent(p, pp); pfs_pdone(pp); } } p->p_oppid = 0; p->p_flags &= ~P_WAITED; /* XXX ? */ wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */ break; /* * Step. Let the target process execute a single instruction. */ case PROCFS_CTL_STEP: LWPHOLD(lp); error = procfs_sstep(lp); LWPRELE(lp); if (error) return (error); break; /* * Run. Let the target process continue running until a breakpoint * or some other trap. */ case PROCFS_CTL_RUN: break; /* * Wait for the target process to stop. * If the target is not being traced then just wait * to enter */ case PROCFS_CTL_WAIT: error = 0; if (p->p_flags & P_TRACED) { while (error == 0 && p->p_stat != SSTOP && (p->p_flags & P_TRACED) && (p->p_pptr == curp)) { error = tsleep((caddr_t) p, PCATCH, "procfsx", 0); } if (error == 0 && !TRACE_WAIT_P(curp, p)) error = EBUSY; } else { while (error == 0 && p->p_stat != SSTOP) { error = tsleep((caddr_t) p, PCATCH, "procfs", 0); } } return (error); default: panic("procfs_control"); } /* * If the process is in a stopped state, make it runnable again. * Do not set LWP_MP_BREAKTSLEEP - that is, do not break a tsleep * that might be in progress. */ if (p->p_stat == SSTOP) proc_unstop(p); return (0); }