File: isadep.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (133 lines) | stat: -rw-r--r-- 2,936 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * ISA-dependent functions for SPARC and SPARC64.
 */

/*
 * Oracle Linux DTrace.
 * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>				/* for struct pt_regs */

#include "Pcontrol.h"
#include "libproc.h"
#include "platform.h"

#define PTRACE_GETREGSET        0x4204

/*
 * Get a SPARC64 regset.
 */
static struct pt_regs *
getregs_sparc64(struct ps_prochandle *P, struct pt_regs *regs)
{
	if (Pstate(P) == PS_RUN ||
	    Pstate(P) == PS_DEAD)
		return NULL;

	if (wrapped_ptrace(P, PTRACE_GETREGS64, P->pid, regs) < 0)
		return NULL;

	return regs;
}

static struct pt_regs32 *
getregs_sparc32(struct ps_prochandle *P, struct pt_regs32 *regs)
{
	if (Pstate(P) == PS_RUN ||
	    Pstate(P) == PS_DEAD)
		return NULL;

	if (wrapped_ptrace(P, PTRACE_GETREGS, P->pid, regs) < 0)
		return NULL;

	return regs;
}

/*
 * Read the first argument of the function at which the process P is halted,
 * which must be a pointer (though other integral arguments happen to work for
 * the SPARC and SPARC64 ABI).
 *
 * For SPARC, the first integral argument to a function will always be in %i0.
 * Horrifically, the value of all the UREG_* constants is off by 1, so we have
 * to correct for that.
 *
 * On error, -1 cast to a uintptr_t is returned, and errno is set.
 */
uintptr_t
Pread_first_arg_sparc64(struct ps_prochandle *P)
{
	struct pt_regs regs;

	if (getregs_sparc64(P, &regs) == NULL)
		return (uintptr_t)-1;

	return regs.u_regs[UREG_I0 - 1];
}

uintptr_t
Pread_first_arg_sparc32(struct ps_prochandle *P)
{
	struct pt_regs32 regs;

	if (getregs_sparc32(P, &regs) == NULL)
		return (uintptr_t)-1;

	return regs.u_regs[UREG_I0 - 1];
}

/*
 * Get the address at which we stopped at a breakpoint.  Unlike on x86, no post
 * facto adjustment is required.
 */
uintptr_t
Pget_bkpt_ip_sparc64(struct ps_prochandle *P, int expect_esrch)
{
	struct pt_regs regs;

	if (getregs_sparc64(P, &regs) == NULL) {
		if ((errno == ESRCH) && (expect_esrch))
			return 0;
		else {
			_dprintf("Unexpected ptrace (PTRACE_GETREGSET) "
			    "error: %s\n", strerror(errno));
			return -1;
		}
	}

	return regs.tpc;
}

/*
 * Reset the instruction pointer address at which the process P is stopped.
 * (Not needed on SPARC.)
 */
long
Preset_bkpt_ip_sparc(struct ps_prochandle *P, uintptr_t addr)
{
    return 0; /* nothing doing */
}

/*
 * Get the address at which the temporary breakpoint should be dropped when a
 * breakpoint is hit.
 */
extern long Pget_next_ip_sparc64(struct ps_prochandle *P, uintptr_t addr)
{
	struct pt_regs regs;

	if (getregs_sparc64(P, &regs) == NULL) {
		_dprintf("Unexpected ptrace (PTRACE_GETREGSET) "
		    "error: %s\n", strerror(errno));
		return -1;
	}

	return regs.tnpc;
}