Grok KTR_EXEC_ENV and KTR_EXEC_ARG.

Make ktrace -c default to removing all trace points (not just the default ones).
Make kdump default to dumping everything in the trace file.
Add 'A' (all) and '-' (remove following) to valid -t arguments.
Dump data block of UNKNOWN trace points in hex + ascii.
Make first time output with -R 0 (instead of time since epoch).
Use svis() instead of vis() to get " escaped (as \") (needs fixed libc)
Correctly pass unsigned values to svis()
Update man pages.
This commit is contained in:
dsl 2003-07-17 09:05:11 +00:00
parent 791508af9b
commit fde07830ad
6 changed files with 182 additions and 111 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: kdump.1,v 1.20 2003/07/11 13:05:26 wiz Exp $
.\" $NetBSD: kdump.1,v 1.21 2003/07/17 09:05:13 dsl Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,7 +33,7 @@
.\"
.\" @(#)kdump.1 8.1 (Berkeley) 6/6/93
.\"
.Dd July 11, 2003
.Dd July 17, 2003
.Dt KDUMP 1
.Os
.Sh NAME
@ -101,6 +101,8 @@ Display relative timestamps (time since previous entry).
.It Fl T
Display absolute timestamps for each entry (seconds since epoch).
.It Fl t Ar trstr
Restrict display to the specified set of kernel trace points.
The default is to display everything in the file.
See the
.Fl t
option of

View File

