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