aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-c2c.txt16
-rw-r--r--tools/perf/Documentation/perf-mem.txt2
-rw-r--r--tools/perf/arch/powerpc/util/Build1
-rw-r--r--tools/perf/arch/powerpc/util/mem-events.c11
-rw-r--r--tools/perf/builtin-script.c9
-rw-r--r--tools/perf/builtin-trace.c25
-rw-r--r--tools/perf/tests/attr.py32
-rw-r--r--tools/perf/tests/evsel-tp-sched.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c16
-rw-r--r--tools/perf/util/c++/clang.cpp2
-rw-r--r--tools/perf/util/cpumap.c11
-rw-r--r--tools/perf/util/mem-events.c2
-rw-r--r--tools/perf/util/ordered-events.c6
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/symbol-elf.c23
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.
19The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows 19The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
20you to track down the cacheline contentions. 20you to track down the cacheline contentions.
21 21
22The tool is based on x86's load latency and precise store facility events 22On x86, the tool is based on load latency and precise store facility events
23provided by Intel CPUs. These events provide: 23provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling
24with thresholding feature.
25
26These 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
121Unless specified otherwise with '-e' option, following events are monitored by 124Unless specified otherwise with '-e' option, following events are monitored by
122default: 125default 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
130and following on PowerPC:
131
132 cpu/mem-loads/
133 cpu/mem-stores/
134
127User can pass any 'perf record' option behind '--' mark, like (to enable 135User can pass any 'perf record' option behind '--' mark, like (to enable
128callchains and system wide monitoring): 136callchains 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
87In addition, for report all perf report options are valid, and for record 87In addition, for report all perf report options are valid, and for record
88all perf record options. 88all 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
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
4libperf-y += perf_regs.o 4libperf-y += perf_regs.o
5libperf-y += mem-events.o
5 6
6libperf-$(CONFIG_DWARF) += dwarf-regs.o 7libperf-$(CONFIG_DWARF) += dwarf-regs.o
7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 8libperf-$(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. */
5char *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
2515static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) 2515static 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
2532static struct perf_evsel *perf_evsel__new_pgfault(u64 config) 2543static 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
4from __future__ import print_function
5
4import os 6import os
5import sys 7import sys
6import glob 8import glob
@@ -8,7 +10,11 @@ import optparse
8import tempfile 10import tempfile
9import logging 11import logging
10import shutil 12import shutil
11import ConfigParser 13
14try:
15 import configparser
16except ImportError:
17 import ConfigParser as configparser
12 18
13def data_equal(a, b): 19def 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
135class Test(object): 141class 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
330def setup_log(verbose): 336def 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
227static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 227static 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
239static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 241static 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(&notes->lock); 338 pthread_mutex_unlock(&notes->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();
186invalid: 193invalid:
187 free(tmp_cpus); 194 free(tmp_cpus);
188out: 195out:
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] = {
28static char mem_loads_name[100]; 28static char mem_loads_name[100];
29static bool mem_loads_name__init; 29static bool mem_loads_name__init;
30 30
31char *perf_mem_events__name(int i) 31char * __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
21from distutils.core import setup, Extension 23from 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
22typedef Elf64_Nhdr GElf_Nhdr; 36typedef 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
104static 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
117static bool elf_sym__filter(GElf_Sym *sym) 138static bool elf_sym__filter(GElf_Sym *sym)