static int wait_for_break (pid_t pid, struct user_regs_struct *state, int *status) { int ret; if (ptrace (PTRACE_SYSCALL, pid, 0, 0) == -1) return -1; // FAIL if ((ret = wait_for_stopped (pid, true, status))) return ret; if (ptrace (PTRACE_GETREGS, pid, 0, state) == -1) return -1; return 0; }
bool DFInstanceLinux::attach() { TRACE << "STARTING ATTACH" << m_attach_count; if (is_attached()) { m_attach_count++; TRACE << "ALREADY ATTACHED SKIPPING..." << m_attach_count; return true; } if (ptrace(PTRACE_ATTACH, m_pid, 0, 0) == -1) { // unable to attach perror("ptrace attach"); LOGE << "Could not attach to PID" << m_pid; return false; } wait_for_stopped(); m_attach_count++; TRACE << "FINISHED ATTACH" << m_attach_count; return m_attach_count > 0; }
int main (int argc, char *argv[]) { pid_t pid; int status = 1; struct tracer *tracer = NULL; struct process *process = NULL; if (argc < 2) return 1; pid = fork (); if (pid < 0) { perror ("fork"); return 2; } if (pid == 0) fork_and_trace_child (argv); if (wait_for_stopped (pid, false, &status)) { fprintf (stderr, "child process unexpectedly dead\n"); return 3; } /* When delivering syscall traps, set bit 7 in the signal number (i.e., deliver SIGTRAP | 0x80). This makes it easy for the tracer to tell the difference between normal traps and those caused by a syscall. (PTRACE_O_TRACESYSGOOD may not work on all architectures.) */ if (ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == -1) return 5; status = 1; if (!(tracer = tracer_alloc ())) { fprintf (stderr, "Can not allocate tracer\n"); goto end; } if (!(process = process_alloc (pid))) { fprintf (stderr, "Can not allocate process\n"); goto end; } if (tracer_add_process (tracer, process) == -1) { fprintf (stderr, "Cannot add process to tracer\n"); goto end; } /* process = NULL should be here (!) */ for (;;) { struct user_regs_struct state1; struct user_regs_struct state2; if (wait_for_break (pid, &state1, &status)) break; if (wait_for_break (pid, &state2, &status)) break; trace_syscall (process, &state1, &state2); } process = NULL; status &= 0xff; end: if (process) process_destroy (process); if (tracer) tracer_destroy (tracer); return status; }