xref: /netbsd-src/external/bsd/libproc/dist/proc_regs.c (revision 58ec3b3ba72d3d15833eebc5e8aa5b6efe518ce6)
1fbcd1dd1Schristos /*
2fbcd1dd1Schristos  * Copyright (c) 2010 The FreeBSD Foundation
3fbcd1dd1Schristos  * All rights reserved.
4fbcd1dd1Schristos  *
5fbcd1dd1Schristos  * This software was developed by Rui Paulo under sponsorship from the
6fbcd1dd1Schristos  * FreeBSD Foundation.
7fbcd1dd1Schristos  *
8fbcd1dd1Schristos  * Redistribution and use in source and binary forms, with or without
9fbcd1dd1Schristos  * modification, are permitted provided that the following conditions
10fbcd1dd1Schristos  * are met:
11fbcd1dd1Schristos  * 1. Redistributions of source code must retain the above copyright
12fbcd1dd1Schristos  *    notice, this list of conditions and the following disclaimer.
13fbcd1dd1Schristos  * 2. Redistributions in binary form must reproduce the above copyright
14fbcd1dd1Schristos  *    notice, this list of conditions and the following disclaimer in the
15fbcd1dd1Schristos  *    documentation and/or other materials provided with the distribution.
16fbcd1dd1Schristos  *
17fbcd1dd1Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18fbcd1dd1Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19fbcd1dd1Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20fbcd1dd1Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21fbcd1dd1Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22fbcd1dd1Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23fbcd1dd1Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24fbcd1dd1Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25fbcd1dd1Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26fbcd1dd1Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27fbcd1dd1Schristos  * SUCH DAMAGE.
28fbcd1dd1Schristos  */
29fbcd1dd1Schristos 
30fbcd1dd1Schristos #include <sys/cdefs.h>
3152ebe1c2Schristos #ifdef __FBSDID
32fbcd1dd1Schristos __FBSDID("$FreeBSD: head/lib/libproc/proc_regs.c 285003 2015-07-01 13:59:26Z br $");
3352ebe1c2Schristos #else
34*58ec3b3bSchristos __RCSID("$NetBSD: proc_regs.c,v 1.4 2015/09/25 19:09:38 christos Exp $");
3552ebe1c2Schristos #endif
36fbcd1dd1Schristos 
37fbcd1dd1Schristos #include <sys/types.h>
38fbcd1dd1Schristos #include <sys/ptrace.h>
39fbcd1dd1Schristos 
40fbcd1dd1Schristos #include <err.h>
41fbcd1dd1Schristos #include <stdio.h>
42fbcd1dd1Schristos #include <string.h>
43fbcd1dd1Schristos #include <errno.h>
4452ebe1c2Schristos #include <sys/ucontext.h>
45fbcd1dd1Schristos #include "_libproc.h"
46fbcd1dd1Schristos 
47fbcd1dd1Schristos int
proc_regget(struct proc_handle * phdl,proc_reg_t reg,unsigned long * regvalue)48fbcd1dd1Schristos proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
49fbcd1dd1Schristos {
50fbcd1dd1Schristos 	struct reg regs;
51fbcd1dd1Schristos 
52fbcd1dd1Schristos 	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
53fbcd1dd1Schristos 	    phdl->status == PS_IDLE) {
54fbcd1dd1Schristos 		errno = ENOENT;
55fbcd1dd1Schristos 		return (-1);
56fbcd1dd1Schristos 	}
57fbcd1dd1Schristos 	memset(&regs, 0, sizeof(regs));
58*58ec3b3bSchristos 	if (ptrace(PT_GETREGS, proc_getpid(phdl), &regs, 0) < 0)
59fbcd1dd1Schristos 		return (-1);
60fbcd1dd1Schristos 	switch (reg) {
61fbcd1dd1Schristos 	case REG_PC:
6252ebe1c2Schristos #ifdef PTRACE_REG_PC
6352ebe1c2Schristos 		*regvalue = PTRACE_REG_PC(&regs);
6452ebe1c2Schristos #else
659a58287bSchristos #	error "Add support for your architecture"
6652ebe1c2Schristos #endif
67fbcd1dd1Schristos 		break;
68fbcd1dd1Schristos 	case REG_SP:
6952ebe1c2Schristos #ifdef PTRACE_REG_SP
7052ebe1c2Schristos 		*regvalue = PTRACE_REG_SP(&regs);
7152ebe1c2Schristos #else
729a58287bSchristos #	error "Add support for your architecture"
7352ebe1c2Schristos #endif
74fbcd1dd1Schristos 		break;
75fbcd1dd1Schristos 	default:
76fbcd1dd1Schristos 		DPRINTFX("ERROR: no support for reg number %d", reg);
77fbcd1dd1Schristos 		return (-1);
78fbcd1dd1Schristos 	}
79fbcd1dd1Schristos 
80fbcd1dd1Schristos 	return (0);
81fbcd1dd1Schristos }
82fbcd1dd1Schristos 
83fbcd1dd1Schristos int
proc_regset(struct proc_handle * phdl,proc_reg_t reg,unsigned long regvalue)84fbcd1dd1Schristos proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
85fbcd1dd1Schristos {
86fbcd1dd1Schristos 	struct reg regs;
87fbcd1dd1Schristos 
88fbcd1dd1Schristos 	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
89fbcd1dd1Schristos 	    phdl->status == PS_IDLE) {
90fbcd1dd1Schristos 		errno = ENOENT;
91fbcd1dd1Schristos 		return (-1);
92fbcd1dd1Schristos 	}
93*58ec3b3bSchristos 	if (ptrace(PT_GETREGS, proc_getpid(phdl), &regs, 0) < 0)
94fbcd1dd1Schristos 		return (-1);
95fbcd1dd1Schristos 	switch (reg) {
96fbcd1dd1Schristos 	case REG_PC:
9752ebe1c2Schristos #ifdef PTRACE_REG_SET_PC
9852ebe1c2Schristos 		PTRACE_REG_SET_PC(&regs, regvalue);
9952ebe1c2Schristos #else
1009a58287bSchristos #	error "Add support for your architecture"
10152ebe1c2Schristos #endif
102fbcd1dd1Schristos 		break;
103fbcd1dd1Schristos 	case REG_SP:
10452ebe1c2Schristos #ifdef PTRACE_REG_SP
10552ebe1c2Schristos 		PTRACE_REG_SP(&regs) = regvalue;
10652ebe1c2Schristos #else
1079a58287bSchristos #	error "Add support for your architecture"
10852ebe1c2Schristos #endif
109fbcd1dd1Schristos 		break;
110fbcd1dd1Schristos 	default:
111fbcd1dd1Schristos 		DPRINTFX("ERROR: no support for reg number %d", reg);
112fbcd1dd1Schristos 		return (-1);
113fbcd1dd1Schristos 	}
114*58ec3b3bSchristos 	if (ptrace(PT_SETREGS, proc_getpid(phdl), &regs, 0) < 0)
115fbcd1dd1Schristos 		return (-1);
116fbcd1dd1Schristos 
117fbcd1dd1Schristos 	return (0);
118fbcd1dd1Schristos }
119