Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c
39563 views
1
/*
2
* CDDL HEADER START
3
*
4
* The contents of this file are subject to the terms of the
5
* Common Development and Distribution License, Version 1.0 only
6
* (the "License"). You may not use this file except in compliance
7
* with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or http://www.opensolaris.org/os/licensing.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
/*
23
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24
* Use is subject to license terms.
25
*/
26
27
#pragma ident "%Z%%M% %I% %E% SMI"
28
29
#include <stdlib.h>
30
#include <assert.h>
31
#include <errno.h>
32
#include <string.h>
33
#include <libgen.h>
34
35
#include <dt_impl.h>
36
#include <dt_pid.h>
37
38
#include <libproc_compat.h>
39
40
/*ARGSUSED*/
41
int
42
dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
43
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
44
{
45
ftp->ftps_type = DTFTP_ENTRY;
46
ftp->ftps_pc = (uintptr_t)symp->st_value;
47
ftp->ftps_size = (size_t)symp->st_size;
48
ftp->ftps_noffs = 1;
49
ftp->ftps_offs[0] = 0;
50
51
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
52
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
53
strerror(errno));
54
return (dt_set_errno(dtp, errno));
55
}
56
57
return (1);
58
}
59
60
int
61
dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
62
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
63
{
64
65
uintptr_t temp;
66
uint32_t *text;
67
int i;
68
int srdepth = 0;
69
70
if ((text = malloc(symp->st_size + 4)) == NULL) {
71
dt_dprintf("mr sparkle: malloc() failed\n");
72
return (DT_PROC_ERR);
73
}
74
75
if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
76
dt_dprintf("mr sparkle: Pread() failed\n");
77
free(text);
78
return (DT_PROC_ERR);
79
}
80
81
/*
82
* Leave a dummy instruction in the last slot to simplify edge
83
* conditions.
84
*/
85
text[symp->st_size / 4] = 0;
86
87
ftp->ftps_type = DTFTP_RETURN;
88
ftp->ftps_pc = symp->st_value;
89
ftp->ftps_size = symp->st_size;
90
ftp->ftps_noffs = 0;
91
92
for (i = 0; i < symp->st_size / 4; i++) {
93
94
if ((text[i] & 0xfc000001) != 0x48000000 &&
95
text[i] != 0x4e800020)
96
continue;
97
98
/*
99
* Check for a jump within this function. If it's outside this
100
* function then it's a tail-call, so a return point.
101
*/
102
if ((text[i] & 0xfc000000) == 0x48000000) {
103
temp = (text[i] & 0x03fffffc);
104
/* Bit 30 denotes an absolute address. */
105
if (!(text[i] & 0x02)) {
106
temp += symp->st_value + i * 4;
107
}
108
else {
109
/* Sign extend the absolute address. */
110
if (temp & 0x02000000) {
111
temp |= (UINTPTR_MAX - 0x03ffffff);
112
}
113
}
114
if (temp >= symp->st_value &&
115
temp <= (symp->st_value + symp->st_size))
116
continue;
117
}
118
dt_dprintf("return at offset %x\n", i * 4);
119
ftp->ftps_offs[ftp->ftps_noffs++] = i * 4;
120
}
121
122
free(text);
123
if (ftp->ftps_noffs > 0) {
124
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
125
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
126
strerror(errno));
127
return (dt_set_errno(dtp, errno));
128
}
129
}
130
131
132
return (ftp->ftps_noffs);
133
}
134
135
/*ARGSUSED*/
136
int
137
dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
138
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
139
{
140
if (off & 0x3)
141
return (DT_PROC_ALIGN);
142
143
ftp->ftps_type = DTFTP_OFFSETS;
144
ftp->ftps_pc = (uintptr_t)symp->st_value;
145
ftp->ftps_size = (size_t)symp->st_size;
146
ftp->ftps_noffs = 1;
147
ftp->ftps_offs[0] = off;
148
149
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
150
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
151
strerror(errno));
152
return (dt_set_errno(dtp, errno));
153
}
154
155
return (1);
156
}
157
158
/*ARGSUSED*/
159
int
160
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
161
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
162
{
163
ulong_t i;
164
165
ftp->ftps_type = DTFTP_OFFSETS;
166
ftp->ftps_pc = (uintptr_t)symp->st_value;
167
ftp->ftps_size = (size_t)symp->st_size;
168
ftp->ftps_noffs = 0;
169
170
/*
171
* If we're matching against everything, just iterate through each
172
* instruction in the function, otherwise look for matching offset
173
* names by constructing the string and comparing it against the
174
* pattern.
175
*/
176
if (strcmp("*", pattern) == 0) {
177
for (i = 0; i < symp->st_size; i += 4) {
178
ftp->ftps_offs[ftp->ftps_noffs++] = i;
179
}
180
} else {
181
char name[sizeof (i) * 2 + 1];
182
183
for (i = 0; i < symp->st_size; i += 4) {
184
(void) sprintf(name, "%lx", i);
185
if (gmatch(name, pattern))
186
ftp->ftps_offs[ftp->ftps_noffs++] = i;
187
}
188
}
189
190
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
191
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
192
strerror(errno));
193
return (dt_set_errno(dtp, errno));
194
}
195
196
return (ftp->ftps_noffs);
197
}
198
199