mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
3.3 KiB
168 lines
3.3 KiB
/* |
|
* Copyright (C) 2004 PathScale, Inc |
|
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
|
* Licensed under the GPL |
|
*/ |
|
|
|
#include <errno.h> |
|
#include <stdlib.h> |
|
#include <sys/ptrace.h> |
|
#ifdef __i386__ |
|
#include <sys/user.h> |
|
#endif |
|
#include <longjmp.h> |
|
#include <sysdep/ptrace_user.h> |
|
#include <sys/uio.h> |
|
#include <asm/sigcontext.h> |
|
#include <linux/elf.h> |
|
|
|
int have_xstate_support; |
|
|
|
int save_i387_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) |
|
return -errno; |
|
return 0; |
|
} |
|
|
|
int save_fp_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
#ifdef PTRACE_GETREGSET |
|
struct iovec iov; |
|
|
|
if (have_xstate_support) { |
|
iov.iov_base = fp_regs; |
|
iov.iov_len = FP_SIZE * sizeof(unsigned long); |
|
if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
|
return -errno; |
|
return 0; |
|
} else |
|
#endif |
|
return save_i387_registers(pid, fp_regs); |
|
} |
|
|
|
int restore_i387_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) |
|
return -errno; |
|
return 0; |
|
} |
|
|
|
int restore_fp_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
#ifdef PTRACE_SETREGSET |
|
struct iovec iov; |
|
if (have_xstate_support) { |
|
iov.iov_base = fp_regs; |
|
iov.iov_len = FP_SIZE * sizeof(unsigned long); |
|
if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
|
return -errno; |
|
return 0; |
|
} else |
|
#endif |
|
return restore_i387_registers(pid, fp_regs); |
|
} |
|
|
|
#ifdef __i386__ |
|
int have_fpx_regs = 1; |
|
int save_fpx_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) |
|
return -errno; |
|
return 0; |
|
} |
|
|
|
int restore_fpx_registers(int pid, unsigned long *fp_regs) |
|
{ |
|
if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) |
|
return -errno; |
|
return 0; |
|
} |
|
|
|
int get_fp_registers(int pid, unsigned long *regs) |
|
{ |
|
if (have_fpx_regs) |
|
return save_fpx_registers(pid, regs); |
|
else |
|
return save_fp_registers(pid, regs); |
|
} |
|
|
|
int put_fp_registers(int pid, unsigned long *regs) |
|
{ |
|
if (have_fpx_regs) |
|
return restore_fpx_registers(pid, regs); |
|
else |
|
return restore_fp_registers(pid, regs); |
|
} |
|
|
|
void arch_init_registers(int pid) |
|
{ |
|
struct user_fpxregs_struct fpx_regs; |
|
int err; |
|
|
|
err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); |
|
if (!err) |
|
return; |
|
|
|
if (errno != EIO) |
|
panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", |
|
errno); |
|
|
|
have_fpx_regs = 0; |
|
} |
|
#else |
|
|
|
int get_fp_registers(int pid, unsigned long *regs) |
|
{ |
|
return save_fp_registers(pid, regs); |
|
} |
|
|
|
int put_fp_registers(int pid, unsigned long *regs) |
|
{ |
|
return restore_fp_registers(pid, regs); |
|
} |
|
|
|
void arch_init_registers(int pid) |
|
{ |
|
#ifdef PTRACE_GETREGSET |
|
void * fp_regs; |
|
struct iovec iov; |
|
|
|
fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); |
|
if(fp_regs == NULL) |
|
return; |
|
|
|
iov.iov_base = fp_regs; |
|
iov.iov_len = FP_SIZE * sizeof(unsigned long); |
|
if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) |
|
have_xstate_support = 1; |
|
|
|
free(fp_regs); |
|
#endif |
|
} |
|
#endif |
|
|
|
unsigned long get_thread_reg(int reg, jmp_buf *buf) |
|
{ |
|
switch (reg) { |
|
#ifdef __i386__ |
|
case HOST_IP: |
|
return buf[0]->__eip; |
|
case HOST_SP: |
|
return buf[0]->__esp; |
|
case HOST_BP: |
|
return buf[0]->__ebp; |
|
#else |
|
case HOST_IP: |
|
return buf[0]->__rip; |
|
case HOST_SP: |
|
return buf[0]->__rsp; |
|
case HOST_BP: |
|
return buf[0]->__rbp; |
|
#endif |
|
default: |
|
printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", |
|
reg); |
|
return 0; |
|
} |
|
}
|
|
|