aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/bpf-loader.c4
-rw-r--r--tools/perf/util/callchain.c27
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/config.c23
-rw-r--r--tools/perf/util/data-convert-bt.c7
-rw-r--r--tools/perf/util/dso.c48
-rw-r--r--tools/perf/util/event.c2
-rw-r--r--tools/perf/util/evlist.c12
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c66
-rw-r--r--tools/perf/util/evsel_fprintf.c1
-rw-r--r--tools/perf/util/header.c7
-rw-r--r--tools/perf/util/hist.c11
-rw-r--r--tools/perf/util/hist.h7
-rw-r--r--tools/perf/util/intel-pt-decoder/Build6
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c5
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt.c4
-rw-r--r--tools/perf/util/llvm-utils.c4
-rw-r--r--tools/perf/util/machine.c25
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/parse-events.c84
-rw-r--r--tools/perf/util/parse-events.y37
-rw-r--r--tools/perf/util/pmu.c113
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c179
-rw-r--r--tools/perf/util/probe-finder.c15
-rw-r--r--tools/perf/util/probe-finder.h3
-rw-r--r--tools/perf/util/scripting-engines/Build2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
-rw-r--r--tools/perf/util/session.c4
-rw-r--r--tools/perf/util/strfilter.c1
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/symbol-elf.c6
-rw-r--r--tools/perf/util/symbol.c6
-rw-r--r--tools/perf/util/symbol_fprintf.c2
-rw-r--r--tools/perf/util/thread_map.c2
-rw-r--r--tools/perf/util/trace-event-info.c71
-rw-r--r--tools/perf/util/trace-event-parse.c17
-rw-r--r--tools/perf/util/trace-event-read.c77
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/unwind-libunwind-local.c54
-rw-r--r--tools/perf/util/util.c15
-rw-r--r--tools/perf/util/util.h3
47 files changed, 695 insertions, 287 deletions
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 3840e3a87057..5da376bc1afc 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -162,6 +162,7 @@ CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET
162CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 162CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
163CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 163CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
164CFLAGS_parse-events.o += -Wno-redundant-decls 164CFLAGS_parse-events.o += -Wno-redundant-decls
165CFLAGS_header.o += -include $(OUTPUT)PERF-VERSION-FILE
165 166
166$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE 167$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
167 $(call rule_mkdir) 168 $(call rule_mkdir)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 36c861103291..bc6bc7062eb4 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -670,13 +670,13 @@ int bpf__probe(struct bpf_object *obj)
670 670
671 err = convert_perf_probe_events(pev, 1); 671 err = convert_perf_probe_events(pev, 1);
672 if (err < 0) { 672 if (err < 0) {
673 pr_debug("bpf_probe: failed to convert perf probe events"); 673 pr_debug("bpf_probe: failed to convert perf probe events\n");
674 goto out; 674 goto out;
675 } 675 }
676 676
677 err = apply_perf_probe_events(pev, 1); 677 err = apply_perf_probe_events(pev, 1);
678 if (err < 0) { 678 if (err < 0) {
679 pr_debug("bpf_probe: failed to apply perf probe events"); 679 pr_debug("bpf_probe: failed to apply perf probe events\n");
680 goto out; 680 goto out;
681 } 681 }
682 682
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 42922512c1c6..aba953421a03 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -48,6 +48,8 @@ static int parse_callchain_mode(const char *value)
48 callchain_param.mode = CHAIN_FOLDED; 48 callchain_param.mode = CHAIN_FOLDED;
49 return 0; 49 return 0;
50 } 50 }
51
52 pr_err("Invalid callchain mode: %s\n", value);
51 return -1; 53 return -1;
52} 54}
53 55
@@ -63,6 +65,8 @@ static int parse_callchain_order(const char *value)
63 callchain_param.order_set = true; 65 callchain_param.order_set = true;
64 return 0; 66 return 0;
65 } 67 }
68
69 pr_err("Invalid callchain order: %s\n", value);
66 return -1; 70 return -1;
67} 71}
68 72
@@ -80,6 +84,8 @@ static int parse_callchain_sort_key(const char *value)
80 callchain_param.branch_callstack = 1; 84 callchain_param.branch_callstack = 1;
81 return 0; 85 return 0;
82 } 86 }
87
88 pr_err("Invalid callchain sort key: %s\n", value);
83 return -1; 89 return -1;
84} 90}
85 91
@@ -97,6 +103,8 @@ static int parse_callchain_value(const char *value)
97 callchain_param.value = CCVAL_COUNT; 103 callchain_param.value = CCVAL_COUNT;
98 return 0; 104 return 0;
99 } 105 }
106
107 pr_err("Invalid callchain config key: %s\n", value);
100 return -1; 108 return -1;
101} 109}
102 110
@@ -210,13 +218,17 @@ int perf_callchain_config(const char *var, const char *value)
210 return parse_callchain_sort_key(value); 218 return parse_callchain_sort_key(value);
211 if (!strcmp(var, "threshold")) { 219 if (!strcmp(var, "threshold")) {
212 callchain_param.min_percent = strtod(value, &endptr); 220 callchain_param.min_percent = strtod(value, &endptr);
213 if (value == endptr) 221 if (value == endptr) {
222 pr_err("Invalid callchain threshold: %s\n", value);
214 return -1; 223 return -1;
224 }
215 } 225 }
216 if (!strcmp(var, "print-limit")) { 226 if (!strcmp(var, "print-limit")) {
217 callchain_param.print_limit = strtod(value, &endptr); 227 callchain_param.print_limit = strtod(value, &endptr);
218 if (value == endptr) 228 if (value == endptr) {
229 pr_err("Invalid callchain print limit: %s\n", value);
219 return -1; 230 return -1;
231 }
220 } 232 }
221 233
222 return 0; 234 return 0;
@@ -437,7 +449,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
437 } 449 }
438 call->ip = cursor_node->ip; 450 call->ip = cursor_node->ip;
439 call->ms.sym = cursor_node->sym; 451 call->ms.sym = cursor_node->sym;
440 call->ms.map = cursor_node->map; 452 call->ms.map = map__get(cursor_node->map);
441 453
442 if (cursor_node->branch) { 454 if (cursor_node->branch) {
443 call->branch_count = 1; 455 call->branch_count = 1;
@@ -477,6 +489,7 @@ add_child(struct callchain_node *parent,
477 489
478 list_for_each_entry_safe(call, tmp, &new->val, list) { 490 list_for_each_entry_safe(call, tmp, &new->val, list) {
479 list_del(&call->list); 491 list_del(&call->list);
492 map__zput(call->ms.map);
480 free(call); 493 free(call);
481 } 494 }
482 free(new); 495 free(new);
@@ -761,6 +774,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
761 list->ms.map, list->ms.sym, 774 list->ms.map, list->ms.sym,
762 false, NULL, 0, 0); 775 false, NULL, 0, 0);
763 list_del(&list->list); 776 list_del(&list->list);
777 map__zput(list->ms.map);
764 free(list); 778 free(list);
765 } 779 }
766 780
@@ -811,7 +825,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
811 } 825 }
812 826
813 node->ip = ip; 827 node->ip = ip;
814 node->map = map; 828 map__zput(node->map);
829 node->map = map__get(map);
815 node->sym = sym; 830 node->sym = sym;
816 node->branch = branch; 831 node->branch = branch;
817 node->nr_loop_iter = nr_loop_iter; 832 node->nr_loop_iter = nr_loop_iter;
@@ -1142,11 +1157,13 @@ static void free_callchain_node(struct callchain_node *node)
1142 1157
1143 list_for_each_entry_safe(list, tmp, &node->parent_val, list) { 1158 list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
1144 list_del(&list->list); 1159 list_del(&list->list);
1160 map__zput(list->ms.map);
1145 free(list); 1161 free(list);
1146 } 1162 }
1147 1163
1148 list_for_each_entry_safe(list, tmp, &node->val, list) { 1164 list_for_each_entry_safe(list, tmp, &node->val, list) {
1149 list_del(&list->list); 1165 list_del(&list->list);
1166 map__zput(list->ms.map);
1150 free(list); 1167 free(list);
1151 } 1168 }
1152 1169
@@ -1210,6 +1227,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
1210 goto out; 1227 goto out;
1211 *new = *chain; 1228 *new = *chain;
1212 new->has_children = false; 1229 new->has_children = false;
1230 map__get(new->ms.map);
1213 list_add_tail(&new->list, &head); 1231 list_add_tail(&new->list, &head);
1214 } 1232 }
1215 parent = parent->parent; 1233 parent = parent->parent;
@@ -1230,6 +1248,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
1230out: 1248out:
1231 list_for_each_entry_safe(chain, new, &head, list) { 1249 list_for_each_entry_safe(chain, new, &head, list) {
1232 list_del(&chain->list); 1250 list_del(&chain->list);
1251 map__zput(chain->ms.map);
1233 free(chain); 1252 free(chain);
1234 } 1253 }
1235 return -ENOMEM; 1254 return -ENOMEM;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 35c8e379530f..4f4b60f1558a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -5,6 +5,7 @@
5#include <linux/list.h> 5#include <linux/list.h>
6#include <linux/rbtree.h> 6#include <linux/rbtree.h>
7#include "event.h" 7#include "event.h"
8#include "map.h"
8#include "symbol.h" 9#include "symbol.h"
9 10
10#define HELP_PAD "\t\t\t\t" 11#define HELP_PAD "\t\t\t\t"
@@ -184,8 +185,13 @@ int callchain_merge(struct callchain_cursor *cursor,
184 */ 185 */
185static inline void callchain_cursor_reset(struct callchain_cursor *cursor) 186static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
186{ 187{
188 struct callchain_cursor_node *node;
189
187 cursor->nr = 0; 190 cursor->nr = 0;
188 cursor->last = &cursor->first; 191 cursor->last = &cursor->first;
192
193 for (node = cursor->first; node != NULL; node = node->next)
194 map__zput(node->map);
189} 195}
190 196
191int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, 197int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 3d906dbbef74..0c7d5a4975cd 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -386,8 +386,10 @@ static int perf_buildid_config(const char *var, const char *value)
386 if (!strcmp(var, "buildid.dir")) { 386 if (!strcmp(var, "buildid.dir")) {
387 const char *dir = perf_config_dirname(var, value); 387 const char *dir = perf_config_dirname(var, value);
388 388
389 if (!dir) 389 if (!dir) {
390 pr_err("Invalid buildid directory!\n");
390 return -1; 391 return -1;
392 }
391 strncpy(buildid_dir, dir, MAXPATHLEN-1); 393 strncpy(buildid_dir, dir, MAXPATHLEN-1);
392 buildid_dir[MAXPATHLEN-1] = '\0'; 394 buildid_dir[MAXPATHLEN-1] = '\0';
393 } 395 }
@@ -405,10 +407,9 @@ static int perf_default_core_config(const char *var __maybe_unused,
405static int perf_ui_config(const char *var, const char *value) 407static int perf_ui_config(const char *var, const char *value)
406{ 408{
407 /* Add other config variables here. */ 409 /* Add other config variables here. */
408 if (!strcmp(var, "ui.show-headers")) { 410 if (!strcmp(var, "ui.show-headers"))
409 symbol_conf.show_hist_headers = perf_config_bool(var, value); 411 symbol_conf.show_hist_headers = perf_config_bool(var, value);
410 return 0; 412
411 }
412 return 0; 413 return 0;
413} 414}
414 415
@@ -646,8 +647,13 @@ static int perf_config_set__init(struct perf_config_set *set)
646 goto out; 647 goto out;
647 } 648 }
648 649
649 if (stat(user_config, &st) < 0) 650 if (stat(user_config, &st) < 0) {
651 if (errno == ENOENT)
652 ret = 0;
650 goto out_free; 653 goto out_free;
654 }
655
656 ret = 0;
651 657
652 if (st.st_uid && (st.st_uid != geteuid())) { 658 if (st.st_uid && (st.st_uid != geteuid())) {
653 warning("File %s not owned by current user or root, " 659 warning("File %s not owned by current user or root, "
@@ -655,11 +661,8 @@ static int perf_config_set__init(struct perf_config_set *set)
655 goto out_free; 661 goto out_free;
656 } 662 }
657 663
658 if (!st.st_size) 664 if (st.st_size)
659 goto out_free; 665 ret = perf_config_from_file(collect_config, user_config, set);
660
661 ret = perf_config_from_file(collect_config, user_config, set);
662
663out_free: 666out_free:
664 free(user_config); 667 free(user_config);
665 } 668 }
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 7123f4de32cc..4e6cbc99f08e 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1473,7 +1473,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1473 }, 1473 },
1474 }; 1474 };
1475 struct ctf_writer *cw = &c.writer; 1475 struct ctf_writer *cw = &c.writer;
1476 int err = -1; 1476 int err;
1477 1477
1478 if (opts->all) { 1478 if (opts->all) {
1479 c.tool.comm = process_comm_event; 1479 c.tool.comm = process_comm_event;
@@ -1481,12 +1481,15 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1481 c.tool.fork = process_fork_event; 1481 c.tool.fork = process_fork_event;
1482 } 1482 }
1483 1483
1484 perf_config(convert__config, &c); 1484 err = perf_config(convert__config, &c);
1485 if (err)
1486 return err;
1485 1487
1486 /* CTF writer */ 1488 /* CTF writer */
1487 if (ctf_writer__init(cw, path)) 1489 if (ctf_writer__init(cw, path))
1488 return -1; 1490 return -1;
1489 1491
1492 err = -1;
1490 /* perf.data session */ 1493 /* perf.data session */
1491 session = perf_session__new(&file, 0, &c.tool); 1494 session = perf_session__new(&file, 0, &c.tool);
1492 if (!session) 1495 if (!session)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d2c6cdd9d42b..28d41e709128 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -9,6 +9,13 @@
9#include "debug.h" 9#include "debug.h"
10#include "vdso.h" 10#include "vdso.h"
11 11
12static const char * const debuglink_paths[] = {
13 "%.0s%s",
14 "%s/%s",
15 "%s/.debug/%s",
16 "/usr/lib/debug%s/%s"
17};
18
12char dso__symtab_origin(const struct dso *dso) 19char dso__symtab_origin(const struct dso *dso)
13{ 20{
14 static const char origin[] = { 21 static const char origin[] = {
@@ -44,24 +51,43 @@ int dso__read_binary_type_filename(const struct dso *dso,
44 size_t len; 51 size_t len;
45 52
46 switch (type) { 53 switch (type) {
47 case DSO_BINARY_TYPE__DEBUGLINK: { 54 case DSO_BINARY_TYPE__DEBUGLINK:
48 char *debuglink; 55 {
56 const char *last_slash;
57 char dso_dir[PATH_MAX];
58 char symfile[PATH_MAX];
59 unsigned int i;
49 60
50 len = __symbol__join_symfs(filename, size, dso->long_name); 61 len = __symbol__join_symfs(filename, size, dso->long_name);
51 debuglink = filename + len; 62 last_slash = filename + len;
52 while (debuglink != filename && *debuglink != '/') 63 while (last_slash != filename && *last_slash != '/')
53 debuglink--; 64 last_slash--;
54 if (*debuglink == '/')
55 debuglink++;
56 65
57 ret = -1; 66 strncpy(dso_dir, filename, last_slash - filename);
58 if (!is_regular_file(filename)) 67 dso_dir[last_slash-filename] = '\0';
68
69 if (!is_regular_file(filename)) {
70 ret = -1;
71 break;
72 }
73
74 ret = filename__read_debuglink(filename, symfile, PATH_MAX);
75 if (ret)
59 break; 76 break;
60 77
61 ret = filename__read_debuglink(filename, debuglink, 78 /* Check predefined locations where debug file might reside */
62 size - (debuglink - filename)); 79 ret = -1;
80 for (i = 0; i < ARRAY_SIZE(debuglink_paths); i++) {
81 snprintf(filename, size,
82 debuglink_paths[i], dso_dir, symfile);
83 if (is_regular_file(filename)) {
84 ret = 0;
85 break;
86 }
63 } 87 }
88
64 break; 89 break;
90 }
65 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 91 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
66 if (dso__build_id_filename(dso, filename, size) == NULL) 92 if (dso__build_id_filename(dso, filename, size) == NULL)
67 ret = -1; 93 ret = -1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8ab0d7da956b..4ea7ce72ed9c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,5 +1,5 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 2#include <linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
3#include <api/fs/fs.h> 3#include <api/fs/fs.h>
4#include "event.h" 4#include "event.h"
5#include "debug.h" 5#include "debug.h"
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d92e02006fb8..b601f2814a30 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1184,7 +1184,7 @@ unsigned long perf_event_mlock_kb_in_pages(void)
1184 return pages; 1184 return pages;
1185} 1185}
1186 1186
1187static size_t perf_evlist__mmap_size(unsigned long pages) 1187size_t perf_evlist__mmap_size(unsigned long pages)
1188{ 1188{
1189 if (pages == UINT_MAX) 1189 if (pages == UINT_MAX)
1190 pages = perf_event_mlock_kb_in_pages(); 1190 pages = perf_event_mlock_kb_in_pages();
@@ -1224,12 +1224,16 @@ static long parse_pages_arg(const char *str, unsigned long min,
1224 if (pages == 0 && min == 0) { 1224 if (pages == 0 && min == 0) {
1225 /* leave number of pages at 0 */ 1225 /* leave number of pages at 0 */
1226 } else if (!is_power_of_2(pages)) { 1226 } else if (!is_power_of_2(pages)) {
1227 char buf[100];
1228
1227 /* round pages up to next power of 2 */ 1229 /* round pages up to next power of 2 */
1228 pages = roundup_pow_of_two(pages); 1230 pages = roundup_pow_of_two(pages);
1229 if (!pages) 1231 if (!pages)
1230 return -EINVAL; 1232 return -EINVAL;
1231 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 1233
1232 pages * page_size, pages); 1234 unit_number__scnprintf(buf, sizeof(buf), pages * page_size);
1235 pr_info("rounding mmap pages size to %s (%lu pages)\n",
1236 buf, pages);
1233 } 1237 }
1234 1238
1235 if (pages > max) 1239 if (pages > max)
@@ -1797,7 +1801,7 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
1797 */ 1801 */
1798 ret = write(evlist->workload.cork_fd, &bf, 1); 1802 ret = write(evlist->workload.cork_fd, &bf, 1);
1799 if (ret < 0) 1803 if (ret < 0)
1800 perror("enable to write to pipe"); 1804 perror("unable to write to pipe");
1801 1805
1802 close(evlist->workload.cork_fd); 1806 close(evlist->workload.cork_fd);
1803 return ret; 1807 return ret;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 4fd034f22d2f..389b9ccdf8c7 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -218,6 +218,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
218 bool overwrite); 218 bool overwrite);
219void perf_evlist__munmap(struct perf_evlist *evlist); 219void perf_evlist__munmap(struct perf_evlist *evlist);
220 220
221size_t perf_evlist__mmap_size(unsigned long pages);
222
221void perf_evlist__disable(struct perf_evlist *evlist); 223void perf_evlist__disable(struct perf_evlist *evlist);
222void perf_evlist__enable(struct perf_evlist *evlist); 224void perf_evlist__enable(struct perf_evlist *evlist);
223void perf_evlist__toggle_enable(struct perf_evlist *evlist); 225void perf_evlist__toggle_enable(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 04e536ae4d88..ac59710b79e0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1448,8 +1448,8 @@ static bool ignore_missing_thread(struct perf_evsel *evsel,
1448 return true; 1448 return true;
1449} 1449}
1450 1450
1451static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1451int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1452 struct thread_map *threads) 1452 struct thread_map *threads)
1453{ 1453{
1454 int cpu, thread, nthreads; 1454 int cpu, thread, nthreads;
1455 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1455 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
@@ -1459,6 +1459,30 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1459 if (perf_missing_features.write_backward && evsel->attr.write_backward) 1459 if (perf_missing_features.write_backward && evsel->attr.write_backward)
1460 return -EINVAL; 1460 return -EINVAL;
1461 1461
1462 if (cpus == NULL) {
1463 static struct cpu_map *empty_cpu_map;
1464
1465 if (empty_cpu_map == NULL) {
1466 empty_cpu_map = cpu_map__dummy_new();
1467 if (empty_cpu_map == NULL)
1468 return -ENOMEM;
1469 }
1470
1471 cpus = empty_cpu_map;
1472 }
1473
1474 if (threads == NULL) {
1475 static struct thread_map *empty_thread_map;
1476
1477 if (empty_thread_map == NULL) {
1478 empty_thread_map = thread_map__new_by_tid(-1);
1479 if (empty_thread_map == NULL)
1480 return -ENOMEM;
1481 }
1482
1483 threads = empty_thread_map;
1484 }
1485
1462 if (evsel->system_wide) 1486 if (evsel->system_wide)
1463 nthreads = 1; 1487 nthreads = 1;
1464 else 1488 else
@@ -1655,46 +1679,16 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
1655 perf_evsel__free_fd(evsel); 1679 perf_evsel__free_fd(evsel);
1656} 1680}
1657 1681
1658static struct {
1659 struct cpu_map map;
1660 int cpus[1];
1661} empty_cpu_map = {
1662 .map.nr = 1,
1663 .cpus = { -1, },
1664};
1665
1666static struct {
1667 struct thread_map map;
1668 int threads[1];
1669} empty_thread_map = {
1670 .map.nr = 1,
1671 .threads = { -1, },
1672};
1673
1674int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1675 struct thread_map *threads)
1676{
1677 if (cpus == NULL) {
1678 /* Work around old compiler warnings about strict aliasing */
1679 cpus = &empty_cpu_map.map;
1680 }
1681
1682 if (threads == NULL)
1683 threads = &empty_thread_map.map;
1684
1685 return __perf_evsel__open(evsel, cpus, threads);
1686}
1687
1688int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 1682int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
1689 struct cpu_map *cpus) 1683 struct cpu_map *cpus)
1690{ 1684{
1691 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map); 1685 return perf_evsel__open(evsel, cpus, NULL);
1692} 1686}
1693 1687
1694int perf_evsel__open_per_thread(struct perf_evsel *evsel, 1688int perf_evsel__open_per_thread(struct perf_evsel *evsel,
1695 struct thread_map *threads) 1689 struct thread_map *threads)
1696{ 1690{
1697 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); 1691 return perf_evsel__open(evsel, NULL, threads);
1698} 1692}
1699 1693
1700static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, 1694static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
@@ -2469,7 +2463,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2469 " -1: Allow use of (almost) all events by all users\n" 2463 " -1: Allow use of (almost) all events by all users\n"
2470 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2464 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n"
2471 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" 2465 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2472 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", 2466 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN\n\n"
2467 "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
2468 " kernel.perf_event_paranoid = -1\n" ,
2473 target->system_wide ? "system-wide " : "", 2469 target->system_wide ? "system-wide " : "",
2474 perf_event_paranoid()); 2470 perf_event_paranoid());
2475 case ENOENT: 2471 case ENOENT:
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 6b2925542c0a..4ef5184819a0 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -168,7 +168,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
168 168
169 if (symbol_conf.bt_stop_list && 169 if (symbol_conf.bt_stop_list &&
170 node->sym && 170 node->sym &&
171 node->sym->name &&
172 strlist__has_entry(symbol_conf.bt_stop_list, 171 strlist__has_entry(symbol_conf.bt_stop_list,
173 node->sym->name)) { 172 node->sym->name)) {
174 break; 173 break;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d89c9c7ef4e5..3d12c16e5103 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -41,6 +41,8 @@ static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
41 41
42#define PERF_MAGIC __perf_magic2 42#define PERF_MAGIC __perf_magic2
43 43
44const char perf_version_string[] = PERF_VERSION;
45
44struct perf_file_attr { 46struct perf_file_attr {
45 struct perf_event_attr attr; 47 struct perf_event_attr attr;
46 struct perf_file_section ids; 48 struct perf_file_section ids;
@@ -2801,8 +2803,10 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2801 } 2803 }
2802 2804
2803 event = pevent_find_event(pevent, evsel->attr.config); 2805 event = pevent_find_event(pevent, evsel->attr.config);
2804 if (event == NULL) 2806 if (event == NULL) {
2807 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
2805 return -1; 2808 return -1;
2809 }
2806 2810
2807 if (!evsel->name) { 2811 if (!evsel->name) {
2808 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); 2812 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
@@ -3201,6 +3205,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
3201 case PERF_EVENT_UPDATE__SCALE: 3205 case PERF_EVENT_UPDATE__SCALE:
3202 ev_scale = (struct event_update_event_scale *) ev->data; 3206 ev_scale = (struct event_update_event_scale *) ev->data;
3203 evsel->scale = ev_scale->scale; 3207 evsel->scale = ev_scale->scale;
3208 break;
3204 case PERF_EVENT_UPDATE__CPUS: 3209 case PERF_EVENT_UPDATE__CPUS:
3205 ev_cpus = (struct event_update_event_cpus *) ev->data; 3210 ev_cpus = (struct event_update_event_cpus *) ev->data;
3206 3211
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6770a9645609..32c6a939e4cc 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,6 +1,7 @@
1#include "util.h" 1#include "util.h"
2#include "build-id.h" 2#include "build-id.h"
3#include "hist.h" 3#include "hist.h"
4#include "map.h"
4#include "session.h" 5#include "session.h"
5#include "sort.h" 6#include "sort.h"
6#include "evlist.h" 7#include "evlist.h"
@@ -1019,6 +1020,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1019 int max_stack_depth, void *arg) 1020 int max_stack_depth, void *arg)
1020{ 1021{
1021 int err, err2; 1022 int err, err2;
1023 struct map *alm = NULL;
1024
1025 if (al && al->map)
1026 alm = map__get(al->map);
1022 1027
1023 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1028 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
1024 iter->evsel, al, max_stack_depth); 1029 iter->evsel, al, max_stack_depth);
@@ -1058,6 +1063,8 @@ out:
1058 if (!err) 1063 if (!err)
1059 err = err2; 1064 err = err2;
1060 1065
1066 map__put(alm);
1067
1061 return err; 1068 return err;
1062} 1069}
1063 1070
@@ -2439,8 +2446,10 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,
2439 symbol_conf.filter_relative = true; 2446 symbol_conf.filter_relative = true;
2440 else if (!strcmp(arg, "absolute")) 2447 else if (!strcmp(arg, "absolute"))
2441 symbol_conf.filter_relative = false; 2448 symbol_conf.filter_relative = false;
2442 else 2449 else {
2450 pr_debug("Invalud percentage: %s\n", arg);
2443 return -1; 2451 return -1;
2452 }
2444 2453
2445 return 0; 2454 return 0;
2446} 2455}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index d4b6514eeef5..28c216e3d5b7 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -283,6 +283,8 @@ void perf_hpp_list__column_register(struct perf_hpp_list *list,
283 struct perf_hpp_fmt *format); 283 struct perf_hpp_fmt *format);
284void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, 284void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
285 struct perf_hpp_fmt *format); 285 struct perf_hpp_fmt *format);
286void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
287 struct perf_hpp_fmt *format);
286 288
287static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) 289static inline void perf_hpp__column_register(struct perf_hpp_fmt *format)
288{ 290{
@@ -294,6 +296,11 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
294 perf_hpp_list__register_sort_field(&perf_hpp_list, format); 296 perf_hpp_list__register_sort_field(&perf_hpp_list, format);
295} 297}
296 298
299static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
300{
301 perf_hpp_list__prepend_sort_field(&perf_hpp_list, format);
302}
303
297#define perf_hpp_list__for_each_format(_list, format) \ 304#define perf_hpp_list__for_each_format(_list, format) \
298 list_for_each_entry(format, &(_list)->fields, list) 305 list_for_each_entry(format, &(_list)->fields, list)
299 306
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 9b742ea8bfe8..7aca5d6d7e1f 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -23,4 +23,8 @@ $(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/in
23 $(call rule_mkdir) 23 $(call rule_mkdir)
24 $(call if_changed_dep,cc_o_c) 24 $(call if_changed_dep,cc_o_c)
25 25
26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init 26CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder
27
28ifneq ($(CC), clang)
29 CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init
30endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index e4e7dc781d21..7cf7f7aca4d2 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include <stdint.h> 23#include <stdint.h>
24#include <inttypes.h> 24#include <inttypes.h>
25#include <linux/compiler.h>
25 26
26#include "../cache.h" 27#include "../cache.h"
27#include "../util.h" 28#include "../util.h"
@@ -1746,6 +1747,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1746 switch (decoder->packet.type) { 1747 switch (decoder->packet.type) {
1747 case INTEL_PT_TIP_PGD: 1748 case INTEL_PT_TIP_PGD:
1748 decoder->continuous_period = false; 1749 decoder->continuous_period = false;
1750 __fallthrough;
1749 case INTEL_PT_TIP_PGE: 1751 case INTEL_PT_TIP_PGE:
1750 case INTEL_PT_TIP: 1752 case INTEL_PT_TIP:
1751 intel_pt_log("ERROR: Unexpected packet\n"); 1753 intel_pt_log("ERROR: Unexpected packet\n");
@@ -1799,6 +1801,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1799 decoder->pge = false; 1801 decoder->pge = false;
1800 decoder->continuous_period = false; 1802 decoder->continuous_period = false;
1801 intel_pt_clear_tx_flags(decoder); 1803 intel_pt_clear_tx_flags(decoder);
1804 __fallthrough;
1805
1802 case INTEL_PT_TNT: 1806 case INTEL_PT_TNT:
1803 decoder->have_tma = false; 1807 decoder->have_tma = false;
1804 intel_pt_log("ERROR: Unexpected packet\n"); 1808 intel_pt_log("ERROR: Unexpected packet\n");
@@ -1839,6 +1843,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1839 switch (decoder->packet.type) { 1843 switch (decoder->packet.type) {
1840 case INTEL_PT_TIP_PGD: 1844 case INTEL_PT_TIP_PGD:
1841 decoder->continuous_period = false; 1845 decoder->continuous_period = false;
1846 __fallthrough;
1842 case INTEL_PT_TIP_PGE: 1847 case INTEL_PT_TIP_PGE:
1843 case INTEL_PT_TIP: 1848 case INTEL_PT_TIP:
1844 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 1849 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index 4f7b32020487..7528ae4f7e28 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -17,6 +17,7 @@
17#include <string.h> 17#include <string.h>
18#include <endian.h> 18#include <endian.h>
19#include <byteswap.h> 19#include <byteswap.h>
20#include <linux/compiler.h>
20 21
21#include "intel-pt-pkt-decoder.h" 22#include "intel-pt-pkt-decoder.h"
22 23
@@ -498,6 +499,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
498 case INTEL_PT_FUP: 499 case INTEL_PT_FUP:
499 if (!(packet->count)) 500 if (!(packet->count))
500 return snprintf(buf, buf_len, "%s no ip", name); 501 return snprintf(buf, buf_len, "%s no ip", name);
502 __fallthrough;
501 case INTEL_PT_CYC: 503 case INTEL_PT_CYC:
502 case INTEL_PT_VMCS: 504 case INTEL_PT_VMCS:
503 case INTEL_PT_MTC: 505 case INTEL_PT_MTC:
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 85d5eeb66c75..da20cd5612e9 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2159,7 +2159,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2159 2159
2160 addr_filters__init(&pt->filts); 2160 addr_filters__init(&pt->filts);
2161 2161
2162 perf_config(intel_pt_perf_config, pt); 2162 err = perf_config(intel_pt_perf_config, pt);
2163 if (err)
2164 goto err_free;
2163 2165
2164 err = auxtrace_queues__init(&pt->queues); 2166 err = auxtrace_queues__init(&pt->queues);
2165 if (err) 2167 if (err)
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index b23ff44cf214..824356488ce6 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -48,8 +48,10 @@ int perf_llvm_config(const char *var, const char *value)
48 llvm_param.kbuild_opts = strdup(value); 48 llvm_param.kbuild_opts = strdup(value);
49 else if (!strcmp(var, "dump-obj")) 49 else if (!strcmp(var, "dump-obj"))
50 llvm_param.dump_obj = !!perf_config_bool(var, value); 50 llvm_param.dump_obj = !!perf_config_bool(var, value);
51 else 51 else {
52 pr_debug("Invalid LLVM config option: %s\n", value);
52 return -1; 53 return -1;
54 }
53 llvm_param.user_set_param = true; 55 llvm_param.user_set_param = true;
54 return 0; 56 return 0;
55} 57}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9b33bef54581..71c9720d4973 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -87,6 +87,25 @@ out_delete:
87 return NULL; 87 return NULL;
88} 88}
89 89
90struct machine *machine__new_kallsyms(void)
91{
92 struct machine *machine = machine__new_host();
93 /*
94 * FIXME:
95 * 1) MAP__FUNCTION will go away when we stop loading separate maps for
96 * functions and data objects.
97 * 2) We should switch to machine__load_kallsyms(), i.e. not explicitely
98 * ask for not using the kcore parsing code, once this one is fixed
99 * to create a map per module.
100 */
101 if (machine && __machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION, true) <= 0) {
102 machine__delete(machine);
103 machine = NULL;
104 }
105
106 return machine;
107}
108
90static void dsos__purge(struct dsos *dsos) 109static void dsos__purge(struct dsos *dsos)
91{ 110{
92 struct dso *pos, *n; 111 struct dso *pos, *n;
@@ -763,7 +782,7 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
763 782
764int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 783int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
765{ 784{
766 enum map_type type; 785 int type;
767 u64 start = machine__get_running_kernel_start(machine, NULL); 786 u64 start = machine__get_running_kernel_start(machine, NULL);
768 787
769 /* In case of renewal the kernel map, destroy previous one */ 788 /* In case of renewal the kernel map, destroy previous one */
@@ -794,7 +813,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
794 813
795void machine__destroy_kernel_maps(struct machine *machine) 814void machine__destroy_kernel_maps(struct machine *machine)
796{ 815{
797 enum map_type type; 816 int type;
798 817
799 for (type = 0; type < MAP__NR_TYPES; ++type) { 818 for (type = 0; type < MAP__NR_TYPES; ++type) {
800 struct kmap *kmap; 819 struct kmap *kmap;
@@ -1546,7 +1565,7 @@ int machine__process_event(struct machine *machine, union perf_event *event,
1546 1565
1547static bool symbol__match_regex(struct symbol *sym, regex_t *regex) 1566static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1548{ 1567{
1549 if (sym->name && !regexec(regex, sym->name, 0, NULL, 0)) 1568 if (!regexec(regex, sym->name, 0, NULL, 0))
1550 return 1; 1569 return 1;
1551 return 0; 1570 return 0;
1552} 1571}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 354de6e56109..a28305029711 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -129,6 +129,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
129void machines__set_comm_exec(struct machines *machines, bool comm_exec); 129void machines__set_comm_exec(struct machines *machines, bool comm_exec);
130 130
131struct machine *machine__new_host(void); 131struct machine *machine__new_host(void);
132struct machine *machine__new_kallsyms(void);
132int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 133int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
133void machine__exit(struct machine *machine); 134void machine__exit(struct machine *machine);
134void machine__delete_threads(struct machine *machine); 135void machine__delete_threads(struct machine *machine);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f9a71c63026..0a943e7b1ea7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -387,10 +387,10 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
387{ 387{
388 const char *dsoname = "[unknown]"; 388 const char *dsoname = "[unknown]";
389 389
390 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 390 if (map && map->dso) {
391 if (symbol_conf.show_kernel_path && map->dso->long_name) 391 if (symbol_conf.show_kernel_path && map->dso->long_name)
392 dsoname = map->dso->long_name; 392 dsoname = map->dso->long_name;
393 else if (map->dso->name) 393 else
394 dsoname = map->dso->name; 394 dsoname = map->dso->name;
395 } 395 }
396 396
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3c876b8ba4de..281e44af31e2 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -211,6 +211,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
211 closedir(evt_dir); 211 closedir(evt_dir);
212 closedir(sys_dir); 212 closedir(sys_dir);
213 path = zalloc(sizeof(*path)); 213 path = zalloc(sizeof(*path));
214 if (!path)
215 return NULL;
214 path->system = malloc(MAX_EVENT_LENGTH); 216 path->system = malloc(MAX_EVENT_LENGTH);
215 if (!path->system) { 217 if (!path->system) {
216 free(path); 218 free(path);
@@ -252,8 +254,7 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name)
252 if (path->system == NULL || path->name == NULL) { 254 if (path->system == NULL || path->name == NULL) {
253 zfree(&path->system); 255 zfree(&path->system);
254 zfree(&path->name); 256 zfree(&path->name);
255 free(path); 257 zfree(&path);
256 path = NULL;
257 } 258 }
258 259
259 return path; 260 return path;
@@ -310,10 +311,11 @@ __add_event(struct list_head *list, int *idx,
310 311
311 event_attr_init(attr); 312 event_attr_init(attr);
312 313
313 evsel = perf_evsel__new_idx(attr, (*idx)++); 314 evsel = perf_evsel__new_idx(attr, *idx);
314 if (!evsel) 315 if (!evsel)
315 return NULL; 316 return NULL;
316 317
318 (*idx)++;
317 evsel->cpus = cpu_map__get(cpus); 319 evsel->cpus = cpu_map__get(cpus);
318 evsel->own_cpus = cpu_map__get(cpus); 320 evsel->own_cpus = cpu_map__get(cpus);
319 321
@@ -1477,10 +1479,9 @@ static void perf_pmu__parse_cleanup(void)
1477 1479
1478 for (i = 0; i < perf_pmu_events_list_num; i++) { 1480 for (i = 0; i < perf_pmu_events_list_num; i++) {
1479 p = perf_pmu_events_list + i; 1481 p = perf_pmu_events_list + i;
1480 free(p->symbol); 1482 zfree(&p->symbol);
1481 } 1483 }
1482 free(perf_pmu_events_list); 1484 zfree(&perf_pmu_events_list);
1483 perf_pmu_events_list = NULL;
1484 perf_pmu_events_list_num = 0; 1485 perf_pmu_events_list_num = 0;
1485 } 1486 }
1486} 1487}
@@ -1504,35 +1505,41 @@ static void perf_pmu__parse_init(void)
1504 struct perf_pmu_alias *alias; 1505 struct perf_pmu_alias *alias;
1505 int len = 0; 1506 int len = 0;
1506 1507
1507 pmu = perf_pmu__find("cpu"); 1508 pmu = NULL;
1508 if ((pmu == NULL) || list_empty(&pmu->aliases)) { 1509 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1510 list_for_each_entry(alias, &pmu->aliases, list) {
1511 if (strchr(alias->name, '-'))
1512 len++;
1513 len++;
1514 }
1515 }
1516
1517 if (len == 0) {
1509 perf_pmu_events_list_num = -1; 1518 perf_pmu_events_list_num = -1;
1510 return; 1519 return;
1511 } 1520 }
1512 list_for_each_entry(alias, &pmu->aliases, list) {
1513 if (strchr(alias->name, '-'))
1514 len++;
1515 len++;
1516 }
1517 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 1521 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
1518 if (!perf_pmu_events_list) 1522 if (!perf_pmu_events_list)
1519 return; 1523 return;
1520 perf_pmu_events_list_num = len; 1524 perf_pmu_events_list_num = len;
1521 1525
1522 len = 0; 1526 len = 0;
1523 list_for_each_entry(alias, &pmu->aliases, list) { 1527 pmu = NULL;
1524 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 1528 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1525 char *tmp = strchr(alias->name, '-'); 1529 list_for_each_entry(alias, &pmu->aliases, list) {
1526 1530 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
1527 if (tmp != NULL) { 1531 char *tmp = strchr(alias->name, '-');
1528 SET_SYMBOL(strndup(alias->name, tmp - alias->name), 1532
1529 PMU_EVENT_SYMBOL_PREFIX); 1533 if (tmp != NULL) {
1530 p++; 1534 SET_SYMBOL(strndup(alias->name, tmp - alias->name),
1531 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 1535 PMU_EVENT_SYMBOL_PREFIX);
1532 len += 2; 1536 p++;
1533 } else { 1537 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
1534 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 1538 len += 2;
1535 len++; 1539 } else {
1540 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
1541 len++;
1542 }
1536 } 1543 }
1537 } 1544 }
1538 qsort(perf_pmu_events_list, len, 1545 qsort(perf_pmu_events_list, len,
@@ -1563,7 +1570,7 @@ perf_pmu__parse_check(const char *name)
1563 r = bsearch(&p, perf_pmu_events_list, 1570 r = bsearch(&p, perf_pmu_events_list,
1564 (size_t) perf_pmu_events_list_num, 1571 (size_t) perf_pmu_events_list_num,
1565 sizeof(struct perf_pmu_event_symbol), comp_pmu); 1572 sizeof(struct perf_pmu_event_symbol), comp_pmu);
1566 free(p.symbol); 1573 zfree(&p.symbol);
1567 return r ? r->type : PMU_EVENT_SYMBOL_ERR; 1574 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1568} 1575}
1569 1576
@@ -1710,8 +1717,8 @@ static void parse_events_print_error(struct parse_events_error *err,
1710 fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str); 1717 fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
1711 if (err->help) 1718 if (err->help)
1712 fprintf(stderr, "\n%s\n", err->help); 1719 fprintf(stderr, "\n%s\n", err->help);
1713 free(err->str); 1720 zfree(&err->str);
1714 free(err->help); 1721 zfree(&err->help);
1715 } 1722 }
1716 1723
1717 fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 1724 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
@@ -2013,17 +2020,14 @@ static bool is_event_supported(u8 type, unsigned config)
2013 .config = config, 2020 .config = config,
2014 .disabled = 1, 2021 .disabled = 1,
2015 }; 2022 };
2016 struct { 2023 struct thread_map *tmap = thread_map__new_by_tid(0);
2017 struct thread_map map; 2024
2018 int threads[1]; 2025 if (tmap == NULL)
2019 } tmap = { 2026 return false;
2020 .map.nr = 1,
2021 .threads = { 0 },
2022 };
2023 2027
2024 evsel = perf_evsel__new(&attr); 2028 evsel = perf_evsel__new(&attr);
2025 if (evsel) { 2029 if (evsel) {
2026 open_return = perf_evsel__open(evsel, NULL, &tmap.map); 2030 open_return = perf_evsel__open(evsel, NULL, tmap);
2027 ret = open_return >= 0; 2031 ret = open_return >= 0;
2028 2032
2029 if (open_return == -EACCES) { 2033 if (open_return == -EACCES) {
@@ -2035,7 +2039,7 @@ static bool is_event_supported(u8 type, unsigned config)
2035 * 2039 *
2036 */ 2040 */
2037 evsel->attr.exclude_kernel = 1; 2041 evsel->attr.exclude_kernel = 1;
2038 ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; 2042 ret = perf_evsel__open(evsel, NULL, tmap) >= 0;
2039 } 2043 }
2040 perf_evsel__delete(evsel); 2044 perf_evsel__delete(evsel);
2041 } 2045 }
@@ -2406,7 +2410,7 @@ void parse_events_terms__purge(struct list_head *terms)
2406 2410
2407 list_for_each_entry_safe(term, h, terms, list) { 2411 list_for_each_entry_safe(term, h, terms, list) {
2408 if (term->array.nr_ranges) 2412 if (term->array.nr_ranges)
2409 free(term->array.ranges); 2413 zfree(&term->array.ranges);
2410 list_del_init(&term->list); 2414 list_del_init(&term->list);
2411 free(term); 2415 free(term);
2412 } 2416 }
@@ -2422,7 +2426,7 @@ void parse_events_terms__delete(struct list_head *terms)
2422 2426
2423void parse_events__clear_array(struct parse_events_array *a) 2427void parse_events__clear_array(struct parse_events_array *a)
2424{ 2428{
2425 free(a->ranges); 2429 zfree(&a->ranges);
2426} 2430}
2427 2431
2428void parse_events_evlist_error(struct parse_events_evlist *data, 2432void parse_events_evlist_error(struct parse_events_evlist *data,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 879115f93edc..a14b47ab3879 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -12,9 +12,13 @@
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/types.h> 13#include <linux/types.h>
14#include "util.h" 14#include "util.h"
15#include "pmu.h"
16#include "debug.h"
15#include "parse-events.h" 17#include "parse-events.h"
16#include "parse-events-bison.h" 18#include "parse-events-bison.h"
17 19
20void parse_events_error(YYLTYPE *loc, void *data, void *scanner, char const *msg);
21
18#define ABORT_ON(val) \ 22#define ABORT_ON(val) \
19do { \ 23do { \
20 if (val) \ 24 if (val) \
@@ -236,15 +240,34 @@ PE_KERNEL_PMU_EVENT sep_dc
236 struct list_head *head; 240 struct list_head *head;
237 struct parse_events_term *term; 241 struct parse_events_term *term;
238 struct list_head *list; 242 struct list_head *list;
243 struct perf_pmu *pmu = NULL;
244 int ok = 0;
239 245
240 ALLOC_LIST(head); 246 /* Add it for all PMUs that support the alias */
241 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
242 $1, 1, &@1, NULL));
243 list_add_tail(&term->list, head);
244
245 ALLOC_LIST(list); 247 ALLOC_LIST(list);
246 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 248 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
247 parse_events_terms__delete(head); 249 struct perf_pmu_alias *alias;
250
251 list_for_each_entry(alias, &pmu->aliases, list) {
252 if (!strcasecmp(alias->name, $1)) {
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 $1, 1, &@1, NULL));
256 list_add_tail(&term->list, head);
257
258 if (!parse_events_add_pmu(data, list,
259 pmu->name, head)) {
260 pr_debug("%s -> %s/%s/\n", $1,
261 pmu->name, alias->str);
262 ok++;
263 }
264
265 parse_events_terms__delete(head);
266 }
267 }
268 }
269 if (!ok)
270 YYABORT;
248 $$ = list; 271 $$ = list;
249} 272}
250| 273|
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index dc6ccaa4e927..49bfee0e3d9e 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -94,32 +94,10 @@ static int pmu_format(const char *name, struct list_head *format)
94 return 0; 94 return 0;
95} 95}
96 96
97static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name) 97static int convert_scale(const char *scale, char **end, double *sval)
98{ 98{
99 struct stat st;
100 ssize_t sret;
101 char scale[128];
102 int fd, ret = -1;
103 char path[PATH_MAX];
104 char *lc; 99 char *lc;
105 100 int ret = 0;
106 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
107
108 fd = open(path, O_RDONLY);
109 if (fd == -1)
110 return -1;
111
112 if (fstat(fd, &st) < 0)
113 goto error;
114
115 sret = read(fd, scale, sizeof(scale)-1);
116 if (sret < 0)
117 goto error;
118
119 if (scale[sret - 1] == '\n')
120 scale[sret - 1] = '\0';
121 else
122 scale[sret] = '\0';
123 101
124 /* 102 /*
125 * save current locale 103 * save current locale
@@ -134,7 +112,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
134 lc = strdup(lc); 112 lc = strdup(lc);
135 if (!lc) { 113 if (!lc) {
136 ret = -ENOMEM; 114 ret = -ENOMEM;
137 goto error; 115 goto out;
138 } 116 }
139 117
140 /* 118 /*
@@ -144,14 +122,42 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
144 */ 122 */
145 setlocale(LC_NUMERIC, "C"); 123 setlocale(LC_NUMERIC, "C");
146 124
147 alias->scale = strtod(scale, NULL); 125 *sval = strtod(scale, end);
148 126
127out:
149 /* restore locale */ 128 /* restore locale */
150 setlocale(LC_NUMERIC, lc); 129 setlocale(LC_NUMERIC, lc);
151
152 free(lc); 130 free(lc);
131 return ret;
132}
133
134static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
135{
136 struct stat st;
137 ssize_t sret;
138 char scale[128];
139 int fd, ret = -1;
140 char path[PATH_MAX];
141
142 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
143
144 fd = open(path, O_RDONLY);
145 if (fd == -1)
146 return -1;
147
148 if (fstat(fd, &st) < 0)
149 goto error;
150
151 sret = read(fd, scale, sizeof(scale)-1);
152 if (sret < 0)
153 goto error;
153 154
154 ret = 0; 155 if (scale[sret - 1] == '\n')
156 scale[sret - 1] = '\0';
157 else
158 scale[sret] = '\0';
159
160 ret = convert_scale(scale, NULL, &alias->scale);
155error: 161error:
156 close(fd); 162 close(fd);
157 return ret; 163 return ret;
@@ -223,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
223} 229}
224 230
225static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 231static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
226 char *desc, char *val, char *long_desc, 232 char *desc, char *val,
227 char *topic) 233 char *long_desc, char *topic,
234 char *unit, char *perpkg)
228{ 235{
229 struct perf_pmu_alias *alias; 236 struct perf_pmu_alias *alias;
230 int ret; 237 int ret;
238 int num;
231 239
232 alias = malloc(sizeof(*alias)); 240 alias = malloc(sizeof(*alias));
233 if (!alias) 241 if (!alias)
@@ -261,6 +269,13 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
261 alias->long_desc = long_desc ? strdup(long_desc) : 269 alias->long_desc = long_desc ? strdup(long_desc) :
262 desc ? strdup(desc) : NULL; 270 desc ? strdup(desc) : NULL;
263 alias->topic = topic ? strdup(topic) : NULL; 271 alias->topic = topic ? strdup(topic) : NULL;
272 if (unit) {
273 if (convert_scale(unit, &unit, &alias->scale) < 0)
274 return -1;
275 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
276 }
277 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
278 alias->str = strdup(val);
264 279
265 list_add_tail(&alias->list, list); 280 list_add_tail(&alias->list, list);
266 281
@@ -278,7 +293,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
278 293
279 buf[ret] = 0; 294 buf[ret] = 0;
280 295
281 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL); 296 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
297 NULL);
282} 298}
283 299
284static inline bool pmu_alias_info_file(char *name) 300static inline bool pmu_alias_info_file(char *name)
@@ -498,7 +514,7 @@ char * __weak get_cpuid_str(void)
498 * to the current running CPU. Then, add all PMU events from that table 514 * to the current running CPU. Then, add all PMU events from that table
499 * as aliases. 515 * as aliases.
500 */ 516 */
501static void pmu_add_cpu_aliases(struct list_head *head) 517static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
502{ 518{
503 int i; 519 int i;
504 struct pmu_events_map *map; 520 struct pmu_events_map *map;
@@ -534,14 +550,21 @@ static void pmu_add_cpu_aliases(struct list_head *head)
534 */ 550 */
535 i = 0; 551 i = 0;
536 while (1) { 552 while (1) {
553 const char *pname;
554
537 pe = &map->table[i++]; 555 pe = &map->table[i++];
538 if (!pe->name) 556 if (!pe->name)
539 break; 557 break;
540 558
559 pname = pe->pmu ? pe->pmu : "cpu";
560 if (strncmp(pname, name, strlen(pname)))
561 continue;
562
541 /* need type casts to override 'const' */ 563 /* need type casts to override 'const' */
542 __perf_pmu__new_alias(head, NULL, (char *)pe->name, 564 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
543 (char *)pe->desc, (char *)pe->event, 565 (char *)pe->desc, (char *)pe->event,
544 (char *)pe->long_desc, (char *)pe->topic); 566 (char *)pe->long_desc, (char *)pe->topic,
567 (char *)pe->unit, (char *)pe->perpkg);
545 } 568 }
546 569
547out: 570out:
@@ -569,15 +592,16 @@ static struct perf_pmu *pmu_lookup(const char *name)
569 if (pmu_format(name, &format)) 592 if (pmu_format(name, &format))
570 return NULL; 593 return NULL;
571 594
572 if (pmu_aliases(name, &aliases)) 595 /*
596 * Check the type first to avoid unnecessary work.
597 */
598 if (pmu_type(name, &type))
573 return NULL; 599 return NULL;
574 600
575 if (!strcmp(name, "cpu")) 601 if (pmu_aliases(name, &aliases))
576 pmu_add_cpu_aliases(&aliases);
577
578 if (pmu_type(name, &type))
579 return NULL; 602 return NULL;
580 603
604 pmu_add_cpu_aliases(&aliases, name);
581 pmu = zalloc(sizeof(*pmu)); 605 pmu = zalloc(sizeof(*pmu));
582 if (!pmu) 606 if (!pmu)
583 return NULL; 607 return NULL;
@@ -921,12 +945,12 @@ static int check_info_data(struct perf_pmu_alias *alias,
921 * define unit, scale and snapshot, fail 945 * define unit, scale and snapshot, fail
922 * if there's more than one. 946 * if there's more than one.
923 */ 947 */
924 if ((info->unit && alias->unit) || 948 if ((info->unit && alias->unit[0]) ||
925 (info->scale && alias->scale) || 949 (info->scale && alias->scale) ||
926 (info->snapshot && alias->snapshot)) 950 (info->snapshot && alias->snapshot))
927 return -EINVAL; 951 return -EINVAL;
928 952
929 if (alias->unit) 953 if (alias->unit[0])
930 info->unit = alias->unit; 954 info->unit = alias->unit;
931 955
932 if (alias->scale) 956 if (alias->scale)
@@ -1065,6 +1089,8 @@ struct sevent {
1065 char *name; 1089 char *name;
1066 char *desc; 1090 char *desc;
1067 char *topic; 1091 char *topic;
1092 char *str;
1093 char *pmu;
1068}; 1094};
1069 1095
1070static int cmp_sevent(const void *a, const void *b) 1096static int cmp_sevent(const void *a, const void *b)
@@ -1161,6 +1187,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1161 aliases[j].desc = long_desc ? alias->long_desc : 1187 aliases[j].desc = long_desc ? alias->long_desc :
1162 alias->desc; 1188 alias->desc;
1163 aliases[j].topic = alias->topic; 1189 aliases[j].topic = alias->topic;
1190 aliases[j].str = alias->str;
1191 aliases[j].pmu = pmu->name;
1164 j++; 1192 j++;
1165 } 1193 }
1166 if (pmu->selectable && 1194 if (pmu->selectable &&
@@ -1175,6 +1203,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1175 len = j; 1203 len = j;
1176 qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 1204 qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
1177 for (j = 0; j < len; j++) { 1205 for (j = 0; j < len; j++) {
1206 /* Skip duplicates */
1207 if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name))
1208 continue;
1178 if (name_only) { 1209 if (name_only) {
1179 printf("%s ", aliases[j].name); 1210 printf("%s ", aliases[j].name);
1180 continue; 1211 continue;
@@ -1192,6 +1223,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1192 printf("%*s", 8, "["); 1223 printf("%*s", 8, "[");
1193 wordwrap(aliases[j].desc, 8, columns, 0); 1224 wordwrap(aliases[j].desc, 8, columns, 0);
1194 printf("]\n"); 1225 printf("]\n");
1226 if (verbose)
1227 printf("%*s%s/%s/\n", 8, "", aliases[j].pmu, aliases[j].str);
1195 } else 1228 } else
1196 printf(" %-50s [Kernel PMU event]\n", aliases[j].name); 1229 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
1197 printed++; 1230 printed++;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 25712034c815..00852ddc7741 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -43,6 +43,7 @@ struct perf_pmu_alias {
43 char *desc; 43 char *desc;
44 char *long_desc; 44 char *long_desc;
45 char *topic; 45 char *topic;
46 char *str;
46 struct list_head terms; /* HEAD struct parse_events_term -> list */ 47 struct list_head terms; /* HEAD struct parse_events_term -> list */
47 struct list_head list; /* ELEM */ 48 struct list_head list; /* ELEM */
48 char unit[UNIT_MAX_LEN+1]; 49 char unit[UNIT_MAX_LEN+1];
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d281ae2b54e8..35f5b7b7715c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)
163 163
164 /* A file path -- this is an offline module */ 164 /* A file path -- this is an offline module */
165 if (module && strchr(module, '/')) 165 if (module && strchr(module, '/'))
166 return machine__findnew_module_map(host_machine, 0, module); 166 return dso__new_map(module);
167 167
168 if (!module) 168 if (!module)
169 module = "kernel"; 169 module = "kernel";
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)
173 if (strncmp(pos->dso->short_name + 1, module, 173 if (strncmp(pos->dso->short_name + 1, module,
174 pos->dso->short_name_len - 2) == 0 && 174 pos->dso->short_name_len - 2) == 0 &&
175 module[pos->dso->short_name_len - 2] == '\0') { 175 module[pos->dso->short_name_len - 2] == '\0') {
176 map__get(pos);
176 return pos; 177 return pos;
177 } 178 }
178 } 179 }
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)
188 return kernel_get_module_map(target); 189 return kernel_get_module_map(target);
189} 190}
190 191
191static void put_target_map(struct map *map, bool user)
192{
193 if (map && user) {
194 /* Only the user map needs to be released */
195 map__put(map);
196 }
197}
198
199
200static int convert_exec_to_group(const char *exec, char **result) 192static int convert_exec_to_group(const char *exec, char **result)
201{ 193{
202 char *ptr1, *ptr2, *exec_copy; 194 char *ptr1, *ptr2, *exec_copy;
@@ -268,21 +260,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
268} 260}
269 261
270/* 262/*
271 * NOTE:
272 * '.gnu.linkonce.this_module' section of kernel module elf directly
273 * maps to 'struct module' from linux/module.h. This section contains
274 * actual module name which will be used by kernel after loading it.
275 * But, we cannot use 'struct module' here since linux/module.h is not
276 * exposed to user-space. Offset of 'name' has remained same from long
277 * time, so hardcoding it here.
278 */
279#ifdef __LP64__
280#define MOD_NAME_OFFSET 24
281#else
282#define MOD_NAME_OFFSET 12
283#endif
284
285/*
286 * @module can be module name of module file path. In case of path, 263 * @module can be module name of module file path. In case of path,
287 * inspect elf and find out what is actual module name. 264 * inspect elf and find out what is actual module name.
288 * Caller has to free mod_name after using it. 265 * Caller has to free mod_name after using it.
@@ -296,6 +273,7 @@ static char *find_module_name(const char *module)
296 Elf_Data *data; 273 Elf_Data *data;
297 Elf_Scn *sec; 274 Elf_Scn *sec;
298 char *mod_name = NULL; 275 char *mod_name = NULL;
276 int name_offset;
299 277
300 fd = open(module, O_RDONLY); 278 fd = open(module, O_RDONLY);
301 if (fd < 0) 279 if (fd < 0)
@@ -317,7 +295,21 @@ static char *find_module_name(const char *module)
317 if (!data || !data->d_buf) 295 if (!data || !data->d_buf)
318 goto ret_err; 296 goto ret_err;
319 297
320 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET); 298 /*
299 * NOTE:
300 * '.gnu.linkonce.this_module' section of kernel module elf directly
301 * maps to 'struct module' from linux/module.h. This section contains
302 * actual module name which will be used by kernel after loading it.
303 * But, we cannot use 'struct module' here since linux/module.h is not
304 * exposed to user-space. Offset of 'name' has remained same from long
305 * time, so hardcoding it here.
306 */
307 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
308 name_offset = 12;
309 else /* expect ELFCLASS64 by default */
310 name_offset = 24;
311
312 mod_name = strdup((char *)data->d_buf + name_offset);
321 313
322ret_err: 314ret_err:
323 elf_end(elf); 315 elf_end(elf);
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
412 } 404 }
413 405
414out: 406out:
415 put_target_map(map, uprobes); 407 map__put(map);
416 return ret; 408 return ret;
417 409
418} 410}
@@ -618,6 +610,67 @@ error:
618 return ret ? : -ENOENT; 610 return ret ? : -ENOENT;
619} 611}
620 612
613/* Adjust symbol name and address */
614static int post_process_probe_trace_point(struct probe_trace_point *tp,
615 struct map *map, unsigned long offs)
616{
617 struct symbol *sym;
618 u64 addr = tp->address + tp->offset - offs;
619
620 sym = map__find_symbol(map, addr);
621 if (!sym)
622 return -ENOENT;
623
624 if (strcmp(sym->name, tp->symbol)) {
625 /* If we have no realname, use symbol for it */
626 if (!tp->realname)
627 tp->realname = tp->symbol;
628 else
629 free(tp->symbol);
630 tp->symbol = strdup(sym->name);
631 if (!tp->symbol)
632 return -ENOMEM;
633 }
634 tp->offset = addr - sym->start;
635 tp->address -= offs;
636
637 return 0;
638}
639
640/*
641 * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
642 * and generate new symbols with suffixes such as .constprop.N or .isra.N
643 * etc. Since those symbols are not recorded in DWARF, we have to find
644 * correct generated symbols from offline ELF binary.
645 * For online kernel or uprobes we don't need this because those are
646 * rebased on _text, or already a section relative address.
647 */
648static int
649post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
650 int ntevs, const char *pathname)
651{
652 struct map *map;
653 unsigned long stext = 0;
654 int i, ret = 0;
655
656 /* Prepare a map for offline binary */
657 map = dso__new_map(pathname);
658 if (!map || get_text_start_address(pathname, &stext) < 0) {
659 pr_warning("Failed to get ELF symbols for %s\n", pathname);
660 return -EINVAL;
661 }
662
663 for (i = 0; i < ntevs; i++) {
664 ret = post_process_probe_trace_point(&tevs[i].point,
665 map, stext);
666 if (ret < 0)
667 break;
668 }
669 map__put(map);
670
671 return ret;
672}
673
621static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 674static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
622 int ntevs, const char *exec) 675 int ntevs, const char *exec)
623{ 676{
@@ -645,18 +698,31 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
645 return ret; 698 return ret;
646} 699}
647 700
648static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 701static int
649 int ntevs, const char *module) 702post_process_module_probe_trace_events(struct probe_trace_event *tevs,
703 int ntevs, const char *module,
704 struct debuginfo *dinfo)
650{ 705{
706 Dwarf_Addr text_offs = 0;
651 int i, ret = 0; 707 int i, ret = 0;
652 char *mod_name = NULL; 708 char *mod_name = NULL;
709 struct map *map;
653 710
654 if (!module) 711 if (!module)
655 return 0; 712 return 0;
656 713
657 mod_name = find_module_name(module); 714 map = get_target_map(module, false);
715 if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
716 pr_warning("Failed to get ELF symbols for %s\n", module);
717 return -EINVAL;
718 }
658 719
720 mod_name = find_module_name(module);
659 for (i = 0; i < ntevs; i++) { 721 for (i = 0; i < ntevs; i++) {
722 ret = post_process_probe_trace_point(&tevs[i].point,
723 map, (unsigned long)text_offs);
724 if (ret < 0)
725 break;
660 tevs[i].point.module = 726 tevs[i].point.module =
661 strdup(mod_name ? mod_name : module); 727 strdup(mod_name ? mod_name : module);
662 if (!tevs[i].point.module) { 728 if (!tevs[i].point.module) {
@@ -666,6 +732,8 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
666 } 732 }
667 733
668 free(mod_name); 734 free(mod_name);
735 map__put(map);
736
669 return ret; 737 return ret;
670} 738}
671 739
@@ -679,7 +747,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
679 747
680 /* Skip post process if the target is an offline kernel */ 748 /* Skip post process if the target is an offline kernel */
681 if (symbol_conf.ignore_vmlinux_buildid) 749 if (symbol_conf.ignore_vmlinux_buildid)
682 return 0; 750 return post_process_offline_probe_trace_events(tevs, ntevs,
751 symbol_conf.vmlinux_name);
683 752
684 reloc_sym = kernel_get_ref_reloc_sym(); 753 reloc_sym = kernel_get_ref_reloc_sym();
685 if (!reloc_sym) { 754 if (!reloc_sym) {
@@ -722,7 +791,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unuse
722static int post_process_probe_trace_events(struct perf_probe_event *pev, 791static int post_process_probe_trace_events(struct perf_probe_event *pev,
723 struct probe_trace_event *tevs, 792 struct probe_trace_event *tevs,
724 int ntevs, const char *module, 793 int ntevs, const char *module,
725 bool uprobe) 794 bool uprobe, struct debuginfo *dinfo)
726{ 795{
727 int ret; 796 int ret;
728 797
@@ -730,7 +799,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
730 ret = add_exec_to_probe_trace_events(tevs, ntevs, module); 799 ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
731 else if (module) 800 else if (module)
732 /* Currently ref_reloc_sym based probe is not for drivers */ 801 /* Currently ref_reloc_sym based probe is not for drivers */
733 ret = add_module_to_probe_trace_events(tevs, ntevs, module); 802 ret = post_process_module_probe_trace_events(tevs, ntevs,
803 module, dinfo);
734 else 804 else
735 ret = post_process_kernel_probe_trace_events(tevs, ntevs); 805 ret = post_process_kernel_probe_trace_events(tevs, ntevs);
736 806
@@ -774,30 +844,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
774 } 844 }
775 } 845 }
776 846
777 debuginfo__delete(dinfo);
778
779 if (ntevs > 0) { /* Succeeded to find trace events */ 847 if (ntevs > 0) { /* Succeeded to find trace events */
780 pr_debug("Found %d probe_trace_events.\n", ntevs); 848 pr_debug("Found %d probe_trace_events.\n", ntevs);
781 ret = post_process_probe_trace_events(pev, *tevs, ntevs, 849 ret = post_process_probe_trace_events(pev, *tevs, ntevs,
782 pev->target, pev->uprobes); 850 pev->target, pev->uprobes, dinfo);
783 if (ret < 0 || ret == ntevs) { 851 if (ret < 0 || ret == ntevs) {
852 pr_debug("Post processing failed or all events are skipped. (%d)\n", ret);
784 clear_probe_trace_events(*tevs, ntevs); 853 clear_probe_trace_events(*tevs, ntevs);
785 zfree(tevs); 854 zfree(tevs);
855 ntevs = 0;
786 } 856 }
787 if (ret != ntevs)
788 return ret < 0 ? ret : ntevs;
789 ntevs = 0;
790 /* Fall through */
791 } 857 }
792 858
859 debuginfo__delete(dinfo);
860
793 if (ntevs == 0) { /* No error but failed to find probe point. */ 861 if (ntevs == 0) { /* No error but failed to find probe point. */
794 pr_warning("Probe point '%s' not found.\n", 862 pr_warning("Probe point '%s' not found.\n",
795 synthesize_perf_probe_point(&pev->point)); 863 synthesize_perf_probe_point(&pev->point));
796 return -ENOENT; 864 return -ENOENT;
797 } 865 } else if (ntevs < 0) {
798 /* Error path : ntevs < 0 */ 866 /* Error path : ntevs < 0 */
799 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 867 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
800 if (ntevs < 0) {
801 if (ntevs == -EBADF) 868 if (ntevs == -EBADF)
802 pr_warning("Warning: No dwarf info found in the vmlinux - " 869 pr_warning("Warning: No dwarf info found in the vmlinux - "
803 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 870 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
@@ -1994,7 +2061,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1994 bool is_kprobe) 2061 bool is_kprobe)
1995{ 2062{
1996 struct symbol *sym = NULL; 2063 struct symbol *sym = NULL;
1997 struct map *map; 2064 struct map *map = NULL;
1998 u64 addr = tp->address; 2065 u64 addr = tp->address;
1999 int ret = -ENOENT; 2066 int ret = -ENOENT;
2000 2067
@@ -2869,7 +2936,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2869 } 2936 }
2870 2937
2871out: 2938out:
2872 put_target_map(map, pev->uprobes); 2939 map__put(map);
2873 free(syms); 2940 free(syms);
2874 return ret; 2941 return ret;
2875 2942
@@ -2956,20 +3023,17 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
2956 3023
2957 tev->nargs = pev->nargs; 3024 tev->nargs = pev->nargs;
2958 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 3025 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
2959 if (!tev->args) { 3026 if (!tev->args)
2960 err = -ENOMEM;
2961 goto errout; 3027 goto errout;
2962 } 3028
2963 for (i = 0; i < tev->nargs; i++) 3029 for (i = 0; i < tev->nargs; i++)
2964 copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]); 3030 copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
2965 3031
2966 return 1; 3032 return 1;
2967 3033
2968errout: 3034errout:
2969 if (*tevs) { 3035 clear_probe_trace_events(*tevs, 1);
2970 clear_probe_trace_events(*tevs, 1); 3036 *tevs = NULL;
2971 *tevs = NULL;
2972 }
2973 return err; 3037 return err;
2974} 3038}
2975 3039
@@ -3362,10 +3426,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3362 return ret; 3426 return ret;
3363 3427
3364 /* Get a symbol map */ 3428 /* Get a symbol map */
3365 if (user) 3429 map = get_target_map(target, user);
3366 map = dso__new_map(target);
3367 else
3368 map = kernel_get_module_map(target);
3369 if (!map) { 3430 if (!map) {
3370 pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); 3431 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
3371 return -EINVAL; 3432 return -EINVAL;
@@ -3397,9 +3458,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3397 } 3458 }
3398 3459
3399end: 3460end:
3400 if (user) { 3461 map__put(map);
3401 map__put(map);
3402 }
3403 exit_probe_symbol_maps(); 3462 exit_probe_symbol_maps();
3404 3463
3405 return ret; 3464 return ret;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index df4debe564da..0d9d6e0803b8 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1501,7 +1501,8 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1501} 1501}
1502 1502
1503/* For the kernel module, we need a special code to get a DIE */ 1503/* For the kernel module, we need a special code to get a DIE */
1504static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) 1504int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
1505 bool adjust_offset)
1505{ 1506{
1506 int n, i; 1507 int n, i;
1507 Elf32_Word shndx; 1508 Elf32_Word shndx;
@@ -1530,6 +1531,8 @@ static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
1530 if (!shdr) 1531 if (!shdr)
1531 return -ENOENT; 1532 return -ENOENT;
1532 *offs = shdr->sh_addr; 1533 *offs = shdr->sh_addr;
1534 if (adjust_offset)
1535 *offs -= shdr->sh_offset;
1533 } 1536 }
1534 } 1537 }
1535 return 0; 1538 return 0;
@@ -1543,16 +1546,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1543 Dwarf_Addr _addr = 0, baseaddr = 0; 1546 Dwarf_Addr _addr = 0, baseaddr = 0;
1544 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1547 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1545 int baseline = 0, lineno = 0, ret = 0; 1548 int baseline = 0, lineno = 0, ret = 0;
1546 bool reloc = false;
1547 1549
1548retry: 1550 /* We always need to relocate the address for aranges */
1551 if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
1552 addr += baseaddr;
1549 /* Find cu die */ 1553 /* Find cu die */
1550 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { 1554 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1551 if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
1552 addr += baseaddr;
1553 reloc = true;
1554 goto retry;
1555 }
1556 pr_warning("Failed to find debug information for address %lx\n", 1555 pr_warning("Failed to find debug information for address %lx\n",
1557 addr); 1556 addr);
1558 ret = -EINVAL; 1557 ret = -EINVAL;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index f1d8558f498e..2956c5198652 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -46,6 +46,9 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
46int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 46int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
47 struct perf_probe_point *ppt); 47 struct perf_probe_point *ppt);
48 48
49int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
50 bool adjust_offset);
51
49/* Find a line range */ 52/* Find a line range */
50int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); 53int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);
51 54
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
index 6516e220c247..82d28c67e0f3 100644
--- a/tools/perf/util/scripting-engines/Build
+++ b/tools/perf/util/scripting-engines/Build
@@ -1,6 +1,6 @@
1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o 1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o 2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
3 3
4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default 4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default
5 5
6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow 6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index e55a132f69b7..dff043a29589 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -217,6 +217,7 @@ static void define_event_symbols(struct event_format *event,
217 cur_field_name); 217 cur_field_name);
218 break; 218 break;
219 case PRINT_HEX: 219 case PRINT_HEX:
220 case PRINT_HEX_STR:
220 define_event_symbols(event, ev_name, args->hex.field); 221 define_event_symbols(event, ev_name, args->hex.field);
221 define_event_symbols(event, ev_name, args->hex.size); 222 define_event_symbols(event, ev_name, args->hex.size);
222 break; 223 break;
@@ -309,10 +310,10 @@ static SV *perl_process_callchain(struct perf_sample *sample,
309 if (node->map) { 310 if (node->map) {
310 struct map *map = node->map; 311 struct map *map = node->map;
311 const char *dsoname = "[unknown]"; 312 const char *dsoname = "[unknown]";
312 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 313 if (map && map->dso) {
313 if (symbol_conf.show_kernel_path && map->dso->long_name) 314 if (symbol_conf.show_kernel_path && map->dso->long_name)
314 dsoname = map->dso->long_name; 315 dsoname = map->dso->long_name;
315 else if (map->dso->name) 316 else
316 dsoname = map->dso->name; 317 dsoname = map->dso->name;
317 } 318 }
318 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) { 319 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
@@ -350,8 +351,10 @@ static void perl_process_tracepoint(struct perf_sample *sample,
350 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 351 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
351 return; 352 return;
352 353
353 if (!event) 354 if (!event) {
354 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); 355 pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
356 return;
357 }
355 358
356 pid = raw_field_value(event, "common_pid", data); 359 pid = raw_field_value(event, "common_pid", data);
357 360
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 089438da1f7f..581e0efd6356 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -236,6 +236,7 @@ static void define_event_symbols(struct event_format *event,
236 cur_field_name); 236 cur_field_name);
237 break; 237 break;
238 case PRINT_HEX: 238 case PRINT_HEX:
239 case PRINT_HEX_STR:
239 define_event_symbols(event, ev_name, args->hex.field); 240 define_event_symbols(event, ev_name, args->hex.field);
240 define_event_symbols(event, ev_name, args->hex.size); 241 define_event_symbols(event, ev_name, args->hex.size);
241 break; 242 break;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f268201048a0..4cdbc8f5f14d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1191,7 +1191,7 @@ static int
1191 u64 sample_type = evsel->attr.sample_type; 1191 u64 sample_type = evsel->attr.sample_type;
1192 u64 read_format = evsel->attr.read_format; 1192 u64 read_format = evsel->attr.read_format;
1193 1193
1194 /* Standard sample delievery. */ 1194 /* Standard sample delivery. */
1195 if (!(sample_type & PERF_SAMPLE_READ)) 1195 if (!(sample_type & PERF_SAMPLE_READ))
1196 return tool->sample(tool, event, sample, evsel, machine); 1196 return tool->sample(tool, event, sample, evsel, machine);
1197 1197
@@ -1901,7 +1901,7 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1901 const char *symbol_name, u64 addr) 1901 const char *symbol_name, u64 addr)
1902{ 1902{
1903 char *bracket; 1903 char *bracket;
1904 enum map_type i; 1904 int i;
1905 struct ref_reloc_sym *ref; 1905 struct ref_reloc_sym *ref;
1906 1906
1907 ref = zalloc(sizeof(struct ref_reloc_sym)); 1907 ref = zalloc(sizeof(struct ref_reloc_sym));
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index bcae659b6546..efb53772e0ec 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -269,6 +269,7 @@ static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
269 len = strfilter_node__sprint_pt(node->l, buf); 269 len = strfilter_node__sprint_pt(node->l, buf);
270 if (len < 0) 270 if (len < 0)
271 return len; 271 return len;
272 __fallthrough;
272 case '!': 273 case '!':
273 if (buf) { 274 if (buf) {
274 *(buf + len++) = *node->p; 275 *(buf + len++) = *node->p;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d8dfaf64b32e..bddca519dd58 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -21,6 +21,8 @@ s64 perf_atoll(const char *str)
21 case 'b': case 'B': 21 case 'b': case 'B':
22 if (*p) 22 if (*p)
23 goto out_err; 23 goto out_err;
24
25 __fallthrough;
24 case '\0': 26 case '\0':
25 return length; 27 return length;
26 default: 28 default:
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0e8f2a..adbc6c02c3aa 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -537,6 +537,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
537 break; 537 break;
538 } else { 538 } else {
539 int n = namesz + descsz; 539 int n = namesz + descsz;
540
541 if (n > (int)sizeof(bf)) {
542 n = sizeof(bf);
543 pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
544 __func__, filename, nhdr.n_namesz, nhdr.n_descsz);
545 }
540 if (read(fd, bf, n) != n) 546 if (read(fd, bf, n) != n)
541 break; 547 break;
542 } 548 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index dc93940de351..70e389bc4af7 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1460,9 +1460,11 @@ int dso__load(struct dso *dso, struct map *map)
1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1461 */ 1461 */
1462 if (!dso->has_build_id && 1462 if (!dso->has_build_id &&
1463 is_regular_file(dso->long_name) && 1463 is_regular_file(dso->long_name)) {
1464 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1464 __symbol__join_symfs(name, PATH_MAX, dso->long_name);
1465 if (filename__read_build_id(name, build_id, BUILD_ID_SIZE) > 0)
1465 dso__set_build_id(dso, build_id); 1466 dso__set_build_id(dso, build_id);
1467 }
1466 1468
1467 /* 1469 /*
1468 * Iterate over candidate debug images. 1470 * Iterate over candidate debug images.
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index 7c6b33e8e2d2..63694e174e5c 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -21,7 +21,7 @@ size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
21 unsigned long offset; 21 unsigned long offset;
22 size_t length; 22 size_t length;
23 23
24 if (sym && sym->name) { 24 if (sym) {
25 length = fprintf(fp, "%s", sym->name); 25 length = fprintf(fp, "%s", sym->name);
26 if (al && print_offsets) { 26 if (al && print_offsets) {
27 if (al->addr < sym->end) 27 if (al->addr < sym->end)
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f9eab200fd75..7c3fcc538a70 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -93,7 +93,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
93{ 93{
94 DIR *proc; 94 DIR *proc;
95 int max_threads = 32, items, i; 95 int max_threads = 32, items, i;
96 char path[256]; 96 char path[NAME_MAX + 1 + 6];
97 struct dirent *dirent, **namelist = NULL; 97 struct dirent *dirent, **namelist = NULL;
98 struct thread_map *threads = thread_map__alloc(max_threads); 98 struct thread_map *threads = thread_map__alloc(max_threads);
99 99
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d995743cb673..e7d60d05596d 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -42,7 +42,7 @@
42#include "evsel.h" 42#include "evsel.h"
43#include "debug.h" 43#include "debug.h"
44 44
45#define VERSION "0.5" 45#define VERSION "0.6"
46 46
47static int output_fd; 47static int output_fd;
48 48
@@ -170,6 +170,12 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
170 return false; 170 return false;
171} 171}
172 172
173#define for_each_event(dir, dent, tps) \
174 while ((dent = readdir(dir))) \
175 if (dent->d_type == DT_DIR && \
176 (strcmp(dent->d_name, ".")) && \
177 (strcmp(dent->d_name, ".."))) \
178
173static int copy_event_system(const char *sys, struct tracepoint_path *tps) 179static int copy_event_system(const char *sys, struct tracepoint_path *tps)
174{ 180{
175 struct dirent *dent; 181 struct dirent *dent;
@@ -186,12 +192,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
186 return -errno; 192 return -errno;
187 } 193 }
188 194
189 while ((dent = readdir(dir))) { 195 for_each_event(dir, dent, tps) {
190 if (dent->d_type != DT_DIR || 196 if (!name_in_tp_list(dent->d_name, tps))
191 strcmp(dent->d_name, ".") == 0 ||
192 strcmp(dent->d_name, "..") == 0 ||
193 !name_in_tp_list(dent->d_name, tps))
194 continue; 197 continue;
198
195 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { 199 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
196 err = -ENOMEM; 200 err = -ENOMEM;
197 goto out; 201 goto out;
@@ -210,12 +214,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
210 } 214 }
211 215
212 rewinddir(dir); 216 rewinddir(dir);
213 while ((dent = readdir(dir))) { 217 for_each_event(dir, dent, tps) {
214 if (dent->d_type != DT_DIR || 218 if (!name_in_tp_list(dent->d_name, tps))
215 strcmp(dent->d_name, ".") == 0 ||
216 strcmp(dent->d_name, "..") == 0 ||
217 !name_in_tp_list(dent->d_name, tps))
218 continue; 219 continue;
220
219 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { 221 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
220 err = -ENOMEM; 222 err = -ENOMEM;
221 goto out; 223 goto out;
@@ -290,13 +292,11 @@ static int record_event_files(struct tracepoint_path *tps)
290 goto out; 292 goto out;
291 } 293 }
292 294
293 while ((dent = readdir(dir))) { 295 for_each_event(dir, dent, tps) {
294 if (dent->d_type != DT_DIR || 296 if (strcmp(dent->d_name, "ftrace") == 0 ||
295 strcmp(dent->d_name, ".") == 0 ||
296 strcmp(dent->d_name, "..") == 0 ||
297 strcmp(dent->d_name, "ftrace") == 0 ||
298 !system_in_tp_list(dent->d_name, tps)) 297 !system_in_tp_list(dent->d_name, tps))
299 continue; 298 continue;
299
300 count++; 300 count++;
301 } 301 }
302 302
@@ -307,13 +307,11 @@ static int record_event_files(struct tracepoint_path *tps)
307 } 307 }
308 308
309 rewinddir(dir); 309 rewinddir(dir);
310 while ((dent = readdir(dir))) { 310 for_each_event(dir, dent, tps) {
311 if (dent->d_type != DT_DIR || 311 if (strcmp(dent->d_name, "ftrace") == 0 ||
312 strcmp(dent->d_name, ".") == 0 ||
313 strcmp(dent->d_name, "..") == 0 ||
314 strcmp(dent->d_name, "ftrace") == 0 ||
315 !system_in_tp_list(dent->d_name, tps)) 312 !system_in_tp_list(dent->d_name, tps))
316 continue; 313 continue;
314
317 if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) { 315 if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) {
318 err = -ENOMEM; 316 err = -ENOMEM;
319 goto out; 317 goto out;
@@ -379,6 +377,34 @@ out:
379 return err; 377 return err;
380} 378}
381 379
380static int record_saved_cmdline(void)
381{
382 unsigned int size;
383 char *path;
384 struct stat st;
385 int ret, err = 0;
386
387 path = get_tracing_file("saved_cmdlines");
388 if (!path) {
389 pr_debug("can't get tracing/saved_cmdline");
390 return -ENOMEM;
391 }
392
393 ret = stat(path, &st);
394 if (ret < 0) {
395 /* not found */
396 size = 0;
397 if (write(output_fd, &size, 8) != 8)
398 err = -EIO;
399 goto out;
400 }
401 err = record_file(path, 8);
402
403out:
404 put_tracing_file(path);
405 return err;
406}
407
382static void 408static void
383put_tracepoints_path(struct tracepoint_path *tps) 409put_tracepoints_path(struct tracepoint_path *tps)
384{ 410{
@@ -539,6 +565,9 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
539 if (err) 565 if (err)
540 goto out; 566 goto out;
541 err = record_ftrace_printk(); 567 err = record_ftrace_printk();
568 if (err)
569 goto out;
570 err = record_saved_cmdline();
542 571
543out: 572out:
544 /* 573 /*
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 33b52eaa39db..de0078e21408 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -160,6 +160,23 @@ void parse_ftrace_printk(struct pevent *pevent,
160 } 160 }
161} 161}
162 162
163void parse_saved_cmdline(struct pevent *pevent,
164 char *file, unsigned int size __maybe_unused)
165{
166 char *comm;
167 char *line;
168 char *next = NULL;
169 int pid;
170
171 line = strtok_r(file, "\n", &next);
172 while (line) {
173 sscanf(line, "%d %ms", &pid, &comm);
174 pevent_register_comm(pevent, comm, pid);
175 free(comm);
176 line = strtok_r(NULL, "\n", &next);
177 }
178}
179
163int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size) 180int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
164{ 181{
165 return pevent_parse_event(pevent, buf, size, "ftrace"); 182 return pevent_parse_event(pevent, buf, size, "ftrace");
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index b67a0ccf5ab9..27420159bf69 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -260,39 +260,53 @@ static int read_header_files(struct pevent *pevent)
260 260
261static int read_ftrace_file(struct pevent *pevent, unsigned long long size) 261static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
262{ 262{
263 int ret;
263 char *buf; 264 char *buf;
264 265
265 buf = malloc(size); 266 buf = malloc(size);
266 if (buf == NULL) 267 if (buf == NULL) {
268 pr_debug("memory allocation failure\n");
267 return -1; 269 return -1;
270 }
268 271
269 if (do_read(buf, size) < 0) { 272 ret = do_read(buf, size);
270 free(buf); 273 if (ret < 0) {
271 return -1; 274 pr_debug("error reading ftrace file.\n");
275 goto out;
272 } 276 }
273 277
274 parse_ftrace_file(pevent, buf, size); 278 ret = parse_ftrace_file(pevent, buf, size);
279 if (ret < 0)
280 pr_debug("error parsing ftrace file.\n");
281out:
275 free(buf); 282 free(buf);
276 return 0; 283 return ret;
277} 284}
278 285
279static int read_event_file(struct pevent *pevent, char *sys, 286static int read_event_file(struct pevent *pevent, char *sys,
280 unsigned long long size) 287 unsigned long long size)
281{ 288{
289 int ret;
282 char *buf; 290 char *buf;
283 291
284 buf = malloc(size); 292 buf = malloc(size);
285 if (buf == NULL) 293 if (buf == NULL) {
294 pr_debug("memory allocation failure\n");
286 return -1; 295 return -1;
296 }
287 297
288 if (do_read(buf, size) < 0) { 298 ret = do_read(buf, size);
299 if (ret < 0) {
289 free(buf); 300 free(buf);
290 return -1; 301 goto out;
291 } 302 }
292 303
293 parse_event_file(pevent, buf, size, sys); 304 ret = parse_event_file(pevent, buf, size, sys);
305 if (ret < 0)
306 pr_debug("error parsing event file.\n");
307out:
294 free(buf); 308 free(buf);
295 return 0; 309 return ret;
296} 310}
297 311
298static int read_ftrace_files(struct pevent *pevent) 312static int read_ftrace_files(struct pevent *pevent)
@@ -341,6 +355,36 @@ static int read_event_files(struct pevent *pevent)
341 return 0; 355 return 0;
342} 356}
343 357
358static int read_saved_cmdline(struct pevent *pevent)
359{
360 unsigned long long size;
361 char *buf;
362 int ret;
363
364 /* it can have 0 size */
365 size = read8(pevent);
366 if (!size)
367 return 0;
368
369 buf = malloc(size + 1);
370 if (buf == NULL) {
371 pr_debug("memory allocation failure\n");
372 return -1;
373 }
374
375 ret = do_read(buf, size);
376 if (ret < 0) {
377 pr_debug("error reading saved cmdlines\n");
378 goto out;
379 }
380
381 parse_saved_cmdline(pevent, buf, size);
382 ret = 0;
383out:
384 free(buf);
385 return ret;
386}
387
344ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe) 388ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
345{ 389{
346 char buf[BUFSIZ]; 390 char buf[BUFSIZ];
@@ -379,10 +423,11 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
379 return -1; 423 return -1;
380 if (show_version) 424 if (show_version)
381 printf("version = %s\n", version); 425 printf("version = %s\n", version);
382 free(version);
383 426
384 if (do_read(buf, 1) < 0) 427 if (do_read(buf, 1) < 0) {
428 free(version);
385 return -1; 429 return -1;
430 }
386 file_bigendian = buf[0]; 431 file_bigendian = buf[0];
387 host_bigendian = bigendian(); 432 host_bigendian = bigendian();
388 433
@@ -423,6 +468,11 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
423 err = read_ftrace_printk(pevent); 468 err = read_ftrace_printk(pevent);
424 if (err) 469 if (err)
425 goto out; 470 goto out;
471 if (atof(version) >= 0.6) {
472 err = read_saved_cmdline(pevent);
473 if (err)
474 goto out;
475 }
426 476
427 size = trace_data_size; 477 size = trace_data_size;
428 repipe = false; 478 repipe = false;
@@ -438,5 +488,6 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
438out: 488out:
439 if (pevent) 489 if (pevent)
440 trace_event__cleanup(tevent); 490 trace_event__cleanup(tevent);
491 free(version);
441 return size; 492 return size;
442} 493}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b0af9c81bb0d..1fbc044f9eb0 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -42,6 +42,7 @@ raw_field_value(struct event_format *event, const char *name, void *data);
42 42
43void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 43void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
44void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 44void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
45void parse_saved_cmdline(struct pevent *pevent, char *file, unsigned int size);
45 46
46ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 47ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
47 48
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 6fec84dff3f7..bfb9b7987692 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -35,6 +35,7 @@
35#include "util.h" 35#include "util.h"
36#include "debug.h" 36#include "debug.h"
37#include "asm/bug.h" 37#include "asm/bug.h"
38#include "dso.h"
38 39
39extern int 40extern int
40UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 41UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
@@ -297,15 +298,58 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
297 int fd; 298 int fd;
298 u64 ofs = dso->data.debug_frame_offset; 299 u64 ofs = dso->data.debug_frame_offset;
299 300
301 /* debug_frame can reside in:
302 * - dso
303 * - debug pointed by symsrc_filename
304 * - gnu_debuglink, which doesn't necessary
305 * has to be pointed by symsrc_filename
306 */
300 if (ofs == 0) { 307 if (ofs == 0) {
301 fd = dso__data_get_fd(dso, machine); 308 fd = dso__data_get_fd(dso, machine);
302 if (fd < 0) 309 if (fd >= 0) {
303 return -EINVAL; 310 ofs = elf_section_offset(fd, ".debug_frame");
311 dso__data_put_fd(dso);
312 }
313
314 if (ofs <= 0) {
315 fd = open(dso->symsrc_filename, O_RDONLY);
316 if (fd >= 0) {
317 ofs = elf_section_offset(fd, ".debug_frame");
318 close(fd);
319 }
320 }
321
322 if (ofs <= 0) {
323 char *debuglink = malloc(PATH_MAX);
324 int ret = 0;
325
326 ret = dso__read_binary_type_filename(
327 dso, DSO_BINARY_TYPE__DEBUGLINK,
328 machine->root_dir, debuglink, PATH_MAX);
329 if (!ret) {
330 fd = open(debuglink, O_RDONLY);
331 if (fd >= 0) {
332 ofs = elf_section_offset(fd,
333 ".debug_frame");
334 close(fd);
335 }
336 }
337 if (ofs > 0) {
338 if (dso->symsrc_filename != NULL) {
339 pr_warning(
340 "%s: overwrite symsrc(%s,%s)\n",
341 __func__,
342 dso->symsrc_filename,
343 debuglink);
344 free(dso->symsrc_filename);
345 }
346 dso->symsrc_filename = debuglink;
347 } else {
348 free(debuglink);
349 }
350 }
304 351
305 /* Check the .debug_frame section for unwinding info */
306 ofs = elf_section_offset(fd, ".debug_frame");
307 dso->data.debug_frame_offset = ofs; 352 dso->data.debug_frame_offset = ofs;
308 dso__data_put_fd(dso);
309 } 353 }
310 354
311 *offset = ofs; 355 *offset = ofs;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9ddd98827d12..d8b45cea54d0 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -85,7 +85,7 @@ int mkdir_p(char *path, mode_t mode)
85 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 85 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
86} 86}
87 87
88int rm_rf(char *path) 88int rm_rf(const char *path)
89{ 89{
90 DIR *dir; 90 DIR *dir;
91 int ret = 0; 91 int ret = 0;
@@ -789,3 +789,16 @@ int is_printable_array(char *p, unsigned int len)
789 } 789 }
790 return 1; 790 return 1;
791} 791}
792
793int unit_number__scnprintf(char *buf, size_t size, u64 n)
794{
795 char unit[4] = "BKMG";
796 int i = 0;
797
798 while (((n / 1024) > 1) && (i < 3)) {
799 n /= 1024;
800 i++;
801 }
802
803 return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
804}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1d639e38aa82..c74708da8571 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -209,7 +209,7 @@ static inline int sane_case(int x, int high)
209} 209}
210 210
211int mkdir_p(char *path, mode_t mode); 211int mkdir_p(char *path, mode_t mode);
212int rm_rf(char *path); 212int rm_rf(const char *path);
213struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)); 213struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
214bool lsdir_no_dot_filter(const char *name, struct dirent *d); 214bool lsdir_no_dot_filter(const char *name, struct dirent *d);
215int copyfile(const char *from, const char *to); 215int copyfile(const char *from, const char *to);
@@ -363,4 +363,5 @@ int is_printable_array(char *p, unsigned int len);
363 363
364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
365 365
366int unit_number__scnprintf(char *buf, size_t size, u64 n);
366#endif /* GIT_COMPAT_UTIL_H */ 367#endif /* GIT_COMPAT_UTIL_H */