regs.c revision bac2da505ee174b7fb984b975c5938f88f0dbab2
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Ian Wienand 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22#include "config.h" 23 24#include <sys/types.h> 25#include <sys/ptrace.h> 26#include <sys/reg.h> 27#include <errno.h> 28#include <stdio.h> 29#include <string.h> 30 31#include "backend.h" 32#include "proc.h" 33 34#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 35# define PTRACE_PEEKUSER PTRACE_PEEKUSR 36#endif 37 38#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 39# define PTRACE_POKEUSER PTRACE_POKEUSR 40#endif 41 42#ifdef __x86_64__ 43# define XIP (8 * RIP) 44# define XSP (8 * RSP) 45#else 46# define XIP (4 * EIP) 47# define XSP (4 * UESP) 48#endif 49 50static arch_addr_t 51conv_32(arch_addr_t val) 52{ 53 /* XXX Drop the multiple double casts when arch_addr_t 54 * becomes integral. */ 55 return (arch_addr_t)(uintptr_t)(uint32_t)(uintptr_t)val; 56} 57 58void * 59get_instruction_pointer(struct Process *proc) 60{ 61 long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, XIP, 0); 62 if (proc->e_machine == EM_386) 63 ret &= 0xffffffff; 64 return (void *)ret; 65} 66 67void 68set_instruction_pointer(struct Process *proc, arch_addr_t addr) 69{ 70 if (proc->e_machine == EM_386) 71 addr = conv_32(addr); 72 ptrace(PTRACE_POKEUSER, proc->pid, XIP, addr); 73} 74 75void * 76get_stack_pointer(struct Process *proc) 77{ 78 long sp = ptrace(PTRACE_PEEKUSER, proc->pid, XSP, 0); 79 if (sp == -1 && errno) { 80 fprintf(stderr, "Couldn't read SP register: %s\n", 81 strerror(errno)); 82 return NULL; 83 } 84 85 /* XXX Drop the multiple double casts when arch_addr_t 86 * becomes integral. */ 87 arch_addr_t ret = (arch_addr_t)(uintptr_t)sp; 88 if (proc->e_machine == EM_386) 89 ret = conv_32(ret); 90 return ret; 91} 92 93void * 94get_return_addr(struct Process *proc, void *sp) 95{ 96 long a = ptrace(PTRACE_PEEKTEXT, proc->pid, sp, 0); 97 if (a == -1 && errno) { 98 fprintf(stderr, "Couldn't read return value: %s\n", 99 strerror(errno)); 100 return NULL; 101 } 102 103 /* XXX Drop the multiple double casts when arch_addr_t 104 * becomes integral. */ 105 arch_addr_t ret = (arch_addr_t)(uintptr_t)a; 106 if (proc->e_machine == EM_386) 107 ret = conv_32(ret); 108 return ret; 109} 110 111void 112set_return_addr(Process *proc, void *addr) { 113 if (proc->e_machine == EM_386) 114 addr = (void *)((long int)addr & 0xffffffff); 115 ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr); 116} 117