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#ifdef __FBSDID
32__FBSDID("$FreeBSD: head/lib/libproc/proc_regs.c 285003 2015-07-01 13:59:26Z br $");
33#else
34__RCSID("$NetBSD: proc_regs.c,v 1.3 2015/09/25 16:07:32 christos Exp $");
35#endif
36
37#include <sys/types.h>
38#include <sys/ptrace.h>
39
40#include <err.h>
41#include <stdio.h>
42#include <string.h>
43#include <errno.h>
44#include <sys/ucontext.h>
45#include "_libproc.h"
46
47int
48proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
49{
50	struct reg regs;
51
52	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
53	    phdl->status == PS_IDLE) {
54		errno = ENOENT;
55		return (-1);
56	}
57	memset(&regs, 0, sizeof(regs));
58	if (ptrace(PT_GETREGS, proc_getpid(phdl), &regs, 0) < 0)
59		return (-1);
60	switch (reg) {
61	case REG_PC:
62#ifdef PTRACE_REG_PC
63		*regvalue = PTRACE_REG_PC(&regs);
64#else
65#	error "Add support for your architecture"
66#endif
67		break;
68	case REG_SP:
69#ifdef PTRACE_REG_SP
70		*regvalue = PTRACE_REG_SP(&regs);
71#else
72#	error "Add support for your architecture"
73#endif
74		break;
75	default:
76		DPRINTFX("ERROR: no support for reg number %d", reg);
77		return (-1);
78	}
79
80	return (0);
81}
82
83int
84proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
85{
86	struct reg regs;
87
88	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
89	    phdl->status == PS_IDLE) {
90		errno = ENOENT;
91		return (-1);
92	}
93	if (ptrace(PT_GETREGS, proc_getpid(phdl), &regs, 0) < 0)
94		return (-1);
95	switch (reg) {
96	case REG_PC:
97#ifdef PTRACE_REG_SET_PC
98		PTRACE_REG_SET_PC(&regs, regvalue);
99#else
100#	error "Add support for your architecture"
101#endif
102		break;
103	case REG_SP:
104#ifdef PTRACE_REG_SP
105		PTRACE_REG_SP(&regs) = regvalue;
106#else
107#	error "Add support for your architecture"
108#endif
109		break;
110	default:
111		DPRINTFX("ERROR: no support for reg number %d", reg);
112		return (-1);
113	}
114	if (ptrace(PT_SETREGS, proc_getpid(phdl), &regs, 0) < 0)
115		return (-1);
116
117	return (0);
118}
119