actions.c revision 5403172acfed6a387c70d9cddbc195d9ba8c1e05
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <memory.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <sys/isa_defs.h>
#include <libproc.h>
#include <priv.h>
#include "ramdata.h"
#include "systable.h"
#include "print.h"
#include "proto.h"
/*
* Actions to take when process stops.
*/
/*
* Function prototypes for static routines in this module.
*/
/*
* Report an lwp to be sleeping (if true).
*/
void
{
/* Make sure we catch sysexit even if we're not tracing it. */
return;
}
make_pname(pri, 0);
(void) fputs("(waiting for child to exit()/exec()...)\n",
stdout);
else
}
Flush();
}
/*
* requested() gets called for these reasons:
* flag == JOBSIG: report nothing; change state to JOBSTOP
* flag == JOBSTOP: report "Continued ..."
* default: report sleeping system call
*
* It returns a new flag: JOBSTOP or SLEEPING or 0.
*/
int
{
int newflag = 0;
switch (flag) {
case JOBSIG:
return (JOBSTOP);
case JOBSTOP:
(void) printf(" Continued with signal #%d, %s",
(void) printf(" [default]");
(void) printf(" [ignored]");
else
(void) printf(" [caught]");
Flush();
}
newflag = 0;
break;
default:
if (!cflag)
break;
}
return (newflag);
}
int
{
if (sig == 0)
return (0);
int sys;
(void) printf(" Stopped by signal #%d, %s",
(void) printf(", in %s()",
Flush();
}
return (JOBSTOP);
}
/*
* Return the signal the process stopped on iff process is already stopped on
* PR_JOBCONTROL or is stopped on PR_SIGNALLED or PR_REQUESTED with a current
* signal that will cause a JOBCONTROL stop when the process is set running.
*/
int
{
int sig = 0;
case PR_JOBCONTROL:
sig = 0;
break;
case PR_SIGNALLED:
case PR_REQUESTED:
case SIGSTOP:
break;
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
break;
}
}
break;
}
}
return (sig);
}
int
{
return (0);
(void) mutex_lock(&count_lock);
(void) mutex_unlock(&count_lock);
}
int sys;
(void) printf(" Received signal #%d, %s",
(void) printf(", in %s()",
(void) printf(" [default]");
(void) printf(" [ignored]");
else
(void) printf(" [caught]");
Flush();
}
return (flag);
}
int
{
return (0);
(void) mutex_lock(&count_lock);
(void) mutex_unlock(&count_lock);
if (cflag) /* just counting */
return (1);
(void) printf(" Incurred fault #%d, %s %%pc = 0x%.8lX",
(void) printf(" addr = 0x%.8lX",
Flush();
return (1);
}
/*
* Set up pri->sys_nargs and pri->sys_args[] (syscall args).
*/
void
{
int nargs;
int i;
#if sparc
/* determine whether syscall is indirect */
#else
pri->sys_indirect = 0;
#endif
(void) printf("%s\t*** Inconsistent syscall: %d vs %d ***\n",
}
for (i = 0;
i++)
}
/*
* Return TRUE iff syscall is being traced.
*/
int
{
long arg;
int nargs;
int i;
int x;
int len;
char *s;
int subcode;
int istraced;
int raw;
/* for reporting sleeping system calls */
/* protect ourself from operating system error */
what = 0;
/*
* Set up the system call arguments (pri->sys_nargs & pri->sys_args[]).
*/
/* get systable entry for this syscall */
/* fetch and remember first argument if it's a string */
long offset;
/*
* Special case for exit from exec().
* The address in pri->sys_args[0] refers to the old process
* image. We must fetch the string from the new image.
*/
long argv;
int naux;
offset = 0;
for (i = 0; i < naux; i++) {
break;
}
}
if (offset == 0 &&
if (data_model == PR_MODEL_LP64)
else {
offset32 = 0;
}
}
} else {
}
/* reallocate if necessary */
"pathname buffer");
}
}
}
}
}
*pri->sys_string = 0;
else {
int argprinted = FALSE;
const char *name;
"%s(", name);
for (i = 0; i < nargs; i++) {
argprinted = TRUE;
if (argprinted)
if (x == LLO)
else
/*
* if nothing printed, then don't print ", "
*/
if (x == NOV)
argprinted = FALSE;
else
argprinted = TRUE;
}
}
}
return (istraced);
}
/*
* sysexit() returns non-zero if anything was printed.
*/
int
{
int subcode;
int istraced;
int raw;
/* protect ourself from operating system error */
return (0);
/*
* If we aren't supposed to be tracing this one, then
* delete it from the traced signal set. We got here
* because the process was sleeping in an untraced syscall.
*/
return (0);
}
/* pick up registers & set pri->Errno before anything else */
switch (what) {
case SYS_exit: /* these are traced on entry */
case SYS_lwp_exit:
case SYS_evtrapret:
case SYS_context:
break;
case SYS_exec: /* these are normally traced on entry */
case SYS_execve:
}
break;
}
/* FALLTHROUGH */
default:
/* we called sysentry() in main() for these */
else
}
break;
}
/* get systable entry for this syscall */
(void) mutex_lock(&count_lock);
else if (subcode != -1 &&
what != SYS_lwp_create))
(void) mutex_unlock(&count_lock);
}
if ((what == SYS_forkall ||
what == SYS_forksys) &&
}
}
if (what == SYS_lwp_create &&
}
/* prepare to print the return code */
}
}
if (istraced) {
if (cflag)
else {
const char *privname;
}
case PRIV_NONE:
break;
case PRIV_ALL:
privname = "ALL";
break;
case PRIV_MULTIPLE:
privname = "MULTIPLE";
break;
case PRIV_ALLZONE:
privname = "ZONE";
break;
default:
break;
}
}
}
} else {
/* show arguments on successful exec */
#ifdef _LP64
/*
* 32-bit system calls return 32-bit values. We
* later mask out the upper bits if we want to
* print these as unsigned values.
*/
if (data_model == PR_MODEL_ILP32) {
}
#endif
switch (what) {
case SYS_llseek:
rv1 &= 0xffffffff;
rv2 &= 0xffffffff;
#ifdef _LONG_LONG_LTOH /* first long of a longlong is the low order */
if (rv2 != 0) {
fmt = "= 0x%lX%.8lX";
break;
}
#else /* the other way around */
if (rv1 != 0) {
fmt = "= 0x%lX%.8lX";
break;
}
#endif
/* FALLTHROUGH */
case SYS_lseek:
case SYS_ulimit:
if (rv1 & 0xff000000) {
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv1 &= 0xffffffff;
#endif
fmt = "= 0x%.8lX";
}
break;
case SYS_sigtimedwait:
if (raw)
/* EMPTY */;
fmt = "= %s";
}
break;
case SYS_port:
#ifdef _LP64
if (data_model == PR_MODEL_LP64) {
}
#endif
break;
}
case HEX:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv1 &= 0xffffffff;
#endif
fmt = "= 0x%.8lX";
break;
case HHX:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv1 &= 0xffffffff;
#endif
fmt = "= 0x%.4lX";
break;
case OCT:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv1 &= 0xffffffff;
#endif
fmt = "= %#lo";
break;
case UNS:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv1 &= 0xffffffff;
#endif
fmt = "= %lu";
break;
default:
fmt = "= %ld";
break;
}
}
case NOV:
break;
case HEX:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv2 &= 0xffffffff;
#endif
fmt = " [0x%.8lX]";
break;
case HHX:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv2 &= 0xffffffff;
#endif
fmt = " [0x%.4lX]";
break;
case OCT:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv2 &= 0xffffffff;
#endif
fmt = " [%#lo]";
break;
case UNS:
#ifdef _LP64
if (data_model == PR_MODEL_ILP32)
rv2 &= 0xffffffff;
#endif
fmt = " [%lu]";
break;
default:
fmt = " [%ld]";
break;
}
}
if (what == SYS_forkall ||
what == SYS_forksys) {
}
}
if (raw) {
(void) printf("%s 0x%.8lX: %s\n",
}
}
/*
* Show buffer contents for read()/pread() or write()/pwrite().
* IOBSIZE bytes have already been shown;
* don't show them again unless there's more.
*/
/* enter region of lengthy output */
Eserialize();
/* exit region of lengthy output */
Xserialize();
}
}
/*
* Do verbose interpretation if requested.
* If buffer contents for read or write have been requested and
* this is a readv() or writev(), force verbose interpretation.
*/
what == SYS_sendmsg) &&
}
}
void
{
int i;
int maxleng =
char *s;
else
if (s != (char *)NULL)
(void) printf("%s 0x%.8lX: \"%s\"\n",
}
}
}
/*
* Display arguments to successful exec().
*/
void
{
int nargs;
long ap;
int ptrsize;
int fail;
#endif /* i386 */
#if sparc
if (data_model == PR_MODEL_LP64) {
+ STACK_BIAS;
sizeof (xnargs));
} else {
sizeof (nargs));
}
#endif /* sparc */
if (fail) {
return;
}
if (raw)
/* enter region of (potentially) lengthy output */
Eserialize();
if (aflag) /* dump the argument list */
if (eflag) /* dump the environment */
/* exit region of lengthy output */
Xserialize();
}
}
void
{
char *string;
unsigned int leng = 0;
int ptrsize;
long arg = 0;
char *argaddr;
char badaddr[32];
if (interrupt)
return;
#ifdef _LP64
if (data_model == PR_MODEL_LP64) {
ptrsize = 8;
} else {
#if defined(_LITTLE_ENDIAN)
#else
#endif
ptrsize = 4;
}
#else
ptrsize = 4;
#endif
while (!interrupt) {
(void) printf("\n%s\t*** Bad argument list? ***\n",
return;
}
if (arg == 0)
break;
}
leng++;
} else {
leng = 0;
}
}
}
/*
* Display contents of read() or write() buffer.
*/
void
{
char buffer[320];
int nbytes;
char *buf;
int n;
break;
char obuf[65];
nbytes -= n;
buf += n;
}
}
}
void
{
int c;
while (--n >= 0) {
int c1 = '\\';
int c2;
switch (c = (*buf++ & 0xff)) {
case '\0':
c2 = '0';
break;
case '\b':
c2 = 'b';
break;
case '\t':
c2 = 't';
break;
case '\n':
c2 = 'n';
break;
case '\v':
c2 = 'v';
break;
case '\f':
c2 = 'f';
break;
case '\r':
c2 = 'r';
break;
default:
if (isprint(c)) {
c1 = ' ';
c2 = c;
} else {
c1 = c>>4;
c2 = c&0xf;
}
break;
}
}
*obuf = '\0';
}