1 // RUN: %clangxx -O0 %s -o %t && %run %t 2 3 // UNSUPPORTED: android 4 5 #include <assert.h> 6 #include <elf.h> 7 #include <signal.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <sys/ptrace.h> 11 #include <sys/types.h> 12 #include <sys/uio.h> 13 #include <sys/user.h> 14 #include <sys/wait.h> 15 #include <unistd.h> 16 #if __mips64 || __arm__ 17 #include <asm/ptrace.h> 18 #include <sys/procfs.h> 19 #endif 20 #ifdef __aarch64__ 21 // GLIBC 2.20+ sys/user does not include asm/ptrace.h 22 #include <asm/ptrace.h> 23 #endif 24 25 int main(void) { 26 pid_t pid; 27 pid = fork(); 28 if (pid == 0) { // child 29 ptrace(PTRACE_TRACEME, 0, NULL, NULL); 30 execl("/bin/true", "true", NULL); 31 } else { 32 wait(NULL); 33 int res; 34 35 #if __x86_64__ 36 user_regs_struct regs; 37 res = ptrace(PTRACE_GETREGS, pid, NULL, ®s); 38 assert(!res); 39 if (regs.rip) 40 printf("%zx\n", regs.rip); 41 42 user_fpregs_struct fpregs; 43 res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs); 44 assert(!res); 45 if (fpregs.mxcsr) 46 printf("%x\n", fpregs.mxcsr); 47 #endif // __x86_64__ 48 49 #if (__powerpc64__ || __mips64 || __arm__) 50 // Check that nothing writes out-of-bounds. 51 struct pt_regs regs_buf[4]; 52 memset(®s_buf, 0xcd, sizeof(regs_buf)); 53 struct pt_regs ®s = regs_buf[1]; 54 res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); 55 assert(!res); 56 assert(memcmp(®s_buf[0], ®s_buf[3], sizeof(regs_buf[3])) == 0); 57 assert(memcmp(®s_buf[2], ®s_buf[3], sizeof(regs_buf[3])) == 0); 58 #if (__powerpc64__) 59 if (regs.nip) 60 printf("%lx\n", regs.nip); 61 #elif (__mips64) 62 if (regs.cp0_epc) 63 printf("%lx\n", regs.cp0_epc); 64 #elif (__arm__) 65 if (regs.ARM_pc) 66 printf("%lx\n", regs.ARM_pc); 67 #endif 68 #if (__powerpc64 || __mips64) 69 elf_fpregset_t fpregs; 70 res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); 71 assert(!res); 72 if ((elf_greg_t)fpregs[32]) // fpscr 73 printf("%lx\n", (elf_greg_t)fpregs[32]); 74 #elif (__arm__) 75 char regbuf[ARM_VFPREGS_SIZE]; 76 res = ptrace((enum __ptrace_request)PTRACE_GETVFPREGS, pid, 0, regbuf); 77 assert(!res); 78 unsigned fpscr = *(unsigned*)(regbuf + (32 * 8)); 79 printf ("%x\n", fpscr); 80 #endif 81 #endif // (__powerpc64__ || __mips64 || __arm__) 82 83 #if (__aarch64__) 84 struct iovec regset_io; 85 86 struct user_pt_regs regs; 87 regset_io.iov_base = ®s; 88 regset_io.iov_len = sizeof(regs); 89 res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)®set_io); 90 assert(!res); 91 if (regs.pc) 92 printf("%llx\n", regs.pc); 93 94 struct user_fpsimd_state fpregs; 95 regset_io.iov_base = &fpregs; 96 regset_io.iov_len = sizeof(fpregs); 97 res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, (void*)®set_io); 98 assert(!res); 99 if (fpregs.fpsr) 100 printf("%x\n", fpregs.fpsr); 101 #endif // (__aarch64__) 102 103 #if (__s390__) 104 struct iovec regset_io; 105 106 struct _user_regs_struct regs; 107 regset_io.iov_base = ®s; 108 regset_io.iov_len = sizeof(regs); 109 res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)®set_io); 110 assert(!res); 111 if (regs.psw.addr) 112 printf("%lx\n", regs.psw.addr); 113 114 struct _user_fpregs_struct fpregs; 115 regset_io.iov_base = &fpregs; 116 regset_io.iov_len = sizeof(fpregs); 117 res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, (void*)®set_io); 118 assert(!res); 119 if (fpregs.fpc) 120 printf("%x\n", fpregs.fpc); 121 #endif // (__s390__) 122 123 siginfo_t siginfo; 124 res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo); 125 assert(!res); 126 assert(siginfo.si_pid == pid); 127 128 ptrace(PTRACE_CONT, pid, NULL, NULL); 129 130 wait(NULL); 131 } 132 return 0; 133 } 134