[PATCH v2 2/5] Implement -Y option for printing command names for PIDs
Masatake YAMATO
yamato at redhat.com
Tue Aug 24 19:26:40 UTC 2021
From: <yamato at redhat.com>
From: Masatake YAMATO <yamato at redhat.com>
In some applications like qemu-kvm, threads change their
command names to indicate their roles in the application.
Users can access the command name via /proc/$pid/comm.
The command name can be a great hit to understand the application
behavior.
This change introduces -Y option that enables printing command names
where PIDs appear.
For example (without -Y option):
[pid 254329] ioctl(18, KVM_RUN <unfinished ...>
[pid 254332] ioctl(21, KVM_RUN <unfinished ...>
[pid 254331] ioctl(20, KVM_RUN <unfinished ...>
[pid 254330] ioctl(19, KVM_RUN <unfinished ...>
[pid 254309] poll([{fd=9, events=POLLOUT}], 1, 0) = 1 ...
[pid 254309] poll([{fd=9, events=POLLOUT}], 1, 0) = 1 ...
(with -Y option):
[pid 254329<CPU 0/KVM>] ioctl(18, KVM_RUN <unfinished ...>
[pid 254332<CPU 3/KVM>] ioctl(21, KVM_RUN <unfinished ...>
[pid 254331<CPU 2/KVM>] ioctl(20, KVM_RUN <unfinished ...>
[pid 254330<CPU 1/KVM>] ioctl(19, KVM_RUN <unfinished ...>
[pid 254309<qemu-system-x86>] poll([{fd=9, events=POLLOUT}], 1, 0) = 1 ...
[pid 254309<qemu-system-x86>] poll([{fd=9, events=POLLOUT}], 1, 0) = 1 ...
This change considers only PIDs in the prefixes of trace lines.
Printing command names for PIDs in arguments and return values is
future work.
* src/strace.c (usage): Add help message for the -Y option.
(printleader): Print the command name for the given tcb.
(init): Add -Y and --decode-pids(=prefix) options.
Call `qualify_decode_pid' when one of the options is given.
Call `maybe_load_task_comm' to handle the case the options
coming after -p option.
* src/filter_qualify.c (qualify_decode_pid): New function
for setting `decode_pids_enabled'.
* doc/strace.1.in (.SS Output format): document the -Y option.
* NEWS: document the -Y option.
Signed-off-by: Masatake YAMATO <yamato at redhat.com>
---
NEWS | 1 +
doc/strace.1.in | 7 +++++++
src/defs.h | 1 +
src/filter_qualify.c | 9 +++++++++
src/strace.c | 48 +++++++++++++++++++++++++++++++++++++++-----
5 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/NEWS b/NEWS
index 08c3ea1aa..5dd3f2897 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Noteworthy changes in release ?.?? (????-??-??)
* Updated lists of BPF_*, IORING_*, MADV_*, MOUNT_ATTR_*, SCTP_*,
and UFFD_* constants.
* Updated lists of ioctl commands from Linux 5.14.
+ * Implemented -Y,--decode-pids option for printing command names for PIDs.
* Bug fixes
* Fixed build using bionic libc.
diff --git a/doc/strace.1.in b/doc/strace.1.in
index a703f58f7..99fba9076 100644
--- a/doc/strace.1.in
+++ b/doc/strace.1.in
@@ -1082,6 +1082,13 @@ protocol-specific information associated with socket file descriptors,
block/character device number associated with device file descriptors,
and PIDs associated with pidfd file descriptors.
.TP
+.B \-Y
+.TQ
+.B \-\-decode\-pids
+.TQ
+.BR \-\-decode\-pids = prefix
+Print command names for PIDs that appear as the prefixes of trace lines.
+.TP
.B \-\-pidns\-translation
If strace and tracee are in different PID namespaces, print PIDs in
strace's namespace, too.
diff --git a/src/defs.h b/src/defs.h
index fa2b98624..33f44dd64 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1264,6 +1264,7 @@ extern void qualify_signals(const char *);
extern void qualify_status(const char *);
extern void qualify_quiet(const char *);
extern void qualify_decode_fd(const char *);
+extern void qualify_decode_pid(const char *);
extern void qualify_read(const char *);
extern void qualify_write(const char *);
extern void qualify_fault(const char *);
diff --git a/src/filter_qualify.c b/src/filter_qualify.c
index a1a647160..24e840c2f 100644
--- a/src/filter_qualify.c
+++ b/src/filter_qualify.c
@@ -463,6 +463,15 @@ qualify_decode_fd(const char *const str)
"decode-fds");
}
+void
+qualify_decode_pid(const char *const str)
+{
+ if (strcmp(str, "prefix") == 0)
+ decode_pids_enabled = 1;
+ else
+ error_msg_and_die("invalid --decode-pids = argument: '%s'", str);
+}
+
void
qualify_trace(const char *const str)
{
diff --git a/src/strace.c b/src/strace.c
index fd230a263..26d11b271 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -418,6 +418,9 @@ Output format:\n\
-yy, --decode-fds=all\n\
print all available information associated with file\n\
descriptors in addition to paths\n\
+ -Y, --decode-pids[=prefix]\n\
+ print command names associated with the pids appeared\n\
+ as prefixes of trace lines\n\
"
#ifdef ENABLE_SECONTEXT
"\
@@ -800,10 +803,18 @@ printleader(struct tcb *tcp)
set_current_tcp(tcp);
current_tcp->curcol = 0;
- if (print_pid_pfx)
- tprintf("%-5d ", tcp->pid);
- else if (nprocs > 1 && !outfname)
- tprintf("[pid %5u] ", tcp->pid);
+ if (print_pid_pfx) {
+ if (decode_pids_enabled)
+ tprintf("%-5d<%s> ", tcp->pid, tcp->comm);
+ else
+ tprintf("%-5d ", tcp->pid);
+ }
+ else if (nprocs > 1 && !outfname) {
+ if (decode_pids_enabled)
+ tprintf("[pid %5u<%s>] ", tcp->pid, tcp->comm);
+ else
+ tprintf("[pid %5u] ", tcp->pid);
+ }
#ifdef ENABLE_SECONTEXT
char *context;
@@ -2027,6 +2038,7 @@ init(int argc, char *argv[])
static const char qqqflag_qual[] = "all";
static const char yflag_qual[] = "path";
static const char yyflag_qual[] = "all";
+ static const char Yflag_qual[] = "prefix";
static const char tflag_str[] = "format:time";
static const char ttflag_str[] = "precision:us,format:time";
static const char tttflag_str[] = "format:unix,precision:us";
@@ -2039,6 +2051,7 @@ init(int argc, char *argv[])
int qflag_short = 0;
int followfork_short = 0;
int yflag_short = 0;
+ int Yflag_short = 0;
bool tflag_long_set = false;
int tflag_short = 0;
bool columns_set = false;
@@ -2095,7 +2108,7 @@ init(int argc, char *argv[])
qualify_signals("all");
static const char optstring[] =
- "+a:Ab:cCdDe:E:fFhiI:kno:O:p:P:qrs:S:tTu:U:vVwxX:yzZ";
+ "+a:Ab:cCdDe:E:fFhiI:kno:O:p:P:qrs:S:tTu:U:vVwxX:yYzZ";
enum {
GETOPT_SECCOMP = 0x100,
@@ -2122,6 +2135,7 @@ init(int argc, char *argv[])
GETOPT_QUAL_KVM,
GETOPT_QUAL_QUIET,
GETOPT_QUAL_DECODE_FD,
+ GETOPT_QUAL_DECODE_PID,
};
static const struct option longopts[] = {
{ "columns", required_argument, 0, 'a' },
@@ -2183,6 +2197,7 @@ init(int argc, char *argv[])
{ "silent", optional_argument, 0, GETOPT_QUAL_QUIET },
{ "silence", optional_argument, 0, GETOPT_QUAL_QUIET },
{ "decode-fds", optional_argument, 0, GETOPT_QUAL_DECODE_FD },
+ { "decode-pids",optional_argument, 0, GETOPT_QUAL_DECODE_PID },
{ 0, 0, 0, 0 }
};
@@ -2379,6 +2394,9 @@ init(int argc, char *argv[])
case 'y':
yflag_short++;
break;
+ case 'Y':
+ Yflag_short++;
+ break;
case GETOPT_PIDNS_TRANSLATION:
pidns_translation++;
break;
@@ -2445,6 +2463,9 @@ init(int argc, char *argv[])
case GETOPT_QUAL_DECODE_FD:
qualify_decode_fd(optarg ?: yflag_qual);
break;
+ case GETOPT_QUAL_DECODE_PID:
+ qualify_decode_pid(optarg ?: Yflag_qual);
+ break;
default:
error_msg_and_help(NULL);
break;
@@ -2505,6 +2526,23 @@ init(int argc, char *argv[])
qualify_decode_fd(yflag_short == 1 ? yflag_qual : yyflag_qual);
}
+ if (Yflag_short) {
+ if (decode_pids_enabled) {
+ error_msg_and_die("-Y and --decode-pids cannot"
+ " be provided simultaneously");
+ }
+
+ qualify_decode_pid(Yflag_qual);
+ }
+ /* If --decode-pids option comes after -p, comm fields of tcbs
+ * are not filled though tcbs are initialized. We must fill the
+ * fields here. */
+ for (unsigned int i = 0; i < tcbtabsize; ++i) {
+ struct tcb *tcp = tcbtab[i];
+ if (tcp->comm[0] == 0)
+ maybe_load_task_comm(tcp);
+ }
+
if (seccomp_filtering && detach_on_execve) {
error_msg("--seccomp-bpf is not enabled because"
" it is not compatible with -b");
--
2.31.1
More information about the Strace-devel
mailing list