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(®s, 0, sizeof(regs));
58*58ec3b3bSchristos if (ptrace(PT_GETREGS, proc_getpid(phdl), ®s, 0) < 0)
59fbcd1dd1Schristos return (-1);
60fbcd1dd1Schristos switch (reg) {
61fbcd1dd1Schristos case REG_PC:
6252ebe1c2Schristos #ifdef PTRACE_REG_PC
6352ebe1c2Schristos *regvalue = PTRACE_REG_PC(®s);
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(®s);
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), ®s, 0) < 0)
94fbcd1dd1Schristos return (-1);
95fbcd1dd1Schristos switch (reg) {
96fbcd1dd1Schristos case REG_PC:
9752ebe1c2Schristos #ifdef PTRACE_REG_SET_PC
9852ebe1c2Schristos PTRACE_REG_SET_PC(®s, 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(®s) = 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), ®s, 0) < 0)
115fbcd1dd1Schristos return (-1);
116fbcd1dd1Schristos
117fbcd1dd1Schristos return (0);
118fbcd1dd1Schristos }
119