diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/Documentation/perf-c2c.txt | 16 | ||||
| -rw-r--r-- | tools/perf/Documentation/perf-mem.txt | 2 | ||||
| -rw-r--r-- | tools/perf/arch/powerpc/util/Build | 1 | ||||
| -rw-r--r-- | tools/perf/arch/powerpc/util/mem-events.c | 11 | ||||
| -rw-r--r-- | tools/perf/builtin-script.c | 9 | ||||
| -rw-r--r-- | tools/perf/builtin-trace.c | 25 | ||||
| -rw-r--r-- | tools/perf/tests/attr.py | 32 | ||||
| -rw-r--r-- | tools/perf/tests/evsel-tp-sched.c | 2 | ||||
| -rw-r--r-- | tools/perf/ui/browsers/annotate.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/c++/clang.cpp | 2 | ||||
| -rw-r--r-- | tools/perf/util/cpumap.c | 11 | ||||
| -rw-r--r-- | tools/perf/util/mem-events.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/ordered-events.c | 6 | ||||
| -rw-r--r-- | tools/perf/util/setup.py | 2 | ||||
| -rw-r--r-- | tools/perf/util/symbol-elf.c | 23 |
15 files changed, 115 insertions, 45 deletions
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt index 095aebdc5bb7..e6150f21267d 100644 --- a/tools/perf/Documentation/perf-c2c.txt +++ b/tools/perf/Documentation/perf-c2c.txt | |||
| @@ -19,8 +19,11 @@ C2C stands for Cache To Cache. | |||
| 19 | The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows | 19 | The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows |
| 20 | you to track down the cacheline contentions. | 20 | you to track down the cacheline contentions. |
| 21 | 21 | ||
| 22 | The tool is based on x86's load latency and precise store facility events | 22 | On x86, the tool is based on load latency and precise store facility events |
| 23 | provided by Intel CPUs. These events provide: | 23 | provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling |
| 24 | with thresholding feature. | ||
| 25 | |||
| 26 | These events provide: | ||
| 24 | - memory address of the access | 27 | - memory address of the access |
| 25 | - type of the access (load and store details) | 28 | - type of the access (load and store details) |
| 26 | - latency (in cycles) of the load access | 29 | - latency (in cycles) of the load access |
| @@ -46,7 +49,7 @@ RECORD OPTIONS | |||
| 46 | 49 | ||
| 47 | -l:: | 50 | -l:: |
| 48 | --ldlat:: | 51 | --ldlat:: |
| 49 | Configure mem-loads latency. | 52 | Configure mem-loads latency. (x86 only) |
| 50 | 53 | ||
| 51 | -k:: | 54 | -k:: |
| 52 | --all-kernel:: | 55 | --all-kernel:: |
| @@ -119,11 +122,16 @@ Following perf record options are configured by default: | |||
| 119 | -W,-d,--phys-data,--sample-cpu | 122 | -W,-d,--phys-data,--sample-cpu |
| 120 | 123 | ||
| 121 | Unless specified otherwise with '-e' option, following events are monitored by | 124 | Unless specified otherwise with '-e' option, following events are monitored by |
| 122 | default: | 125 | default on x86: |
| 123 | 126 | ||
| 124 | cpu/mem-loads,ldlat=30/P | 127 | cpu/mem-loads,ldlat=30/P |
| 125 | cpu/mem-stores/P | 128 | cpu/mem-stores/P |
| 126 | 129 | ||
| 130 | and following on PowerPC: | ||
| 131 | |||
| 132 | cpu/mem-loads/ | ||
| 133 | cpu/mem-stores/ | ||
| 134 | |||
| 127 | User can pass any 'perf record' option behind '--' mark, like (to enable | 135 | User can pass any 'perf record' option behind '--' mark, like (to enable |
| 128 | callchains and system wide monitoring): | 136 | callchains and system wide monitoring): |
| 129 | 137 | ||
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt index f8d2167cf3e7..199ea0f0a6c0 100644 --- a/tools/perf/Documentation/perf-mem.txt +++ b/tools/perf/Documentation/perf-mem.txt | |||
| @@ -82,7 +82,7 @@ RECORD OPTIONS | |||
| 82 | Be more verbose (show counter open errors, etc) | 82 | Be more verbose (show counter open errors, etc) |
| 83 | 83 | ||
| 84 | --ldlat <n>:: | 84 | --ldlat <n>:: |
| 85 | Specify desired latency for loads event. | 85 | Specify desired latency for loads event. (x86 only) |
| 86 | 86 | ||
| 87 | In addition, for report all perf report options are valid, and for record | 87 | In addition, for report all perf report options are valid, and for record |
| 88 | all perf record options. | 88 | all perf record options. |
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index 2e6595310420..ba98bd006488 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build | |||
| @@ -2,6 +2,7 @@ libperf-y += header.o | |||
| 2 | libperf-y += sym-handling.o | 2 | libperf-y += sym-handling.o |
| 3 | libperf-y += kvm-stat.o | 3 | libperf-y += kvm-stat.o |
| 4 | libperf-y += perf_regs.o | 4 | libperf-y += perf_regs.o |
| 5 | libperf-y += mem-events.o | ||
| 5 | 6 | ||
| 6 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 7 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
| 7 | libperf-$(CONFIG_DWARF) += skip-callchain-idx.o | 8 | libperf-$(CONFIG_DWARF) += skip-callchain-idx.o |
diff --git a/tools/perf/arch/powerpc/util/mem-events.c b/tools/perf/arch/powerpc/util/mem-events.c new file mode 100644 index 000000000000..d08311f04e95 --- /dev/null +++ b/tools/perf/arch/powerpc/util/mem-events.c | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | #include "mem-events.h" | ||
| 3 | |||
| 4 | /* PowerPC does not support 'ldlat' parameter. */ | ||
| 5 | char *perf_mem_events__name(int i) | ||
| 6 | { | ||
| 7 | if (i == PERF_MEM_EVENTS__LOAD) | ||
| 8 | return (char *) "cpu/mem-loads/"; | ||
| 9 | |||
| 10 | return (char *) "cpu/mem-stores/"; | ||
| 11 | } | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index d079f36d342d..ac221f137ed2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -1681,13 +1681,8 @@ static void perf_sample__fprint_metric(struct perf_script *script, | |||
| 1681 | .force_header = false, | 1681 | .force_header = false, |
| 1682 | }; | 1682 | }; |
| 1683 | struct perf_evsel *ev2; | 1683 | struct perf_evsel *ev2; |
| 1684 | static bool init; | ||
| 1685 | u64 val; | 1684 | u64 val; |
| 1686 | 1685 | ||
| 1687 | if (!init) { | ||
| 1688 | perf_stat__init_shadow_stats(); | ||
| 1689 | init = true; | ||
| 1690 | } | ||
| 1691 | if (!evsel->stats) | 1686 | if (!evsel->stats) |
| 1692 | perf_evlist__alloc_stats(script->session->evlist, false); | 1687 | perf_evlist__alloc_stats(script->session->evlist, false); |
| 1693 | if (evsel_script(evsel->leader)->gnum++ == 0) | 1688 | if (evsel_script(evsel->leader)->gnum++ == 0) |
| @@ -1794,7 +1789,7 @@ static void process_event(struct perf_script *script, | |||
| 1794 | return; | 1789 | return; |
| 1795 | } | 1790 | } |
| 1796 | 1791 | ||
| 1797 | if (PRINT_FIELD(TRACE)) { | 1792 | if (PRINT_FIELD(TRACE) && sample->raw_data) { |
| 1798 | event_format__fprintf(evsel->tp_format, sample->cpu, | 1793 | event_format__fprintf(evsel->tp_format, sample->cpu, |
| 1799 | sample->raw_data, sample->raw_size, fp); | 1794 | sample->raw_data, sample->raw_size, fp); |
| 1800 | } | 1795 | } |
| @@ -2359,6 +2354,8 @@ static int __cmd_script(struct perf_script *script) | |||
| 2359 | 2354 | ||
| 2360 | signal(SIGINT, sig_handler); | 2355 | signal(SIGINT, sig_handler); |
| 2361 | 2356 | ||
| 2357 | perf_stat__init_shadow_stats(); | ||
| 2358 | |||
| 2362 | /* override event processing functions */ | 2359 | /* override event processing functions */ |
| 2363 | if (script->show_task_events) { | 2360 | if (script->show_task_events) { |
| 2364 | script->tool.comm = process_comm_event; | 2361 | script->tool.comm = process_comm_event; |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index ed4583128b9c..b36061cd1ab8 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
| @@ -2514,19 +2514,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); | |||
| 2514 | 2514 | ||
| 2515 | static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) | 2515 | static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) |
| 2516 | { | 2516 | { |
| 2517 | struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); | 2517 | bool found = false; |
| 2518 | struct perf_evsel *evsel, *tmp; | ||
| 2519 | struct parse_events_error err = { .idx = 0, }; | ||
| 2520 | int ret = parse_events(evlist, "probe:vfs_getname*", &err); | ||
| 2518 | 2521 | ||
| 2519 | if (IS_ERR(evsel)) | 2522 | if (ret) |
| 2520 | return false; | 2523 | return false; |
| 2521 | 2524 | ||
| 2522 | if (perf_evsel__field(evsel, "pathname") == NULL) { | 2525 | evlist__for_each_entry_safe(evlist, evsel, tmp) { |
| 2526 | if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname")) | ||
| 2527 | continue; | ||
| 2528 | |||
| 2529 | if (perf_evsel__field(evsel, "pathname")) { | ||
| 2530 | evsel->handler = trace__vfs_getname; | ||
| 2531 | found = true; | ||
| 2532 | continue; | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | list_del_init(&evsel->node); | ||
| 2536 | evsel->evlist = NULL; | ||
| 2523 | perf_evsel__delete(evsel); | 2537 | perf_evsel__delete(evsel); |
| 2524 | return false; | ||
| 2525 | } | 2538 | } |
| 2526 | 2539 | ||
| 2527 | evsel->handler = trace__vfs_getname; | 2540 | return found; |
| 2528 | perf_evlist__add(evlist, evsel); | ||
| 2529 | return true; | ||
| 2530 | } | 2541 | } |
| 2531 | 2542 | ||
| 2532 | static struct perf_evsel *perf_evsel__new_pgfault(u64 config) | 2543 | static struct perf_evsel *perf_evsel__new_pgfault(u64 config) |
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py index 44090a9a19f3..e952127e4fb0 100644 --- a/tools/perf/tests/attr.py +++ b/tools/perf/tests/attr.py | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #! /usr/bin/python | 1 | #! /usr/bin/python |
| 2 | # SPDX-License-Identifier: GPL-2.0 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | 3 | ||
| 4 | from __future__ import print_function | ||
| 5 | |||
| 4 | import os | 6 | import os |
| 5 | import sys | 7 | import sys |
| 6 | import glob | 8 | import glob |
| @@ -8,7 +10,11 @@ import optparse | |||
| 8 | import tempfile | 10 | import tempfile |
| 9 | import logging | 11 | import logging |
| 10 | import shutil | 12 | import shutil |
| 11 | import ConfigParser | 13 | |
| 14 | try: | ||
| 15 | import configparser | ||
| 16 | except ImportError: | ||
| 17 | import ConfigParser as configparser | ||
| 12 | 18 | ||
| 13 | def data_equal(a, b): | 19 | def data_equal(a, b): |
| 14 | # Allow multiple values in assignment separated by '|' | 20 | # Allow multiple values in assignment separated by '|' |
| @@ -100,20 +106,20 @@ class Event(dict): | |||
| 100 | def equal(self, other): | 106 | def equal(self, other): |
| 101 | for t in Event.terms: | 107 | for t in Event.terms: |
| 102 | log.debug(" [%s] %s %s" % (t, self[t], other[t])); | 108 | log.debug(" [%s] %s %s" % (t, self[t], other[t])); |
| 103 | if not self.has_key(t) or not other.has_key(t): | 109 | if t not in self or t not in other: |
| 104 | return False | 110 | return False |
| 105 | if not data_equal(self[t], other[t]): | 111 | if not data_equal(self[t], other[t]): |
| 106 | return False | 112 | return False |
| 107 | return True | 113 | return True |
| 108 | 114 | ||
| 109 | def optional(self): | 115 | def optional(self): |
| 110 | if self.has_key('optional') and self['optional'] == '1': | 116 | if 'optional' in self and self['optional'] == '1': |
| 111 | return True | 117 | return True |
| 112 | return False | 118 | return False |
| 113 | 119 | ||
| 114 | def diff(self, other): | 120 | def diff(self, other): |
| 115 | for t in Event.terms: | 121 | for t in Event.terms: |
| 116 | if not self.has_key(t) or not other.has_key(t): | 122 | if t not in self or t not in other: |
| 117 | continue | 123 | continue |
| 118 | if not data_equal(self[t], other[t]): | 124 | if not data_equal(self[t], other[t]): |
| 119 | log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) | 125 | log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) |
| @@ -134,7 +140,7 @@ class Event(dict): | |||
| 134 | # - expected values assignments | 140 | # - expected values assignments |
| 135 | class Test(object): | 141 | class Test(object): |
| 136 | def __init__(self, path, options): | 142 | def __init__(self, path, options): |
| 137 | parser = ConfigParser.SafeConfigParser() | 143 | parser = configparser.SafeConfigParser() |
| 138 | parser.read(path) | 144 | parser.read(path) |
| 139 | 145 | ||
| 140 | log.warning("running '%s'" % path) | 146 | log.warning("running '%s'" % path) |
| @@ -193,7 +199,7 @@ class Test(object): | |||
| 193 | return True | 199 | return True |
| 194 | 200 | ||
| 195 | def load_events(self, path, events): | 201 | def load_events(self, path, events): |
| 196 | parser_event = ConfigParser.SafeConfigParser() | 202 | parser_event = configparser.SafeConfigParser() |
| 197 | parser_event.read(path) | 203 | parser_event.read(path) |
| 198 | 204 | ||
| 199 | # The event record section header contains 'event' word, | 205 | # The event record section header contains 'event' word, |
| @@ -207,7 +213,7 @@ class Test(object): | |||
| 207 | # Read parent event if there's any | 213 | # Read parent event if there's any |
| 208 | if (':' in section): | 214 | if (':' in section): |
| 209 | base = section[section.index(':') + 1:] | 215 | base = section[section.index(':') + 1:] |
| 210 | parser_base = ConfigParser.SafeConfigParser() | 216 | parser_base = configparser.SafeConfigParser() |
| 211 | parser_base.read(self.test_dir + '/' + base) | 217 | parser_base.read(self.test_dir + '/' + base) |
| 212 | base_items = parser_base.items('event') | 218 | base_items = parser_base.items('event') |
| 213 | 219 | ||
| @@ -322,9 +328,9 @@ def run_tests(options): | |||
| 322 | for f in glob.glob(options.test_dir + '/' + options.test): | 328 | for f in glob.glob(options.test_dir + '/' + options.test): |
| 323 | try: | 329 | try: |
| 324 | Test(f, options).run() | 330 | Test(f, options).run() |
| 325 | except Unsup, obj: | 331 | except Unsup as obj: |
| 326 | log.warning("unsupp %s" % obj.getMsg()) | 332 | log.warning("unsupp %s" % obj.getMsg()) |
| 327 | except Notest, obj: | 333 | except Notest as obj: |
| 328 | log.warning("skipped %s" % obj.getMsg()) | 334 | log.warning("skipped %s" % obj.getMsg()) |
| 329 | 335 | ||
| 330 | def setup_log(verbose): | 336 | def setup_log(verbose): |
| @@ -363,7 +369,7 @@ def main(): | |||
| 363 | parser.add_option("-p", "--perf", | 369 | parser.add_option("-p", "--perf", |
| 364 | action="store", type="string", dest="perf") | 370 | action="store", type="string", dest="perf") |
| 365 | parser.add_option("-v", "--verbose", | 371 | parser.add_option("-v", "--verbose", |
| 366 | action="count", dest="verbose") | 372 | default=0, action="count", dest="verbose") |
| 367 | 373 | ||
| 368 | options, args = parser.parse_args() | 374 | options, args = parser.parse_args() |
| 369 | if args: | 375 | if args: |
| @@ -373,7 +379,7 @@ def main(): | |||
| 373 | setup_log(options.verbose) | 379 | setup_log(options.verbose) |
| 374 | 380 | ||
| 375 | if not options.test_dir: | 381 | if not options.test_dir: |
| 376 | print 'FAILED no -d option specified' | 382 | print('FAILED no -d option specified') |
| 377 | sys.exit(-1) | 383 | sys.exit(-1) |
| 378 | 384 | ||
| 379 | if not options.test: | 385 | if not options.test: |
| @@ -382,8 +388,8 @@ def main(): | |||
| 382 | try: | 388 | try: |
| 383 | run_tests(options) | 389 | run_tests(options) |
| 384 | 390 | ||
| 385 | except Fail, obj: | 391 | except Fail as obj: |
| 386 | print "FAILED %s" % obj.getMsg(); | 392 | print("FAILED %s" % obj.getMsg()) |
| 387 | sys.exit(-1) | 393 | sys.exit(-1) |
| 388 | 394 | ||
| 389 | sys.exit(0) | 395 | sys.exit(0) |
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 5f8501c68da4..5cbba70bcdd0 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c | |||
| @@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, | |||
| 17 | return -1; | 17 | return -1; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED); | 20 | is_signed = !!(field->flags & TEP_FIELD_IS_SIGNED); |
| 21 | if (should_be_signed && !is_signed) { | 21 | if (should_be_signed && !is_signed) { |
| 22 | pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", | 22 | pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", |
| 23 | evsel->name, name, is_signed, should_be_signed); | 23 | evsel->name, name, is_signed, should_be_signed); |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 1d00e5ec7906..82e16bf84466 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
| @@ -224,20 +224,24 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser) | |||
| 224 | return ret; | 224 | return ret; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) | 227 | static double disasm__cmp(struct annotation_line *a, struct annotation_line *b, |
| 228 | int percent_type) | ||
| 228 | { | 229 | { |
| 229 | int i; | 230 | int i; |
| 230 | 231 | ||
| 231 | for (i = 0; i < a->data_nr; i++) { | 232 | for (i = 0; i < a->data_nr; i++) { |
| 232 | if (a->data[i].percent == b->data[i].percent) | 233 | if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type]) |
| 233 | continue; | 234 | continue; |
| 234 | return a->data[i].percent < b->data[i].percent; | 235 | return a->data[i].percent[percent_type] - |
| 236 | b->data[i].percent[percent_type]; | ||
| 235 | } | 237 | } |
| 236 | return 0; | 238 | return 0; |
| 237 | } | 239 | } |
| 238 | 240 | ||
| 239 | static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) | 241 | static void disasm_rb_tree__insert(struct annotate_browser *browser, |
| 242 | struct annotation_line *al) | ||
| 240 | { | 243 | { |
| 244 | struct rb_root *root = &browser->entries; | ||
| 241 | struct rb_node **p = &root->rb_node; | 245 | struct rb_node **p = &root->rb_node; |
| 242 | struct rb_node *parent = NULL; | 246 | struct rb_node *parent = NULL; |
| 243 | struct annotation_line *l; | 247 | struct annotation_line *l; |
| @@ -246,7 +250,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line | |||
| 246 | parent = *p; | 250 | parent = *p; |
| 247 | l = rb_entry(parent, struct annotation_line, rb_node); | 251 | l = rb_entry(parent, struct annotation_line, rb_node); |
| 248 | 252 | ||
| 249 | if (disasm__cmp(al, l)) | 253 | if (disasm__cmp(al, l, browser->opts->percent_type) < 0) |
| 250 | p = &(*p)->rb_left; | 254 | p = &(*p)->rb_left; |
| 251 | else | 255 | else |
| 252 | p = &(*p)->rb_right; | 256 | p = &(*p)->rb_right; |
| @@ -329,7 +333,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, | |||
| 329 | RB_CLEAR_NODE(&pos->al.rb_node); | 333 | RB_CLEAR_NODE(&pos->al.rb_node); |
| 330 | continue; | 334 | continue; |
| 331 | } | 335 | } |
| 332 | disasm_rb_tree__insert(&browser->entries, &pos->al); | 336 | disasm_rb_tree__insert(browser, &pos->al); |
| 333 | } | 337 | } |
| 334 | pthread_mutex_unlock(¬es->lock); | 338 | pthread_mutex_unlock(¬es->lock); |
| 335 | 339 | ||
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index 89512504551b..39c0004f2886 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp | |||
| @@ -160,7 +160,7 @@ getBPFObjectFromModule(llvm::Module *Module) | |||
| 160 | } | 160 | } |
| 161 | PM.run(*Module); | 161 | PM.run(*Module); |
| 162 | 162 | ||
| 163 | return std::move(Buffer); | 163 | return Buffer; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | } | 166 | } |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 1ccbd3342069..383674f448fc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
| @@ -134,7 +134,12 @@ struct cpu_map *cpu_map__new(const char *cpu_list) | |||
| 134 | if (!cpu_list) | 134 | if (!cpu_list) |
| 135 | return cpu_map__read_all_cpu_map(); | 135 | return cpu_map__read_all_cpu_map(); |
| 136 | 136 | ||
| 137 | if (!isdigit(*cpu_list)) | 137 | /* |
| 138 | * must handle the case of empty cpumap to cover | ||
| 139 | * TOPOLOGY header for NUMA nodes with no CPU | ||
| 140 | * ( e.g., because of CPU hotplug) | ||
| 141 | */ | ||
| 142 | if (!isdigit(*cpu_list) && *cpu_list != '\0') | ||
| 138 | goto out; | 143 | goto out; |
| 139 | 144 | ||
| 140 | while (isdigit(*cpu_list)) { | 145 | while (isdigit(*cpu_list)) { |
| @@ -181,8 +186,10 @@ struct cpu_map *cpu_map__new(const char *cpu_list) | |||
| 181 | 186 | ||
| 182 | if (nr_cpus > 0) | 187 | if (nr_cpus > 0) |
| 183 | cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); | 188 | cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); |
| 184 | else | 189 | else if (*cpu_list != '\0') |
| 185 | cpus = cpu_map__default_new(); | 190 | cpus = cpu_map__default_new(); |
| 191 | else | ||
| 192 | cpus = cpu_map__dummy_new(); | ||
| 186 | invalid: | 193 | invalid: |
| 187 | free(tmp_cpus); | 194 | free(tmp_cpus); |
| 188 | out: | 195 | out: |
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 93f74d8d3cdd..42c3e5a229d2 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c | |||
| @@ -28,7 +28,7 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { | |||
| 28 | static char mem_loads_name[100]; | 28 | static char mem_loads_name[100]; |
| 29 | static bool mem_loads_name__init; | 29 | static bool mem_loads_name__init; |
| 30 | 30 | ||
| 31 | char *perf_mem_events__name(int i) | 31 | char * __weak perf_mem_events__name(int i) |
| 32 | { | 32 | { |
| 33 | if (i == PERF_MEM_EVENTS__LOAD) { | 33 | if (i == PERF_MEM_EVENTS__LOAD) { |
| 34 | if (!mem_loads_name__init) { | 34 | if (!mem_loads_name__init) { |
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 897589507d97..ea523d3b248f 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c | |||
| @@ -391,8 +391,10 @@ void ordered_events__free(struct ordered_events *oe) | |||
| 391 | * Current buffer might not have all the events allocated | 391 | * Current buffer might not have all the events allocated |
| 392 | * yet, we need to free only allocated ones ... | 392 | * yet, we need to free only allocated ones ... |
| 393 | */ | 393 | */ |
| 394 | list_del(&oe->buffer->list); | 394 | if (oe->buffer) { |
| 395 | ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe); | 395 | list_del(&oe->buffer->list); |
| 396 | ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe); | ||
| 397 | } | ||
| 396 | 398 | ||
| 397 | /* ... and continue with the rest */ | 399 | /* ... and continue with the rest */ |
| 398 | list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) { | 400 | list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) { |
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 63f758c655d5..64d1f36dee99 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py | |||
| @@ -17,6 +17,8 @@ if cc == "clang": | |||
| 17 | vars[var] = sub("-mcet", "", vars[var]) | 17 | vars[var] = sub("-mcet", "", vars[var]) |
| 18 | if not clang_has_option("-fcf-protection"): | 18 | if not clang_has_option("-fcf-protection"): |
| 19 | vars[var] = sub("-fcf-protection", "", vars[var]) | 19 | vars[var] = sub("-fcf-protection", "", vars[var]) |
| 20 | if not clang_has_option("-fstack-clash-protection"): | ||
| 21 | vars[var] = sub("-fstack-clash-protection", "", vars[var]) | ||
| 20 | 22 | ||
| 21 | from distutils.core import setup, Extension | 23 | from distutils.core import setup, Extension |
| 22 | 24 | ||
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 66a84d5846c8..dca7dfae69ad 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
| @@ -19,6 +19,20 @@ | |||
| 19 | #define EM_AARCH64 183 /* ARM 64 bit */ | 19 | #define EM_AARCH64 183 /* ARM 64 bit */ |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | #ifndef ELF32_ST_VISIBILITY | ||
| 23 | #define ELF32_ST_VISIBILITY(o) ((o) & 0x03) | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /* For ELF64 the definitions are the same. */ | ||
| 27 | #ifndef ELF64_ST_VISIBILITY | ||
| 28 | #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) | ||
| 29 | #endif | ||
| 30 | |||
| 31 | /* How to extract information held in the st_other field. */ | ||
| 32 | #ifndef GELF_ST_VISIBILITY | ||
| 33 | #define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val) | ||
| 34 | #endif | ||
| 35 | |||
| 22 | typedef Elf64_Nhdr GElf_Nhdr; | 36 | typedef Elf64_Nhdr GElf_Nhdr; |
| 23 | 37 | ||
| 24 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT | 38 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT |
| @@ -87,6 +101,11 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym) | |||
| 87 | return GELF_ST_TYPE(sym->st_info); | 101 | return GELF_ST_TYPE(sym->st_info); |
| 88 | } | 102 | } |
| 89 | 103 | ||
| 104 | static inline uint8_t elf_sym__visibility(const GElf_Sym *sym) | ||
| 105 | { | ||
| 106 | return GELF_ST_VISIBILITY(sym->st_other); | ||
| 107 | } | ||
| 108 | |||
| 90 | #ifndef STT_GNU_IFUNC | 109 | #ifndef STT_GNU_IFUNC |
| 91 | #define STT_GNU_IFUNC 10 | 110 | #define STT_GNU_IFUNC 10 |
| 92 | #endif | 111 | #endif |
| @@ -111,7 +130,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym) | |||
| 111 | return elf_sym__type(sym) == STT_NOTYPE && | 130 | return elf_sym__type(sym) == STT_NOTYPE && |
| 112 | sym->st_name != 0 && | 131 | sym->st_name != 0 && |
| 113 | sym->st_shndx != SHN_UNDEF && | 132 | sym->st_shndx != SHN_UNDEF && |
| 114 | sym->st_shndx != SHN_ABS; | 133 | sym->st_shndx != SHN_ABS && |
| 134 | elf_sym__visibility(sym) != STV_HIDDEN && | ||
| 135 | elf_sym__visibility(sym) != STV_INTERNAL; | ||
| 115 | } | 136 | } |
| 116 | 137 | ||
| 117 | static bool elf_sym__filter(GElf_Sym *sym) | 138 | static bool elf_sym__filter(GElf_Sym *sym) |
