^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (C) 2004 PathScale, Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Licensed under the GPL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #ifdef __i386__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sys/user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <longjmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sysdep/ptrace_user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/sigcontext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int have_xstate_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int save_i387_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int save_fp_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #ifdef PTRACE_GETREGSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct iovec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (have_xstate_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) iov.iov_base = fp_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) iov.iov_len = FP_SIZE * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return save_i387_registers(pid, fp_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int restore_i387_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int restore_fp_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifdef PTRACE_SETREGSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct iovec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (have_xstate_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) iov.iov_base = fp_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) iov.iov_len = FP_SIZE * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return restore_i387_registers(pid, fp_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #ifdef __i386__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int have_fpx_regs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int save_fpx_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int restore_fpx_registers(int pid, unsigned long *fp_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int get_fp_registers(int pid, unsigned long *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (have_fpx_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return save_fpx_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return save_fp_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int put_fp_registers(int pid, unsigned long *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (have_fpx_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return restore_fpx_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return restore_fp_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) void arch_init_registers(int pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct user_fpxregs_struct fpx_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (errno != EIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) have_fpx_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int get_fp_registers(int pid, unsigned long *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return save_fp_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int put_fp_registers(int pid, unsigned long *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return restore_fp_registers(pid, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void arch_init_registers(int pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #ifdef PTRACE_GETREGSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void * fp_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct iovec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if(fp_regs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) iov.iov_base = fp_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) iov.iov_len = FP_SIZE * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) have_xstate_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) free(fp_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned long get_thread_reg(int reg, jmp_buf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #ifdef __i386__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case HOST_IP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return buf[0]->__eip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case HOST_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return buf[0]->__esp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case HOST_BP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return buf[0]->__ebp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case HOST_IP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return buf[0]->__rip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case HOST_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return buf[0]->__rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case HOST_BP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return buf[0]->__rbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }