proc_regs.c revision 351792
1316713Smarkj/*- 2316713Smarkj * Copyright (c) 2010 The FreeBSD Foundation 3316713Smarkj * All rights reserved. 4316713Smarkj * 5210688Srpaulo * This software was developed by Rui Paulo under sponsorship from the 6316713Smarkj * FreeBSD Foundation. 7316713Smarkj * 8316713Smarkj * Redistribution and use in source and binary forms, with or without 9316713Smarkj * modification, are permitted provided that the following conditions 10316713Smarkj * are met: 11316713Smarkj * 1. Redistributions of source code must retain the above copyright 12316713Smarkj * notice, this list of conditions and the following disclaimer. 13316713Smarkj * 2. Redistributions in binary form must reproduce the above copyright 14316713Smarkj * notice, this list of conditions and the following disclaimer in the 15316713Smarkj * documentation and/or other materials provided with the distribution. 16316713Smarkj * 17316713Smarkj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18316713Smarkj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19316713Smarkj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20316713Smarkj * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21316713Smarkj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22316713Smarkj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23316713Smarkj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24316713Smarkj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25316713Smarkj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26316713Smarkj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27316713Smarkj * SUCH DAMAGE. 28316713Smarkj */ 29210688Srpaulo 30210688Srpaulo#include <sys/cdefs.h> 31210688Srpaulo__FBSDID("$FreeBSD: stable/11/lib/libproc/proc_regs.c 351792 2019-09-03 20:19:43Z kevans $"); 32210688Srpaulo 33210688Srpaulo#include <sys/types.h> 34351792Skevans#define _WANT_MIPS_REGNUM 35210688Srpaulo#include <sys/ptrace.h> 36210688Srpaulo 37210688Srpaulo#include <err.h> 38210688Srpaulo#include <stdio.h> 39210688Srpaulo#include <string.h> 40210688Srpaulo#include <errno.h> 41316713Smarkj 42210688Srpaulo#include "_libproc.h" 43210688Srpaulo 44210688Srpauloint 45210688Srpauloproc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue) 46210688Srpaulo{ 47210688Srpaulo struct reg regs; 48210688Srpaulo 49210688Srpaulo if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD || 50210688Srpaulo phdl->status == PS_IDLE) { 51210688Srpaulo errno = ENOENT; 52210688Srpaulo return (-1); 53210688Srpaulo } 54210688Srpaulo memset(®s, 0, sizeof(regs)); 55210688Srpaulo if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)®s, 0) < 0) 56210688Srpaulo return (-1); 57210688Srpaulo switch (reg) { 58210688Srpaulo case REG_PC: 59285003Sbr#if defined(__aarch64__) 60285003Sbr *regvalue = regs.elr; 61285003Sbr#elif defined(__amd64__) 62210688Srpaulo *regvalue = regs.r_rip; 63278529Sgnn#elif defined(__arm__) 64278529Sgnn *regvalue = regs.r_pc; 65210688Srpaulo#elif defined(__i386__) 66210688Srpaulo *regvalue = regs.r_eip; 67233402Sgonzo#elif defined(__mips__) 68233402Sgonzo *regvalue = regs.r_regs[PC]; 69242723Sjhibbits#elif defined(__powerpc__) 70242723Sjhibbits *regvalue = regs.pc; 71294662Sbr#elif defined(__riscv__) 72294662Sbr *regvalue = regs.sepc; 73210688Srpaulo#endif 74210688Srpaulo break; 75210688Srpaulo case REG_SP: 76285003Sbr#if defined(__aarch64__) 77285003Sbr *regvalue = regs.sp; 78285003Sbr#elif defined(__amd64__) 79210688Srpaulo *regvalue = regs.r_rsp; 80278529Sgnn#elif defined(__arm__) 81278529Sgnn *regvalue = regs.r_sp; 82210688Srpaulo#elif defined(__i386__) 83210688Srpaulo *regvalue = regs.r_esp; 84233402Sgonzo#elif defined(__mips__) 85233402Sgonzo *regvalue = regs.r_regs[SP]; 86242723Sjhibbits#elif defined(__powerpc__) 87242723Sjhibbits *regvalue = regs.fixreg[1]; 88294662Sbr#elif defined(__riscv__) 89294662Sbr *regvalue = regs.sp; 90210688Srpaulo#endif 91210688Srpaulo break; 92210688Srpaulo default: 93257222Smarkj DPRINTFX("ERROR: no support for reg number %d", reg); 94210688Srpaulo return (-1); 95210688Srpaulo } 96210688Srpaulo 97210688Srpaulo return (0); 98210688Srpaulo} 99210688Srpaulo 100210688Srpauloint 101210688Srpauloproc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue) 102210688Srpaulo{ 103210688Srpaulo struct reg regs; 104210688Srpaulo 105210688Srpaulo if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD || 106210688Srpaulo phdl->status == PS_IDLE) { 107210688Srpaulo errno = ENOENT; 108210688Srpaulo return (-1); 109210688Srpaulo } 110210688Srpaulo if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)®s, 0) < 0) 111210688Srpaulo return (-1); 112210688Srpaulo switch (reg) { 113210688Srpaulo case REG_PC: 114285003Sbr#if defined(__aarch64__) 115285003Sbr regs.elr = regvalue; 116285003Sbr#elif defined(__amd64__) 117210688Srpaulo regs.r_rip = regvalue; 118278529Sgnn#elif defined(__arm__) 119278529Sgnn regs.r_pc = regvalue; 120210688Srpaulo#elif defined(__i386__) 121210688Srpaulo regs.r_eip = regvalue; 122233402Sgonzo#elif defined(__mips__) 123233402Sgonzo regs.r_regs[PC] = regvalue; 124242723Sjhibbits#elif defined(__powerpc__) 125242723Sjhibbits regs.pc = regvalue; 126294662Sbr#elif defined(__riscv__) 127294662Sbr regs.sepc = regvalue; 128210688Srpaulo#endif 129210688Srpaulo break; 130210688Srpaulo case REG_SP: 131285003Sbr#if defined(__aarch64__) 132285003Sbr regs.sp = regvalue; 133285003Sbr#elif defined(__amd64__) 134210688Srpaulo regs.r_rsp = regvalue; 135278529Sgnn#elif defined(__arm__) 136278529Sgnn regs.r_sp = regvalue; 137210688Srpaulo#elif defined(__i386__) 138210688Srpaulo regs.r_esp = regvalue; 139233402Sgonzo#elif defined(__mips__) 140233402Sgonzo regs.r_regs[PC] = regvalue; 141242723Sjhibbits#elif defined(__powerpc__) 142242723Sjhibbits regs.fixreg[1] = regvalue; 143294662Sbr#elif defined(__riscv__) 144294662Sbr regs.sp = regvalue; 145210688Srpaulo#endif 146210688Srpaulo break; 147210688Srpaulo default: 148257222Smarkj DPRINTFX("ERROR: no support for reg number %d", reg); 149210688Srpaulo return (-1); 150210688Srpaulo } 151210688Srpaulo if (ptrace(PT_SETREGS, proc_getpid(phdl), (caddr_t)®s, 0) < 0) 152210688Srpaulo return (-1); 153210688Srpaulo 154210688Srpaulo return (0); 155210688Srpaulo} 156