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); }
int main(int argc, char *argv[]) { if (argc != 3) { return 1; } int pid = atoi(argv[1]); unsigned long addr = strtol(argv[2], NULL, 16); struct proc *p = attach(pid); printf("attach %d\n", p->pid); proc_mprotect(p, (void *)(addr & -0x1000), PROT_READ); printf("begin...\n"); assert(p->stat<UNTRACED && p->stat>RUNNING); proc_cont(p, 0); while (1) { proc_wait(p); //printf("stat %d\n", p->stat); if (p->stat == SIGNAL_DELIVER_STOP) { if (WSTOPSIG(p->status) == SIGSEGV) { siginfo_t siginfo; ptrace(PTRACE_GETSIGINFO, p->pid, NULL, &siginfo); printf("memory address %p\n", siginfo.si_addr); if (siginfo.si_addr == (void *)addr) { proc_mprotect(p, (void *)(addr & -0x1000), PROT_READ|PROT_WRITE); ptrace(PTRACE_SINGLESTEP, p->pid, NULL, NULL); proc_wait(p); //fprintf(stderr, "%d %x\n", p->stat, p->status); proc_write(p, (void *)addr, (char *)&locked, 4); proc_mprotect(p, (void *)(addr & -0x1000), PROT_READ); } else { if (siginfo.si_addr >= (void *)(addr & ~0xfff) && siginfo.si_addr < (void *)((addr + 0xfff) & ~0xfff)) { proc_mprotect(p, (void *)(addr & -0x1000), PROT_READ|PROT_WRITE); ptrace(PTRACE_SINGLESTEP, p->pid, NULL, NULL); proc_wait(p); proc_mprotect(p, (void *)(addr & -0x1000), PROT_READ); } } } } proc_cont(p, 0); } //proc_exit(p, 42); proc_detach(p); }
int proc_bkptdel(struct proc_handle *phdl, uintptr_t address, unsigned long saved) { struct ptrace_io_desc piod; unsigned long paddr, caddr; int ret = 0; if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD || phdl->status == PS_IDLE) { errno = ENOENT; return (-1); } DPRINTFX("removing breakpoint at 0x%lx", address); if (phdl->status != PS_STOP) if (proc_stop(phdl) != 0) return (-1); /* * Overwrite the breakpoint instruction that we setup previously. */ caddr = address; paddr = saved; 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; } if (phdl->status != PS_STOP) /* Restart the process if we had to stop it. */ proc_cont(phdl); return (ret); }
static void handle_command(void) { int ret; mt_msg cmd; void *payload = NULL; ret = safe_read(server_fd, &cmd, sizeof(cmd)); if (ret != sizeof(cmd)) { if (ret > 0) error("cmd read wrong size %d\n", ret); close(server_fd); server_fd = -1; return; } if (cmd.payload_len) { payload = malloc(cmd.payload_len); if (safe_read(server_fd, payload, cmd.payload_len) != cmd.payload_len) { fprintf(stderr, "can't read payload_len (%u)\n", cmd.payload_len); goto finish; } } switch(cmd.operation) { case MT_SCAN: { unsigned long data_len; void * data = mem_scan(&cmd, payload, &data_len); ret = TEMP_FAILURE_RETRY(sem_wait(&shm->sem)); if (!ret) { MT_SEND_MSG(MT_SCAN, cmd.pid, 0, data_len, data, 0, NULL); sem_post(&shm->sem); } break; } case MT_XMAP: { void *xmap_base = NULL; unsigned int xmap_size = 0; xmap_base = get_executable_mappings(cmd.pid, &xmap_size); ret = TEMP_FAILURE_RETRY(sem_wait(&shm->sem)); if (!ret) { MT_SEND_MSG(MT_XMAP, cmd.pid, cmd.tid, xmap_size, xmap_base, 0, NULL); sem_post(&shm->sem); } free(xmap_base); break; } case MT_START: shm->info.do_trace = 1; break; case MT_STOP: shm->info.do_trace = 0; break; case MT_CONT: proc_cont(cmd.pid); break; case MT_INFO: ret = TEMP_FAILURE_RETRY(sem_wait(&shm->sem)); if (!ret) { MT_SEND_MSG(MT_INFO, cmd.pid, cmd.tid, sizeof(shm->info), &shm->info, 0, NULL); sem_post(&shm->sem); } break; default: break; } finish: if (payload) free(payload); }