1/*-
2 * Copyright (c) 2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Rui Paulo under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: stable/11/lib/libproc/proc_regs.c 351792 2019-09-03 20:19:43Z kevans $");
32
33#include <sys/types.h>
34#define	_WANT_MIPS_REGNUM
35#include <sys/ptrace.h>
36
37#include <err.h>
38#include <stdio.h>
39#include <string.h>
40#include <errno.h>
41
42#include "_libproc.h"
43
44int
45proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
46{
47	struct reg regs;
48
49	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
50	    phdl->status == PS_IDLE) {
51		errno = ENOENT;
52		return (-1);
53	}
54	memset(&regs, 0, sizeof(regs));
55	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
56		return (-1);
57	switch (reg) {
58	case REG_PC:
59#if defined(__aarch64__)
60		*regvalue = regs.elr;
61#elif defined(__amd64__)
62		*regvalue = regs.r_rip;
63#elif defined(__arm__)
64		*regvalue = regs.r_pc;
65#elif defined(__i386__)
66		*regvalue = regs.r_eip;
67#elif defined(__mips__)
68		*regvalue = regs.r_regs[PC];
69#elif defined(__powerpc__)
70		*regvalue = regs.pc;
71#elif defined(__riscv__)
72		*regvalue = regs.sepc;
73#endif
74		break;
75	case REG_SP:
76#if defined(__aarch64__)
77		*regvalue = regs.sp;
78#elif defined(__amd64__)
79		*regvalue = regs.r_rsp;
80#elif defined(__arm__)
81		*regvalue = regs.r_sp;
82#elif defined(__i386__)
83		*regvalue = regs.r_esp;
84#elif defined(__mips__)
85		*regvalue = regs.r_regs[SP];
86#elif defined(__powerpc__)
87		*regvalue = regs.fixreg[1];
88#elif defined(__riscv__)
89		*regvalue = regs.sp;
90#endif
91		break;
92	default:
93		DPRINTFX("ERROR: no support for reg number %d", reg);
94		return (-1);
95	}
96
97	return (0);
98}
99
100int
101proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
102{
103	struct reg regs;
104
105	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
106	    phdl->status == PS_IDLE) {
107		errno = ENOENT;
108		return (-1);
109	}
110	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
111		return (-1);
112	switch (reg) {
113	case REG_PC:
114#if defined(__aarch64__)
115		regs.elr = regvalue;
116#elif defined(__amd64__)
117		regs.r_rip = regvalue;
118#elif defined(__arm__)
119		regs.r_pc = regvalue;
120#elif defined(__i386__)
121		regs.r_eip = regvalue;
122#elif defined(__mips__)
123		regs.r_regs[PC] = regvalue;
124#elif defined(__powerpc__)
125		regs.pc = regvalue;
126#elif defined(__riscv__)
127		regs.sepc = regvalue;
128#endif
129		break;
130	case REG_SP:
131#if defined(__aarch64__)
132		regs.sp = regvalue;
133#elif defined(__amd64__)
134		regs.r_rsp = regvalue;
135#elif defined(__arm__)
136		regs.r_sp = regvalue;
137#elif defined(__i386__)
138		regs.r_esp = regvalue;
139#elif defined(__mips__)
140		regs.r_regs[PC] = regvalue;
141#elif defined(__powerpc__)
142		regs.fixreg[1] = regvalue;
143#elif defined(__riscv__)
144		regs.sp = regvalue;
145#endif
146		break;
147	default:
148		DPRINTFX("ERROR: no support for reg number %d", reg);
149		return (-1);
150	}
151	if (ptrace(PT_SETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
152		return (-1);
153
154	return (0);
155}
156