lx_systrace.c revision 193974072f41a843678abf5f61979c748687e66b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/dtrace_impl.h>
#define LX_SYSTRACE_SHIFT 16
#define LX_SYSTRACE_ISENTRY(x) ((int)(x) >> LX_SYSTRACE_SHIFT)
#define LX_SYSTRACE_ENTRY_AFRAMES 2
#define LX_SYSTRACE_RETURN_AFRAMES 4
typedef struct lx_systrace_sysent {
const char *lss_name;
static dev_info_t *lx_systrace_devi;
static dtrace_provider_id_t lx_systrace_id;
static kmutex_t lx_systrace_lock;
static uint_t lx_systrace_nenabled;
static int lx_systrace_nsysent;
static lx_systrace_sysent_t *lx_systrace_sysent;
/*ARGSUSED*/
static void
{
if (sysnum >= lx_systrace_nsysent)
return;
return;
}
/*ARGSUSED*/
static void
{
if (sysnum >= lx_systrace_nsysent)
return;
return;
}
/*ARGSUSED*/
static void
{
int i;
return;
for (i = 0; i < lx_systrace_nsysent; i++) {
continue;
(void *)((uintptr_t)LX_SYSTRACE_ENTRY(i)));
(void *)((uintptr_t)LX_SYSTRACE_RETURN(i)));
}
}
/*ARGSUSED*/
static void
{
if (lx_systrace_nenabled++ == 0)
} else {
}
}
/*ARGSUSED*/
static void
{
} else {
}
if (--lx_systrace_nenabled == 0)
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static uint64_t
int aframes)
{
int i;
if (argno >= 6)
return (0);
/*
* Walk the four frames down the stack to the entry or return callback.
* Our callback calls dtrace_probe() which calls dtrace_dif_variable()
* which invokes this function to get the extended arguments. We get
* the frame pointer in via call to dtrace_getfp() above which makes for
* four frames.
*/
for (i = 0; i < 4; i++) {
}
/*
* Skip the first argument to the callback -- the system call number.
*/
argno++;
#ifdef __amd64
/*
* On amd64, the first 6 arguments are passed in registers while
* subsequent arguments are on the stack.
*/
argno -= 6;
#endif
return (val);
}
static const dtrace_pattr_t lx_systrace_attr = {
};
static dtrace_pops_t lx_systrace_pops = {
NULL,
NULL,
NULL,
NULL,
NULL,
};
static int
{
int i;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
&lx_systrace_id) != 0) {
return (DDI_FAILURE);
}
/*
* Count up the lx_brand system calls.
*/
continue;
/*
* Initialize our corresponding table.
*/
KM_SLEEP);
lx_systrace_nsysent = i;
for (i = 0; i < lx_systrace_nsysent; i++) {
}
/*
* Install probe triggers.
*/
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
switch (cmd) {
case DDI_DETACH:
break;
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
if (dtrace_unregister(lx_systrace_id) != 0)
return (DDI_FAILURE);
/*
* Free table.
*/
sizeof (lx_systrace_sysent_t));
lx_systrace_nsysent = 0;
/*
* Reset probe triggers.
*/
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
return (0);
}
static struct cb_ops lx_systrace_cb_ops = {
lx_systrace_open, /* open */
nodev, /* close */
nulldev, /* strategy */
nulldev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
nodev, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
ddi_prop_op, /* cb_prop_op */
0, /* streamtab */
};
static struct dev_ops lx_systrace_ops = {
DEVO_REV, /* devo_rev */
0, /* refcnt */
ddi_getinfo_1to1, /* get_dev_info */
nulldev, /* identify */
nulldev, /* probe */
lx_systrace_attach, /* attach */
lx_systrace_detach, /* detach */
nodev, /* reset */
&lx_systrace_cb_ops, /* driver operations */
NULL, /* bus operations */
nodev, /* dev power */
ddi_quiesce_not_needed, /* quiesce */
};
/*
* Module linkage information for the kernel.
*/
&mod_driverops, /* module type (this is a pseudo driver) */
"Linux Brand System Call Tracing", /* name of module */
&lx_systrace_ops /* driver ops */
};
static struct modlinkage modlinkage = {
(void *)&modldrv,
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
{
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}