summaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c744
1 files changed, 401 insertions, 343 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d298197..d59cdadf3a79 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -64,6 +64,10 @@
# define O_CLOEXEC 02000000
#endif
+#ifndef F_LINUX_SPECIFIC_BASE
+# define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
struct trace {
struct perf_tool tool;
struct syscalltbl *sctbl;
@@ -279,34 +283,21 @@ out_delete:
({ struct syscall_tp *fields = evsel->priv; \
fields->name.pointer(&fields->name, sample); })
-struct strarray {
- int offset;
- int nr_entries;
- const char **entries;
-};
+size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val)
+{
+ int idx = val - sa->offset;
-#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
- .nr_entries = ARRAY_SIZE(array), \
- .entries = array, \
-}
+ if (idx < 0 || idx >= sa->nr_entries)
+ return scnprintf(bf, size, intfmt, val);
-#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
- .offset = off, \
- .nr_entries = ARRAY_SIZE(array), \
- .entries = array, \
+ return scnprintf(bf, size, "%s", sa->entries[idx]);
}
static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
const char *intfmt,
struct syscall_arg *arg)
{
- struct strarray *sa = arg->parm;
- int idx = arg->val - sa->offset;
-
- if (idx < 0 || idx >= sa->nr_entries)
- return scnprintf(bf, size, intfmt, arg->val);
-
- return scnprintf(bf, size, "%s", sa->entries[idx]);
+ return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->val);
}
static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
@@ -317,24 +308,35 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
#define SCA_STRARRAY syscall_arg__scnprintf_strarray
-#if defined(__i386__) || defined(__x86_64__)
-/*
- * FIXME: Make this available to all arches as soon as the ioctl beautifier
- * gets rewritten to support all arches.
- */
-static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
- struct syscall_arg *arg)
-{
- return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
+struct strarrays {
+ int nr_entries;
+ struct strarray **entries;
+};
+
+#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
}
-#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
-#endif /* defined(__i386__) || defined(__x86_64__) */
+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
+ struct syscall_arg *arg)
+{
+ struct strarrays *sas = arg->parm;
+ int i;
-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg);
+ for (i = 0; i < sas->nr_entries; ++i) {
+ struct strarray *sa = sas->entries[i];
+ int idx = arg->val - sa->offset;
-#define SCA_FD syscall_arg__scnprintf_fd
+ if (idx >= 0 && idx < sa->nr_entries) {
+ if (sa->entries[idx] == NULL)
+ break;
+ return scnprintf(bf, size, "%s", sa->entries[idx]);
+ }
+ }
+
+ return scnprintf(bf, size, "%d", arg->val);
+}
#ifndef AT_FDCWD
#define AT_FDCWD -100
@@ -358,21 +360,20 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
-static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%#lx", arg->val);
}
-#define SCA_HEX syscall_arg__scnprintf_hex
-
-static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg)
{
return scnprintf(bf, size, "%d", arg->val);
}
-#define SCA_INT syscall_arg__scnprintf_int
+size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return scnprintf(bf, size, "%ld", arg->val);
+}
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
@@ -407,12 +408,27 @@ 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",
+ "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "GETLK64",
+ "SETLK64", "SETLKW64", "SETOWN_EX", "GETOWN_EX",
+ "GETOWNER_UIDS",
};
static DEFINE_STRARRAY(fcntl_cmds);
+static const char *fcntl_linux_specific_cmds[] = {
+ "SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC",
+ "SETPIPE_SZ", "GETPIPE_SZ", "ADD_SEALS", "GET_SEALS",
+ "GET_RW_HINT", "SET_RW_HINT", "GET_FILE_RW_HINT", "SET_FILE_RW_HINT",
+};
+
+static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE);
+
+static struct strarray *fcntl_cmds_arrays[] = {
+ &strarray__fcntl_cmds,
+ &strarray__fcntl_linux_specific_cmds,
+};
+
+static DEFINE_STRARRAYS(fcntl_cmds_arrays);
+
static const char *rlimit_resources[] = {
"CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
"MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
@@ -495,33 +511,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
-#if defined(__i386__) || defined(__x86_64__)
-/*
- * FIXME: Make this available to all arches.
- */
-#define TCGETS 0x5401
-
-static const char *tioctls[] = {
- "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
- "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
- "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
- "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
- "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
- "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
- "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
- "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
- "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
- "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
- "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
- [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
- "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
- "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
- "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
-};
-
-static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
-#endif /* defined(__i386__) || defined(__x86_64__) */
-
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
@@ -552,9 +541,9 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
-#define STRARRAY(arg, name, array) \
- .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
- .arg_parm = { [arg] = &strarray__##array, }
+#define STRARRAY(name, array) \
+ { .scnprintf = SCA_STRARRAY, \
+ .parm = &strarray__##array, }
#include "trace/beauty/eventfd.c"
#include "trace/beauty/flock.c"
@@ -571,242 +560,219 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
#include "trace/beauty/socket_type.c"
#include "trace/beauty/waitid_options.c"
+struct syscall_arg_fmt {
+ size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
+ void *parm;
+ const char *name;
+ bool show_zero;
+};
+
static struct syscall_fmt {
const char *name;
const char *alias;
- size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
- void *arg_parm[6];
- bool errmsg;
+ struct syscall_arg_fmt arg[6];
+ u8 nr_args;
bool errpid;
bool timeout;
bool hexret;
} syscall_fmts[] = {
- { .name = "access", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
- { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
- { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
+ { .name = "access",
+ .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
+ { .name = "arch_prctl", .alias = "prctl", },
+ { .name = "bpf",
+ .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
{ .name = "brk", .hexret = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
- { .name = "chdir", .errmsg = true, },
- { .name = "chmod", .errmsg = true, },
- { .name = "chroot", .errmsg = true, },
- { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
- { .name = "clone", .errpid = true, },
- { .name = "close", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
- { .name = "connect", .errmsg = true, },
- { .name = "creat", .errmsg = true, },
- { .name = "dup", .errmsg = true, },
- { .name = "dup2", .errmsg = true, },
- { .name = "dup3", .errmsg = true, },
- { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
- { .name = "eventfd2", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
- { .name = "faccessat", .errmsg = true, },
- { .name = "fadvise64", .errmsg = true, },
- { .name = "fallocate", .errmsg = true, },
- { .name = "fchdir", .errmsg = true, },
- { .name = "fchmod", .errmsg = true, },
- { .name = "fchmodat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "fchown", .errmsg = true, },
- { .name = "fchownat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "fcntl", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
- .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
- { .name = "fdatasync", .errmsg = true, },
- { .name = "flock", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
- { .name = "fsetxattr", .errmsg = true, },
- { .name = "fstat", .errmsg = true, .alias = "newfstat", },
- { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
- { .name = "fstatfs", .errmsg = true, },
- { .name = "fsync", .errmsg = true, },
- { .name = "ftruncate", .errmsg = true, },
- { .name = "futex", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
- { .name = "futimesat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "getdents", .errmsg = true, },
- { .name = "getdents64", .errmsg = true, },
- { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
+ { .name = "clock_gettime",
+ .arg = { [0] = STRARRAY(clk_id, clockid), }, },
+ { .name = "clone", .errpid = true, .nr_args = 5,
+ .arg = { [0] = { .name = "flags", .scnprintf = SCA_CLONE_FLAGS, },
+ [1] = { .name = "child_stack", .scnprintf = SCA_HEX, },
+ [2] = { .name = "parent_tidptr", .scnprintf = SCA_HEX, },
+ [3] = { .name = "child_tidptr", .scnprintf = SCA_HEX, },
+ [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
+ { .name = "close",
+ .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
+ { .name = "epoll_ctl",
+ .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
+ { .name = "eventfd2",
+ .arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
+ { .name = "fchmodat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "fchownat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "fcntl",
+ .arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
+ .parm = &strarrays__fcntl_cmds_arrays,
+ .show_zero = true, },
+ [2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
+ { .name = "flock",
+ .arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
+ { .name = "fstat", .alias = "newfstat", },
+ { .name = "fstatat", .alias = "newfstatat", },
+ { .name = "futex",
+ .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
+ { .name = "futimesat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "getitimer",
+ .arg = { [0] = STRARRAY(which, itimers), }, },
{ .name = "getpid", .errpid = true, },
{ .name = "getpgid", .errpid = true, },
{ .name = "getppid", .errpid = true, },
- { .name = "getrandom", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
- { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
- { .name = "getxattr", .errmsg = true, },
- { .name = "inotify_add_watch", .errmsg = true, },
- { .name = "ioctl", .errmsg = true,
- .arg_scnprintf = {
+ { .name = "getrandom",
+ .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
+ { .name = "getrlimit",
+ .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
+ { .name = "ioctl",
+ .arg = {
#if defined(__i386__) || defined(__x86_64__)
/*
* FIXME: Make this available to all arches.
*/
- [1] = SCA_STRHEXARRAY, /* cmd */
- [2] = SCA_HEX, /* arg */ },
- .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
+ [1] = { .scnprintf = SCA_IOCTL_CMD, /* cmd */ },
+ [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
#else
- [2] = SCA_HEX, /* arg */ }, },
+ [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
#endif
- { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
- { .name = "kill", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
- { .name = "lchown", .errmsg = true, },
- { .name = "lgetxattr", .errmsg = true, },
- { .name = "linkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "listxattr", .errmsg = true, },
- { .name = "llistxattr", .errmsg = true, },
- { .name = "lremovexattr", .errmsg = true, },
- { .name = "lseek", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
- .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
- { .name = "lsetxattr", .errmsg = true, },
- { .name = "lstat", .errmsg = true, .alias = "newlstat", },
- { .name = "lsxattr", .errmsg = true, },
- { .name = "madvise", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* start */
- [2] = SCA_MADV_BHV, /* behavior */ }, },
- { .name = "mkdir", .errmsg = true, },
- { .name = "mkdirat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "mknod", .errmsg = true, },
- { .name = "mknodat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
- { .name = "mlock", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
- { .name = "mlockall", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+ { .name = "keyctl",
+ .arg = { [0] = STRARRAY(option, keyctl_options), }, },
+ { .name = "kill",
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "linkat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "lseek",
+ .arg = { [2] = STRARRAY(whence, whences), }, },
+ { .name = "lstat", .alias = "newlstat", },
+ { .name = "madvise",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
+ [2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
+ { .name = "mkdirat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "mknodat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
+ { .name = "mlock",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
+ { .name = "mlockall",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
{ .name = "mmap", .hexret = true,
/* The standard mmap maps to old_mmap on s390x */
#if defined(__s390x__)
.alias = "old_mmap",
#endif
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */
- [2] = SCA_MMAP_PROT, /* prot */
- [3] = SCA_MMAP_FLAGS, /* flags */ }, },
- { .name = "mprotect", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* start */
- [2] = SCA_MMAP_PROT, /* prot */ }, },
- { .name = "mq_unlink", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
+ [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
+ [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
+ { .name = "mprotect",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
+ [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
+ { .name = "mq_unlink",
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
{ .name = "mremap", .hexret = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */
- [3] = SCA_MREMAP_FLAGS, /* flags */
- [4] = SCA_HEX, /* new_addr */ }, },
- { .name = "munlock", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
- { .name = "munmap", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
- { .name = "name_to_handle_at", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "newfstatat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "open", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
- { .name = "open_by_handle_at", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
- [2] = SCA_OPEN_FLAGS, /* flags */ }, },
- { .name = "openat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
- [2] = SCA_OPEN_FLAGS, /* flags */ }, },
- { .name = "perf_event_open", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_INT, /* cpu */
- [3] = SCA_FD, /* group_fd */
- [4] = SCA_PERF_FLAGS, /* flags */ }, },
- { .name = "pipe2", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
- { .name = "poll", .errmsg = true, .timeout = true, },
- { .name = "ppoll", .errmsg = true, .timeout = true, },
- { .name = "pread", .errmsg = true, .alias = "pread64", },
- { .name = "preadv", .errmsg = true, .alias = "pread", },
- { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
- { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
- { .name = "pwritev", .errmsg = true, },
- { .name = "read", .errmsg = true, },
- { .name = "readlink", .errmsg = true, },
- { .name = "readlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "readv", .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 = "removexattr", .errmsg = true, },
- { .name = "renameat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "rmdir", .errmsg = true, },
- { .name = "rt_sigaction", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
- { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
- { .name = "rt_sigqueueinfo", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
- { .name = "rt_tgsigqueueinfo", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
- { .name = "sched_getattr", .errmsg = true, },
- { .name = "sched_setattr", .errmsg = true, },
- { .name = "sched_setscheduler", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
- { .name = "seccomp", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
- [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
- { .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 */ }, },
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
+ [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
+ [4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
+ { .name = "munlock",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
+ { .name = "munmap",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
+ { .name = "name_to_handle_at",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "newfstatat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "open",
+ .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
+ { .name = "open_by_handle_at",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
+ [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
+ { .name = "openat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
+ [2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
+ { .name = "perf_event_open",
+ .arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
+ [3] = { .scnprintf = SCA_FD, /* group_fd */ },
+ [4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
+ { .name = "pipe2",
+ .arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
+ { .name = "pkey_alloc",
+ .arg = { [1] = { .scnprintf = SCA_PKEY_ALLOC_ACCESS_RIGHTS, /* access_rights */ }, }, },
+ { .name = "pkey_free",
+ .arg = { [0] = { .scnprintf = SCA_INT, /* key */ }, }, },
+ { .name = "pkey_mprotect",
+ .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
+ [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
+ [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, },
+ { .name = "poll", .timeout = true, },
+ { .name = "ppoll", .timeout = true, },
+ { .name = "pread", .alias = "pread64", },
+ { .name = "preadv", .alias = "pread", },
+ { .name = "prlimit64",
+ .arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
+ { .name = "pwrite", .alias = "pwrite64", },
+ { .name = "readlinkat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "recvfrom",
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
+ { .name = "recvmmsg",
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
+ { .name = "recvmsg",
+ .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
+ { .name = "renameat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "rt_sigaction",
+ .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "rt_sigprocmask",
+ .arg = { [0] = STRARRAY(how, sighow), }, },
+ { .name = "rt_sigqueueinfo",
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "rt_tgsigqueueinfo",
+ .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "sched_setscheduler",
+ .arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
+ { .name = "seccomp",
+ .arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
+ [1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
+ { .name = "select", .timeout = true, },
+ { .name = "sendmmsg",
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
+ { .name = "sendmsg",
+ .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
+ { .name = "sendto",
+ .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "set_tid_address", .errpid = true, },
- { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
- { .name = "setpgid", .errmsg = true, },
- { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
- { .name = "setxattr", .errmsg = true, },
- { .name = "shutdown", .errmsg = true, },
- { .name = "socket", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
- [1] = SCA_SK_TYPE, /* type */ },
- .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
- { .name = "socketpair", .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 = "statfs", .errmsg = true, },
- { .name = "statx", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* flags */
- [2] = SCA_STATX_FLAGS, /* flags */
- [3] = SCA_STATX_MASK, /* mask */ }, },
- { .name = "swapoff", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
- { .name = "swapon", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
- { .name = "symlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "tgkill", .errmsg = true,
- .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
- { .name = "tkill", .errmsg = true,
- .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
- { .name = "truncate", .errmsg = true, },
- { .name = "uname", .errmsg = true, .alias = "newuname", },
- { .name = "unlinkat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
- { .name = "utime", .errmsg = true, },
- { .name = "utimensat", .errmsg = true,
- .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
- { .name = "utimes", .errmsg = true, },
- { .name = "vmsplice", .errmsg = true, },
+ { .name = "setitimer",
+ .arg = { [0] = STRARRAY(which, itimers), }, },
+ { .name = "setrlimit",
+ .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
+ { .name = "socket",
+ .arg = { [0] = STRARRAY(family, socket_families),
+ [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
+ { .name = "socketpair",
+ .arg = { [0] = STRARRAY(family, socket_families),
+ [1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
+ { .name = "stat", .alias = "newstat", },
+ { .name = "statx",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
+ [2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
+ [3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
+ { .name = "swapoff",
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
+ { .name = "swapon",
+ .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
+ { .name = "symlinkat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "tgkill",
+ .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "tkill",
+ .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
+ { .name = "uname", .alias = "newuname", },
+ { .name = "unlinkat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+ { .name = "utimensat",
+ .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
{ .name = "wait4", .errpid = true,
- .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
+ .arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
{ .name = "waitid", .errpid = true,
- .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
- { .name = "write", .errmsg = true, },
- { .name = "writev", .errmsg = true, },
+ .arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
};
static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -828,8 +794,7 @@ struct syscall {
const char *name;
bool is_exit;
struct syscall_fmt *fmt;
- size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
- void **arg_parm;
+ struct syscall_arg_fmt *arg_fmt;
};
/*
@@ -859,6 +824,8 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
* filename.ptr: The filename char pointer that will be vfs_getname'd
* filename.entry_str_pos: Where to insert the string translated from
* filename.ptr by the vfs_getname tracepoint/kprobe.
+ * ret_scnprintf: syscall args may set this to a different syscall return
+ * formatter, for instance, fcntl may return fds, file flags, etc.
*/
struct thread_trace {
u64 entry_time;
@@ -867,6 +834,7 @@ struct thread_trace {
unsigned long pfmaj, pfmin;
char *entry_str;
double runtime_ms;
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
struct {
unsigned long ptr;
short int entry_str_pos;
@@ -917,6 +885,15 @@ fail:
return NULL;
}
+
+void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
+{
+ struct thread_trace *ttrace = thread__priv(arg->thread);
+
+ ttrace->ret_scnprintf = ret_scnprintf;
+}
+
#define TRACE_PFMAJ (1 << 0)
#define TRACE_PFMIN (1 << 1)
@@ -996,8 +973,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
return ttrace->paths.table[fd];
}
-static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
- struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
{
int fd = arg->val;
size_t printed = scnprintf(bf, size, "%d", fd);
@@ -1162,32 +1138,46 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
return err;
}
+static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
+{
+ int idx;
+
+ if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0)
+ nr_args = sc->fmt->nr_args;
+
+ sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt));
+ if (sc->arg_fmt == NULL)
+ return -1;
+
+ for (idx = 0; idx < nr_args; ++idx) {
+ if (sc->fmt)
+ sc->arg_fmt[idx] = sc->fmt->arg[idx];
+ }
+
+ sc->nr_args = nr_args;
+ return 0;
+}
+
static int syscall__set_arg_fmts(struct syscall *sc)
{
struct format_field *field;
int idx = 0, len;
- sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
- if (sc->arg_scnprintf == NULL)
- return -1;
-
- if (sc->fmt)
- sc->arg_parm = sc->fmt->arg_parm;
+ for (field = sc->args; field; field = field->next, ++idx) {
+ if (sc->fmt && sc->fmt->arg[idx].scnprintf)
+ continue;
- for (field = sc->args; field; field = field->next) {
- if (sc->fmt && sc->fmt->arg_scnprintf[idx])
- sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
- else if (strcmp(field->type, "const char *") == 0 &&
+ if (strcmp(field->type, "const char *") == 0 &&
(strcmp(field->name, "filename") == 0 ||
strcmp(field->name, "path") == 0 ||
strcmp(field->name, "pathname") == 0))
- sc->arg_scnprintf[idx] = SCA_FILENAME;
+ sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
else if (field->flags & FIELD_IS_POINTER)
- sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
+ sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
else if (strcmp(field->type, "pid_t") == 0)
- sc->arg_scnprintf[idx] = SCA_PID;
+ sc->arg_fmt[idx].scnprintf = SCA_PID;
else if (strcmp(field->type, "umode_t") == 0)
- sc->arg_scnprintf[idx] = SCA_MODE_T;
+ sc->arg_fmt[idx].scnprintf = SCA_MODE_T;
else if ((strcmp(field->type, "int") == 0 ||
strcmp(field->type, "unsigned int") == 0 ||
strcmp(field->type, "long") == 0) &&
@@ -1200,9 +1190,8 @@ static int syscall__set_arg_fmts(struct syscall *sc)
* 23 unsigned int
* 7 unsigned long
*/
- sc->arg_scnprintf[idx] = SCA_FD;
+ sc->arg_fmt[idx].scnprintf = SCA_FD;
}
- ++idx;
}
return 0;
@@ -1247,11 +1236,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
sc->tp_format = trace_event__tp_format("syscalls", tp_name);
}
+ if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
+ return -1;
+
if (IS_ERR(sc->tp_format))
return -1;
sc->args = sc->tp_format->format.fields;
- sc->nr_args = sc->tp_format->format.nr_fields;
/*
* We need to check and discard the first variable '__syscall_nr'
* or 'nr' that mean the syscall number. It is needless here.
@@ -1321,33 +1312,68 @@ out:
* variable to read it. Most notably this avoids extended load instructions
* on unaligned addresses
*/
+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
+{
+ unsigned long val;
+ unsigned char *p = arg->args + sizeof(unsigned long) * idx;
+
+ memcpy(&val, p, sizeof(val));
+ return val;
+}
+
+static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
+ struct syscall_arg *arg)
+{
+ if (sc->arg_fmt && sc->arg_fmt[arg->idx].name)
+ return scnprintf(bf, size, "%s: ", sc->arg_fmt[arg->idx].name);
+
+ return scnprintf(bf, size, "arg%d: ", arg->idx);
+}
+
+static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
+ struct syscall_arg *arg, unsigned long val)
+{
+ if (sc->arg_fmt && sc->arg_fmt[arg->idx].scnprintf) {
+ arg->val = val;
+ if (sc->arg_fmt[arg->idx].parm)
+ arg->parm = sc->arg_fmt[arg->idx].parm;
+ return sc->arg_fmt[arg->idx].scnprintf(bf, size, arg);
+ }
+ return scnprintf(bf, size, "%ld", val);
+}
static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
unsigned char *args, struct trace *trace,
struct thread *thread)
{
size_t printed = 0;
- unsigned char *p;
unsigned long val;
+ u8 bit = 1;
+ struct syscall_arg arg = {
+ .args = args,
+ .idx = 0,
+ .mask = 0,
+ .trace = trace,
+ .thread = thread,
+ };
+ struct thread_trace *ttrace = thread__priv(thread);
+
+ /*
+ * Things like fcntl will set this in its 'cmd' formatter to pick the
+ * right formatter for the return value (an fd? file flags?), which is
+ * not needed for syscalls that always return a given type, say an fd.
+ */
+ ttrace->ret_scnprintf = NULL;
if (sc->args != NULL) {
struct format_field *field;
- u8 bit = 1;
- struct syscall_arg arg = {
- .idx = 0,
- .mask = 0,
- .trace = trace,
- .thread = thread,
- };
for (field = sc->args; field;
field = field->next, ++arg.idx, bit <<= 1) {
if (arg.mask & bit)
continue;
- /* special care for unaligned accesses */
- p = args + sizeof(unsigned long) * arg.idx;
- memcpy(&val, p, sizeof(val));
+ val = syscall_arg__val(&arg, arg.idx);
/*
* Suppress this argument if its value is zero and
@@ -1355,23 +1381,16 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
* strarray for it.
*/
if (val == 0 &&
- !(sc->arg_scnprintf &&
- sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
- sc->arg_parm[arg.idx]))
+ !(sc->arg_fmt &&
+ (sc->arg_fmt[arg.idx].show_zero ||
+ sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
+ sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
+ sc->arg_fmt[arg.idx].parm))
continue;
printed += scnprintf(bf + printed, size - printed,
"%s%s: ", printed ? ", " : "", field->name);
- if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
- arg.val = val;
- if (sc->arg_parm)
- arg.parm = sc->arg_parm[arg.idx];
- printed += sc->arg_scnprintf[arg.idx](bf + printed,
- size - printed, &arg);
- } else {
- printed += scnprintf(bf + printed, size - printed,
- "%ld", val);
- }
+ printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
}
} else if (IS_ERR(sc->tp_format)) {
/*
@@ -1379,16 +1398,17 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
* may end up not having any args, like with gettid(), so only
* print the raw args when we didn't manage to read it.
*/
- int i = 0;
-
- while (i < 6) {
- /* special care for unaligned accesses */
- p = args + sizeof(unsigned long) * i;
- memcpy(&val, p, sizeof(val));
- printed += scnprintf(bf + printed, size - printed,
- "%sarg%d: %ld",
- printed ? ", " : "", i, val);
- ++i;
+ while (arg.idx < sc->nr_args) {
+ if (arg.mask & bit)
+ goto next_arg;
+ val = syscall_arg__val(&arg, arg.idx);
+ if (printed)
+ printed += scnprintf(bf + printed, size - printed, ", ");
+ printed += syscall__scnprintf_name(sc, bf + printed, size - printed, &arg);
+ printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
+next_arg:
+ ++arg.idx;
+ bit <<= 1;
}
}
@@ -1635,17 +1655,31 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
}
if (sc->fmt == NULL) {
+ if (ret < 0)
+ goto errno_print;
signed_print:
fprintf(trace->output, ") = %ld", ret);
- } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
+ } else if (ret < 0) {
+errno_print: {
char bf[STRERR_BUFSIZE];
const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
*e = audit_errno_to_name(-ret);
fprintf(trace->output, ") = -1 %s %s", e, emsg);
+ }
} else if (ret == 0 && sc->fmt->timeout)
fprintf(trace->output, ") = 0 Timeout");
- else if (sc->fmt->hexret)
+ else if (ttrace->ret_scnprintf) {
+ char bf[1024];
+ struct syscall_arg arg = {
+ .val = ret,
+ .thread = thread,
+ .trace = trace,
+ };
+ ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
+ ttrace->ret_scnprintf = NULL;
+ fprintf(trace->output, ") = %s", bf);
+ } else if (sc->fmt->hexret)
fprintf(trace->output, ") = %#lx", ret);
else if (sc->fmt->errpid) {
struct thread *child = machine__find_thread(trace->host, ret, ret);
@@ -2171,6 +2205,30 @@ out_enomem:
goto out;
}
+static int trace__set_filter_loop_pids(struct trace *trace)
+{
+ unsigned int nr = 1;
+ pid_t pids[32] = {
+ getpid(),
+ };
+ struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
+
+ while (thread && nr < ARRAY_SIZE(pids)) {
+ struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
+
+ if (parent == NULL)
+ break;
+
+ if (!strcmp(thread__comm_str(parent), "sshd")) {
+ pids[nr++] = parent->tid;
+ break;
+ }
+ thread = parent;
+ }
+
+ return perf_evlist__set_filter_pids(trace->evlist, nr, pids);
+}
+
static int trace__run(struct trace *trace, int argc, const char **argv)
{
struct perf_evlist *evlist = trace->evlist;
@@ -2294,7 +2352,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (trace->filter_pids.nr > 0)
err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
else if (thread_map__pid(evlist->threads, 0) == -1)
- err = perf_evlist__set_filter_pid(evlist, getpid());
+ err = trace__set_filter_loop_pids(trace);
if (err < 0)
goto out_error_mem;
@@ -2756,7 +2814,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
struct trace *trace = (struct trace *)opt->value;
const char *s = str;
char *sep = NULL, *lists[2] = { NULL, NULL, };
- int len = strlen(str), err = -1, list;
+ int len = strlen(str) + 1, err = -1, list;
char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
char group_name[PATH_MAX];