Implement -C option to combine regular and -c output

* defs.h (cflag_t): New enum.
* strace.1: Document -C option.
* strace.c (cflag): Update type.
(main): Handle -C option.
(trace): Update use of cflag.
* count.c (count_syscall): Move clearing of TCB_INSYSCALL to ...
* syscall.c (trace_syscall): ... here.  Update use of cflag.
Based on patch by Adrien Kunysz.
This commit is contained in:
Дмитрий Левин 2010-03-28 19:24:54 +00:00
parent c94a774a3b
commit e3a7ef5a2a
5 changed files with 51 additions and 18 deletions

@ -50,7 +50,6 @@ static struct timeval shortest = { 1000000, 0 };
int
count_syscall(struct tcb *tcp, struct timeval *tv)
{
tcp->flags &= ~TCB_INSYSCALL;
if (tcp->scno < 0 || tcp->scno >= nsyscalls)
return 0;

9
defs.h

@ -456,10 +456,17 @@ extern const struct xlat open_access_modes[];
#define TRACE_SIGNAL 020 /* Trace signal-related syscalls. */
#define TRACE_DESC 040 /* Trace file descriptor-related syscalls. */
typedef enum {
CFLAG_NONE = 0,
CFLAG_ONLY_STATS,
CFLAG_BOTH
} cflag_t;
extern struct tcb **tcbtab;
extern int *qual_flags;
extern int debug, followfork;
extern int dtime, cflag, xflag, qflag;
extern int dtime, xflag, qflag;
extern cflag_t cflag;
extern int acolumn;
extern unsigned int nprocs, tcbtabsize;
extern int max_strlen;

@ -43,7 +43,7 @@ strace \- trace system calls and signals
.SH SYNOPSIS
.B strace
[
.B \-dffhiqrtttTvxx
.B \-CdffhiqrtttTvxx
]
[
.BI \-a column
@ -243,6 +243,11 @@ program exit. On Linux, this attempts to show system time (CPU time spent
running in the kernel) independent of wall clock time. If -c is used with
-f or -F (below), only aggregate totals for all traced processes are kept.
.TP
.B \-C
Like
.B \-c
but also print regular output while processes are running.
.TP
.B \-d
Show some debugging output of
.B strace

@ -83,7 +83,8 @@ extern char *optarg;
int debug = 0, followfork = 0;
int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
int dtime = 0, xflag = 0, qflag = 0;
cflag_t cflag = CFLAG_NONE;
static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
/*
* daemonized_tracer supports -D option.
@ -719,15 +720,27 @@ main(int argc, char *argv[])
qualify("verbose=all");
qualify("signal=all");
while ((c = getopt(argc, argv,
"+cdfFhiqrtTvVxz"
"+cCdfFhiqrtTvVxz"
#ifndef USE_PROCFS
"D"
#endif
"a:e:o:O:p:s:S:u:E:")) != EOF) {
switch (c) {
case 'c':
cflag++;
dtime++;
if (cflag == CFLAG_BOTH) {
fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
progname);
exit(1);
}
cflag = CFLAG_ONLY_STATS;
break;
case 'C':
if (cflag == CFLAG_ONLY_STATS) {
fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
progname);
exit(1);
}
cflag = CFLAG_BOTH;
break;
case 'd':
debug++;
@ -838,7 +851,7 @@ main(int argc, char *argv[])
if (followfork > 1 && cflag) {
fprintf(stderr,
"%s: -c and -ff are mutually exclusive options\n",
"%s: (-c or -C) and -ff are mutually exclusive options\n",
progname);
exit(1);
}
@ -2144,7 +2157,8 @@ trace()
}
break;
case PR_SIGNALLED:
if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
if (cflag != CFLAG_ONLY_STATS
&& (qual_flags[what] & QUAL_SIGNAL)) {
printleader(tcp);
tprintf("--- %s (%s) ---",
signame(what), strsignal(what));
@ -2160,7 +2174,8 @@ trace()
}
break;
case PR_FAULTED:
if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
if (cflag != CFLAGS_ONLY_STATS
&& (qual_flags[what] & QUAL_FAULT)) {
printleader(tcp);
tprintf("=== FAULT %d ===", what);
printtrailer();
@ -2383,7 +2398,7 @@ Process %d attached (waiting for parent)\n",
if (WIFSIGNALED(status)) {
if (pid == strace_child)
exit_code = 0x100 | WTERMSIG(status);
if (!cflag
if (cflag != CFLAG_ONLY_STATS
&& (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
printleader(tcp);
tprintf("+++ killed by %s %s+++",
@ -2482,7 +2497,7 @@ Process %d attached (waiting for parent)\n",
}
continue;
}
if (!cflag
if (cflag != CFLAG_ONLY_STATS
&& (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
unsigned long addr = 0;
long pc = 0;

@ -2369,7 +2369,7 @@ trace_syscall(struct tcb *tcp)
long u_error;
/* Measure the exit time as early as possible to avoid errors. */
if (dtime)
if (dtime || cflag)
gettimeofday(&tv, NULL);
/* BTW, why we don't just memorize syscall no. on entry
@ -2407,8 +2407,15 @@ trace_syscall(struct tcb *tcp)
tprintf(" resumed> ");
}
if (cflag)
return count_syscall(tcp, &tv);
if (cflag) {
struct timeval t = tv;
int rc = count_syscall(tcp, &t);
if (cflag == CFLAG_ONLY_STATS)
{
tcp->flags &= ~TCB_INSYSCALL;
return rc;
}
}
if (res != 1) {
tprintf(") ");
@ -2647,9 +2654,9 @@ trace_syscall(struct tcb *tcp)
return 0;
}
if (cflag) {
gettimeofday(&tcp->etime, NULL);
if (cflag == CFLAG_ONLY_STATS) {
tcp->flags |= TCB_INSYSCALL;
gettimeofday(&tcp->etime, NULL);
return 0;
}
@ -2669,7 +2676,7 @@ trace_syscall(struct tcb *tcp)
return -1;
tcp->flags |= TCB_INSYSCALL;
/* Measure the entrance time as late as possible to avoid errors. */
if (dtime)
if (dtime || cflag)
gettimeofday(&tcp->etime, NULL);
return sys_res;
}