Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 1 | // RUN: %clangxx -O0 %s -o %t && %run %t |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 2 | |
| 3 | #include <assert.h> |
| 4 | #include <signal.h> |
| 5 | #include <stdio.h> |
| 6 | #include <sys/ptrace.h> |
| 7 | #include <sys/types.h> |
| 8 | #include <sys/user.h> |
| 9 | #include <sys/wait.h> |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 10 | #include <sys/uio.h> |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 11 | #include <unistd.h> |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 12 | #include <elf.h> |
| 13 | #if __mips64 || __arm__ |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 14 | #include <asm/ptrace.h> |
| 15 | #include <sys/procfs.h> |
| 16 | #endif |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 17 | #ifdef __aarch64__ |
| 18 | // GLIBC 2.20+ sys/user does not include asm/ptrace.h |
| 19 | #include <asm/ptrace.h> |
| 20 | #endif |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 21 | |
| 22 | int main(void) { |
| 23 | pid_t pid; |
| 24 | pid = fork(); |
| 25 | if (pid == 0) { // child |
| 26 | ptrace(PTRACE_TRACEME, 0, NULL, NULL); |
| 27 | execl("/bin/true", "true", NULL); |
| 28 | } else { |
| 29 | wait(NULL); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 30 | int res; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 31 | |
| 32 | #if __x86_64__ |
| 33 | user_regs_struct regs; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 34 | res = ptrace(PTRACE_GETREGS, pid, NULL, ®s); |
| 35 | assert(!res); |
| 36 | if (regs.rip) |
| 37 | printf("%zx\n", regs.rip); |
| 38 | |
| 39 | user_fpregs_struct fpregs; |
| 40 | res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs); |
| 41 | assert(!res); |
| 42 | if (fpregs.mxcsr) |
| 43 | printf("%x\n", fpregs.mxcsr); |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 44 | #endif // __x86_64__ |
| 45 | |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 46 | #if (__powerpc64__ || __mips64 || __arm__) |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 47 | struct pt_regs regs; |
| 48 | res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); |
| 49 | assert(!res); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 50 | #if (__powerpc64__) |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 51 | if (regs.nip) |
| 52 | printf("%lx\n", regs.nip); |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 53 | #elif (__mips64) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 54 | if (regs.cp0_epc) |
| 55 | printf("%lx\n", regs.cp0_epc); |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 56 | #elif (__arm__) |
| 57 | if (regs.ARM_pc) |
| 58 | printf("%lx\n", regs.ARM_pc); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 59 | #endif |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 60 | #if (__powerpc64 || __mips64) |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 61 | elf_fpregset_t fpregs; |
| 62 | res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); |
| 63 | assert(!res); |
| 64 | if ((elf_greg_t)fpregs[32]) // fpscr |
| 65 | printf("%lx\n", (elf_greg_t)fpregs[32]); |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 66 | #elif (__arm__) |
| 67 | char regbuf[ARM_VFPREGS_SIZE]; |
| 68 | res = ptrace((enum __ptrace_request)PTRACE_GETVFPREGS, pid, 0, regbuf); |
| 69 | assert(!res); |
| 70 | unsigned fpscr = *(unsigned*)(regbuf + (32 * 8)); |
| 71 | printf ("%x\n", fpscr); |
| 72 | #endif |
| 73 | #endif // (__powerpc64__ || __mips64 || __arm__) |
| 74 | |
| 75 | #if (__aarch64__) |
| 76 | struct iovec regset_io; |
| 77 | |
| 78 | struct user_pt_regs regs; |
| 79 | regset_io.iov_base = ®s; |
| 80 | regset_io.iov_len = sizeof(regs); |
| 81 | res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)®set_io); |
| 82 | assert(!res); |
| 83 | if (regs.pc) |
| 84 | printf("%llx\n", regs.pc); |
| 85 | |
| 86 | struct user_fpsimd_state fpregs; |
| 87 | regset_io.iov_base = &fpregs; |
| 88 | regset_io.iov_len = sizeof(fpregs); |
| 89 | res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, (void*)®set_io); |
| 90 | assert(!res); |
| 91 | if (fpregs.fpsr) |
| 92 | printf("%x\n", fpregs.fpsr); |
| 93 | #endif // (__aarch64__) |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 94 | |
| 95 | siginfo_t siginfo; |
| 96 | res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo); |
| 97 | assert(!res); |
| 98 | assert(siginfo.si_pid == pid); |
| 99 | |
| 100 | ptrace(PTRACE_CONT, pid, NULL, NULL); |
| 101 | |
| 102 | wait(NULL); |
| 103 | } |
| 104 | return 0; |
| 105 | } |