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