perf trace: Add option to show process COMM
[platform/adaptation/renesas_rcar/renesas_kernel.git] / tools / perf / builtin-trace.c
index 7cb6052..be65843 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <libaudit.h>
 #include <stdlib.h>
+#include <sys/eventfd.h>
 #include <sys/mman.h>
 #include <linux/futex.h>
 
@@ -244,6 +245,162 @@ static const char *whences[] = { "SET", "CUR", "END",
 };
 static DEFINE_STRARRAY(whences);
 
+static const char *fcntl_cmds[] = {
+       "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
+       "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
+       "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
+       "F_GETOWNER_UIDS",
+};
+static DEFINE_STRARRAY(fcntl_cmds);
+
+static const char *rlimit_resources[] = {
+       "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
+       "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
+       "RTTIME",
+};
+static DEFINE_STRARRAY(rlimit_resources);
+
+static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
+static DEFINE_STRARRAY(sighow);
+
+static const char *socket_families[] = {
+       "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
+       "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
+       "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
+       "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
+       "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
+       "ALG", "NFC", "VSOCK",
+};
+static DEFINE_STRARRAY(socket_families);
+
+#ifndef SOCK_TYPE_MASK
+#define SOCK_TYPE_MASK 0xf
+#endif
+
+static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
+                                                     struct syscall_arg *arg)
+{
+       size_t printed;
+       int type = arg->val,
+           flags = type & ~SOCK_TYPE_MASK;
+
+       type &= SOCK_TYPE_MASK;
+       /*
+        * Can't use a strarray, MIPS may override for ABI reasons.
+        */
+       switch (type) {
+#define        P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
+       P_SK_TYPE(STREAM);
+       P_SK_TYPE(DGRAM);
+       P_SK_TYPE(RAW);
+       P_SK_TYPE(RDM);
+       P_SK_TYPE(SEQPACKET);
+       P_SK_TYPE(DCCP);
+       P_SK_TYPE(PACKET);
+#undef P_SK_TYPE
+       default:
+               printed = scnprintf(bf, size, "%#x", type);
+       }
+
+#define        P_SK_FLAG(n) \
+       if (flags & SOCK_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
+               flags &= ~SOCK_##n; \
+       }
+
+       P_SK_FLAG(CLOEXEC);
+       P_SK_FLAG(NONBLOCK);
+#undef P_SK_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
+
+       return printed;
+}
+
+#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
+
+#ifndef MSG_PROBE
+#define MSG_PROBE           0x10
+#endif
+#ifndef MSG_SENDPAGE_NOTLAST
+#define MSG_SENDPAGE_NOTLAST 0x20000
+#endif
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN        0x20000000
+#endif
+
+static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
+                                              struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+       if (flags == 0)
+               return scnprintf(bf, size, "NONE");
+#define        P_MSG_FLAG(n) \
+       if (flags & MSG_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~MSG_##n; \
+       }
+
+       P_MSG_FLAG(OOB);
+       P_MSG_FLAG(PEEK);
+       P_MSG_FLAG(DONTROUTE);
+       P_MSG_FLAG(TRYHARD);
+       P_MSG_FLAG(CTRUNC);
+       P_MSG_FLAG(PROBE);
+       P_MSG_FLAG(TRUNC);
+       P_MSG_FLAG(DONTWAIT);
+       P_MSG_FLAG(EOR);
+       P_MSG_FLAG(WAITALL);
+       P_MSG_FLAG(FIN);
+       P_MSG_FLAG(SYN);
+       P_MSG_FLAG(CONFIRM);
+       P_MSG_FLAG(RST);
+       P_MSG_FLAG(ERRQUEUE);
+       P_MSG_FLAG(NOSIGNAL);
+       P_MSG_FLAG(MORE);
+       P_MSG_FLAG(WAITFORONE);
+       P_MSG_FLAG(SENDPAGE_NOTLAST);
+       P_MSG_FLAG(FASTOPEN);
+       P_MSG_FLAG(CMSG_CLOEXEC);
+#undef P_MSG_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
+
+#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
+
+static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
+                                                struct syscall_arg *arg)
+{
+       size_t printed = 0;
+       int mode = arg->val;
+
+       if (mode == F_OK) /* 0 */
+               return scnprintf(bf, size, "F");
+#define        P_MODE(n) \
+       if (mode & n##_OK) { \
+               printed += scnprintf(bf + printed, size - printed, "%s", #n); \
+               mode &= ~n##_OK; \
+       }
+
+       P_MODE(R);
+       P_MODE(W);
+       P_MODE(X);
+#undef P_MODE
+
+       if (mode)
+               printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
+
+       return printed;
+}
+
+#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
+
 static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
                                               struct syscall_arg *arg)
 {
@@ -300,6 +457,77 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
 
 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
 
+static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
+                                                  struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+       if (flags == 0)
+               return scnprintf(bf, size, "NONE");
+#define        P_FLAG(n) \
+       if (flags & EFD_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~EFD_##n; \
+       }
+
+       P_FLAG(SEMAPHORE);
+       P_FLAG(CLOEXEC);
+       P_FLAG(NONBLOCK);
+#undef P_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
+
+#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
+
+static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
+{
+       int sig = arg->val;
+
+       switch (sig) {
+#define        P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
+       P_SIGNUM(HUP);
+       P_SIGNUM(INT);
+       P_SIGNUM(QUIT);
+       P_SIGNUM(ILL);
+       P_SIGNUM(TRAP);
+       P_SIGNUM(ABRT);
+       P_SIGNUM(BUS);
+       P_SIGNUM(FPE);
+       P_SIGNUM(KILL);
+       P_SIGNUM(USR1);
+       P_SIGNUM(SEGV);
+       P_SIGNUM(USR2);
+       P_SIGNUM(PIPE);
+       P_SIGNUM(ALRM);
+       P_SIGNUM(TERM);
+       P_SIGNUM(STKFLT);
+       P_SIGNUM(CHLD);
+       P_SIGNUM(CONT);
+       P_SIGNUM(STOP);
+       P_SIGNUM(TSTP);
+       P_SIGNUM(TTIN);
+       P_SIGNUM(TTOU);
+       P_SIGNUM(URG);
+       P_SIGNUM(XCPU);
+       P_SIGNUM(XFSZ);
+       P_SIGNUM(VTALRM);
+       P_SIGNUM(PROF);
+       P_SIGNUM(WINCH);
+       P_SIGNUM(IO);
+       P_SIGNUM(PWR);
+       P_SIGNUM(SYS);
+       default: break;
+       }
+
+       return scnprintf(bf, size, "%#x", sig);
+}
+
+#define SCA_SIGNUM syscall_arg__scnprintf_signum
+
 static struct syscall_fmt {
        const char *name;
        const char *alias;
@@ -309,12 +537,17 @@ static struct syscall_fmt {
        bool       timeout;
        bool       hexret;
 } syscall_fmts[] = {
-       { .name     = "access",     .errmsg = true, },
+       { .name     = "access",     .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
        { .name     = "arch_prctl", .errmsg = true, .alias = "prctl", },
        { .name     = "brk",        .hexret = true,
          .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
-       { .name     = "mmap",       .hexret = true, },
        { .name     = "connect",    .errmsg = true, },
+       { .name     = "eventfd2",   .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
+       { .name     = "fcntl",      .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
+         .arg_parm      = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
        { .name     = "fstat",      .errmsg = true, .alias = "newfstat", },
        { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat", },
        { .name     = "futex",      .errmsg = true,
@@ -322,8 +555,13 @@ static struct syscall_fmt {
        { .name     = "getitimer",  .errmsg = true,
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
          .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
+       { .name     = "getrlimit",  .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
        { .name     = "ioctl",      .errmsg = true,
          .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
+       { .name     = "kill",       .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "lseek",      .errmsg = true,
          .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
          .arg_parm      = { [2] = &strarray__whences, /* whence */ }, },
@@ -352,15 +590,48 @@ static struct syscall_fmt {
        { .name     = "poll",       .errmsg = true, .timeout = true, },
        { .name     = "ppoll",      .errmsg = true, .timeout = true, },
        { .name     = "pread",      .errmsg = true, .alias = "pread64", },
+       { .name     = "prlimit64",  .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [1] = &strarray__rlimit_resources, /* resource */ }, },
        { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64", },
        { .name     = "read",       .errmsg = true, },
-       { .name     = "recvfrom",   .errmsg = true, },
+       { .name     = "recvfrom",   .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "recvmmsg",   .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "recvmsg",    .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "rt_sigaction", .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
+       { .name     = "rt_sigprocmask", .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* how */ },
+         .arg_parm      = { [0] = &strarray__sighow, /* how */ }, },
+       { .name     = "rt_sigqueueinfo", .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+       { .name     = "rt_tgsigqueueinfo", .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "select",     .errmsg = true, .timeout = true, },
+       { .name     = "sendmmsg",    .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "sendmsg",    .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "sendto",     .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
        { .name     = "setitimer",  .errmsg = true,
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
          .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
-       { .name     = "socket",     .errmsg = true, },
+       { .name     = "setrlimit",  .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
+       { .name     = "socket",     .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
+                            [1] = SCA_SK_TYPE, /* type */ },
+         .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
        { .name     = "stat",       .errmsg = true, .alias = "newstat", },
+       { .name     = "tgkill",     .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
+       { .name     = "tkill",      .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "uname",      .errmsg = true, .alias = "newuname", },
 };
 
@@ -446,6 +717,7 @@ struct trace {
        struct perf_record_opts opts;
        struct machine          host;
        u64                     base_time;
+       bool                    full_time;
        FILE                    *output;
        unsigned long           nr_events;
        struct strlist          *ev_qualifier;
@@ -454,6 +726,7 @@ struct trace {
        struct intlist          *pid_list;
        bool                    sched;
        bool                    multiple_threads;
+       bool                    show_comm;
        double                  duration_filter;
        double                  runtime_ms;
 };
@@ -483,8 +756,11 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
        size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
        printed += fprintf_duration(duration, fp);
 
-       if (trace->multiple_threads)
+       if (trace->multiple_threads) {
+               if (trace->show_comm)
+                       printed += fprintf(fp, "%.14s/", thread->comm);
                printed += fprintf(fp, "%d ", thread->tid);
+       }
 
        return printed;
 }
@@ -640,6 +916,9 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
                        if (arg.mask & bit)
                                continue;
 
+                       if (args[arg.idx] == 0)
+                               continue;
+
                        printed += scnprintf(bf + printed, size - printed,
                                             "%s%s: ", printed ? ", " : "", field->name);
                        if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
@@ -888,7 +1167,7 @@ static int trace__process_sample(struct perf_tool *tool,
        if (skip_sample(trace, sample))
                return 0;
 
-       if (trace->base_time == 0)
+       if (!trace->full_time && trace->base_time == 0)
                trace->base_time = sample->time;
 
        if (handler)
@@ -1017,7 +1296,7 @@ again:
                                continue;
                        }
 
-                       if (trace->base_time == 0)
+                       if (!trace->full_time && trace->base_time == 0)
                                trace->base_time = sample.time;
 
                        if (type != PERF_RECORD_SAMPLE) {
@@ -1228,10 +1507,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                        .mmap_pages    = 1024,
                },
                .output = stdout,
+               .show_comm = true,
        };
        const char *output_name = NULL;
        const char *ev_qualifier_str = NULL;
        const struct option trace_options[] = {
+       OPT_BOOLEAN(0, "comm", &trace.show_comm,
+                   "show the thread COMM next to its id"),
        OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
                    "list of events to trace"),
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1255,6 +1537,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                     trace__set_duration),
        OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
        OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+       OPT_BOOLEAN('T', "time", &trace.full_time,
+                   "Show full timestamp, not time relative to first start"),
        OPT_END()
        };
        int err;