Deleted Added
sdiff udiff text old ( 179237 ) new ( 184698 )
full compact
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 6 unchanged lines hidden (view full) ---

15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
22 *
23 * $FreeBSD: head/sys/cddl/dev/systrace/systrace.c 179237 2008-05-23 05:59:42Z jb $
24 *
25 */
26
27/*
28 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
30 */
31

--- 13 unchanged lines hidden (view full) ---

45#include <sys/lock.h>
46#include <sys/malloc.h>
47#include <sys/module.h>
48#include <sys/mutex.h>
49#include <sys/poll.h>
50#include <sys/proc.h>
51#include <sys/selinfo.h>
52#include <sys/smp.h>
53#include <sys/syscall.h>
54#include <sys/sysent.h>
55#include <sys/sysproto.h>
56#include <sys/uio.h>
57#include <sys/unistd.h>
58#include <machine/stdarg.h>
59
60#include <sys/dtrace.h>
61
62#define SYSTRACE_ARTIFICIAL_FRAMES 1
63
64#define SYSTRACE_SHIFT 16
65#define SYSTRACE_ISENTRY(x) ((int)(x) >> SYSTRACE_SHIFT)
66#define SYSTRACE_SYSNUM(x) ((int)(x) & ((1 << SYSTRACE_SHIFT) - 1))
67#define SYSTRACE_ENTRY(id) ((1 << SYSTRACE_SHIFT) | (id))
68#define SYSTRACE_RETURN(id) (id)
69
70#if ((1 << SYSTRACE_SHIFT) <= SYS_MAXSYSCALL)
71#error 1 << SYSTRACE_SHIFT must exceed number of system calls
72#endif
73
74extern char *syscallnames[];
75
76static d_open_t systrace_open;
77static int systrace_unload(void);
78static void systrace_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
79static void systrace_args(int, void *, u_int64_t *, int *);
80static void systrace_probe(u_int32_t, int, struct sysent *, void *);
81static void systrace_provide(void *, dtrace_probedesc_t *);
82static void systrace_destroy(void *, dtrace_id_t, void *);
83static void systrace_enable(void *, dtrace_id_t, void *);
84static void systrace_disable(void *, dtrace_id_t, void *);
85static void systrace_load(void *);
86
87static struct cdevsw systrace_cdevsw = {
88 .d_version = D_VERSION,
89 .d_open = systrace_open,
90 .d_name = "systrace",
91};
92
93static dtrace_pattr_t systrace_attr = {
94{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
95{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
96{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
97{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
98{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
99};
100

--- 8 unchanged lines hidden (view full) ---

109 NULL,
110 NULL,
111 systrace_destroy
112};
113
114static struct cdev *systrace_cdev;
115static dtrace_provider_id_t systrace_id;
116
117/*
118 * The syscall arguments are processed into a DTrace argument array
119 * using a generated function. See sys/kern/makesyscalls.sh.
120 */
121#include <kern/systrace_args.c>
122
123static void
124systrace_probe(u_int32_t id, int sysnum, struct sysent *sysent, void *params)
125{
126 int n_args = 0;
127 u_int64_t uargs[8];
128
129 /*
130 * Check if this syscall has a custom argument conversion
131 * function registered. If so, it is a syscall registered
132 * by a loaded module.
133 */
134 if (sysent->sy_systrace_args_func != NULL)
135 /*
136 * Convert the syscall parameters using the registered
137 * function.
138 */
139 (*sysent->sy_systrace_args_func)(params, uargs, &n_args);
140 else
141 /*
142 * Use the built-in system call argument conversion
143 * function to translate the syscall structure fields
144 * into thhe array of 64-bit values that DTrace
145 * expects.
146 */
147 systrace_args(sysnum, params, uargs, &n_args);
148
149 /* Process the probe using the converted argments. */
150 dtrace_probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4]);
151}
152
153static void
154systrace_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
155{
156 int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
157
158 systrace_setargdesc(sysnum, desc->dtargd_ndx, desc->dtargd_native,
159 sizeof(desc->dtargd_native));

--- 7 unchanged lines hidden (view full) ---

167static void
168systrace_provide(void *arg, dtrace_probedesc_t *desc)
169{
170 int i;
171
172 if (desc != NULL)
173 return;
174
175 for (i = 0; i < SYS_MAXSYSCALL; i++) {
176 if (dtrace_probe_lookup(systrace_id, NULL,
177 syscallnames[i], "entry") != 0)
178 continue;
179
180 (void) dtrace_probe_create(systrace_id, NULL, syscallnames[i],
181 "entry", SYSTRACE_ARTIFICIAL_FRAMES,
182 (void *)((uintptr_t)SYSTRACE_ENTRY(i)));
183 (void) dtrace_probe_create(systrace_id, NULL, syscallnames[i],
184 "return", SYSTRACE_ARTIFICIAL_FRAMES,
185 (void *)((uintptr_t)SYSTRACE_RETURN(i)));
186 }
187}
188
189static void
190systrace_destroy(void *arg, dtrace_id_t id, void *parg)
191{

--- 12 unchanged lines hidden (view full) ---

204#endif
205}
206
207static void
208systrace_enable(void *arg, dtrace_id_t id, void *parg)
209{
210 int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
211
212 if (SYSTRACE_ISENTRY((uintptr_t)parg))
213 sysent[sysnum].sy_entry = id;
214 else
215 sysent[sysnum].sy_return = id;
216}
217
218static void
219systrace_disable(void *arg, dtrace_id_t id, void *parg)
220{
221 int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
222
223 sysent[sysnum].sy_entry = 0;
224 sysent[sysnum].sy_return = 0;
225}
226
227static void
228systrace_load(void *dummy)
229{
230 /* Create the /dev/dtrace/systrace entry. */
231 systrace_cdev = make_dev(&systrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
232 "dtrace/systrace");
233
234 if (dtrace_register("syscall", &systrace_attr, DTRACE_PRIV_USER,
235 NULL, &systrace_pops, NULL, &systrace_id) != 0)
236 return;
237
238 systrace_probe_func = systrace_probe;
239}
240
241
242static int
243systrace_unload()
244{
245 int error = 0;
246
247 if ((error = dtrace_unregister(systrace_id)) != 0)
248 return (error);
249
250 systrace_probe_func = NULL;
251
252 destroy_dev(systrace_cdev);
253
254 return (error);
255}
256
257static int
258systrace_modevent(module_t mod __unused, int type, void *data __unused)

--- 22 unchanged lines hidden (view full) ---

281systrace_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
282{
283 return (0);
284}
285
286SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_load, NULL);
287SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_unload, NULL);
288
289DEV_MODULE(systrace, systrace_modevent, NULL);
290MODULE_VERSION(systrace, 1);
291MODULE_DEPEND(systrace, dtrace, 1, 1, 1);
292MODULE_DEPEND(systrace, opensolaris, 1, 1, 1);