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(&regs, 0, sizeof(regs));
55210688Srpaulo	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 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)&regs, 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)&regs, 0) < 0)
152210688Srpaulo		return (-1);
153210688Srpaulo
154210688Srpaulo	return (0);
155210688Srpaulo}
156