| // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 |
| // XFAIL: android |
| // XFAIL: mips |
| // |
| // RUN: %clangxx_asan -O0 %s -o %t && %run %t |
| // RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <sys/ptrace.h> |
| #include <sys/types.h> |
| #include <sys/user.h> |
| #include <sys/wait.h> |
| #include <unistd.h> |
| #include <sys/uio.h> // for iovec |
| #include <elf.h> // for NT_PRSTATUS |
| #ifdef __aarch64__ |
| # include <asm/ptrace.h> |
| #endif |
| |
| #if defined(__i386__) || defined(__x86_64__) |
| typedef user_regs_struct regs_struct; |
| typedef user_fpregs_struct fpregs_struct; |
| #if defined(__i386__) |
| #define REG_IP eip |
| #else |
| #define REG_IP rip |
| #endif |
| #define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.REG_IP)) |
| #define PRINT_REG_FP(__fpregs) printf ("%lx\n", (unsigned long) (__fpregs.cwd)) |
| #define __PTRACE_FPREQUEST PTRACE_GETFPREGS |
| |
| #elif defined(__aarch64__) |
| typedef struct user_pt_regs regs_struct; |
| typedef struct user_fpsimd_state fpregs_struct; |
| #define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.pc)) |
| #define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs.fpsr)) |
| #define ARCH_IOVEC_FOR_GETREGSET |
| |
| #elif defined(__powerpc64__) |
| typedef struct pt_regs regs_struct; |
| typedef elf_fpregset_t fpregs_struct; |
| #define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.nip)) |
| #define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t)fpregs[32]) |
| #define ARCH_IOVEC_FOR_GETREGSET |
| |
| #elif defined(__mips__) |
| typedef struct pt_regs regs_struct; |
| typedef elf_fpregset_t fpregs_struct; |
| #define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.cp0_epc)) |
| #define PRINT_REG_FP(__fpregs) printf ("%lx\n", (elf_greg_t) (__fpregs[32])) |
| #define __PTRACE_FPREQUEST PTRACE_GETFPREGS |
| |
| #elif defined(__arm__) |
| # include <asm/ptrace.h> |
| # include <sys/procfs.h> |
| typedef struct pt_regs regs_struct; |
| typedef char fpregs_struct[ARM_VFPREGS_SIZE]; |
| #define PRINT_REG_PC(__regs) printf ("%x\n", (unsigned) (__regs.ARM_pc)) |
| #define PRINT_REG_FP(__fpregs) printf ("%x\n", (unsigned) (__fpregs + 32 * 8)) |
| #define __PTRACE_FPREQUEST PTRACE_GETVFPREGS |
| |
| #elif defined(__s390__) |
| typedef _user_regs_struct regs_struct; |
| typedef _user_fpregs_struct fpregs_struct; |
| #define PRINT_REG_PC(__regs) printf ("%lx\n", (unsigned long) (__regs.psw.addr)) |
| #define PRINT_REG_FP(__fpregs) printf ("%lx\n", (unsigned long) (__fpregs.fpc)) |
| #define ARCH_IOVEC_FOR_GETREGSET |
| #endif |
| |
| |
| int main(void) { |
| pid_t pid; |
| pid = fork(); |
| if (pid == 0) { // child |
| ptrace(PTRACE_TRACEME, 0, NULL, NULL); |
| execl("/bin/true", "true", NULL); |
| } else { |
| wait(NULL); |
| regs_struct regs; |
| regs_struct* volatile pregs = ®s; |
| #ifdef ARCH_IOVEC_FOR_GETREGSET |
| struct iovec regset_io; |
| #endif |
| int res; |
| |
| #ifdef POSITIVE |
| ++pregs; |
| #endif |
| |
| #ifdef ARCH_IOVEC_FOR_GETREGSET |
| # define __PTRACE_REQUEST PTRACE_GETREGSET |
| # define __PTRACE_ARGS (void*)NT_PRSTATUS, (void*)®set_io |
| regset_io.iov_base = pregs; |
| regset_io.iov_len = sizeof(regs_struct); |
| #else |
| # define __PTRACE_REQUEST PTRACE_GETREGS |
| # define __PTRACE_ARGS NULL, pregs |
| #endif |
| res = ptrace((enum __ptrace_request)__PTRACE_REQUEST, pid, __PTRACE_ARGS); |
| // CHECK: AddressSanitizer: stack-buffer-overflow |
| // CHECK: {{.*ptrace.cc:}}[[@LINE-2]] |
| assert(!res); |
| PRINT_REG_PC(regs); |
| |
| fpregs_struct fpregs; |
| #ifdef ARCH_IOVEC_FOR_GETREGSET |
| # define __PTRACE_FPREQUEST PTRACE_GETREGSET |
| # define __PTRACE_FPARGS (void*)NT_PRSTATUS, (void*)®set_io |
| regset_io.iov_base = &fpregs; |
| regset_io.iov_len = sizeof(fpregs_struct); |
| res = ptrace((enum __ptrace_request)PTRACE_GETREGSET, pid, (void*)NT_FPREGSET, |
| (void*)®set_io); |
| #else |
| # define __PTRACE_FPARGS NULL, &fpregs |
| #endif |
| res = ptrace((enum __ptrace_request)__PTRACE_FPREQUEST, pid, __PTRACE_FPARGS); |
| assert(!res); |
| PRINT_REG_FP(fpregs); |
| |
| #ifdef __i386__ |
| user_fpxregs_struct fpxregs; |
| res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs); |
| assert(!res); |
| printf("%lx\n", (unsigned long)fpxregs.mxcsr); |
| #endif |
| |
| ptrace(PTRACE_CONT, pid, NULL, NULL); |
| wait(NULL); |
| } |
| return 0; |
| } |