15c48b108SAl Viro /*
25c48b108SAl Viro * Copyright (C) 2004 PathScale, Inc
35c48b108SAl Viro * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
45c48b108SAl Viro * Licensed under the GPL
55c48b108SAl Viro */
65c48b108SAl Viro
75c48b108SAl Viro #include <errno.h>
86f602afdSThomas Meyer #include <stdlib.h>
95c48b108SAl Viro #include <sys/ptrace.h>
1038b64aedSRichard Weinberger #ifdef __i386__
115c48b108SAl Viro #include <sys/user.h>
1238b64aedSRichard Weinberger #endif
1337185b33SAl Viro #include <longjmp.h>
1437185b33SAl Viro #include <sysdep/ptrace_user.h>
15a78ff111SEli Cooper #include <sys/uio.h>
16a78ff111SEli Cooper #include <asm/sigcontext.h>
17a78ff111SEli Cooper #include <linux/elf.h>
18dbba7f70SAl Viro #include <registers.h>
193f17fed2SBenjamin Berg #include <sys/mman.h>
205c48b108SAl Viro
21*5298b7cfSBenjamin Berg static unsigned long ptrace_regset;
223f17fed2SBenjamin Berg unsigned long host_fp_size;
23a78ff111SEli Cooper
get_fp_registers(int pid,unsigned long * regs)243f17fed2SBenjamin Berg int get_fp_registers(int pid, unsigned long *regs)
255c48b108SAl Viro {
263f17fed2SBenjamin Berg struct iovec iov = {
273f17fed2SBenjamin Berg .iov_base = regs,
283f17fed2SBenjamin Berg .iov_len = host_fp_size,
293f17fed2SBenjamin Berg };
305c48b108SAl Viro
31*5298b7cfSBenjamin Berg if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0)
32a78ff111SEli Cooper return -errno;
33a78ff111SEli Cooper return 0;
34a78ff111SEli Cooper }
35a78ff111SEli Cooper
put_fp_registers(int pid,unsigned long * regs)363f17fed2SBenjamin Berg int put_fp_registers(int pid, unsigned long *regs)
375c48b108SAl Viro {
383f17fed2SBenjamin Berg struct iovec iov = {
393f17fed2SBenjamin Berg .iov_base = regs,
403f17fed2SBenjamin Berg .iov_len = host_fp_size,
413f17fed2SBenjamin Berg };
425c48b108SAl Viro
43*5298b7cfSBenjamin Berg if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0)
44a78ff111SEli Cooper return -errno;
45a78ff111SEli Cooper return 0;
46a78ff111SEli Cooper }
47a78ff111SEli Cooper
arch_init_registers(int pid)483f17fed2SBenjamin Berg int arch_init_registers(int pid)
495c48b108SAl Viro {
503f17fed2SBenjamin Berg struct iovec iov = {
513f17fed2SBenjamin Berg /* Just use plenty of space, it does not cost us anything */
523f17fed2SBenjamin Berg .iov_len = 2 * 1024 * 1024,
533f17fed2SBenjamin Berg };
543f17fed2SBenjamin Berg int ret;
553f17fed2SBenjamin Berg
563f17fed2SBenjamin Berg iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ,
573f17fed2SBenjamin Berg MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
583f17fed2SBenjamin Berg if (iov.iov_base == MAP_FAILED)
593f17fed2SBenjamin Berg return -ENOMEM;
603f17fed2SBenjamin Berg
613f17fed2SBenjamin Berg /* GDB has x86_xsave_length, which uses x86_cpuid_count */
62*5298b7cfSBenjamin Berg ptrace_regset = NT_X86_XSTATE;
63*5298b7cfSBenjamin Berg ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov);
643f17fed2SBenjamin Berg if (ret)
653f17fed2SBenjamin Berg ret = -errno;
66*5298b7cfSBenjamin Berg
67*5298b7cfSBenjamin Berg if (ret == -ENODEV) {
68*5298b7cfSBenjamin Berg #ifdef CONFIG_X86_32
69*5298b7cfSBenjamin Berg ptrace_regset = NT_PRXFPREG;
70*5298b7cfSBenjamin Berg #else
71*5298b7cfSBenjamin Berg ptrace_regset = NT_PRFPREG;
72*5298b7cfSBenjamin Berg #endif
73*5298b7cfSBenjamin Berg iov.iov_len = 2 * 1024 * 1024;
74*5298b7cfSBenjamin Berg ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov);
75*5298b7cfSBenjamin Berg if (ret)
76*5298b7cfSBenjamin Berg ret = -errno;
77*5298b7cfSBenjamin Berg }
78*5298b7cfSBenjamin Berg
793f17fed2SBenjamin Berg munmap(iov.iov_base, 2 * 1024 * 1024);
803f17fed2SBenjamin Berg
813f17fed2SBenjamin Berg host_fp_size = iov.iov_len;
823f17fed2SBenjamin Berg
833f17fed2SBenjamin Berg return ret;
845c48b108SAl Viro }
855c48b108SAl Viro
get_thread_reg(int reg,jmp_buf * buf)865c48b108SAl Viro unsigned long get_thread_reg(int reg, jmp_buf *buf)
875c48b108SAl Viro {
885c48b108SAl Viro switch (reg) {
895c48b108SAl Viro #ifdef __i386__
90a10c95d8SAl Viro case HOST_IP:
915c48b108SAl Viro return buf[0]->__eip;
92a10c95d8SAl Viro case HOST_SP:
935c48b108SAl Viro return buf[0]->__esp;
94a10c95d8SAl Viro case HOST_BP:
955c48b108SAl Viro return buf[0]->__ebp;
965c48b108SAl Viro #else
97a10c95d8SAl Viro case HOST_IP:
985c48b108SAl Viro return buf[0]->__rip;
99a10c95d8SAl Viro case HOST_SP:
1005c48b108SAl Viro return buf[0]->__rsp;
101a10c95d8SAl Viro case HOST_BP:
1025c48b108SAl Viro return buf[0]->__rbp;
1035c48b108SAl Viro #endif
1045c48b108SAl Viro default:
1055c48b108SAl Viro printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
1065c48b108SAl Viro reg);
1075c48b108SAl Viro return 0;
1085c48b108SAl Viro }
1095c48b108SAl Viro }
110