1210688Srpaulo/*
2210688Srpaulo * Copyright (c) 2010 The FreeBSD Foundation
3210688Srpaulo * All rights reserved.
4210688Srpaulo *
5210688Srpaulo * This software was developed by Rui Paulo under sponsorship from the
6210688Srpaulo * FreeBSD Foundation.
7210688Srpaulo *
8210688Srpaulo * Redistribution and use in source and binary forms, with or without
9210688Srpaulo * modification, are permitted provided that the following conditions
10210688Srpaulo * are met:
11210688Srpaulo * 1. Redistributions of source code must retain the above copyright
12210688Srpaulo *    notice, this list of conditions and the following disclaimer.
13210688Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
14210688Srpaulo *    notice, this list of conditions and the following disclaimer in the
15210688Srpaulo *    documentation and/or other materials provided with the distribution.
16210688Srpaulo *
17210688Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18210688Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19210688Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20210688Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21210688Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22210688Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23210688Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24210688Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25210688Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26210688Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27210688Srpaulo * SUCH DAMAGE.
28210688Srpaulo */
29210688Srpaulo
30210688Srpaulo#include <sys/cdefs.h>
31210688Srpaulo__FBSDID("$FreeBSD$");
32210688Srpaulo
33210688Srpaulo#include <sys/types.h>
34210688Srpaulo#include <sys/ptrace.h>
35210688Srpaulo
36210688Srpaulo#include <err.h>
37210688Srpaulo#include <stdio.h>
38210688Srpaulo#include <string.h>
39210688Srpaulo#include <errno.h>
40210688Srpaulo#include "_libproc.h"
41210688Srpaulo
42210688Srpauloint
43210688Srpauloproc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue)
44210688Srpaulo{
45210688Srpaulo	struct reg regs;
46210688Srpaulo
47210688Srpaulo	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
48210688Srpaulo	    phdl->status == PS_IDLE) {
49210688Srpaulo		errno = ENOENT;
50210688Srpaulo		return (-1);
51210688Srpaulo	}
52210688Srpaulo	memset(&regs, 0, sizeof(regs));
53210688Srpaulo	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
54210688Srpaulo		return (-1);
55210688Srpaulo	switch (reg) {
56210688Srpaulo	case REG_PC:
57210688Srpaulo#if defined(__amd64__)
58210688Srpaulo		*regvalue = regs.r_rip;
59210688Srpaulo#elif defined(__i386__)
60210688Srpaulo		*regvalue = regs.r_eip;
61233402Sgonzo#elif defined(__mips__)
62233402Sgonzo		*regvalue = regs.r_regs[PC];
63242723Sjhibbits#elif defined(__powerpc__)
64242723Sjhibbits		*regvalue = regs.pc;
65210688Srpaulo#endif
66210688Srpaulo		break;
67210688Srpaulo	case REG_SP:
68210688Srpaulo#if defined(__amd64__)
69210688Srpaulo		*regvalue = regs.r_rsp;
70210688Srpaulo#elif defined(__i386__)
71210688Srpaulo		*regvalue = regs.r_esp;
72233402Sgonzo#elif defined(__mips__)
73233402Sgonzo		*regvalue = regs.r_regs[SP];
74242723Sjhibbits#elif defined(__powerpc__)
75242723Sjhibbits		*regvalue = regs.fixreg[1];
76210688Srpaulo#endif
77210688Srpaulo		break;
78210688Srpaulo	default:
79259895Smarkj		DPRINTFX("ERROR: no support for reg number %d", reg);
80210688Srpaulo		return (-1);
81210688Srpaulo	}
82210688Srpaulo
83210688Srpaulo	return (0);
84210688Srpaulo}
85210688Srpaulo
86210688Srpauloint
87210688Srpauloproc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue)
88210688Srpaulo{
89210688Srpaulo	struct reg regs;
90210688Srpaulo
91210688Srpaulo	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
92210688Srpaulo	    phdl->status == PS_IDLE) {
93210688Srpaulo		errno = ENOENT;
94210688Srpaulo		return (-1);
95210688Srpaulo	}
96210688Srpaulo	if (ptrace(PT_GETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
97210688Srpaulo		return (-1);
98210688Srpaulo	switch (reg) {
99210688Srpaulo	case REG_PC:
100210688Srpaulo#if defined(__amd64__)
101210688Srpaulo		regs.r_rip = regvalue;
102210688Srpaulo#elif defined(__i386__)
103210688Srpaulo		regs.r_eip = regvalue;
104233402Sgonzo#elif defined(__mips__)
105233402Sgonzo		regs.r_regs[PC] = regvalue;
106242723Sjhibbits#elif defined(__powerpc__)
107242723Sjhibbits		regs.pc = regvalue;
108210688Srpaulo#endif
109210688Srpaulo		break;
110210688Srpaulo	case REG_SP:
111210688Srpaulo#if defined(__amd64__)
112210688Srpaulo		regs.r_rsp = regvalue;
113210688Srpaulo#elif defined(__i386__)
114210688Srpaulo		regs.r_esp = regvalue;
115233402Sgonzo#elif defined(__mips__)
116233402Sgonzo		regs.r_regs[PC] = regvalue;
117242723Sjhibbits#elif defined(__powerpc__)
118242723Sjhibbits		regs.fixreg[1] = regvalue;
119210688Srpaulo#endif
120210688Srpaulo		break;
121210688Srpaulo	default:
122259895Smarkj		DPRINTFX("ERROR: no support for reg number %d", reg);
123210688Srpaulo		return (-1);
124210688Srpaulo	}
125210688Srpaulo	if (ptrace(PT_SETREGS, proc_getpid(phdl), (caddr_t)&regs, 0) < 0)
126210688Srpaulo		return (-1);
127210688Srpaulo
128210688Srpaulo	return (0);
129210688Srpaulo}
130