diff --git a/apps/test-ptrace-syscall.c b/apps/test-ptrace-syscall.c new file mode 100644 index 00000000..36cef3a7 --- /dev/null +++ b/apps/test-ptrace-syscall.c @@ -0,0 +1,69 @@ +#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; +} +