xref: /freebsd/cddl/contrib/opensolaris/lib/libdtrace/arm/dt_isadep.c (revision 27067774dce3388702a4cf744d7096c6fb71b688)
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