diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-02-16 02:45:56 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-02-16 02:45:56 -0500 |
commit | fe7a2eaa71c55aadbf95d01d32df8dccc0db0646 (patch) | |
tree | 1f5f60ba774358e953c1b688c7e7c246be936117 /tools | |
parent | a7636d9ecfa3ab7800a7c04c1f89378229eff609 (diff) | |
parent | 1ad826bad5bd0b6ccfb203f78c70302b764df0be (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:
User visible changes:
- Do not print trailing spaces in the hists browser (top, report) to
avoid line wrapping issues when long C++ demangled functions are
sampled (Arnaldo Carvalho de Melo)
- Allow 'perf config' to show --system or --user settings (Taeung Song)
- Add better warning about the need to install the audit-lib-python
package when using perf python scripts (Taeung Song)
- Fix symbol resolution when kernel modules files are only in the
build id cache (~/.debug) (Wang Nan)
Build fixes:
- Fix 'perf test' build on older systems where 'signal' is reserved (Arnaldo Carvalho de Melo)
Infrastructure changes:
- Free the terms list_head in parse_events__free_terms(), also unlink the entries
when deleting them (Wang Nan)
- Fix releasing event_class in 'perf data' fixing integration with
libbabeltrace (Wang Nan)
- Add EXTRA_LDFLAGS option to Makefile (Zubair Lutfullah Kakakhel)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-config.txt | 14 | ||||
-rw-r--r-- | tools/perf/Makefile.perf | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/intel-pt.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-config.c | 27 | ||||
-rw-r--r-- | tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py | 5 | ||||
-rw-r--r-- | tools/perf/tests/bp_signal.c | 12 | ||||
-rw-r--r-- | tools/perf/tests/parse-events.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 27 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 1 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 44 | ||||
-rw-r--r-- | tools/perf/util/build-id.h | 1 | ||||
-rw-r--r-- | tools/perf/util/cache.h | 3 | ||||
-rw-r--r-- | tools/perf/util/config.c | 4 | ||||
-rw-r--r-- | tools/perf/util/data-convert-bt.c | 18 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 21 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 5 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 17 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.y | 8 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 2 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 23 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 4 |
22 files changed, 200 insertions, 45 deletions
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index c7158bfb1649..15949e2a7805 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt | |||
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file. | |||
8 | SYNOPSIS | 8 | SYNOPSIS |
9 | -------- | 9 | -------- |
10 | [verse] | 10 | [verse] |
11 | 'perf config' -l | --list | 11 | 'perf config' [<file-option>] -l | --list |
12 | 12 | ||
13 | DESCRIPTION | 13 | DESCRIPTION |
14 | ----------- | 14 | ----------- |
@@ -21,6 +21,14 @@ OPTIONS | |||
21 | --list:: | 21 | --list:: |
22 | Show current config variables, name and value, for all sections. | 22 | Show current config variables, name and value, for all sections. |
23 | 23 | ||
24 | --user:: | ||
25 | For writing and reading options: write to user | ||
26 | '$HOME/.perfconfig' file or read it. | ||
27 | |||
28 | --system:: | ||
29 | For writing and reading options: write to system-wide | ||
30 | '$(sysconfdir)/perfconfig' or read it. | ||
31 | |||
24 | CONFIGURATION FILE | 32 | CONFIGURATION FILE |
25 | ------------------ | 33 | ------------------ |
26 | 34 | ||
@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration. | |||
30 | The file '$(sysconfdir)/perfconfig' can be used to | 38 | The file '$(sysconfdir)/perfconfig' can be used to |
31 | store a system-wide default configuration. | 39 | store a system-wide default configuration. |
32 | 40 | ||
41 | When reading or writing, the values are read from the system and user | ||
42 | configuration files by default, and options '--system' and '--user' | ||
43 | can be used to tell the command to read from or write to only that location. | ||
44 | |||
33 | Syntax | 45 | Syntax |
34 | ~~~~~~ | 46 | ~~~~~~ |
35 | 47 | ||
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d404117810a7..4a4fad4182f5 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -139,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc) | |||
139 | $(call allow-override,AR,$(CROSS_COMPILE)ar) | 139 | $(call allow-override,AR,$(CROSS_COMPILE)ar) |
140 | $(call allow-override,LD,$(CROSS_COMPILE)ld) | 140 | $(call allow-override,LD,$(CROSS_COMPILE)ld) |
141 | 141 | ||
142 | LD += $(EXTRA_LDFLAGS) | ||
143 | |||
142 | PKG_CONFIG = $(CROSS_COMPILE)pkg-config | 144 | PKG_CONFIG = $(CROSS_COMPILE)pkg-config |
143 | 145 | ||
144 | RM = rm -f | 146 | RM = rm -f |
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 6f7d453b0e32..a3395179c9ee 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
@@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats, | |||
89 | 89 | ||
90 | *config = attr.config; | 90 | *config = attr.config; |
91 | out_free: | 91 | out_free: |
92 | parse_events__free_terms(terms); | 92 | parse_events_terms__delete(terms); |
93 | return err; | 93 | return err; |
94 | } | 94 | } |
95 | 95 | ||
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index f04e804a9fad..c42448ed5dfe 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c | |||
@@ -13,8 +13,10 @@ | |||
13 | #include "util/util.h" | 13 | #include "util/util.h" |
14 | #include "util/debug.h" | 14 | #include "util/debug.h" |
15 | 15 | ||
16 | static bool use_system_config, use_user_config; | ||
17 | |||
16 | static const char * const config_usage[] = { | 18 | static const char * const config_usage[] = { |
17 | "perf config [options]", | 19 | "perf config [<file-option>] [options]", |
18 | NULL | 20 | NULL |
19 | }; | 21 | }; |
20 | 22 | ||
@@ -25,6 +27,8 @@ enum actions { | |||
25 | static struct option config_options[] = { | 27 | static struct option config_options[] = { |
26 | OPT_SET_UINT('l', "list", &actions, | 28 | OPT_SET_UINT('l', "list", &actions, |
27 | "show current config variables", ACTION_LIST), | 29 | "show current config variables", ACTION_LIST), |
30 | OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"), | ||
31 | OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"), | ||
28 | OPT_END() | 32 | OPT_END() |
29 | }; | 33 | }; |
30 | 34 | ||
@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value, | |||
42 | int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) | 46 | int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) |
43 | { | 47 | { |
44 | int ret = 0; | 48 | int ret = 0; |
49 | char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); | ||
45 | 50 | ||
46 | argc = parse_options(argc, argv, config_options, config_usage, | 51 | argc = parse_options(argc, argv, config_options, config_usage, |
47 | PARSE_OPT_STOP_AT_NON_OPTION); | 52 | PARSE_OPT_STOP_AT_NON_OPTION); |
48 | 53 | ||
54 | if (use_system_config && use_user_config) { | ||
55 | pr_err("Error: only one config file at a time\n"); | ||
56 | parse_options_usage(config_usage, config_options, "user", 0); | ||
57 | parse_options_usage(NULL, config_options, "system", 0); | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | if (use_system_config) | ||
62 | config_exclusive_filename = perf_etc_perfconfig(); | ||
63 | else if (use_user_config) | ||
64 | config_exclusive_filename = user_config; | ||
65 | |||
49 | switch (actions) { | 66 | switch (actions) { |
50 | case ACTION_LIST: | 67 | case ACTION_LIST: |
51 | if (argc) { | 68 | if (argc) { |
@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) | |||
53 | parse_options_usage(config_usage, config_options, "l", 1); | 70 | parse_options_usage(config_usage, config_options, "l", 1); |
54 | } else { | 71 | } else { |
55 | ret = perf_config(show_config, NULL); | 72 | ret = perf_config(show_config, NULL); |
56 | if (ret < 0) | 73 | if (ret < 0) { |
74 | const char * config_filename = config_exclusive_filename; | ||
75 | if (!config_exclusive_filename) | ||
76 | config_filename = user_config; | ||
57 | pr_err("Nothing configured, " | 77 | pr_err("Nothing configured, " |
58 | "please check your ~/.perfconfig file\n"); | 78 | "please check your %s \n", config_filename); |
79 | } | ||
59 | } | 80 | } |
60 | break; | 81 | break; |
61 | default: | 82 | default: |
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py index 15c8400240fd..1d95009592eb 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py | |||
@@ -71,7 +71,10 @@ try: | |||
71 | except: | 71 | except: |
72 | if not audit_package_warned: | 72 | if not audit_package_warned: |
73 | audit_package_warned = True | 73 | audit_package_warned = True |
74 | print "Install the audit-libs-python package to get syscall names" | 74 | print "Install the audit-libs-python package to get syscall names.\n" \ |
75 | "For example:\n # apt-get install python-audit (Ubuntu)" \ | ||
76 | "\n # yum install audit-libs-python (Fedora)" \ | ||
77 | "\n etc.\n" | ||
75 | 78 | ||
76 | def syscall_name(id): | 79 | def syscall_name(id): |
77 | try: | 80 | try: |
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index 1d1bb489b4e8..e7664fe3bd33 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c | |||
@@ -103,7 +103,7 @@ static void sig_handler(int signum __maybe_unused, | |||
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
106 | static int __event(bool is_x, void *addr, int signal) | 106 | static int __event(bool is_x, void *addr, int sig) |
107 | { | 107 | { |
108 | struct perf_event_attr pe; | 108 | struct perf_event_attr pe; |
109 | int fd; | 109 | int fd; |
@@ -133,7 +133,7 @@ static int __event(bool is_x, void *addr, int signal) | |||
133 | } | 133 | } |
134 | 134 | ||
135 | fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); | 135 | fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); |
136 | fcntl(fd, F_SETSIG, signal); | 136 | fcntl(fd, F_SETSIG, sig); |
137 | fcntl(fd, F_SETOWN, getpid()); | 137 | fcntl(fd, F_SETOWN, getpid()); |
138 | 138 | ||
139 | ioctl(fd, PERF_EVENT_IOC_RESET, 0); | 139 | ioctl(fd, PERF_EVENT_IOC_RESET, 0); |
@@ -141,14 +141,14 @@ static int __event(bool is_x, void *addr, int signal) | |||
141 | return fd; | 141 | return fd; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int bp_event(void *addr, int signal) | 144 | static int bp_event(void *addr, int sig) |
145 | { | 145 | { |
146 | return __event(true, addr, signal); | 146 | return __event(true, addr, sig); |
147 | } | 147 | } |
148 | 148 | ||
149 | static int wp_event(void *addr, int signal) | 149 | static int wp_event(void *addr, int sig) |
150 | { | 150 | { |
151 | return __event(false, addr, signal); | 151 | return __event(false, addr, sig); |
152 | } | 152 | } |
153 | 153 | ||
154 | static long long bp_count(int fd) | 154 | static long long bp_count(int fd) |
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index abe8849d1d70..6648274f4601 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -1666,7 +1666,7 @@ static int test_term(struct terms_test *t) | |||
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | ret = t->check(&terms); | 1668 | ret = t->check(&terms); |
1669 | parse_events__free_terms(&terms); | 1669 | parse_events_terms__purge(&terms); |
1670 | 1670 | ||
1671 | return ret; | 1671 | return ret; |
1672 | } | 1672 | } |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a5a5390476ac..1819771243f9 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -1061,7 +1061,6 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
1061 | struct hist_entry *entry, | 1061 | struct hist_entry *entry, |
1062 | unsigned short row) | 1062 | unsigned short row) |
1063 | { | 1063 | { |
1064 | char s[256]; | ||
1065 | int printed = 0; | 1064 | int printed = 0; |
1066 | int width = browser->b.width; | 1065 | int width = browser->b.width; |
1067 | char folded_sign = ' '; | 1066 | char folded_sign = ' '; |
@@ -1086,16 +1085,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
1086 | .folded_sign = folded_sign, | 1085 | .folded_sign = folded_sign, |
1087 | .current_entry = current_entry, | 1086 | .current_entry = current_entry, |
1088 | }; | 1087 | }; |
1089 | struct perf_hpp hpp = { | ||
1090 | .buf = s, | ||
1091 | .size = sizeof(s), | ||
1092 | .ptr = &arg, | ||
1093 | }; | ||
1094 | int column = 0; | 1088 | int column = 0; |
1095 | 1089 | ||
1096 | hist_browser__gotorc(browser, row, 0); | 1090 | hist_browser__gotorc(browser, row, 0); |
1097 | 1091 | ||
1098 | hists__for_each_format(browser->hists, fmt) { | 1092 | hists__for_each_format(browser->hists, fmt) { |
1093 | char s[2048]; | ||
1094 | struct perf_hpp hpp = { | ||
1095 | .buf = s, | ||
1096 | .size = sizeof(s), | ||
1097 | .ptr = &arg, | ||
1098 | }; | ||
1099 | |||
1099 | if (perf_hpp__should_skip(fmt, entry->hists) || | 1100 | if (perf_hpp__should_skip(fmt, entry->hists) || |
1100 | column++ < browser->b.horiz_scroll) | 1101 | column++ < browser->b.horiz_scroll) |
1101 | continue; | 1102 | continue; |
@@ -1120,11 +1121,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
1120 | } | 1121 | } |
1121 | 1122 | ||
1122 | if (fmt->color) { | 1123 | if (fmt->color) { |
1123 | width -= fmt->color(fmt, &hpp, entry); | 1124 | int ret = fmt->color(fmt, &hpp, entry); |
1125 | hist_entry__snprintf_alignment(entry, &hpp, fmt, ret); | ||
1126 | /* | ||
1127 | * fmt->color() already used ui_browser to | ||
1128 | * print the non alignment bits, skip it (+ret): | ||
1129 | */ | ||
1130 | ui_browser__printf(&browser->b, "%s", s + ret); | ||
1124 | } else { | 1131 | } else { |
1125 | width -= fmt->entry(fmt, &hpp, entry); | 1132 | hist_entry__snprintf_alignment(entry, &hpp, fmt, fmt->entry(fmt, &hpp, entry)); |
1126 | ui_browser__printf(&browser->b, "%s", s); | 1133 | ui_browser__printf(&browser->b, "%s", s); |
1127 | } | 1134 | } |
1135 | width -= hpp.buf - s; | ||
1128 | } | 1136 | } |
1129 | 1137 | ||
1130 | /* The scroll bar isn't being used */ | 1138 | /* The scroll bar isn't being used */ |
@@ -1452,9 +1460,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, | |||
1452 | first = false; | 1460 | first = false; |
1453 | 1461 | ||
1454 | ret = fmt->entry(fmt, &hpp, he); | 1462 | ret = fmt->entry(fmt, &hpp, he); |
1463 | ret = hist_entry__snprintf_alignment(he, &hpp, fmt, ret); | ||
1455 | advance_hpp(&hpp, ret); | 1464 | advance_hpp(&hpp, ret); |
1456 | } | 1465 | } |
1457 | printed += fprintf(fp, "%s\n", rtrim(s)); | 1466 | printed += fprintf(fp, "%s\n", s); |
1458 | 1467 | ||
1459 | if (folded_sign == '-') | 1468 | if (folded_sign == '-') |
1460 | printed += hist_browser__fprintf_callchain(browser, he, fp); | 1469 | printed += hist_browser__fprintf_callchain(browser, he, fp); |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 1a6e8f7f38c4..87b022ff03d8 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -403,6 +403,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) | |||
403 | else | 403 | else |
404 | ret = fmt->entry(fmt, hpp, he); | 404 | ret = fmt->entry(fmt, hpp, he); |
405 | 405 | ||
406 | ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret); | ||
406 | advance_hpp(hpp, ret); | 407 | advance_hpp(hpp, ret); |
407 | } | 408 | } |
408 | 409 | ||
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index b28100ee1732..f1479eeef7da 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) | |||
166 | return build_id__filename(build_id_hex, bf, size); | 166 | return build_id__filename(build_id_hex, bf, size); |
167 | } | 167 | } |
168 | 168 | ||
169 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) | ||
170 | { | ||
171 | char *id_name, *ch; | ||
172 | struct stat sb; | ||
173 | |||
174 | id_name = dso__build_id_filename(dso, bf, size); | ||
175 | if (!id_name) | ||
176 | goto err; | ||
177 | if (access(id_name, F_OK)) | ||
178 | goto err; | ||
179 | if (lstat(id_name, &sb) == -1) | ||
180 | goto err; | ||
181 | if ((size_t)sb.st_size > size - 1) | ||
182 | goto err; | ||
183 | if (readlink(id_name, bf, size - 1) < 0) | ||
184 | goto err; | ||
185 | |||
186 | bf[sb.st_size] = '\0'; | ||
187 | |||
188 | /* | ||
189 | * link should be: | ||
190 | * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92 | ||
191 | */ | ||
192 | ch = strrchr(bf, '/'); | ||
193 | if (!ch) | ||
194 | goto err; | ||
195 | if (ch - 3 < bf) | ||
196 | goto err; | ||
197 | |||
198 | return strncmp(".ko", ch - 3, 3) == 0; | ||
199 | err: | ||
200 | /* | ||
201 | * If dso__build_id_filename work, get id_name again, | ||
202 | * because id_name points to bf and is broken. | ||
203 | */ | ||
204 | if (id_name) | ||
205 | id_name = dso__build_id_filename(dso, bf, size); | ||
206 | pr_err("Invalid build id: %s\n", id_name ? : | ||
207 | dso->long_name ? : | ||
208 | dso->short_name ? : | ||
209 | "[unknown]"); | ||
210 | return false; | ||
211 | } | ||
212 | |||
169 | #define dsos__for_each_with_build_id(pos, head) \ | 213 | #define dsos__for_each_with_build_id(pos, head) \ |
170 | list_for_each_entry(pos, head, node) \ | 214 | list_for_each_entry(pos, head, node) \ |
171 | if (!pos->has_build_id) \ | 215 | if (!pos->has_build_id) \ |
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 27a14a8a945b..64af3e20610d 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
@@ -16,6 +16,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); | |||
16 | int filename__sprintf_build_id(const char *pathname, char *sbuild_id); | 16 | int filename__sprintf_build_id(const char *pathname, char *sbuild_id); |
17 | 17 | ||
18 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); | 18 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); |
19 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); | ||
19 | 20 | ||
20 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, | 21 | int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, |
21 | struct perf_sample *sample, struct perf_evsel *evsel, | 22 | struct perf_sample *sample, struct perf_evsel *evsel, |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 07b5d63947b1..3ca453f0c51f 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -23,6 +23,8 @@ | |||
23 | #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" | 23 | #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" |
24 | #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" | 24 | #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" |
25 | 25 | ||
26 | extern const char *config_exclusive_filename; | ||
27 | |||
26 | typedef int (*config_fn_t)(const char *, const char *, void *); | 28 | typedef int (*config_fn_t)(const char *, const char *, void *); |
27 | extern int perf_default_config(const char *, const char *, void *); | 29 | extern int perf_default_config(const char *, const char *, void *); |
28 | extern int perf_config(config_fn_t fn, void *); | 30 | extern int perf_config(config_fn_t fn, void *); |
@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *); | |||
31 | extern int perf_config_bool(const char *, const char *); | 33 | extern int perf_config_bool(const char *, const char *); |
32 | extern int config_error_nonbool(const char *); | 34 | extern int config_error_nonbool(const char *); |
33 | extern const char *perf_config_dirname(const char *, const char *); | 35 | extern const char *perf_config_dirname(const char *, const char *); |
36 | extern const char *perf_etc_perfconfig(void); | ||
34 | 37 | ||
35 | char *alias_lookup(const char *alias); | 38 | char *alias_lookup(const char *alias); |
36 | int split_cmdline(char *cmdline, const char ***argv); | 39 | int split_cmdline(char *cmdline, const char ***argv); |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index d3e12e30e1d5..4e727635476e 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -26,7 +26,7 @@ static const char *config_file_name; | |||
26 | static int config_linenr; | 26 | static int config_linenr; |
27 | static int config_file_eof; | 27 | static int config_file_eof; |
28 | 28 | ||
29 | static const char *config_exclusive_filename; | 29 | const char *config_exclusive_filename; |
30 | 30 | ||
31 | static int get_next_char(void) | 31 | static int get_next_char(void) |
32 | { | 32 | { |
@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat | |||
434 | return ret; | 434 | return ret; |
435 | } | 435 | } |
436 | 436 | ||
437 | static const char *perf_etc_perfconfig(void) | 437 | const char *perf_etc_perfconfig(void) |
438 | { | 438 | { |
439 | static const char *system_wide; | 439 | static const char *system_wide; |
440 | if (!system_wide) | 440 | if (!system_wide) |
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 34cd1e4039d3..b722e57d5a87 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -858,6 +858,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session) | |||
858 | return 0; | 858 | return 0; |
859 | } | 859 | } |
860 | 860 | ||
861 | static void cleanup_events(struct perf_session *session) | ||
862 | { | ||
863 | struct perf_evlist *evlist = session->evlist; | ||
864 | struct perf_evsel *evsel; | ||
865 | |||
866 | evlist__for_each(evlist, evsel) { | ||
867 | struct evsel_priv *priv; | ||
868 | |||
869 | priv = evsel->priv; | ||
870 | bt_ctf_event_class_put(priv->event_class); | ||
871 | zfree(&evsel->priv); | ||
872 | } | ||
873 | |||
874 | perf_evlist__delete(evlist); | ||
875 | session->evlist = NULL; | ||
876 | } | ||
877 | |||
861 | static int setup_streams(struct ctf_writer *cw, struct perf_session *session) | 878 | static int setup_streams(struct ctf_writer *cw, struct perf_session *session) |
862 | { | 879 | { |
863 | struct ctf_stream **stream; | 880 | struct ctf_stream **stream; |
@@ -1171,6 +1188,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) | |||
1171 | (double) c.events_size / 1024.0 / 1024.0, | 1188 | (double) c.events_size / 1024.0 / 1024.0, |
1172 | c.events_count); | 1189 | c.events_count); |
1173 | 1190 | ||
1191 | cleanup_events(session); | ||
1174 | perf_session__delete(session); | 1192 | perf_session__delete(session); |
1175 | ctf_writer__cleanup(cw); | 1193 | ctf_writer__cleanup(cw); |
1176 | 1194 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 12f2d794dc28..561e9473a915 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -1015,6 +1015,27 @@ void hist_entry__delete(struct hist_entry *he) | |||
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | /* | 1017 | /* |
1018 | * If this is not the last column, then we need to pad it according to the | ||
1019 | * pre-calculated max lenght for this column, otherwise don't bother adding | ||
1020 | * spaces because that would break viewing this with, for instance, 'less', | ||
1021 | * that would show tons of trailing spaces when a long C++ demangled method | ||
1022 | * names is sampled. | ||
1023 | */ | ||
1024 | int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, | ||
1025 | struct perf_hpp_fmt *fmt, int printed) | ||
1026 | { | ||
1027 | if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { | ||
1028 | const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists)); | ||
1029 | if (printed < width) { | ||
1030 | advance_hpp(hpp, printed); | ||
1031 | printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | return printed; | ||
1036 | } | ||
1037 | |||
1038 | /* | ||
1018 | * collapse the histogram | 1039 | * collapse the histogram |
1019 | */ | 1040 | */ |
1020 | 1041 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1c7544a8fe1a..840b6d6aa44f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -122,11 +122,16 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |||
122 | int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, | 122 | int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, |
123 | int max_stack_depth, void *arg); | 123 | int max_stack_depth, void *arg); |
124 | 124 | ||
125 | struct perf_hpp; | ||
126 | struct perf_hpp_fmt; | ||
127 | |||
125 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); | 128 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); |
126 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); | 129 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); |
127 | int hist_entry__transaction_len(void); | 130 | int hist_entry__transaction_len(void); |
128 | int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, | 131 | int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, |
129 | struct hists *hists); | 132 | struct hists *hists); |
133 | int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, | ||
134 | struct perf_hpp_fmt *fmt, int printed); | ||
130 | void hist_entry__delete(struct hist_entry *he); | 135 | void hist_entry__delete(struct hist_entry *he); |
131 | 136 | ||
132 | void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); | 137 | void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 813d9b272c81..e5583fd4e7bd 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -1386,8 +1386,7 @@ int parse_events_terms(struct list_head *terms, const char *str) | |||
1386 | return 0; | 1386 | return 0; |
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | if (data.terms) | 1389 | parse_events_terms__delete(data.terms); |
1390 | parse_events__free_terms(data.terms); | ||
1391 | return ret; | 1390 | return ret; |
1392 | } | 1391 | } |
1393 | 1392 | ||
@@ -2068,12 +2067,22 @@ int parse_events_term__clone(struct parse_events_term **new, | |||
2068 | term->err_term, term->err_val); | 2067 | term->err_term, term->err_val); |
2069 | } | 2068 | } |
2070 | 2069 | ||
2071 | void parse_events__free_terms(struct list_head *terms) | 2070 | void parse_events_terms__purge(struct list_head *terms) |
2072 | { | 2071 | { |
2073 | struct parse_events_term *term, *h; | 2072 | struct parse_events_term *term, *h; |
2074 | 2073 | ||
2075 | list_for_each_entry_safe(term, h, terms, list) | 2074 | list_for_each_entry_safe(term, h, terms, list) { |
2075 | list_del_init(&term->list); | ||
2076 | free(term); | 2076 | free(term); |
2077 | } | ||
2078 | } | ||
2079 | |||
2080 | void parse_events_terms__delete(struct list_head *terms) | ||
2081 | { | ||
2082 | if (!terms) | ||
2083 | return; | ||
2084 | parse_events_terms__purge(terms); | ||
2085 | free(terms); | ||
2077 | } | 2086 | } |
2078 | 2087 | ||
2079 | void parse_events_evlist_error(struct parse_events_evlist *data, | 2088 | void parse_events_evlist_error(struct parse_events_evlist *data, |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index f1a6db107241..53628bf3da67 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -115,7 +115,8 @@ int parse_events_term__sym_hw(struct parse_events_term **term, | |||
115 | char *config, unsigned idx); | 115 | char *config, unsigned idx); |
116 | int parse_events_term__clone(struct parse_events_term **new, | 116 | int parse_events_term__clone(struct parse_events_term **new, |
117 | struct parse_events_term *term); | 117 | struct parse_events_term *term); |
118 | void parse_events__free_terms(struct list_head *terms); | 118 | void parse_events_terms__delete(struct list_head *terms); |
119 | void parse_events_terms__purge(struct list_head *terms); | ||
119 | int parse_events__modifier_event(struct list_head *list, char *str, bool add); | 120 | int parse_events__modifier_event(struct list_head *list, char *str, bool add); |
120 | int parse_events__modifier_group(struct list_head *list, char *event_mod); | 121 | int parse_events__modifier_group(struct list_head *list, char *event_mod); |
121 | int parse_events_name(struct list_head *list, char *name); | 122 | int parse_events_name(struct list_head *list, char *name); |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index ad379968d4c1..c0eac88ef474 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y | |||
@@ -218,7 +218,7 @@ PE_NAME '/' event_config '/' | |||
218 | 218 | ||
219 | ALLOC_LIST(list); | 219 | ALLOC_LIST(list); |
220 | ABORT_ON(parse_events_add_pmu(data, list, $1, $3)); | 220 | ABORT_ON(parse_events_add_pmu(data, list, $1, $3)); |
221 | parse_events__free_terms($3); | 221 | parse_events_terms__delete($3); |
222 | $$ = list; | 222 | $$ = list; |
223 | } | 223 | } |
224 | | | 224 | | |
@@ -246,7 +246,7 @@ PE_KERNEL_PMU_EVENT sep_dc | |||
246 | 246 | ||
247 | ALLOC_LIST(list); | 247 | ALLOC_LIST(list); |
248 | ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); | 248 | ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); |
249 | parse_events__free_terms(head); | 249 | parse_events_terms__delete(head); |
250 | $$ = list; | 250 | $$ = list; |
251 | } | 251 | } |
252 | | | 252 | | |
@@ -266,7 +266,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc | |||
266 | 266 | ||
267 | ALLOC_LIST(list); | 267 | ALLOC_LIST(list); |
268 | ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); | 268 | ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); |
269 | parse_events__free_terms(head); | 269 | parse_events_terms__delete(head); |
270 | $$ = list; | 270 | $$ = list; |
271 | } | 271 | } |
272 | 272 | ||
@@ -285,7 +285,7 @@ value_sym '/' event_config '/' | |||
285 | 285 | ||
286 | ALLOC_LIST(list); | 286 | ALLOC_LIST(list); |
287 | ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); | 287 | ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); |
288 | parse_events__free_terms($3); | 288 | parse_events_terms__delete($3); |
289 | $$ = list; | 289 | $$ = list; |
290 | } | 290 | } |
291 | | | 291 | | |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 41a9c875e492..cf59fbaee491 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -354,7 +354,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, | |||
354 | list_for_each_entry(term, &alias->terms, list) { | 354 | list_for_each_entry(term, &alias->terms, list) { |
355 | ret = parse_events_term__clone(&cloned, term); | 355 | ret = parse_events_term__clone(&cloned, term); |
356 | if (ret) { | 356 | if (ret) { |
357 | parse_events__free_terms(&list); | 357 | parse_events_terms__purge(&list); |
358 | return ret; | 358 | return ret; |
359 | } | 359 | } |
360 | list_add_tail(&cloned->list, &list); | 360 | list_add_tail(&cloned->list, &list); |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index de620f7f40f4..de715756f281 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -28,7 +28,15 @@ int sort__has_socket = 0; | |||
28 | int sort__has_thread = 0; | 28 | int sort__has_thread = 0; |
29 | enum sort_mode sort__mode = SORT_MODE__NORMAL; | 29 | enum sort_mode sort__mode = SORT_MODE__NORMAL; |
30 | 30 | ||
31 | 31 | /* | |
32 | * Replaces all occurrences of a char used with the: | ||
33 | * | ||
34 | * -t, --field-separator | ||
35 | * | ||
36 | * option, that uses a special separator character and don't pad with spaces, | ||
37 | * replacing all occurances of this separator in symbol names (and other | ||
38 | * output) with a '.' character, that thus it's the only non valid separator. | ||
39 | */ | ||
32 | static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) | 40 | static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) |
33 | { | 41 | { |
34 | int n; | 42 | int n; |
@@ -247,10 +255,8 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, | |||
247 | ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); | 255 | ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); |
248 | ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", | 256 | ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", |
249 | ip - map->unmap_ip(map, sym->start)); | 257 | ip - map->unmap_ip(map, sym->start)); |
250 | ret += repsep_snprintf(bf + ret, size - ret, "%-*s", | ||
251 | width - ret, ""); | ||
252 | } else { | 258 | } else { |
253 | ret += repsep_snprintf(bf + ret, size - ret, "%-*s", | 259 | ret += repsep_snprintf(bf + ret, size - ret, "%.*s", |
254 | width - ret, | 260 | width - ret, |
255 | sym->name); | 261 | sym->name); |
256 | } | 262 | } |
@@ -258,14 +264,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, | |||
258 | size_t len = BITS_PER_LONG / 4; | 264 | size_t len = BITS_PER_LONG / 4; |
259 | ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", | 265 | ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", |
260 | len, ip); | 266 | len, ip); |
261 | ret += repsep_snprintf(bf + ret, size - ret, "%-*s", | ||
262 | width - ret, ""); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | if (ret > width) | 269 | return ret; |
266 | bf[width] = '\0'; | ||
267 | |||
268 | return width; | ||
269 | } | 270 | } |
270 | 271 | ||
271 | static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, | 272 | static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, |
@@ -811,7 +812,7 @@ static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, | |||
811 | else | 812 | else |
812 | out = "No"; | 813 | out = "No"; |
813 | 814 | ||
814 | return repsep_snprintf(bf, size, "%-*s", width, out); | 815 | return repsep_snprintf(bf, size, "%.*s", width, out); |
815 | } | 816 | } |
816 | 817 | ||
817 | static int64_t | 818 | static int64_t |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 90cedfa30e43..e7588dc91518 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1529,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1529 | if (!runtime_ss && syms_ss) | 1529 | if (!runtime_ss && syms_ss) |
1530 | runtime_ss = syms_ss; | 1530 | runtime_ss = syms_ss; |
1531 | 1531 | ||
1532 | if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE) | ||
1533 | if (dso__build_id_is_kmod(dso, name, PATH_MAX)) | ||
1534 | kmod = true; | ||
1535 | |||
1532 | if (syms_ss) | 1536 | if (syms_ss) |
1533 | ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); | 1537 | ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); |
1534 | else | 1538 | else |