#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char * argv[]) { pid_t p = fork(); if (!p) { if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) { fprintf(stderr, "%s: ptrace: %s\n", argv[0], strerror(errno)); return 1; } execvp(argv[optind], &argv[optind]); return 1; } while (1) { int status = 0; pid_t res = waitpid(p, &status, WSTOPPED); if (res < 0) { fprintf(stderr, "%s: waitpid: %s\n", argv[0], strerror(errno)); } else { if (WIFSTOPPED(status)) { if (WSTOPSIG(status) == SIGTRAP) { struct URegs regs; ptrace(PTRACE_GETREGS, p, NULL, ®s); /* Event type */ int event = (status >> 16) & 0xFF; switch (event) { case PTRACE_EVENT_SYSCALL_ENTER: if (uregs_syscall_num(®s) == SYS_SLEEP) { fprintf(stderr, "%s: sleep called, rewriting to yield\n", argv[0]); uregs_syscall_num(®s) = SYS_YIELD; ptrace(PTRACE_SETREGS, p, NULL, ®s); } break; default: break; } ptrace(PTRACE_CONT, p, NULL, NULL); } else { ptrace(PTRACE_CONT, p, NULL, (void*)(uintptr_t)WSTOPSIG(status)); } } else if (WIFSIGNALED(status)) { return 0; } else if (WIFEXITED(status)) { return 0; } } } return 0; }