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 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 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 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 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