diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-08-06 02:51:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-08-06 02:51:18 -0400 |
commit | b6b6c18fcd9af2a71d7b2cfca0388a928308f963 (patch) | |
tree | 2ccdd26199ce3fc1183b7ba636d73c4d8643112a | |
parent | 75f80859b130a1cc84e59e71295ce2dd51fe1c81 (diff) | |
parent | f151f53aa4f54a647353e1935e4c6cef7f094dd4 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
New features:
- Deref sys_enter pointer args with contents from probe:vfs_getname, showing
pathnames instead of pointers in many syscalls in 'perf trace'. (Arnaldo Carvalho de Melo)
- Make 'perf trace' write to stderr by default, just like 'strace'. (Milian Woff)
Infrastructure changes:
- color_vfprintf() fixes. (Andi Kleen, Jiri Olsa)
- Allow enabling/disabling PERF_SAMPLE_TIME per event. (Kan Liang)
- Fix build errors with mipsel-linux-uclibc compiler. (Petri Gynther)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/build/feature/test-glibc.c | 11 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 4 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 175 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 14 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 2 | ||||
-rw-r--r-- | tools/perf/util/cloexec.h | 2 | ||||
-rw-r--r-- | tools/perf/util/color.c | 21 | ||||
-rw-r--r-- | tools/perf/util/color.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 25 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 12 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 1 | ||||
-rw-r--r-- | tools/perf/util/parse-events.l | 1 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 2 |
16 files changed, 220 insertions, 58 deletions
diff --git a/tools/build/feature/test-glibc.c b/tools/build/feature/test-glibc.c index b0820345cd98..9367f7586676 100644 --- a/tools/build/feature/test-glibc.c +++ b/tools/build/feature/test-glibc.c | |||
@@ -1,8 +1,19 @@ | |||
1 | #include <stdlib.h> | ||
2 | |||
3 | #if !defined(__UCLIBC__) | ||
1 | #include <gnu/libc-version.h> | 4 | #include <gnu/libc-version.h> |
5 | #else | ||
6 | #define XSTR(s) STR(s) | ||
7 | #define STR(s) #s | ||
8 | #endif | ||
2 | 9 | ||
3 | int main(void) | 10 | int main(void) |
4 | { | 11 | { |
12 | #if !defined(__UCLIBC__) | ||
5 | const char *version = gnu_get_libc_version(); | 13 | const char *version = gnu_get_libc_version(); |
14 | #else | ||
15 | const char *version = XSTR(__GLIBC__) "." XSTR(__GLIBC_MINOR__); | ||
16 | #endif | ||
6 | 17 | ||
7 | return (long)version; | 18 | return (long)version; |
8 | } | 19 | } |
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index ac41350ca485..0d852d1bc90f 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -49,7 +49,9 @@ OPTIONS | |||
49 | These params can be used to overload default config values per event. | 49 | These params can be used to overload default config values per event. |
50 | Here is a list of the params. | 50 | Here is a list of the params. |
51 | - 'period': Set event sampling period | 51 | - 'period': Set event sampling period |
52 | 52 | - 'time': Disable/enable time stamping. Acceptable values are 1 for | |
53 | enabling time stamping. 0 for disabling time stamping. | ||
54 | The default is 1. | ||
53 | Note: If user explicitly sets options which conflict with the params, | 55 | Note: If user explicitly sets options which conflict with the params, |
54 | the value set by the params will be overridden. | 56 | the value set by the params will be overridden. |
55 | 57 | ||
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f51131b11ad7..25cf6b404e8a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -779,7 +779,7 @@ int record_parse_callchain_opt(const struct option *opt, | |||
779 | return 0; | 779 | return 0; |
780 | } | 780 | } |
781 | 781 | ||
782 | ret = parse_callchain_record_opt(arg); | 782 | ret = parse_callchain_record_opt(arg, &callchain_param); |
783 | if (!ret) | 783 | if (!ret) |
784 | callchain_debug(); | 784 | callchain_debug(); |
785 | 785 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index bd31380122f9..7912feb9a024 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1861,7 +1861,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1861 | else | 1861 | else |
1862 | symbol_conf.use_callchain = false; | 1862 | symbol_conf.use_callchain = false; |
1863 | 1863 | ||
1864 | if (pevent_set_function_resolver(session->tevent.pevent, | 1864 | if (session->tevent.pevent && |
1865 | pevent_set_function_resolver(session->tevent.pevent, | ||
1865 | machine__resolve_kernel_addr, | 1866 | machine__resolve_kernel_addr, |
1866 | &session->machines.host) < 0) { | 1867 | &session->machines.host) < 0) { |
1867 | pr_err("%s: failed to set libtraceevent function resolver\n", __func__); | 1868 | pr_err("%s: failed to set libtraceevent function resolver\n", __func__); |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 06cfa93c0305..a47497011c93 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -744,6 +744,11 @@ static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, | |||
744 | 744 | ||
745 | #define SCA_ACCMODE syscall_arg__scnprintf_access_mode | 745 | #define SCA_ACCMODE syscall_arg__scnprintf_access_mode |
746 | 746 | ||
747 | static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, | ||
748 | struct syscall_arg *arg); | ||
749 | |||
750 | #define SCA_FILENAME syscall_arg__scnprintf_filename | ||
751 | |||
747 | static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, | 752 | static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, |
748 | struct syscall_arg *arg) | 753 | struct syscall_arg *arg) |
749 | { | 754 | { |
@@ -971,14 +976,23 @@ static struct syscall_fmt { | |||
971 | bool hexret; | 976 | bool hexret; |
972 | } syscall_fmts[] = { | 977 | } syscall_fmts[] = { |
973 | { .name = "access", .errmsg = true, | 978 | { .name = "access", .errmsg = true, |
974 | .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, | 979 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ |
980 | [1] = SCA_ACCMODE, /* mode */ }, }, | ||
975 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, | 981 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, |
976 | { .name = "brk", .hexret = true, | 982 | { .name = "brk", .hexret = true, |
977 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, | 983 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, |
984 | { .name = "chdir", .errmsg = true, | ||
985 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
986 | { .name = "chmod", .errmsg = true, | ||
987 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
988 | { .name = "chroot", .errmsg = true, | ||
989 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
978 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, | 990 | { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, |
979 | { .name = "close", .errmsg = true, | 991 | { .name = "close", .errmsg = true, |
980 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, | 992 | .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, |
981 | { .name = "connect", .errmsg = true, }, | 993 | { .name = "connect", .errmsg = true, }, |
994 | { .name = "creat", .errmsg = true, | ||
995 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
982 | { .name = "dup", .errmsg = true, | 996 | { .name = "dup", .errmsg = true, |
983 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 997 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
984 | { .name = "dup2", .errmsg = true, | 998 | { .name = "dup2", .errmsg = true, |
@@ -989,7 +1003,8 @@ static struct syscall_fmt { | |||
989 | { .name = "eventfd2", .errmsg = true, | 1003 | { .name = "eventfd2", .errmsg = true, |
990 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, | 1004 | .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, |
991 | { .name = "faccessat", .errmsg = true, | 1005 | { .name = "faccessat", .errmsg = true, |
992 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1006 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1007 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
993 | { .name = "fadvise64", .errmsg = true, | 1008 | { .name = "fadvise64", .errmsg = true, |
994 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1009 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
995 | { .name = "fallocate", .errmsg = true, | 1010 | { .name = "fallocate", .errmsg = true, |
@@ -1003,7 +1018,8 @@ static struct syscall_fmt { | |||
1003 | { .name = "fchown", .errmsg = true, | 1018 | { .name = "fchown", .errmsg = true, |
1004 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1019 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1005 | { .name = "fchownat", .errmsg = true, | 1020 | { .name = "fchownat", .errmsg = true, |
1006 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 1021 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ |
1022 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
1007 | { .name = "fcntl", .errmsg = true, | 1023 | { .name = "fcntl", .errmsg = true, |
1008 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 1024 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ |
1009 | [1] = SCA_STRARRAY, /* cmd */ }, | 1025 | [1] = SCA_STRARRAY, /* cmd */ }, |
@@ -1018,7 +1034,8 @@ static struct syscall_fmt { | |||
1018 | { .name = "fstat", .errmsg = true, .alias = "newfstat", | 1034 | { .name = "fstat", .errmsg = true, .alias = "newfstat", |
1019 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1035 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1020 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", | 1036 | { .name = "fstatat", .errmsg = true, .alias = "newfstatat", |
1021 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1037 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1038 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
1022 | { .name = "fstatfs", .errmsg = true, | 1039 | { .name = "fstatfs", .errmsg = true, |
1023 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1040 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1024 | { .name = "fsync", .errmsg = true, | 1041 | { .name = "fsync", .errmsg = true, |
@@ -1035,6 +1052,10 @@ static struct syscall_fmt { | |||
1035 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1052 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1036 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 1053 | { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
1037 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 1054 | { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
1055 | { .name = "getxattr", .errmsg = true, | ||
1056 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1057 | { .name = "inotify_add_watch", .errmsg = true, | ||
1058 | .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, | ||
1038 | { .name = "ioctl", .errmsg = true, | 1059 | { .name = "ioctl", .errmsg = true, |
1039 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 1060 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ |
1040 | #if defined(__i386__) || defined(__x86_64__) | 1061 | #if defined(__i386__) || defined(__x86_64__) |
@@ -1049,18 +1070,33 @@ static struct syscall_fmt { | |||
1049 | #endif | 1070 | #endif |
1050 | { .name = "kill", .errmsg = true, | 1071 | { .name = "kill", .errmsg = true, |
1051 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 1072 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
1073 | { .name = "lchown", .errmsg = true, | ||
1074 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
1075 | { .name = "lgetxattr", .errmsg = true, | ||
1076 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1052 | { .name = "linkat", .errmsg = true, | 1077 | { .name = "linkat", .errmsg = true, |
1053 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 1078 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
1079 | { .name = "listxattr", .errmsg = true, | ||
1080 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1054 | { .name = "lseek", .errmsg = true, | 1081 | { .name = "lseek", .errmsg = true, |
1055 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ | 1082 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ |
1056 | [2] = SCA_STRARRAY, /* whence */ }, | 1083 | [2] = SCA_STRARRAY, /* whence */ }, |
1057 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, | 1084 | .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, |
1085 | { .name = "lsetxattr", .errmsg = true, | ||
1086 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1058 | { .name = "lstat", .errmsg = true, .alias = "newlstat", }, | 1087 | { .name = "lstat", .errmsg = true, .alias = "newlstat", }, |
1088 | { .name = "lsxattr", .errmsg = true, | ||
1089 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1059 | { .name = "madvise", .errmsg = true, | 1090 | { .name = "madvise", .errmsg = true, |
1060 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ | 1091 | .arg_scnprintf = { [0] = SCA_HEX, /* start */ |
1061 | [2] = SCA_MADV_BHV, /* behavior */ }, }, | 1092 | [2] = SCA_MADV_BHV, /* behavior */ }, }, |
1093 | { .name = "mkdir", .errmsg = true, | ||
1094 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1062 | { .name = "mkdirat", .errmsg = true, | 1095 | { .name = "mkdirat", .errmsg = true, |
1063 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 1096 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ |
1097 | [1] = SCA_FILENAME, /* pathname */ }, }, | ||
1098 | { .name = "mknod", .errmsg = true, | ||
1099 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
1064 | { .name = "mknodat", .errmsg = true, | 1100 | { .name = "mknodat", .errmsg = true, |
1065 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, | 1101 | .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, |
1066 | { .name = "mlock", .errmsg = true, | 1102 | { .name = "mlock", .errmsg = true, |
@@ -1086,14 +1122,17 @@ static struct syscall_fmt { | |||
1086 | { .name = "name_to_handle_at", .errmsg = true, | 1122 | { .name = "name_to_handle_at", .errmsg = true, |
1087 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1123 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
1088 | { .name = "newfstatat", .errmsg = true, | 1124 | { .name = "newfstatat", .errmsg = true, |
1089 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1125 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1126 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
1090 | { .name = "open", .errmsg = true, | 1127 | { .name = "open", .errmsg = true, |
1091 | .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, | 1128 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ |
1129 | [1] = SCA_OPEN_FLAGS, /* flags */ }, }, | ||
1092 | { .name = "open_by_handle_at", .errmsg = true, | 1130 | { .name = "open_by_handle_at", .errmsg = true, |
1093 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 1131 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1094 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 1132 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
1095 | { .name = "openat", .errmsg = true, | 1133 | { .name = "openat", .errmsg = true, |
1096 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ | 1134 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1135 | [1] = SCA_FILENAME, /* filename */ | ||
1097 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, | 1136 | [2] = SCA_OPEN_FLAGS, /* flags */ }, }, |
1098 | { .name = "perf_event_open", .errmsg = true, | 1137 | { .name = "perf_event_open", .errmsg = true, |
1099 | .arg_scnprintf = { [1] = SCA_INT, /* pid */ | 1138 | .arg_scnprintf = { [1] = SCA_INT, /* pid */ |
@@ -1115,8 +1154,11 @@ static struct syscall_fmt { | |||
1115 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1154 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1116 | { .name = "read", .errmsg = true, | 1155 | { .name = "read", .errmsg = true, |
1117 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1156 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1157 | { .name = "readlink", .errmsg = true, | ||
1158 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
1118 | { .name = "readlinkat", .errmsg = true, | 1159 | { .name = "readlinkat", .errmsg = true, |
1119 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1160 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1161 | [1] = SCA_FILENAME, /* pathname */ }, }, | ||
1120 | { .name = "readv", .errmsg = true, | 1162 | { .name = "readv", .errmsg = true, |
1121 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1163 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1122 | { .name = "recvfrom", .errmsg = true, | 1164 | { .name = "recvfrom", .errmsg = true, |
@@ -1125,8 +1167,12 @@ static struct syscall_fmt { | |||
1125 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, | 1167 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
1126 | { .name = "recvmsg", .errmsg = true, | 1168 | { .name = "recvmsg", .errmsg = true, |
1127 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, | 1169 | .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, |
1170 | { .name = "removexattr", .errmsg = true, | ||
1171 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1128 | { .name = "renameat", .errmsg = true, | 1172 | { .name = "renameat", .errmsg = true, |
1129 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1173 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
1174 | { .name = "rmdir", .errmsg = true, | ||
1175 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1130 | { .name = "rt_sigaction", .errmsg = true, | 1176 | { .name = "rt_sigaction", .errmsg = true, |
1131 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, | 1177 | .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, |
1132 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, | 1178 | { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, |
@@ -1143,6 +1189,8 @@ static struct syscall_fmt { | |||
1143 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, | 1189 | .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, |
1144 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, | 1190 | { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, |
1145 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, | 1191 | { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, |
1192 | { .name = "setxattr", .errmsg = true, | ||
1193 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1146 | { .name = "shutdown", .errmsg = true, | 1194 | { .name = "shutdown", .errmsg = true, |
1147 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1195 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1148 | { .name = "socket", .errmsg = true, | 1196 | { .name = "socket", .errmsg = true, |
@@ -1154,17 +1202,31 @@ static struct syscall_fmt { | |||
1154 | [1] = SCA_SK_TYPE, /* type */ }, | 1202 | [1] = SCA_SK_TYPE, /* type */ }, |
1155 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, | 1203 | .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, |
1156 | { .name = "stat", .errmsg = true, .alias = "newstat", }, | 1204 | { .name = "stat", .errmsg = true, .alias = "newstat", }, |
1205 | { .name = "statfs", .errmsg = true, | ||
1206 | .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, | ||
1207 | { .name = "swapoff", .errmsg = true, | ||
1208 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, | ||
1209 | { .name = "swapon", .errmsg = true, | ||
1210 | .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, | ||
1157 | { .name = "symlinkat", .errmsg = true, | 1211 | { .name = "symlinkat", .errmsg = true, |
1158 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1212 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, |
1159 | { .name = "tgkill", .errmsg = true, | 1213 | { .name = "tgkill", .errmsg = true, |
1160 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, | 1214 | .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, |
1161 | { .name = "tkill", .errmsg = true, | 1215 | { .name = "tkill", .errmsg = true, |
1162 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, | 1216 | .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, |
1217 | { .name = "truncate", .errmsg = true, | ||
1218 | .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, | ||
1163 | { .name = "uname", .errmsg = true, .alias = "newuname", }, | 1219 | { .name = "uname", .errmsg = true, .alias = "newuname", }, |
1164 | { .name = "unlinkat", .errmsg = true, | 1220 | { .name = "unlinkat", .errmsg = true, |
1165 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, | 1221 | .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ |
1222 | [1] = SCA_FILENAME, /* pathname */ }, }, | ||
1223 | { .name = "utime", .errmsg = true, | ||
1224 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
1166 | { .name = "utimensat", .errmsg = true, | 1225 | { .name = "utimensat", .errmsg = true, |
1167 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, | 1226 | .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ |
1227 | [1] = SCA_FILENAME, /* filename */ }, }, | ||
1228 | { .name = "utimes", .errmsg = true, | ||
1229 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, | ||
1168 | { .name = "write", .errmsg = true, | 1230 | { .name = "write", .errmsg = true, |
1169 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, | 1231 | .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, |
1170 | { .name = "writev", .errmsg = true, | 1232 | { .name = "writev", .errmsg = true, |
@@ -1208,6 +1270,11 @@ static size_t fprintf_duration(unsigned long t, FILE *fp) | |||
1208 | return printed + fprintf(fp, "): "); | 1270 | return printed + fprintf(fp, "): "); |
1209 | } | 1271 | } |
1210 | 1272 | ||
1273 | /** | ||
1274 | * filename.ptr: The filename char pointer that will be vfs_getname'd | ||
1275 | * filename.entry_str_pos: Where to insert the string translated from | ||
1276 | * filename.ptr by the vfs_getname tracepoint/kprobe. | ||
1277 | */ | ||
1211 | struct thread_trace { | 1278 | struct thread_trace { |
1212 | u64 entry_time; | 1279 | u64 entry_time; |
1213 | u64 exit_time; | 1280 | u64 exit_time; |
@@ -1216,6 +1283,10 @@ struct thread_trace { | |||
1216 | unsigned long pfmaj, pfmin; | 1283 | unsigned long pfmaj, pfmin; |
1217 | char *entry_str; | 1284 | char *entry_str; |
1218 | double runtime_ms; | 1285 | double runtime_ms; |
1286 | struct { | ||
1287 | unsigned long ptr; | ||
1288 | int entry_str_pos; | ||
1289 | } filename; | ||
1219 | struct { | 1290 | struct { |
1220 | int max; | 1291 | int max; |
1221 | char **table; | 1292 | char **table; |
@@ -1262,6 +1333,8 @@ fail: | |||
1262 | #define TRACE_PFMAJ (1 << 0) | 1333 | #define TRACE_PFMAJ (1 << 0) |
1263 | #define TRACE_PFMIN (1 << 1) | 1334 | #define TRACE_PFMIN (1 << 1) |
1264 | 1335 | ||
1336 | static const size_t trace__entry_str_size = 2048; | ||
1337 | |||
1265 | struct trace { | 1338 | struct trace { |
1266 | struct perf_tool tool; | 1339 | struct perf_tool tool; |
1267 | struct { | 1340 | struct { |
@@ -1312,6 +1385,7 @@ struct trace { | |||
1312 | bool show_tool_stats; | 1385 | bool show_tool_stats; |
1313 | bool trace_syscalls; | 1386 | bool trace_syscalls; |
1314 | bool force; | 1387 | bool force; |
1388 | bool vfs_getname; | ||
1315 | int trace_pgfaults; | 1389 | int trace_pgfaults; |
1316 | }; | 1390 | }; |
1317 | 1391 | ||
@@ -1415,6 +1489,27 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, | |||
1415 | return printed; | 1489 | return printed; |
1416 | } | 1490 | } |
1417 | 1491 | ||
1492 | static void thread__set_filename_pos(struct thread *thread, const char *bf, | ||
1493 | unsigned long ptr) | ||
1494 | { | ||
1495 | struct thread_trace *ttrace = thread__priv(thread); | ||
1496 | |||
1497 | ttrace->filename.ptr = ptr; | ||
1498 | ttrace->filename.entry_str_pos = bf - ttrace->entry_str; | ||
1499 | } | ||
1500 | |||
1501 | static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, | ||
1502 | struct syscall_arg *arg) | ||
1503 | { | ||
1504 | unsigned long ptr = arg->val; | ||
1505 | |||
1506 | if (!arg->trace->vfs_getname) | ||
1507 | return scnprintf(bf, size, "%#x", ptr); | ||
1508 | |||
1509 | thread__set_filename_pos(arg->thread, bf, ptr); | ||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1418 | static bool trace__filter_duration(struct trace *trace, double t) | 1513 | static bool trace__filter_duration(struct trace *trace, double t) |
1419 | { | 1514 | { |
1420 | return t < (trace->duration_filter * NSEC_PER_MSEC); | 1515 | return t < (trace->duration_filter * NSEC_PER_MSEC); |
@@ -1821,7 +1916,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, | |||
1821 | args = perf_evsel__sc_tp_ptr(evsel, args, sample); | 1916 | args = perf_evsel__sc_tp_ptr(evsel, args, sample); |
1822 | 1917 | ||
1823 | if (ttrace->entry_str == NULL) { | 1918 | if (ttrace->entry_str == NULL) { |
1824 | ttrace->entry_str = malloc(1024); | 1919 | ttrace->entry_str = malloc(trace__entry_str_size); |
1825 | if (!ttrace->entry_str) | 1920 | if (!ttrace->entry_str) |
1826 | goto out_put; | 1921 | goto out_put; |
1827 | } | 1922 | } |
@@ -1831,9 +1926,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, | |||
1831 | 1926 | ||
1832 | ttrace->entry_time = sample->time; | 1927 | ttrace->entry_time = sample->time; |
1833 | msg = ttrace->entry_str; | 1928 | msg = ttrace->entry_str; |
1834 | printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); | 1929 | printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); |
1835 | 1930 | ||
1836 | printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, | 1931 | printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed, |
1837 | args, trace, thread); | 1932 | args, trace, thread); |
1838 | 1933 | ||
1839 | if (sc->is_exit) { | 1934 | if (sc->is_exit) { |
@@ -1935,7 +2030,45 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel, | |||
1935 | union perf_event *event __maybe_unused, | 2030 | union perf_event *event __maybe_unused, |
1936 | struct perf_sample *sample) | 2031 | struct perf_sample *sample) |
1937 | { | 2032 | { |
2033 | struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); | ||
2034 | struct thread_trace *ttrace; | ||
2035 | size_t filename_len, entry_str_len, to_move; | ||
2036 | ssize_t remaining_space; | ||
2037 | char *pos; | ||
2038 | const char *filename; | ||
2039 | |||
1938 | trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname"); | 2040 | trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname"); |
2041 | |||
2042 | if (!thread) | ||
2043 | goto out; | ||
2044 | |||
2045 | ttrace = thread__priv(thread); | ||
2046 | if (!ttrace) | ||
2047 | goto out; | ||
2048 | |||
2049 | if (!ttrace->filename.ptr) | ||
2050 | goto out; | ||
2051 | |||
2052 | entry_str_len = strlen(ttrace->entry_str); | ||
2053 | remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */ | ||
2054 | if (remaining_space <= 0) | ||
2055 | goto out; | ||
2056 | |||
2057 | filename = trace->last_vfs_getname; | ||
2058 | filename_len = strlen(filename); | ||
2059 | if (filename_len > (size_t)remaining_space) { | ||
2060 | filename += filename_len - remaining_space; | ||
2061 | filename_len = remaining_space; | ||
2062 | } | ||
2063 | |||
2064 | to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */ | ||
2065 | pos = ttrace->entry_str + ttrace->filename.entry_str_pos; | ||
2066 | memmove(pos + filename_len, pos, to_move); | ||
2067 | memcpy(pos, filename, filename_len); | ||
2068 | |||
2069 | ttrace->filename.ptr = 0; | ||
2070 | ttrace->filename.entry_str_pos = 0; | ||
2071 | out: | ||
1939 | return 0; | 2072 | return 0; |
1940 | } | 2073 | } |
1941 | 2074 | ||
@@ -2188,19 +2321,20 @@ static int trace__record(struct trace *trace, int argc, const char **argv) | |||
2188 | 2321 | ||
2189 | static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); | 2322 | static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); |
2190 | 2323 | ||
2191 | static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist) | 2324 | static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) |
2192 | { | 2325 | { |
2193 | struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); | 2326 | struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); |
2194 | if (evsel == NULL) | 2327 | if (evsel == NULL) |
2195 | return; | 2328 | return false; |
2196 | 2329 | ||
2197 | if (perf_evsel__field(evsel, "pathname") == NULL) { | 2330 | if (perf_evsel__field(evsel, "pathname") == NULL) { |
2198 | perf_evsel__delete(evsel); | 2331 | perf_evsel__delete(evsel); |
2199 | return; | 2332 | return false; |
2200 | } | 2333 | } |
2201 | 2334 | ||
2202 | evsel->handler = trace__vfs_getname; | 2335 | evsel->handler = trace__vfs_getname; |
2203 | perf_evlist__add(evlist, evsel); | 2336 | perf_evlist__add(evlist, evsel); |
2337 | return true; | ||
2204 | } | 2338 | } |
2205 | 2339 | ||
2206 | static int perf_evlist__add_pgfault(struct perf_evlist *evlist, | 2340 | static int perf_evlist__add_pgfault(struct perf_evlist *evlist, |
@@ -2330,7 +2464,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
2330 | goto out_error_raw_syscalls; | 2464 | goto out_error_raw_syscalls; |
2331 | 2465 | ||
2332 | if (trace->trace_syscalls) | 2466 | if (trace->trace_syscalls) |
2333 | perf_evlist__add_vfs_getname(evlist); | 2467 | trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); |
2334 | 2468 | ||
2335 | if ((trace->trace_pgfaults & TRACE_PFMAJ) && | 2469 | if ((trace->trace_pgfaults & TRACE_PFMAJ) && |
2336 | perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { | 2470 | perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { |
@@ -2394,9 +2528,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
2394 | err = trace__set_ev_qualifier_filter(trace); | 2528 | err = trace__set_ev_qualifier_filter(trace); |
2395 | if (err < 0) | 2529 | if (err < 0) |
2396 | goto out_errno; | 2530 | goto out_errno; |
2397 | } | ||
2398 | 2531 | ||
2399 | pr_debug("%s\n", trace->syscalls.events.sys_exit->filter); | 2532 | pr_debug("event qualifier tracepoint filter: %s\n", |
2533 | trace->syscalls.events.sys_exit->filter); | ||
2534 | } | ||
2400 | 2535 | ||
2401 | err = perf_evlist__apply_filters(evlist, &evsel); | 2536 | err = perf_evlist__apply_filters(evlist, &evsel); |
2402 | if (err < 0) | 2537 | if (err < 0) |
@@ -2830,7 +2965,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2830 | .mmap_pages = UINT_MAX, | 2965 | .mmap_pages = UINT_MAX, |
2831 | .proc_map_timeout = 500, | 2966 | .proc_map_timeout = 500, |
2832 | }, | 2967 | }, |
2833 | .output = stdout, | 2968 | .output = stderr, |
2834 | .show_comm = true, | 2969 | .show_comm = true, |
2835 | .trace_syscalls = true, | 2970 | .trace_syscalls = true, |
2836 | }; | 2971 | }; |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 9f643ee77001..931cca8e6ae8 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -53,7 +53,7 @@ static int get_stack_size(const char *str, unsigned long *_size) | |||
53 | } | 53 | } |
54 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | 54 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ |
55 | 55 | ||
56 | int parse_callchain_record_opt(const char *arg) | 56 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param) |
57 | { | 57 | { |
58 | char *tok, *name, *saveptr = NULL; | 58 | char *tok, *name, *saveptr = NULL; |
59 | char *buf; | 59 | char *buf; |
@@ -73,7 +73,7 @@ int parse_callchain_record_opt(const char *arg) | |||
73 | /* Framepointer style */ | 73 | /* Framepointer style */ |
74 | if (!strncmp(name, "fp", sizeof("fp"))) { | 74 | if (!strncmp(name, "fp", sizeof("fp"))) { |
75 | if (!strtok_r(NULL, ",", &saveptr)) { | 75 | if (!strtok_r(NULL, ",", &saveptr)) { |
76 | callchain_param.record_mode = CALLCHAIN_FP; | 76 | param->record_mode = CALLCHAIN_FP; |
77 | ret = 0; | 77 | ret = 0; |
78 | } else | 78 | } else |
79 | pr_err("callchain: No more arguments " | 79 | pr_err("callchain: No more arguments " |
@@ -86,20 +86,20 @@ int parse_callchain_record_opt(const char *arg) | |||
86 | const unsigned long default_stack_dump_size = 8192; | 86 | const unsigned long default_stack_dump_size = 8192; |
87 | 87 | ||
88 | ret = 0; | 88 | ret = 0; |
89 | callchain_param.record_mode = CALLCHAIN_DWARF; | 89 | param->record_mode = CALLCHAIN_DWARF; |
90 | callchain_param.dump_size = default_stack_dump_size; | 90 | param->dump_size = default_stack_dump_size; |
91 | 91 | ||
92 | tok = strtok_r(NULL, ",", &saveptr); | 92 | tok = strtok_r(NULL, ",", &saveptr); |
93 | if (tok) { | 93 | if (tok) { |
94 | unsigned long size = 0; | 94 | unsigned long size = 0; |
95 | 95 | ||
96 | ret = get_stack_size(tok, &size); | 96 | ret = get_stack_size(tok, &size); |
97 | callchain_param.dump_size = size; | 97 | param->dump_size = size; |
98 | } | 98 | } |
99 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | 99 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ |
100 | } else if (!strncmp(name, "lbr", sizeof("lbr"))) { | 100 | } else if (!strncmp(name, "lbr", sizeof("lbr"))) { |
101 | if (!strtok_r(NULL, ",", &saveptr)) { | 101 | if (!strtok_r(NULL, ",", &saveptr)) { |
102 | callchain_param.record_mode = CALLCHAIN_LBR; | 102 | param->record_mode = CALLCHAIN_LBR; |
103 | ret = 0; | 103 | ret = 0; |
104 | } else | 104 | } else |
105 | pr_err("callchain: No more arguments " | 105 | pr_err("callchain: No more arguments " |
@@ -219,7 +219,7 @@ int perf_callchain_config(const char *var, const char *value) | |||
219 | var += sizeof("call-graph.") - 1; | 219 | var += sizeof("call-graph.") - 1; |
220 | 220 | ||
221 | if (!strcmp(var, "record-mode")) | 221 | if (!strcmp(var, "record-mode")) |
222 | return parse_callchain_record_opt(value); | 222 | return parse_callchain_record_opt(value, &callchain_param); |
223 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 223 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
224 | if (!strcmp(var, "dump-size")) { | 224 | if (!strcmp(var, "dump-size")) { |
225 | unsigned long size = 0; | 225 | unsigned long size = 0; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 679c2c6d8ade..68a32c2fe87a 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -177,7 +177,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * | |||
177 | bool hide_unresolved); | 177 | bool hide_unresolved); |
178 | 178 | ||
179 | extern const char record_callchain_help[]; | 179 | extern const char record_callchain_help[]; |
180 | int parse_callchain_record_opt(const char *arg); | 180 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); |
181 | int parse_callchain_report_opt(const char *arg); | 181 | int parse_callchain_report_opt(const char *arg); |
182 | int perf_callchain_config(const char *var, const char *value); | 182 | int perf_callchain_config(const char *var, const char *value); |
183 | 183 | ||
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h index 68888c29b04a..3bee6773ddb0 100644 --- a/tools/perf/util/cloexec.h +++ b/tools/perf/util/cloexec.h | |||
@@ -4,7 +4,7 @@ | |||
4 | unsigned long perf_event_open_cloexec_flag(void); | 4 | unsigned long perf_event_open_cloexec_flag(void); |
5 | 5 | ||
6 | #ifdef __GLIBC_PREREQ | 6 | #ifdef __GLIBC_PREREQ |
7 | #if !__GLIBC_PREREQ(2, 6) | 7 | #if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__) |
8 | extern int sched_getcpu(void) __THROW; | 8 | extern int sched_getcpu(void) __THROW; |
9 | #endif | 9 | #endif |
10 | #endif | 10 | #endif |
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 55355b3d4f85..9b9565416f90 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c | |||
@@ -67,8 +67,9 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color, | |||
67 | return r; | 67 | return r; |
68 | } | 68 | } |
69 | 69 | ||
70 | /* Colors are not included in return value */ | ||
70 | static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, | 71 | static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, |
71 | va_list args, const char *trail) | 72 | va_list args) |
72 | { | 73 | { |
73 | int r = 0; | 74 | int r = 0; |
74 | 75 | ||
@@ -83,12 +84,10 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, | |||
83 | } | 84 | } |
84 | 85 | ||
85 | if (perf_use_color_default && *color) | 86 | if (perf_use_color_default && *color) |
86 | r += fprintf(fp, "%s", color); | 87 | fprintf(fp, "%s", color); |
87 | r += vfprintf(fp, fmt, args); | 88 | r += vfprintf(fp, fmt, args); |
88 | if (perf_use_color_default && *color) | 89 | if (perf_use_color_default && *color) |
89 | r += fprintf(fp, "%s", PERF_COLOR_RESET); | 90 | fprintf(fp, "%s", PERF_COLOR_RESET); |
90 | if (trail) | ||
91 | r += fprintf(fp, "%s", trail); | ||
92 | return r; | 91 | return r; |
93 | } | 92 | } |
94 | 93 | ||
@@ -100,7 +99,7 @@ int color_vsnprintf(char *bf, size_t size, const char *color, | |||
100 | 99 | ||
101 | int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) | 100 | int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) |
102 | { | 101 | { |
103 | return __color_vfprintf(fp, color, fmt, args, NULL); | 102 | return __color_vfprintf(fp, color, fmt, args); |
104 | } | 103 | } |
105 | 104 | ||
106 | int color_snprintf(char *bf, size_t size, const char *color, | 105 | int color_snprintf(char *bf, size_t size, const char *color, |
@@ -126,16 +125,6 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) | |||
126 | return r; | 125 | return r; |
127 | } | 126 | } |
128 | 127 | ||
129 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) | ||
130 | { | ||
131 | va_list args; | ||
132 | int r; | ||
133 | va_start(args, fmt); | ||
134 | r = __color_vfprintf(fp, color, fmt, args, "\n"); | ||
135 | va_end(args); | ||
136 | return r; | ||
137 | } | ||
138 | |||
139 | /* | 128 | /* |
140 | * This function splits the buffer by newlines and colors the lines individually. | 129 | * This function splits the buffer by newlines and colors the lines individually. |
141 | * | 130 | * |
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index 38146f922c54..a93997f16dec 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h | |||
@@ -35,7 +35,6 @@ int color_vsnprintf(char *bf, size_t size, const char *color, | |||
35 | int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); | 35 | int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); |
36 | int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); | 36 | int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); |
37 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); | 37 | int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); |
38 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); | ||
39 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); | 38 | int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); |
40 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); | 39 | int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); |
41 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); | 40 | int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7d3acba5a512..f572f469a30d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -545,14 +545,15 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) | |||
545 | 545 | ||
546 | static void | 546 | static void |
547 | perf_evsel__config_callgraph(struct perf_evsel *evsel, | 547 | perf_evsel__config_callgraph(struct perf_evsel *evsel, |
548 | struct record_opts *opts) | 548 | struct record_opts *opts, |
549 | struct callchain_param *param) | ||
549 | { | 550 | { |
550 | bool function = perf_evsel__is_function_event(evsel); | 551 | bool function = perf_evsel__is_function_event(evsel); |
551 | struct perf_event_attr *attr = &evsel->attr; | 552 | struct perf_event_attr *attr = &evsel->attr; |
552 | 553 | ||
553 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); | 554 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); |
554 | 555 | ||
555 | if (callchain_param.record_mode == CALLCHAIN_LBR) { | 556 | if (param->record_mode == CALLCHAIN_LBR) { |
556 | if (!opts->branch_stack) { | 557 | if (!opts->branch_stack) { |
557 | if (attr->exclude_user) { | 558 | if (attr->exclude_user) { |
558 | pr_warning("LBR callstack option is only available " | 559 | pr_warning("LBR callstack option is only available " |
@@ -568,12 +569,12 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, | |||
568 | "Falling back to framepointers.\n"); | 569 | "Falling back to framepointers.\n"); |
569 | } | 570 | } |
570 | 571 | ||
571 | if (callchain_param.record_mode == CALLCHAIN_DWARF) { | 572 | if (param->record_mode == CALLCHAIN_DWARF) { |
572 | if (!function) { | 573 | if (!function) { |
573 | perf_evsel__set_sample_bit(evsel, REGS_USER); | 574 | perf_evsel__set_sample_bit(evsel, REGS_USER); |
574 | perf_evsel__set_sample_bit(evsel, STACK_USER); | 575 | perf_evsel__set_sample_bit(evsel, STACK_USER); |
575 | attr->sample_regs_user = PERF_REGS_MASK; | 576 | attr->sample_regs_user = PERF_REGS_MASK; |
576 | attr->sample_stack_user = callchain_param.dump_size; | 577 | attr->sample_stack_user = param->dump_size; |
577 | attr->exclude_callchain_user = 1; | 578 | attr->exclude_callchain_user = 1; |
578 | } else { | 579 | } else { |
579 | pr_info("Cannot use DWARF unwind for function trace event," | 580 | pr_info("Cannot use DWARF unwind for function trace event," |
@@ -587,15 +588,23 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, | |||
587 | } | 588 | } |
588 | } | 589 | } |
589 | 590 | ||
590 | static void apply_config_terms(struct perf_event_attr *attr __maybe_unused, | 591 | static void apply_config_terms(struct perf_evsel *evsel) |
591 | struct list_head *config_terms) | ||
592 | { | 592 | { |
593 | struct perf_evsel_config_term *term; | 593 | struct perf_evsel_config_term *term; |
594 | struct list_head *config_terms = &evsel->config_terms; | ||
595 | struct perf_event_attr *attr = &evsel->attr; | ||
594 | 596 | ||
595 | list_for_each_entry(term, config_terms, list) { | 597 | list_for_each_entry(term, config_terms, list) { |
596 | switch (term->type) { | 598 | switch (term->type) { |
597 | case PERF_EVSEL__CONFIG_TERM_PERIOD: | 599 | case PERF_EVSEL__CONFIG_TERM_PERIOD: |
598 | attr->sample_period = term->val.period; | 600 | attr->sample_period = term->val.period; |
601 | break; | ||
602 | case PERF_EVSEL__CONFIG_TERM_TIME: | ||
603 | if (term->val.time) | ||
604 | perf_evsel__set_sample_bit(evsel, TIME); | ||
605 | else | ||
606 | perf_evsel__reset_sample_bit(evsel, TIME); | ||
607 | break; | ||
599 | default: | 608 | default: |
600 | break; | 609 | break; |
601 | } | 610 | } |
@@ -706,7 +715,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
706 | evsel->attr.exclude_callchain_user = 1; | 715 | evsel->attr.exclude_callchain_user = 1; |
707 | 716 | ||
708 | if (callchain_param.enabled && !evsel->no_aux_samples) | 717 | if (callchain_param.enabled && !evsel->no_aux_samples) |
709 | perf_evsel__config_callgraph(evsel, opts); | 718 | perf_evsel__config_callgraph(evsel, opts, &callchain_param); |
710 | 719 | ||
711 | if (opts->sample_intr_regs) { | 720 | if (opts->sample_intr_regs) { |
712 | attr->sample_regs_intr = PERF_REGS_MASK; | 721 | attr->sample_regs_intr = PERF_REGS_MASK; |
@@ -798,7 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
798 | * Apply event specific term settings, | 807 | * Apply event specific term settings, |
799 | * it overloads any global configuration. | 808 | * it overloads any global configuration. |
800 | */ | 809 | */ |
801 | apply_config_terms(attr, &evsel->config_terms); | 810 | apply_config_terms(evsel); |
802 | } | 811 | } |
803 | 812 | ||
804 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 813 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index a7d2175358b8..6a129081f3ad 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -39,6 +39,7 @@ struct cgroup_sel; | |||
39 | */ | 39 | */ |
40 | enum { | 40 | enum { |
41 | PERF_EVSEL__CONFIG_TERM_PERIOD, | 41 | PERF_EVSEL__CONFIG_TERM_PERIOD, |
42 | PERF_EVSEL__CONFIG_TERM_TIME, | ||
42 | PERF_EVSEL__CONFIG_TERM_MAX, | 43 | PERF_EVSEL__CONFIG_TERM_MAX, |
43 | }; | 44 | }; |
44 | 45 | ||
@@ -47,6 +48,7 @@ struct perf_evsel_config_term { | |||
47 | int type; | 48 | int type; |
48 | union { | 49 | union { |
49 | u64 period; | 50 | u64 period; |
51 | bool time; | ||
50 | } val; | 52 | } val; |
51 | }; | 53 | }; |
52 | 54 | ||
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 09bee93fd0ec..a6cb9afc20e2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -603,6 +603,14 @@ do { \ | |||
603 | * attr->branch_sample_type = term->val.num; | 603 | * attr->branch_sample_type = term->val.num; |
604 | */ | 604 | */ |
605 | break; | 605 | break; |
606 | case PARSE_EVENTS__TERM_TYPE_TIME: | ||
607 | CHECK_TYPE_VAL(NUM); | ||
608 | if (term->val.num > 1) { | ||
609 | err->str = strdup("expected 0 or 1"); | ||
610 | err->idx = term->err_val; | ||
611 | return -EINVAL; | ||
612 | } | ||
613 | break; | ||
606 | case PARSE_EVENTS__TERM_TYPE_NAME: | 614 | case PARSE_EVENTS__TERM_TYPE_NAME: |
607 | CHECK_TYPE_VAL(STR); | 615 | CHECK_TYPE_VAL(STR); |
608 | break; | 616 | break; |
@@ -650,6 +658,10 @@ do { \ | |||
650 | switch (term->type_term) { | 658 | switch (term->type_term) { |
651 | case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: | 659 | case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: |
652 | ADD_CONFIG_TERM(PERIOD, period, term->val.num); | 660 | ADD_CONFIG_TERM(PERIOD, period, term->val.num); |
661 | break; | ||
662 | case PARSE_EVENTS__TERM_TYPE_TIME: | ||
663 | ADD_CONFIG_TERM(TIME, time, term->val.num); | ||
664 | break; | ||
653 | default: | 665 | default: |
654 | break; | 666 | break; |
655 | } | 667 | } |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 2063048a4354..e6f9aacc1cce 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -63,6 +63,7 @@ enum { | |||
63 | PARSE_EVENTS__TERM_TYPE_NAME, | 63 | PARSE_EVENTS__TERM_TYPE_NAME, |
64 | PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, | 64 | PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, |
65 | PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, | 65 | PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, |
66 | PARSE_EVENTS__TERM_TYPE_TIME, | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | struct parse_events_term { | 69 | struct parse_events_term { |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 13cef3c65565..f5427505ae77 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -183,6 +183,7 @@ config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } | |||
183 | name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } | 183 | name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } |
184 | period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } | 184 | period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } |
185 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } | 185 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } |
186 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } | ||
186 | , { return ','; } | 187 | , { return ','; } |
187 | "/" { BEGIN(INITIAL); return '/'; } | 188 | "/" { BEGIN(INITIAL); return '/'; } |
188 | {name_minus} { return str(yyscanner, PE_NAME); } | 189 | {name_minus} { return str(yyscanner, PE_NAME); } |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 7bcb8c315615..b615cdf211d6 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -607,7 +607,7 @@ static char *formats_error_string(struct list_head *formats) | |||
607 | { | 607 | { |
608 | struct perf_pmu_format *format; | 608 | struct perf_pmu_format *format; |
609 | char *err, *str; | 609 | char *err, *str; |
610 | static const char *static_terms = "config,config1,config2,name,period,branch_type\n"; | 610 | static const char *static_terms = "config,config1,config2,name,period,branch_type,time\n"; |
611 | unsigned i = 0; | 611 | unsigned i = 0; |
612 | 612 | ||
613 | if (!asprintf(&str, "valid terms:")) | 613 | if (!asprintf(&str, "valid terms:")) |