1 /* 2 * Copyright (C) 2004 PathScale, Inc 3 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 * Licensed under the GPL 5 */ 6 7 #include <errno.h> 8 #include <stdlib.h> 9 #include <sys/ptrace.h> 10 #ifdef __i386__ 11 #include <sys/user.h> 12 #endif 13 #include <longjmp.h> 14 #include <sysdep/ptrace_user.h> 15 #include <sys/uio.h> 16 #include <asm/sigcontext.h> 17 #include <linux/elf.h> 18 #include <registers.h> 19 #include <sys/mman.h> 20 21 static unsigned long ptrace_regset; 22 unsigned long host_fp_size; 23 24 int get_fp_registers(int pid, unsigned long *regs) 25 { 26 struct iovec iov = { 27 .iov_base = regs, 28 .iov_len = host_fp_size, 29 }; 30 31 if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0) 32 return -errno; 33 return 0; 34 } 35 36 int put_fp_registers(int pid, unsigned long *regs) 37 { 38 struct iovec iov = { 39 .iov_base = regs, 40 .iov_len = host_fp_size, 41 }; 42 43 if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0) 44 return -errno; 45 return 0; 46 } 47 48 int arch_init_registers(int pid) 49 { 50 struct iovec iov = { 51 /* Just use plenty of space, it does not cost us anything */ 52 .iov_len = 2 * 1024 * 1024, 53 }; 54 int ret; 55 56 iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ, 57 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 58 if (iov.iov_base == MAP_FAILED) 59 return -ENOMEM; 60 61 /* GDB has x86_xsave_length, which uses x86_cpuid_count */ 62 ptrace_regset = NT_X86_XSTATE; 63 ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); 64 if (ret) 65 ret = -errno; 66 67 if (ret == -ENODEV) { 68 #ifdef CONFIG_X86_32 69 ptrace_regset = NT_PRXFPREG; 70 #else 71 ptrace_regset = NT_PRFPREG; 72 #endif 73 iov.iov_len = 2 * 1024 * 1024; 74 ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); 75 if (ret) 76 ret = -errno; 77 } 78 79 munmap(iov.iov_base, 2 * 1024 * 1024); 80 81 host_fp_size = iov.iov_len; 82 83 return ret; 84 } 85 86 unsigned long get_thread_reg(int reg, jmp_buf *buf) 87 { 88 switch (reg) { 89 #ifdef __i386__ 90 case HOST_IP: 91 return buf[0]->__eip; 92 case HOST_SP: 93 return buf[0]->__esp; 94 case HOST_BP: 95 return buf[0]->__ebp; 96 #else 97 case HOST_IP: 98 return buf[0]->__rip; 99 case HOST_SP: 100 return buf[0]->__rsp; 101 case HOST_BP: 102 return buf[0]->__rbp; 103 #endif 104 default: 105 printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", 106 reg); 107 return 0; 108 } 109 } 110