/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 (c) 1994, by Sun Microsytems, Inc.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Interfaces to control kernel tracing and kernel probes
*/
#ifndef DEBUG
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> /* for strerror() */
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include "tnfctl_int.h"
#include "kernel_int.h"
/* The TNF pseudo-device */
/* Dummy "test" function -- just used to flag enabled probes */
/* Dummy "commit" function -- just used to flag trace enabled */
/* Dummy "rollback" function -- just used to flag trace disabled */
/* Dummy "end" function */
/* Dummy "alloc" function */
/* Minimum and maximum allowed buffer sizes. */
/* XXX -- maximum should be some function of physmem. */
/*
* Initialize the kernel interface: Open the TNF control device,
* and determine the current kernel probes state, including the
* current pidfilter list.
*/
{
int kfd;
if (kfd < 0) {
return (tnfctl_status_map(errno));
}
return (tnfctl_status_map(errno));
if (prexstat)
return (prexstat);
return (TNFCTL_ERR_NONE);
}
/*
* Close the TNF control device.
*/
{
return (TNFCTL_ERR_NONE);
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_NONE);
}
/*
* Returns function addresses that can be plugged into function pointers
* in kernel probes. These are actually dummy values that get
* interpreted by a routine in this file when a probe is flushed.
*/
void
{
*endp = PRBK_DUMMY_END;
}
/*
* Returns test function address
*/
void
{
}
/*
* Allocate a trace buffer. Check for reasonable size; reject if there's
* already a buffer.
*/
{
int saved_val;
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_BUFEXISTS);
}
if (size < KERNEL_MINBUF_SIZE) {
return (TNFCTL_ERR_SIZETOOSMALL);
} else if (size > KERNEL_MAXBUF_SIZE) {
/* REMIND: make this an error ? */
}
(void) prbk_get_buf_attrs(hdl);
return (tnfctl_status_map(saved_val));
}
if (prexstat)
return (prexstat);
return (TNFCTL_ERR_NONE);
}
/*
* Deallocate the kernel's trace buffer.
*/
{
int saved_val;
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_NOBUF);
}
return (TNFCTL_ERR_BADDEALLOC);
}
(void) prbk_get_buf_attrs(hdl);
return (tnfctl_status_map(saved_val));
}
if (prexstat)
return (prexstat);
return (TNFCTL_ERR_NONE);
}
/*
* Turns kernel global tracing on or off.
*/
{
return (TNFCTL_ERR_NOBUF);
else
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_NONE);
}
/*
* Turn process filter mode on or off. The process filter is maintained
* even when process filtering is off, but has no effect: all processes
* are traced.
*/
{
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_NONE);
}
/*
* Return the process filter list.
*/
int *ret_count)
{
int *filterset;
int i;
return (tnfctl_status_map(errno));
if (kstate.pidfilter_size == 0) {
*ret_count = 0;
*ret_list_p = NULL;
return (TNFCTL_ERR_NONE);
}
sizeof (pid_t));
return (TNFCTL_ERR_ALLOCFAIL);
return (tnfctl_status_map(errno));
/* filterset[0] contains size of array */
return (TNFCTL_ERR_ALLOCFAIL);
for (i = 1; i <= filterset[0]; ++i)
*ret_list_p = ret_list;
return (TNFCTL_ERR_NONE);
}
/*
* Add the pid to the process filter list.
* check whether it's already in the filter list,
* and whether the process exists.
*/
{
return (tnfctl_status_map(errno));
}
return (TNFCTL_ERR_NONE);
}
/*
* Drop the pid from the process filter list.
*/
{
return (TNFCTL_ERR_NOPROCESS);
} else {
return (tnfctl_status_map(errno));
}
}
return (TNFCTL_ERR_NONE);
}
/*
* get the buffer attributes - side effect tnfctl handle
*/
static tnfctl_errcode_t
{
return (tnfctl_status_map(errno));
}
else
return (TNFCTL_ERR_NONE);
}
/*
* "Flush" a probe: i.e., sync up the kernel state with the
* (desired) state stored in our data structure.
*/
{
return (tnfctl_status_map(errno));
return (TNFCTL_ERR_NONE);
}
/*
* Refresh our understanding of the existing probes in the kernel.
*/
{
int maxprobe, i;
int pos;
prbctlref_t *p = NULL;
if (prexstat)
return (prexstat);
/*
* Here is where you'd set obj_p->new to B_FALSE and obj_p->old to
* B_TRUE for all existing objects. We currently don't need
*/
return (tnfctl_status_map(errno));
/* XXX Inadequate in the presence of module unloading */
return (TNFCTL_ERR_NONE);
}
if (prexstat)
return (prexstat);
for (i = 1; i <= maxprobe; ++i) {
}
/* make sure we are in the correct object */
/* get a pointer to correct probe */
/*
* This probe has vanished due to a module
* unload.
*/
} else {
return (tnfctl_status_map(errno));
}
} else {
/*
* seeing this probe for the first time
* (alloc_probe_space() initialized this
* "valid" field to B_FALSE)
*/
/* Update our info about this probe */
if (p->attr_string == NULL)
return (TNFCTL_ERR_ALLOCFAIL);
/*
* NOTE: the next statement is a structure
* copy and *not* a pointer assignment
*/
/* LINTED pointer cast may result in improper alignment */
p->attr_string) < 0)
return (tnfctl_status_map(errno));
if (hndl->create_func) {
p->probe_handle);
}
}
}
}
return (TNFCTL_ERR_NONE);
}
/*
* check if there are any new probes in the kernel that we aren't aware of.
* If so, allocate space for those probes in our data structure.
*/
static tnfctl_errcode_t
{
int min_probe_num, i;
/* we know that: hndl->maxprobe != maxprobe */
/* no objects allocated */
min_probe_num = 1;
} else {
/* find last object */
}
}
return (TNFCTL_ERR_ALLOCFAIL);
/* add to the linked list */
/* NULL, B_FALSE, or 0's not explicitly initialized */
return (TNFCTL_ERR_ALLOCFAIL);
}
for (i = min_probe_num; i <= maxprobe; i++) {
return (TNFCTL_ERR_ALLOCFAIL);
}
/* link in probe handle into chain off tnfctl_handle_t */
probe_p++;
}
return (TNFCTL_ERR_NONE);
}