#include #include #include #include #include #include #include #include //#include #include char *prog_name; /* this is entry address in kernel gate page for break syscall * this macro need be changed with kernel */ #define __kernel_syscall_via_break 0xa000000000010620UL /* here is syscall_via_break code in kernel side, break instruction * is the first slot of the bundle * GLOBAL_ENTRY(__kernel_syscall_via_break) * { .mib * break 0x100000 * nop.i 0 * br.ret.sptk.many b6 *} */ static int singlestep_slot1, singlestep_slot2; void print_instruction (int child_pid, int state) { long ip, slot; unsigned long psr; ip = ptrace (PTRACE_PEEKUSER, child_pid, PT_CR_IIP, 0); psr = ptrace(PTRACE_PEEKUSER, child_pid, PT_CR_IPSR, 0); slot = (psr >> 41) & 0x3; if (ip == __kernel_syscall_via_break) { if (slot == 1) singlestep_slot1++; else if (slot == 2) singlestep_slot2++; } } int main (int argc, char **argv, char **envp) { int status, pid, child_pid, state = 1, arg = 1; int ret; singlestep_slot1 = singlestep_slot2 = 0; prog_name = argv[0]; child_pid = fork (); if (child_pid == 0) { ptrace (PTRACE_TRACEME, 0, 0, 0); execve (argv[arg], argv + arg, envp); printf ("%s: execve failed (errno=%d)\n", prog_name, errno); exit(-2); } while (1) { pid = wait4 (-1, &status, 0, 0); if (pid == -1) { if (errno == EINTR) continue; printf ("%s: wait4() failed (errno=%d)\n", prog_name, errno); } if (WIFSIGNALED (status) || WIFEXITED (status) || (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP)) { if (WIFEXITED (status)) { printf ("%s: exit status %d\n", prog_name, WEXITSTATUS (status)); break; } else if (WIFSIGNALED (status)) { printf ("%s: terminated by signal %d\n", prog_name, WTERMSIG (status)); } else { printf ("%s: got signal %d\n", prog_name, WSTOPSIG (status)); } } print_instruction (child_pid, state); ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0); } if (WEXITSTATUS (status) == 0) { if (singlestep_slot1 == 0) printf("single step on syscall failed\n"); else { printf("single step on syscall succeed\n"); printf("single step on break bundle slot 0: %d slot 1: %d \n", singlestep_slot1, singlestep_slot2); } } return 0; }