/*
* 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
*/
/*
*/
#include <mdb/mdb_modapi.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <thr_uberdata.h>
#include <stddef.h>
#include "findstack.h"
struct rwindow {
};
#endif
#ifndef STACK_BIAS
#define STACK_BIAS 0
#endif
#ifdef __amd64
#else
#ifdef __i386
#else
#endif
#endif
int
{
/*
* When run with "-i", ::stacks filters out "FREE" threads.
* We therefore need to recognize "FREE", and set it to a
* value that will never match fsi_tstate.
*/
} else {
return (-1);
}
return (0);
}
void
{
}
int
{
} else {
return (-1);
}
return (0);
}
void
{
}
static int
{
const char *s, *next;
return (0);
/*
* It doesn't match the name, but -- for convenience -- we want to
* allow matches before ".so.[suffix]". An aside: why doesn't
* strrstr() exist? (Don't google that. I'm serious, don't do it.
* If you do, and you read the thread of "why doesn't strrstr() exist?"
* circa 2005 you will see things that you will NEVER be able to unsee!)
*/
s = next;
continue;
}
}
/*
* If we have a library that has the libc directory in the path, we
* want to match against anything that would match libc.so.1. (This
* is necessary to be able to easily deal with libc implementations
* that have alternate hardware capabilities.)
*/
}
if (match) {
}
return (0);
}
int
{
return (-1);
return (0);
}
typedef struct stacks_ulwp {
/*ARGSUSED*/
int
{
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
stacks_ulwp_compare(const void *l, const void *r)
{
return (1);
return (-1);
return (0);
}
/*ARGSUSED*/
int
{
fsip->fsi_failed = 0;
fsip->fsi_overflow = 0;
if (!stacks_ulwp_initialized) {
if (mdb_walk("ulwp",
mdb_warn("couldn't walk 'ulwp'");
return (-1);
}
}
return (-1);
}
mdb_warn("couldn't read ulwp_t for tid %d at %p",
return (-1);
}
return (-1);
}
#if !defined(__i386)
return (-1);
}
#endif
mdb_warn("couldn't read frame for thread 0x%p at %p",
return (-1);
}
break;
} else {
break;
}
}
return (0);
}
void
{
if (!stacks_ulwp_initialized)
return;
}
void
stacks_help(void)
{
"::stacks processes all of the thread stacks in the process, grouping\n"
"together threads which have the same:\n"
"\n"
" * Thread state,\n"
" * Sync object type, and\n"
" * PCs in their stack trace.\n"
"\n"
"The default output (no address or options) is just a dump of the thread\n"
"groups in the process. For a view of active threads, use \"::stacks -i\",\n"
"which filters out threads sleeping on a CV. More general filtering options\n"
"are described below, in the \"FILTERS\" section.\n"
"\n"
"::stacks can be used in a pipeline. The input to ::stacks is one or more\n"
"thread IDs. When output into a pipe, ::stacks prints all of the threads \n"
"input, filtered by the given filtering options. This means that multiple\n"
"::stacks invocations can be piped together to achieve more complicated\n"
"filters. For example, to get threads which have both '__door_return' and\n"
"'mutex_lock' in their stack trace, you could do:\n"
"\n"
" ::stacks -c __door_return | ::stacks -c mutex_lock\n"
"\n"
"To get the full list of threads in each group, use the '-a' flag:\n"
"\n"
" ::stacks -a\n"
"\n");
mdb_dec_indent(2);
mdb_printf("%<b>OPTIONS%</b>\n");
mdb_inc_indent(2);
mdb_printf("%s",
" -a Print all of the grouped threads, instead of just a count.\n"
" -f Force a re-run of the thread stack gathering.\n"
" -v Be verbose about thread stack gathering.\n"
"\n");
mdb_dec_indent(2);
mdb_printf("%<b>FILTERS%</b>\n");
mdb_inc_indent(2);
mdb_printf("%s",
" -i Show active threads; equivalent to '-S CV'.\n"
" -c func[+offset]\n"
" -C func[+offset]\n"
" -m module\n"
" Only print threads whose stacks contain functions from module.\n"
" -M module\n"
" Only print threads whose stacks do not contain functions from\n"
" module.\n"
" -s {type | ALL}\n"
" Only print threads which are on a 'type' synchronization object\n"
" (SOBJ).\n"
" -S {type | ALL}\n"
" Only print threads which are not on a 'type' SOBJ.\n"
" -t tstate\n"
" Only print threads which are in thread state 'tstate'.\n"
" -T tstate\n"
" Only print threads which are not in thread state 'tstate'.\n"
"\n");
}