// tracer2.c #include #include #include #include #include #include int main(int argc, char **argv) { pid_t child = fork(); if (child == 0) { ptrace(PTRACE_TRACEME, 0, 0, 0); raise(SIGSTOP); execv(argv[1], &argv[1]); perror("exec"); exit(1); } int status; waitpid(child, &status, 0); // Use TRACEEXEC to catch the exec, then CONT (not SYSCALL) ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEEXEC); ptrace(PTRACE_CONT, child, 0, 0); FILE *log = fopen("/tmp/signal_trace.txt", "w"); int count = 0; while (1) { waitpid(child, &status, 0); if (WIFEXITED(status)) { fprintf(log, "Exited: %d (signals: %d)\n", WEXITSTATUS(status), count); break; } if (WIFSIGNALED(status)) { fprintf(log, "Killed by signal %d\n", WTERMSIG(status)); break; } if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); // Exec event — swallow, continue if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) { fprintf(log, "Exec event\n"); ptrace(PTRACE_CONT, child, 0, 0); continue; } struct user_regs_struct regs; ptrace(PTRACE_GETREGS, child, 0, ®s); fprintf(log, "Signal %2d at RIP=0x%llx RDI=%lld RSI=0x%llx\n", sig, regs.rip, regs.rdi, regs.rsi); fflush(log); count++; // Forward the signal ptrace(PTRACE_CONT, child, 0, sig); } } fclose(log); return 0; }