xref: /llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/ptrace.cpp (revision 4ae3e13c7dbd3a04f4e6ff9e3143ba1ecd467f4d)
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, &regs);
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(&regs_buf, 0xcd, sizeof(regs_buf));
53d31b2dc2SDmitry Vyukov     struct pt_regs &regs = regs_buf[1];
5474989affSNico Weber     res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, &regs);
5574989affSNico Weber     assert(!res);
56d31b2dc2SDmitry Vyukov     assert(memcmp(&regs_buf[0], &regs_buf[3], sizeof(regs_buf[3])) == 0);
57d31b2dc2SDmitry Vyukov     assert(memcmp(&regs_buf[2], &regs_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 = &regs;
8874989affSNico Weber     regset_io.iov_len = sizeof(regs);
8974989affSNico Weber     res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)&regset_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*)&regset_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 = &regs;
108*4ae3e13cSYouling Tang     regset_io.iov_len = sizeof(regs);
109*4ae3e13cSYouling Tang     res =
110*4ae3e13cSYouling Tang         ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, (void *)&regset_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 *)&regset_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 = &regs;
13074989affSNico Weber     regset_io.iov_len = sizeof(regs);
13174989affSNico Weber     res = ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, (void*)&regset_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*)&regset_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