@ -1,4 +1,4 @@
/* $NetBSD: kdump.c,v 1.57 2003/07/13 18:54:29 dsl Exp $ */
/* $NetBSD: kdump.c,v 1.58 2003/07/17 09:05:13 dsl Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\
#if 0
static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: kdump.c,v 1.57 2003/07/13 18:54:29 dsl Exp $");
__RCSID("$NetBSD: kdump.c,v 1.58 2003/07/17 09:05:13 dsl Exp $");
#endif
#endif /* not lint */
@ -100,7 +100,7 @@ static const char *linux_ptrace_ops[] = {
int main __P((int, char **));
int fread_tail __P((char *, int, int));
void dumpheader __P((struct ktr_header *));
int dumpheader __P((struct ktr_header *));
void ioctldecode __P((u_long));
void ktrsyscall __P((struct ktr_syscall *));
void ktrsysret __P((struct ktr_sysret *, int));
@ -116,6 +116,8 @@ void eprint __P((int));
void rprint __P((register_t));
char *ioctlname __P((long));
static const char *signame __P((long, int));
static void hexdump_buf(const void *, int);
static void visdump_buf(const void *, int, int);
int
main(argc, argv)
@ -124,8 +126,10 @@ main(argc, argv)
{
int ch, ktrlen, size;
void *m;
int trpoints = ALL_POINTS;
int trpoints = 0;
int trset = 0;
const char *emul_name = "netbsd";
int col;
while ((ch = getopt(argc, argv, "e:f:dlm:Nnp:RTt:x")) != -1)
switch (ch) {
@ -160,7 +164,8 @@ main(argc, argv)
timestamp = 1;
break;
case 't':
trpoints = getpoints(optarg);
trset = 1;
trpoints = getpoints(trpoints, optarg);
if (trpoints < 0)
errx(1, "unknown trace point in %s", optarg);
break;
@ -173,6 +178,9 @@ main(argc, argv)
argv += optind;
argc -= optind;
if (!trset)
trpoints = ALL_POINTS;
if (tracefile == NULL) {
if (argc == 1) {
tracefile = argv[0];
@ -195,55 +203,63 @@ main(argc, argv)
if (!freopen(tracefile, "r", stdin))
err(1, "%s", tracefile);
while (fread_tail((char *)&ktr_header, sizeof(struct ktr_header), 1)) {
if (trpoints & (1<<ktr_header.ktr_type))
if (do_pid == -1 || ktr_header.ktr_pid == do_pid)
dumpheader(&ktr_header);
if (trpoints & (1<<ktr_header.ktr_type)
&& (do_pid == -1 || ktr_header.ktr_pid == do_pid))
col = dumpheader(&ktr_header);
else
col = -1;
if ((ktrlen = ktr_header.ktr_len) < 0)
errx(1, "bogus length 0x%x", ktrlen);
if (ktrlen > size) {
while(ktrlen > size) size *= 2;
m = (void *)realloc(m, size);
while (ktrlen > size)
size *= 2;
m = realloc(m, size);
if (m == NULL)
errx(1, "realloc: %s", strerror(ENOMEM));
}
if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
errx(1, "data too short");
if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
if (col == -1)
continue;
/* update context to match currently processed record */
if (do_pid != -1 && ktr_header.ktr_pid != do_pid)
continue;
ectx_sanify(ktr_header.ktr_pid);
switch (ktr_header.ktr_type) {
case KTR_SYSCALL:
ktrsyscall((struct ktr_syscall *)m);
ktrsyscall(m);
break;
case KTR_SYSRET:
ktrsysret((struct ktr_sysret *)m, ktrlen);
ktrsysret(m, ktrlen);
break;
case KTR_NAMEI:
ktrnamei(m, ktrlen);
break;
case KTR_GENIO:
ktrgenio((struct ktr_genio *)m, ktrlen);
ktrgenio(m, ktrlen);
break;
case KTR_PSIG:
ktrpsig((struct ktr_psig *)m);
ktrpsig(m);
break;
case KTR_CSW:
ktrcsw((struct ktr_csw *)m);
ktrcsw(m);
break;
case KTR_EMUL:
ktremul(m, ktrlen, size);
break;
case KTR_USER:
ktruser((struct ktr_user *)m, ktrlen);
ktruser(m, ktrlen);
break;
case KTR_MMSG:
ktrmmsg((struct ktr_mmsg *)m, ktrlen);
ktrmmsg(m, ktrlen);
break;
case KTR_EXEC_ARG:
case KTR_EXEC_ENV:
visdump_buf(m, ktrlen, col);
break;
default:
printf("\n");
hexdump_buf(m, ktrlen);
}
if (tail)
(void)fflush(stdout);
@ -265,13 +281,14 @@ fread_tail(buf, size, num)
return (i);
}
void
int
dumpheader(kth)
struct ktr_header *kth;
{
char unknown[64], *type;
static struct timeval prevtime;
struct timeval temp;
int col;
switch (kth->ktr_type) {
case KTR_SYSCALL:
@ -301,22 +318,32 @@ dumpheader(kth)
case KTR_MMSG:
type = "MMSG";
break;
case KTR_EXEC_ENV:
type = "ENV";
break;
case KTR_EXEC_ARG:
type = "ARG";
break;
default:
(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
type = unknown;
}
(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
col = printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
if (timestamp) {
if (timestamp == 2) {
timersub(&kth->ktr_time, &prevtime, &temp);
if (prevtime.tv_sec == 0)
temp.tv_sec = temp.tv_usec = 0;
else
timersub(&kth->ktr_time, &prevtime, &temp);
prevtime = kth->ktr_time;
} else
temp = kth->ktr_time;
(void)printf("%ld.%06ld ",
col += printf("%ld.%06ld ",
(long int)temp.tv_sec, (long int)temp.tv_usec);
}
(void)printf("%s ", type);
col += printf("%-4s ", type);
return col;
}
void
@ -549,41 +576,34 @@ ktremul(name, len, bufsize)
}
static void
hexdump_buf(void *vdp, int datalen)
hexdump_buf(const void *vdp, int datalen)
{
char chars[16];
unsigned char *dp = vdp;
int line_len, i, l, c;
const unsigned char *dp = vdp;
int line_end, off, l, c;
char *cp;
for (; datalen > 0; datalen -= 16) {
line_len = 16;
printf(" ");
if (line_len > datalen)
line_len = datalen;
cp = chars;
l = 0;
printf("\t%3.3lx ", (u_long)dp - (u_long)vdp);
for (i = 0; i < line_len; i++) {
for (off = 0; off < datalen;) {
line_end = off + 16;
if (line_end > datalen)
line_end = datalen;
printf("\t%3.3x ", off);
for (l = 0, cp = chars; off < line_end; off++) {
c = *dp++;
if (i == 8)
if ((off & 7) == 0)
l += printf(" ");
l += printf(" %2.2x", c);
*cp++ = isgraph(c) ? c : '.';
} while (--i);
};
printf("%*s %.*s\n", 50 - l, "", (int)(cp - chars), chars);
}
}
void
ktrgenio(ktr, len)
struct ktr_genio *ktr;
int len;
static void
visdump_buf(const void *vdp, int datalen, int col)
{
int datalen = len - sizeof (struct ktr_genio);
char *dp = (char *)ktr + sizeof (struct ktr_genio);
const unsigned char *dp = vdp;
char *cp;
int col = 0;
int width;
char visbuf[5];
static int screenwidth = 0;
@ -597,20 +617,12 @@ ktrgenio(ktr, len)
else
screenwidth = 80;
}
printf("fd %d %s %d bytes\n", ktr->ktr_fd,
ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
if (maxdata == 0)
return;
if (maxdata > 0 && datalen > maxdata)
datalen = maxdata;
if (hexdump) {
hexdump_buf(dp, datalen);
return;
}
(void)printf(" \"");
col = 8;
(void)printf("\"");
col++;
for (; datalen > 0; datalen--, dp++) {
(void) vis(visbuf, *dp, VIS_CSTYLE, datalen>1?*(dp+1):0);
(void)svis(visbuf, *dp, VIS_CSTYLE,
datalen > 1 ? *(dp + 1) : 0, "\"");
cp = visbuf;
/*
* Keep track of printables and
@ -626,12 +638,12 @@ ktrgenio(ktr, len)
(void)putchar('\n');
continue;
case '\t':
width = 8 - (col&07);
width = 8 - (col & 07);
break;
default:
width = strlen(cp);
}
if (col + width > (screenwidth-2)) {
if (col + width > (screenwidth - 2)) {
(void)printf("\\\n\t");
col = 8;
}
@ -645,6 +657,28 @@ ktrgenio(ktr, len)
(void)printf("\"\n");
}
void
ktrgenio(ktr, len)
struct ktr_genio *ktr;
int len;
{
int datalen = len - sizeof (struct ktr_genio);
char *dp = (char *)ktr + sizeof (struct ktr_genio);
printf("fd %d %s %d bytes\n", ktr->ktr_fd,
ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
if (maxdata == 0)
return;
if (maxdata > 0 && datalen > maxdata)
datalen = maxdata;
if (hexdump) {
hexdump_buf(dp, datalen);
return;
}
(void)printf(" ");
visdump_buf(dp, datalen, 7);
}
void
ktrpsig(psig)
struct ktr_psig *psig;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ktrace.1,v 1.21 2003/05/06 08:22:08 wiz Exp $
.\" $NetBSD: ktrace.1,v 1.22 2003/07/17 09:05:11 dsl Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,7 +33,7 @@
.\"
.\" @(#)ktrace.1 8.1 (Berkeley) 6/6/93
.\"
.Dd May 2, 2003
.Dd July 17, 2003
.Dt KTRACE 1
.Os
.Sh NAME
@ -139,7 +139,9 @@ Print at most
.Ar maxdata
bytes of data.
This is used for pointer type arguments, e.g., strings.
The data will be escaped in C-style.
The data will be escaped in C-style unless
.Fl x
is specified when it will be output in hex and ascii.
.It Fl o Ar outfile
Log trace records to
.Ar outfile .
@ -162,26 +164,34 @@ The string argument represents the kernel trace points, one per letter.
The following table equates the letters with the tracepoints:
.Pp
.Bl -tag -width flag -compact
.It Cm A
trace all tracepoints
.It Cm a
trace exec arguments
.It Cm c
trace system calls
.It Cm e
trace emulation changes
.It Cm n
trace namei translations
.It Cm i
trace
.Tn I/O
.It Cm n
trace namei translations
.It Cm m
trace Mach messages when running Mach binaries with COMPAT_MACH
(currently limited to i386 and powerpc ports).
.It Cm s
trace signal processing
.It Cm u
trace user data
.It Cm m
trace Mach messages when running Mach binaries with COMPAT_MACH
(currently limited to i386 and powerpc ports).
.It Cm v
trace exec environment
.It Cm w
trace context switches
.It Cm +
trace the default set of trace points (c, e, i, m, n, s, u)
.It Cm -
do not trace following trace points
.El
.It Fl e Ar emulation
If an emulation of a process is unknown,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ktrace.c,v 1.26 2002/12/09 21:29:27 manu Exp $ */
/* $NetBSD: ktrace.c,v 1.27 2003/07/17 09:05:12 dsl Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\
#if 0
static char sccsid[] = "@(#)ktrace.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: ktrace.c,v 1.26 2002/12/09 21:29:27 manu Exp $");
__RCSID("$NetBSD: ktrace.c,v 1.27 2003/07/17 09:05:12 dsl Exp $");
#endif
#endif /* not lint */
@ -85,7 +85,7 @@ main(argc, argv)
char **argv;
{
enum { NOTSET, CLEAR, CLEARALL } clear;
int append, ch, fd, inherit, ops, pid, pidset, synclog, trpoints;
int append, ch, fd, trset, ops, pid, pidset, synclog, trpoints;
const char *outfile;
#ifdef KTRUSS
const char *infile;
@ -93,8 +93,8 @@ main(argc, argv)
#endif
clear = NOTSET;
append = ops = pidset = inherit = synclog = 0;
trpoints = DEF_POINTS;
append = ops = pidset = trset = synclog = 0;
trpoints = 0;
pid = 0; /* Appease GCC */
#ifdef KTRUSS
@ -138,7 +138,7 @@ main(argc, argv)
pidset = 1;
break;
case 'i':
inherit = 1;
trpoints |= KTRFAC_INHERIT;
break;
#ifdef KTRUSS
case 'l':
@ -170,7 +170,8 @@ main(argc, argv)
break;
#endif
case 't':
trpoints = getpoints(optarg);
trset = 1;
trpoints = getpoints(trpoints, optarg);
if (trpoints < 0) {
warnx("unknown facility in %s", optarg);
usage();
@ -182,9 +183,12 @@ main(argc, argv)
argv += optind;
argc -= optind;
if (!trset)
trpoints |= clear == NOTSET ? DEF_POINTS : ALL_POINTS;
if ((pidset && *argv) || (!pidset && !*argv)) {
#ifdef KTRUSS
if(!infile)
if (!infile)
#endif
usage();
}
@ -204,9 +208,6 @@ main(argc, argv)
*/
free(malloc(1));
if (inherit)
trpoints |= KTRFAC_INHERIT;
(void)signal(SIGSYS, no_ktrace);
if (clear != NOTSET) {
if (clear == CLEARALL) {
@ -235,7 +236,7 @@ main(argc, argv)
err(1, "exec of '%s' failed", argv[0]);
}
#else
(void) do_ktrace(outfile, ops, trpoints, getpid());
(void)do_ktrace(outfile, ops, trpoints, getpid());
execvp(argv[0], &argv[0]);
err(1, "exec of '%s' failed", argv[0]);
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: ktrace.h,v 1.11 2002/12/09 21:29:27 manu Exp $ */
/* $NetBSD: ktrace.h,v 1.12 2003/07/17 09:05:12 dsl Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -39,12 +39,12 @@
KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_EMUL | KTRFAC_USER | \
KTRFAC_MMSG)
#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
#define ALL_POINTS KTRFAC_MASK
#define DEF_TRACEFILE "ktrace.out"
#include <sys/cdefs.h>
int getpoints __P((char *));
char *ioctlname __P((long));
void dumpfile __P((const char *, int, int));
int getpoints(int, char *);
char *ioctlname(long);
void dumpfile(const char *, int, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr.c,v 1.9 2002/12/09 21:29:27 manu Exp $ */
/* $NetBSD: subr.c,v 1.10 2003/07/17 09:05:12 dsl Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)subr.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: subr.c,v 1.9 2002/12/09 21:29:27 manu Exp $");
__RCSID("$NetBSD: subr.c,v 1.10 2003/07/17 09:05:12 dsl Exp $");
#endif
#endif /* not lint */
@ -54,44 +54,68 @@ __RCSID("$NetBSD: subr.c,v 1.9 2002/12/09 21:29:27 manu Exp $");
#include "ktrace.h"
int
getpoints(s)
char *s;
getpoints(int facs, char *s)
{
int facs = 0;
int fac;
int add = 1;
while (*s) {
switch(*s) {
/* Make -t-x equivalent to -t+-x since that is rather more useful */
if (*s == '-' && (facs & ALL_POINTS) == 0)
facs |= DEF_POINTS;
for (;;) {
switch (*s++) {
case 0:
return facs;
case 'A':
fac = ALL_POINTS;
break;
case 'a':
fac = KTRFAC_EXEC_ARG;
break;
case 'c':
facs |= KTRFAC_SYSCALL | KTRFAC_SYSRET;
fac = KTRFAC_SYSCALL | KTRFAC_SYSRET;
break;
case 'e':
facs |= KTRFAC_EMUL;
break;
case 'n':
facs |= KTRFAC_NAMEI;
fac = KTRFAC_EMUL;
break;
case 'i':
facs |= KTRFAC_GENIO;
fac = KTRFAC_GENIO;
break;
case 's':
facs |= KTRFAC_PSIG;
break;
case 'u':
facs |= KTRFAC_USER;
case 'n':
fac = KTRFAC_NAMEI;
break;
case 'm':
facs |= KTRFAC_MMSG;
fac = KTRFAC_MMSG;
break;
case 's':
fac = KTRFAC_PSIG;
break;
case 'u':
fac = KTRFAC_USER;
break;
case 'v':
fac = KTRFAC_EXEC_ENV;
break;
case 'w':
facs |= KTRFAC_CSW;
fac = KTRFAC_CSW;
break;
case '+':
facs |= DEF_POINTS;
if (!add) {
add = 1;
continue;
}
fac = DEF_POINTS;
break;
case '-':
add = 0;
continue;
default:
return (-1);
}
s++;
if (add)
facs |= fac;
else
facs &= ~fac;
}
return (facs);
}