xref: /freebsd/lib/libproc/proc_regs.c (revision 5c2bc3db201a4fe8d7911cf816bea104d5dc2138)
1fcf9fc10SMark Johnston /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni  *
48eb20f36SRui Paulo  * Copyright (c) 2010 The FreeBSD Foundation
58eb20f36SRui Paulo  *
68eb20f36SRui Paulo  * This software was developed by Rui Paulo under sponsorship from the
78eb20f36SRui Paulo  * FreeBSD Foundation.
88eb20f36SRui Paulo  *
98eb20f36SRui Paulo  * Redistribution and use in source and binary forms, with or without
108eb20f36SRui Paulo  * modification, are permitted provided that the following conditions
118eb20f36SRui Paulo  * are met:
128eb20f36SRui Paulo  * 1. Redistributions of source code must retain the above copyright
138eb20f36SRui Paulo  *    notice, this list of conditions and the following disclaimer.
148eb20f36SRui Paulo  * 2. Redistributions in binary form must reproduce the above copyright
158eb20f36SRui Paulo  *    notice, this list of conditions and the following disclaimer in the
168eb20f36SRui Paulo  *    documentation and/or other materials provided with the distribution.
178eb20f36SRui Paulo  *
188eb20f36SRui Paulo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
198eb20f36SRui Paulo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
208eb20f36SRui Paulo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
218eb20f36SRui Paulo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
228eb20f36SRui Paulo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
238eb20f36SRui Paulo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
248eb20f36SRui Paulo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
258eb20f36SRui Paulo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
268eb20f36SRui Paulo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
278eb20f36SRui Paulo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
288eb20f36SRui Paulo  * SUCH DAMAGE.
298eb20f36SRui Paulo  */
308eb20f36SRui Paulo 
318eb20f36SRui Paulo #include <sys/types.h>
328eb20f36SRui Paulo #include <sys/ptrace.h>
338eb20f36SRui Paulo 
348eb20f36SRui Paulo #include <err.h>
358eb20f36SRui Paulo #include <stdio.h>
368eb20f36SRui Paulo #include <string.h>
378eb20f36SRui Paulo #include <errno.h>
38fcf9fc10SMark Johnston 
398eb20f36SRui Paulo #include "_libproc.h"
408eb20f36SRui Paulo 
418eb20f36SRui Paulo int
428eb20f36SRui Paulo proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
438eb20f36SRui Paulo {
448eb20f36SRui Paulo 	struct reg regs;
458eb20f36SRui Paulo 
468eb20f36SRui Paulo 	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
478eb20f36SRui Paulo 	    phdl->status == PS_IDLE) {
488eb20f36SRui Paulo 		errno = ENOENT;
498eb20f36SRui Paulo 		return (-1);
508eb20f36SRui Paulo 	}
518eb20f36SRui Paulo 	memset(&regs, 0, sizeof(regs));
528eb20f36SRui Paulo 	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
538eb20f36SRui Paulo 		return (-1);
548eb20f36SRui Paulo 	switch (reg) {
558eb20f36SRui Paulo 	case REG_PC:
5627e54fb5SRuslan Bukin #if defined(__aarch64__)
5727e54fb5SRuslan Bukin 		*regvalue = regs.elr;
5827e54fb5SRuslan Bukin #elif defined(__amd64__)
598eb20f36SRui Paulo 		*regvalue = regs.r_rip;
60fcb56067SGeorge V. Neville-Neil #elif defined(__arm__)
61fcb56067SGeorge V. Neville-Neil 		*regvalue = regs.r_pc;
628eb20f36SRui Paulo #elif defined(__i386__)
638eb20f36SRui Paulo 		*regvalue = regs.r_eip;
64c7570492SJustin Hibbits #elif defined(__powerpc__)
65c7570492SJustin Hibbits 		*regvalue = regs.pc;
66ca20f8ecSRuslan Bukin #elif defined(__riscv)
677dd3aed9SRuslan Bukin 		*regvalue = regs.sepc;
688eb20f36SRui Paulo #endif
698eb20f36SRui Paulo 		break;
708eb20f36SRui Paulo 	case REG_SP:
7127e54fb5SRuslan Bukin #if defined(__aarch64__)
7227e54fb5SRuslan Bukin 		*regvalue = regs.sp;
7327e54fb5SRuslan Bukin #elif defined(__amd64__)
748eb20f36SRui Paulo 		*regvalue = regs.r_rsp;
75fcb56067SGeorge V. Neville-Neil #elif defined(__arm__)
76fcb56067SGeorge V. Neville-Neil 		*regvalue = regs.r_sp;
778eb20f36SRui Paulo #elif defined(__i386__)
788eb20f36SRui Paulo 		*regvalue = regs.r_esp;
79c7570492SJustin Hibbits #elif defined(__powerpc__)
80c7570492SJustin Hibbits 		*regvalue = regs.fixreg[1];
81ca20f8ecSRuslan Bukin #elif defined(__riscv)
827dd3aed9SRuslan Bukin 		*regvalue = regs.sp;
838eb20f36SRui Paulo #endif
848eb20f36SRui Paulo 		break;
858eb20f36SRui Paulo 	default:
8630e81f7eSMark Johnston 		DPRINTFX("ERROR: no support for reg number %d", reg);
878eb20f36SRui Paulo 		return (-1);
888eb20f36SRui Paulo 	}
898eb20f36SRui Paulo 
908eb20f36SRui Paulo 	return (0);
918eb20f36SRui Paulo }
928eb20f36SRui Paulo 
938eb20f36SRui Paulo int
948eb20f36SRui Paulo proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
958eb20f36SRui Paulo {
968eb20f36SRui Paulo 	struct reg regs;
978eb20f36SRui Paulo 
988eb20f36SRui Paulo 	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
998eb20f36SRui Paulo 	    phdl->status == PS_IDLE) {
1008eb20f36SRui Paulo 		errno = ENOENT;
1018eb20f36SRui Paulo 		return (-1);
1028eb20f36SRui Paulo 	}
1038eb20f36SRui Paulo 	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
1048eb20f36SRui Paulo 		return (-1);
1058eb20f36SRui Paulo 	switch (reg) {
1068eb20f36SRui Paulo 	case REG_PC:
10727e54fb5SRuslan Bukin #if defined(__aarch64__)
10827e54fb5SRuslan Bukin 		regs.elr = regvalue;
10927e54fb5SRuslan Bukin #elif defined(__amd64__)
1108eb20f36SRui Paulo 		regs.r_rip = regvalue;
111fcb56067SGeorge V. Neville-Neil #elif defined(__arm__)
112fcb56067SGeorge V. Neville-Neil 		regs.r_pc = regvalue;
1138eb20f36SRui Paulo #elif defined(__i386__)
1148eb20f36SRui Paulo 		regs.r_eip = regvalue;
115c7570492SJustin Hibbits #elif defined(__powerpc__)
116c7570492SJustin Hibbits 		regs.pc = regvalue;
117ca20f8ecSRuslan Bukin #elif defined(__riscv)
1187dd3aed9SRuslan Bukin 		regs.sepc = regvalue;
1198eb20f36SRui Paulo #endif
1208eb20f36SRui Paulo 		break;
1218eb20f36SRui Paulo 	case REG_SP:
12227e54fb5SRuslan Bukin #if defined(__aarch64__)
12327e54fb5SRuslan Bukin 		regs.sp = regvalue;
12427e54fb5SRuslan Bukin #elif defined(__amd64__)
1258eb20f36SRui Paulo 		regs.r_rsp = regvalue;
126fcb56067SGeorge V. Neville-Neil #elif defined(__arm__)
127fcb56067SGeorge V. Neville-Neil 		regs.r_sp = regvalue;
1288eb20f36SRui Paulo #elif defined(__i386__)
1298eb20f36SRui Paulo 		regs.r_esp = regvalue;
130c7570492SJustin Hibbits #elif defined(__powerpc__)
131c7570492SJustin Hibbits 		regs.fixreg[1] = regvalue;
132ca20f8ecSRuslan Bukin #elif defined(__riscv)
1337dd3aed9SRuslan Bukin 		regs.sp = regvalue;
1348eb20f36SRui Paulo #endif
1358eb20f36SRui Paulo 		break;
1368eb20f36SRui Paulo 	default:
13730e81f7eSMark Johnston 		DPRINTFX("ERROR: no support for reg number %d", reg);
1388eb20f36SRui Paulo 		return (-1);
1398eb20f36SRui Paulo 	}
1408eb20f36SRui Paulo 	if (ptrace(PT_SETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
1418eb20f36SRui Paulo 		return (-1);
1428eb20f36SRui Paulo 
1438eb20f36SRui Paulo 	return (0);
1448eb20f36SRui Paulo }
145