174989affSNico Weber // RUN: %clangxx -O0 %s -o %t && %run %t
274989affSNico Weber
374989affSNico Weber // UNSUPPORTED: android
474989affSNico Weber
574989affSNico Weber #include <assert.h>
6d31b2dc2SDmitry Vyukov #include <elf.h>
774989affSNico Weber #include <signal.h>
874989affSNico Weber #include <stdio.h>
9d31b2dc2SDmitry Vyukov #include <string.h>
1074989affSNico Weber #include <sys/ptrace.h>
1174989affSNico Weber #include <sys/types.h>
12d31b2dc2SDmitry Vyukov #include <sys/uio.h>
1374989affSNico Weber #include <sys/user.h>
1474989affSNico Weber #include <sys/wait.h>
1574989affSNico Weber #include <unistd.h>
1674989affSNico Weber #if __mips64 || __arm__
1774989affSNico Weber #include <asm/ptrace.h>
1874989affSNico Weber #include <sys/procfs.h>
1974989affSNico Weber #endif
20*4ae3e13cSYouling Tang #if defined(__aarch64__) || defined(__loongarch__)
2174989affSNico Weber // GLIBC 2.20+ sys/user does not include asm/ptrace.h
2274989affSNico Weber #include <asm/ptrace.h>
2374989affSNico Weber #endif
2474989affSNico Weber
main(void)2574989affSNico Weber int main(void) {
2674989affSNico Weber pid_t pid;
2774989affSNico Weber pid = fork();
2874989affSNico Weber if (pid == 0) { // child
2974989affSNico Weber ptrace(PTRACE_TRACEME, 0, NULL, NULL);
3074989affSNico Weber execl("/bin/true", "true", NULL);
3174989affSNico Weber } else {
3274989affSNico Weber wait(NULL);
3374989affSNico Weber int res;
3474989affSNico Weber
3574989affSNico Weber #if __x86_64__
3674989affSNico Weber user_regs_struct regs;
3774989affSNico Weber res = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
3874989affSNico Weber assert(!res);
3974989affSNico Weber if (regs.rip)
4074989affSNico Weber printf("%zx\n", regs.rip);
4174989affSNico Weber
4274989affSNico Weber user_fpregs_struct fpregs;
4374989affSNico Weber res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs);
4474989affSNico Weber assert(!res);
4574989affSNico Weber if (fpregs.mxcsr)
4674989affSNico Weber printf("%x\n", fpregs.mxcsr);
4774989affSNico Weber #endif // __x86_64__
4874989affSNico Weber
4974989affSNico Weber #if (__powerpc64__ || __mips64 || __arm__)
50d31b2dc2SDmitry Vyukov // Check that nothing writes out-of-bounds.
51d31b2dc2SDmitry Vyukov struct pt_regs regs_buf[4];
52d31b2dc2SDmitry Vyukov memset(®s_buf, 0xcd, sizeof(regs_buf));
53d31b2dc2SDmitry Vyukov struct pt_regs ®s = regs_buf[1];
5474989affSNico Weber res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s);
5574989affSNico Weber assert(!res);
56d31b2dc2SDmitry Vyukov assert(memcmp(®s_buf[0], ®s_buf[3], sizeof(regs_buf[3])) == 0);
57d31b2dc2SDmitry Vyukov assert(memcmp(®s_buf[2], ®s_buf[3], sizeof(regs_buf[3])) == 0);
5874989affSNico Weber #if (__powerpc64__)
5974989affSNico Weber if (regs.nip)
6074989affSNico Weber printf("%lx\n", regs.nip);
6174989affSNico Weber #elif (__mips64)
6274989affSNico Weber if (regs.cp0_epc)
6374989affSNico Weber printf("%lx\n", regs.cp0_epc);
6474989affSNico Weber #elif (__arm__)
6574989affSNico Weber if (regs.ARM_pc)
6674989affSNico Weber printf("%lx\n", regs.ARM_pc);
6774989affSNico Weber #endif
6874989affSNico Weber #if (__powerpc64 || __mips64)
6974989affSNico Weber elf_fpregset_t fpregs;
7074989affSNico Weber res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs);
7174989affSNico Weber assert(!res);
7274989affSNico Weber if ((elf_greg_t)fpregs[32]) // fpscr
7374989affSNico Weber printf("%lx\n", (elf_greg_t)fpregs[32]);
7474989affSNico Weber #elif (__arm__)
7574989affSNico Weber char regbuf[ARM_VFPREGS_SIZE];
7674989affSNico Weber res = ptrace((enum __ptrace_request)PTRACE_GETVFPREGS, pid, 0, regbuf);
7774989affSNico Weber assert(!res);
7874989affSNico Weber unsigned fpscr = *(unsigned*)(regbuf + (32 * 8));
7974989affSNico Weber printf ("%x\n", fpscr);
8074989affSNico Weber #endif
8174989affSNico Weber #endif // (__powerpc64__ || __mips64 || __arm__)
8274989affSNico Weber
8374989affSNico Weber #if (__aarch64__)
8474989affSNico Weber struct iovec regset_io;
8574989affSNico Weber
8674989affSNico Weber struct user_pt_regs regs;
8774989affSNico Weber regset_io.iov_base = ®s;
8874989affSNico Weber regset_io.iov_len = sizeof(regs);
8974989affSNico Weber res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)®set_io);
9074989affSNico Weber assert(!res);
9174989affSNico Weber if (regs.pc)
9274989affSNico Weber printf("%llx\n", regs.pc);
9374989affSNico Weber
9474989affSNico Weber struct user_fpsimd_state fpregs;
9574989affSNico Weber regset_io.iov_base = &fpregs;
9674989affSNico Weber regset_io.iov_len = sizeof(fpregs);
9774989affSNico Weber res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, (void*)®set_io);
9874989affSNico Weber assert(!res);
9974989affSNico Weber if (fpregs.fpsr)
10074989affSNico Weber printf("%x\n", fpregs.fpsr);
10174989affSNico Weber #endif // (__aarch64__)
10274989affSNico Weber
103*4ae3e13cSYouling Tang #if (__loongarch__)
104*4ae3e13cSYouling Tang struct iovec regset_io;
105*4ae3e13cSYouling Tang
106*4ae3e13cSYouling Tang struct user_pt_regs regs;
107*4ae3e13cSYouling Tang regset_io.iov_base = ®s;
108*4ae3e13cSYouling Tang regset_io.iov_len = sizeof(regs);
109*4ae3e13cSYouling Tang res =
110*4ae3e13cSYouling Tang ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, (void *)®set_io);
111*4ae3e13cSYouling Tang assert(!res);
112*4ae3e13cSYouling Tang if (regs.csr_era)
113*4ae3e13cSYouling Tang printf("%lx\n", regs.csr_era);
114*4ae3e13cSYouling Tang
115*4ae3e13cSYouling Tang struct user_fp_state fpregs;
116*4ae3e13cSYouling Tang regset_io.iov_base = &fpregs;
117*4ae3e13cSYouling Tang regset_io.iov_len = sizeof(fpregs);
118*4ae3e13cSYouling Tang res =
119*4ae3e13cSYouling Tang ptrace(PTRACE_GETREGSET, pid, (void *)NT_FPREGSET, (void *)®set_io);
120*4ae3e13cSYouling Tang assert(!res);
121*4ae3e13cSYouling Tang if (fpregs.fcsr)
122*4ae3e13cSYouling Tang printf("%x\n", fpregs.fcsr);
123*4ae3e13cSYouling Tang #endif // (__loongarch__)
124*4ae3e13cSYouling Tang
12574989affSNico Weber #if (__s390__)
12674989affSNico Weber struct iovec regset_io;
12774989affSNico Weber
12874989affSNico Weber struct _user_regs_struct regs;
12974989affSNico Weber regset_io.iov_base = ®s;
13074989affSNico Weber regset_io.iov_len = sizeof(regs);
13174989affSNico Weber res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)®set_io);
13274989affSNico Weber assert(!res);
13374989affSNico Weber if (regs.psw.addr)
13474989affSNico Weber printf("%lx\n", regs.psw.addr);
13574989affSNico Weber
13674989affSNico Weber struct _user_fpregs_struct fpregs;
13774989affSNico Weber regset_io.iov_base = &fpregs;
13874989affSNico Weber regset_io.iov_len = sizeof(fpregs);
13974989affSNico Weber res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, (void*)®set_io);
14074989affSNico Weber assert(!res);
14174989affSNico Weber if (fpregs.fpc)
14274989affSNico Weber printf("%x\n", fpregs.fpc);
14374989affSNico Weber #endif // (__s390__)
14474989affSNico Weber
14574989affSNico Weber siginfo_t siginfo;
14674989affSNico Weber res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo);
14774989affSNico Weber assert(!res);
14874989affSNico Weber assert(siginfo.si_pid == pid);
14974989affSNico Weber
15074989affSNico Weber ptrace(PTRACE_CONT, pid, NULL, NULL);
15174989affSNico Weber
15274989affSNico Weber wait(NULL);
15374989affSNico Weber }
15474989affSNico Weber return 0;
15574989affSNico Weber }
156