diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-01-30 17:34:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-01-30 17:34:55 -0500 |
commit | 6155bc14315763cf0f1989b3636ccc2f3e57f0d6 (patch) | |
tree | 71ad20ee6d447900cf9760686cc0167528cc2f19 | |
parent | bc208e0ee0f46744aac95c29366144271a6962bb (diff) | |
parent | e742f3dc0886a92403d578e8ac771e5e33d06d08 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"Mostly tooling fixes, but also an event groups fix, two PMU driver
fixes and a CPU model variant addition"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf: Tighten (and fix) the grouping condition
perf/x86/intel: Add model number for Airmont
perf/rapl: Fix crash in rapl_scale()
perf/x86/intel/uncore: Move uncore_box_init() out of driver initialization
perf probe: Fix probing kretprobes
perf symbols: Introduce 'for' method to iterate over the symbols with a given name
perf probe: Do not rely on map__load() filter to find symbols
perf symbols: Introduce method to iterate symbols ordered by name
perf symbols: Return the first entry with a given name in find_by_name method
perf annotate: Fix memory leaks in LOCK handling
perf annotate: Handle ins parsing failures
perf scripting perl: Force to use stdbool
perf evlist: Remove extraneous 'was' on error message
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_rapl.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 18 | ||||
-rw-r--r-- | include/linux/perf_event.h | 6 | ||||
-rw-r--r-- | kernel/events/core.c | 15 | ||||
-rw-r--r-- | tools/perf/scripts/perl/Perf-Trace-Util/Context.c | 5 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 18 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 2 | ||||
-rw-r--r-- | tools/perf/util/map.h | 16 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 34 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 31 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
13 files changed, 107 insertions, 51 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 944bf019b74f..498b6d967138 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -2431,6 +2431,7 @@ __init int intel_pmu_init(void) | |||
2431 | break; | 2431 | break; |
2432 | 2432 | ||
2433 | case 55: /* 22nm Atom "Silvermont" */ | 2433 | case 55: /* 22nm Atom "Silvermont" */ |
2434 | case 76: /* 14nm Atom "Airmont" */ | ||
2434 | case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ | 2435 | case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ |
2435 | memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, | 2436 | memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, |
2436 | sizeof(hw_cache_event_ids)); | 2437 | sizeof(hw_cache_event_ids)); |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c index 6e434f8e5fc8..c4bb8b8e5017 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c +++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c | |||
@@ -142,7 +142,7 @@ static inline u64 rapl_scale(u64 v) | |||
142 | * or use ldexp(count, -32). | 142 | * or use ldexp(count, -32). |
143 | * Watts = Joules/Time delta | 143 | * Watts = Joules/Time delta |
144 | */ | 144 | */ |
145 | return v << (32 - __this_cpu_read(rapl_pmu->hw_unit)); | 145 | return v << (32 - __this_cpu_read(rapl_pmu)->hw_unit); |
146 | } | 146 | } |
147 | 147 | ||
148 | static u64 rapl_event_update(struct perf_event *event) | 148 | static u64 rapl_event_update(struct perf_event *event) |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 10b8d3eaaf15..c635b8b49e93 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -840,7 +840,6 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id | |||
840 | box->phys_id = phys_id; | 840 | box->phys_id = phys_id; |
841 | box->pci_dev = pdev; | 841 | box->pci_dev = pdev; |
842 | box->pmu = pmu; | 842 | box->pmu = pmu; |
843 | uncore_box_init(box); | ||
844 | pci_set_drvdata(pdev, box); | 843 | pci_set_drvdata(pdev, box); |
845 | 844 | ||
846 | raw_spin_lock(&uncore_box_lock); | 845 | raw_spin_lock(&uncore_box_lock); |
@@ -1004,10 +1003,8 @@ static int uncore_cpu_starting(int cpu) | |||
1004 | pmu = &type->pmus[j]; | 1003 | pmu = &type->pmus[j]; |
1005 | box = *per_cpu_ptr(pmu->box, cpu); | 1004 | box = *per_cpu_ptr(pmu->box, cpu); |
1006 | /* called by uncore_cpu_init? */ | 1005 | /* called by uncore_cpu_init? */ |
1007 | if (box && box->phys_id >= 0) { | 1006 | if (box && box->phys_id >= 0) |
1008 | uncore_box_init(box); | ||
1009 | continue; | 1007 | continue; |
1010 | } | ||
1011 | 1008 | ||
1012 | for_each_online_cpu(k) { | 1009 | for_each_online_cpu(k) { |
1013 | exist = *per_cpu_ptr(pmu->box, k); | 1010 | exist = *per_cpu_ptr(pmu->box, k); |
@@ -1023,10 +1020,8 @@ static int uncore_cpu_starting(int cpu) | |||
1023 | } | 1020 | } |
1024 | } | 1021 | } |
1025 | 1022 | ||
1026 | if (box) { | 1023 | if (box) |
1027 | box->phys_id = phys_id; | 1024 | box->phys_id = phys_id; |
1028 | uncore_box_init(box); | ||
1029 | } | ||
1030 | } | 1025 | } |
1031 | } | 1026 | } |
1032 | return 0; | 1027 | return 0; |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 863d9b02563e..6c8c1e7e69d8 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -257,6 +257,14 @@ static inline int uncore_num_counters(struct intel_uncore_box *box) | |||
257 | return box->pmu->type->num_counters; | 257 | return box->pmu->type->num_counters; |
258 | } | 258 | } |
259 | 259 | ||
260 | static inline void uncore_box_init(struct intel_uncore_box *box) | ||
261 | { | ||
262 | if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { | ||
263 | if (box->pmu->type->ops->init_box) | ||
264 | box->pmu->type->ops->init_box(box); | ||
265 | } | ||
266 | } | ||
267 | |||
260 | static inline void uncore_disable_box(struct intel_uncore_box *box) | 268 | static inline void uncore_disable_box(struct intel_uncore_box *box) |
261 | { | 269 | { |
262 | if (box->pmu->type->ops->disable_box) | 270 | if (box->pmu->type->ops->disable_box) |
@@ -265,6 +273,8 @@ static inline void uncore_disable_box(struct intel_uncore_box *box) | |||
265 | 273 | ||
266 | static inline void uncore_enable_box(struct intel_uncore_box *box) | 274 | static inline void uncore_enable_box(struct intel_uncore_box *box) |
267 | { | 275 | { |
276 | uncore_box_init(box); | ||
277 | |||
268 | if (box->pmu->type->ops->enable_box) | 278 | if (box->pmu->type->ops->enable_box) |
269 | box->pmu->type->ops->enable_box(box); | 279 | box->pmu->type->ops->enable_box(box); |
270 | } | 280 | } |
@@ -287,14 +297,6 @@ static inline u64 uncore_read_counter(struct intel_uncore_box *box, | |||
287 | return box->pmu->type->ops->read_counter(box, event); | 297 | return box->pmu->type->ops->read_counter(box, event); |
288 | } | 298 | } |
289 | 299 | ||
290 | static inline void uncore_box_init(struct intel_uncore_box *box) | ||
291 | { | ||
292 | if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { | ||
293 | if (box->pmu->type->ops->init_box) | ||
294 | box->pmu->type->ops->init_box(box); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static inline bool uncore_box_is_fake(struct intel_uncore_box *box) | 300 | static inline bool uncore_box_is_fake(struct intel_uncore_box *box) |
299 | { | 301 | { |
300 | return (box->phys_id < 0); | 302 | return (box->phys_id < 0); |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 4f7a61ca4b39..664de5a4ec46 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -450,11 +450,6 @@ struct perf_event { | |||
450 | #endif /* CONFIG_PERF_EVENTS */ | 450 | #endif /* CONFIG_PERF_EVENTS */ |
451 | }; | 451 | }; |
452 | 452 | ||
453 | enum perf_event_context_type { | ||
454 | task_context, | ||
455 | cpu_context, | ||
456 | }; | ||
457 | |||
458 | /** | 453 | /** |
459 | * struct perf_event_context - event context structure | 454 | * struct perf_event_context - event context structure |
460 | * | 455 | * |
@@ -462,7 +457,6 @@ enum perf_event_context_type { | |||
462 | */ | 457 | */ |
463 | struct perf_event_context { | 458 | struct perf_event_context { |
464 | struct pmu *pmu; | 459 | struct pmu *pmu; |
465 | enum perf_event_context_type type; | ||
466 | /* | 460 | /* |
467 | * Protect the states of the events in the list, | 461 | * Protect the states of the events in the list, |
468 | * nr_active, and the list: | 462 | * nr_active, and the list: |
diff --git a/kernel/events/core.c b/kernel/events/core.c index 882f835a0d85..19efcf13375a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -6776,7 +6776,6 @@ skip_type: | |||
6776 | __perf_event_init_context(&cpuctx->ctx); | 6776 | __perf_event_init_context(&cpuctx->ctx); |
6777 | lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); | 6777 | lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); |
6778 | lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); | 6778 | lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); |
6779 | cpuctx->ctx.type = cpu_context; | ||
6780 | cpuctx->ctx.pmu = pmu; | 6779 | cpuctx->ctx.pmu = pmu; |
6781 | 6780 | ||
6782 | __perf_cpu_hrtimer_init(cpuctx, cpu); | 6781 | __perf_cpu_hrtimer_init(cpuctx, cpu); |
@@ -7420,7 +7419,19 @@ SYSCALL_DEFINE5(perf_event_open, | |||
7420 | * task or CPU context: | 7419 | * task or CPU context: |
7421 | */ | 7420 | */ |
7422 | if (move_group) { | 7421 | if (move_group) { |
7423 | if (group_leader->ctx->type != ctx->type) | 7422 | /* |
7423 | * Make sure we're both on the same task, or both | ||
7424 | * per-cpu events. | ||
7425 | */ | ||
7426 | if (group_leader->ctx->task != ctx->task) | ||
7427 | goto err_context; | ||
7428 | |||
7429 | /* | ||
7430 | * Make sure we're both events for the same CPU; | ||
7431 | * grouping events for different CPUs is broken; since | ||
7432 | * you can never concurrently schedule them anyhow. | ||
7433 | */ | ||
7434 | if (group_leader->cpu != event->cpu) | ||
7424 | goto err_context; | 7435 | goto err_context; |
7425 | } else { | 7436 | } else { |
7426 | if (group_leader->ctx != ctx) | 7437 | if (group_leader->ctx != ctx) |
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c index 790ceba6ad3f..28431d1bbcf5 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c +++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c | |||
@@ -5,7 +5,10 @@ | |||
5 | * ANY CHANGES MADE HERE WILL BE LOST! | 5 | * ANY CHANGES MADE HERE WILL BE LOST! |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | #include <stdbool.h> | |
9 | #ifndef HAS_BOOL | ||
10 | # define HAS_BOOL 1 | ||
11 | #endif | ||
9 | #line 1 "Context.xs" | 12 | #line 1 "Context.xs" |
10 | /* | 13 | /* |
11 | * Context.xs. XS interfaces for perf script. | 14 | * Context.xs. XS interfaces for perf script. |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 79999ceaf2be..01bc4e23a2cf 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -177,14 +177,17 @@ static int lock__parse(struct ins_operands *ops) | |||
177 | goto out_free_ops; | 177 | goto out_free_ops; |
178 | 178 | ||
179 | ops->locked.ins = ins__find(name); | 179 | ops->locked.ins = ins__find(name); |
180 | free(name); | ||
181 | |||
180 | if (ops->locked.ins == NULL) | 182 | if (ops->locked.ins == NULL) |
181 | goto out_free_ops; | 183 | goto out_free_ops; |
182 | 184 | ||
183 | if (!ops->locked.ins->ops) | 185 | if (!ops->locked.ins->ops) |
184 | return 0; | 186 | return 0; |
185 | 187 | ||
186 | if (ops->locked.ins->ops->parse) | 188 | if (ops->locked.ins->ops->parse && |
187 | ops->locked.ins->ops->parse(ops->locked.ops); | 189 | ops->locked.ins->ops->parse(ops->locked.ops) < 0) |
190 | goto out_free_ops; | ||
188 | 191 | ||
189 | return 0; | 192 | return 0; |
190 | 193 | ||
@@ -208,6 +211,13 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, | |||
208 | 211 | ||
209 | static void lock__delete(struct ins_operands *ops) | 212 | static void lock__delete(struct ins_operands *ops) |
210 | { | 213 | { |
214 | struct ins *ins = ops->locked.ins; | ||
215 | |||
216 | if (ins && ins->ops->free) | ||
217 | ins->ops->free(ops->locked.ops); | ||
218 | else | ||
219 | ins__delete(ops->locked.ops); | ||
220 | |||
211 | zfree(&ops->locked.ops); | 221 | zfree(&ops->locked.ops); |
212 | zfree(&ops->target.raw); | 222 | zfree(&ops->target.raw); |
213 | zfree(&ops->target.name); | 223 | zfree(&ops->target.name); |
@@ -531,8 +541,8 @@ static void disasm_line__init_ins(struct disasm_line *dl) | |||
531 | if (!dl->ins->ops) | 541 | if (!dl->ins->ops) |
532 | return; | 542 | return; |
533 | 543 | ||
534 | if (dl->ins->ops->parse) | 544 | if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) |
535 | dl->ins->ops->parse(&dl->ops); | 545 | dl->ins = NULL; |
536 | } | 546 | } |
537 | 547 | ||
538 | static int disasm_line__parse(char *line, char **namep, char **rawp) | 548 | static int disasm_line__parse(char *line, char **namep, char **rawp) |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index cbab1fb77b1d..2e507b5025a3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -1445,7 +1445,7 @@ int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, | |||
1445 | case ENOENT: | 1445 | case ENOENT: |
1446 | scnprintf(buf, size, "%s", | 1446 | scnprintf(buf, size, "%s", |
1447 | "Error:\tUnable to find debugfs\n" | 1447 | "Error:\tUnable to find debugfs\n" |
1448 | "Hint:\tWas your kernel was compiled with debugfs support?\n" | 1448 | "Hint:\tWas your kernel compiled with debugfs support?\n" |
1449 | "Hint:\tIs the debugfs filesystem mounted?\n" | 1449 | "Hint:\tIs the debugfs filesystem mounted?\n" |
1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); | 1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); |
1451 | break; | 1451 | break; |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6951a9d42339..0e42438b1e59 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -116,6 +116,22 @@ struct thread; | |||
116 | #define map__for_each_symbol(map, pos, n) \ | 116 | #define map__for_each_symbol(map, pos, n) \ |
117 | dso__for_each_symbol(map->dso, pos, n, map->type) | 117 | dso__for_each_symbol(map->dso, pos, n, map->type) |
118 | 118 | ||
119 | /* map__for_each_symbol_with_name - iterate over the symbols in the given map | ||
120 | * that have the given name | ||
121 | * | ||
122 | * @map: the 'struct map *' in which symbols itereated | ||
123 | * @sym_name: the symbol name | ||
124 | * @pos: the 'struct symbol *' to use as a loop cursor | ||
125 | * @filter: to use when loading the DSO | ||
126 | */ | ||
127 | #define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ | ||
128 | for (pos = map__find_symbol_by_name(map, sym_name, filter); \ | ||
129 | pos && strcmp(pos->name, sym_name) == 0; \ | ||
130 | pos = symbol__next_by_name(pos)) | ||
131 | |||
132 | #define map__for_each_symbol_by_name(map, sym_name, pos) \ | ||
133 | __map__for_each_symbol_by_name(map, sym_name, (pos), NULL) | ||
134 | |||
119 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); | 135 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); |
120 | 136 | ||
121 | void map__init(struct map *map, enum map_type type, | 137 | void map__init(struct map *map, enum map_type type, |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 94a717bf007d..919937eb0be2 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -446,7 +446,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs, | |||
446 | } | 446 | } |
447 | 447 | ||
448 | for (i = 0; i < ntevs; i++) { | 448 | for (i = 0; i < ntevs; i++) { |
449 | if (tevs[i].point.address) { | 449 | if (tevs[i].point.address && !tevs[i].point.retprobe) { |
450 | tmp = strdup(reloc_sym->name); | 450 | tmp = strdup(reloc_sym->name); |
451 | if (!tmp) | 451 | if (!tmp) |
452 | return -ENOMEM; | 452 | return -ENOMEM; |
@@ -2193,18 +2193,17 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2193 | return ret; | 2193 | return ret; |
2194 | } | 2194 | } |
2195 | 2195 | ||
2196 | static char *looking_function_name; | 2196 | static int find_probe_functions(struct map *map, char *name) |
2197 | static int num_matched_functions; | ||
2198 | |||
2199 | static int probe_function_filter(struct map *map __maybe_unused, | ||
2200 | struct symbol *sym) | ||
2201 | { | 2197 | { |
2202 | if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && | 2198 | int found = 0; |
2203 | strcmp(looking_function_name, sym->name) == 0) { | 2199 | struct symbol *sym; |
2204 | num_matched_functions++; | 2200 | |
2205 | return 0; | 2201 | map__for_each_symbol_by_name(map, name, sym) { |
2202 | if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) | ||
2203 | found++; | ||
2206 | } | 2204 | } |
2207 | return 1; | 2205 | |
2206 | return found; | ||
2208 | } | 2207 | } |
2209 | 2208 | ||
2210 | #define strdup_or_goto(str, label) \ | 2209 | #define strdup_or_goto(str, label) \ |
@@ -2222,10 +2221,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2222 | struct kmap *kmap = NULL; | 2221 | struct kmap *kmap = NULL; |
2223 | struct ref_reloc_sym *reloc_sym = NULL; | 2222 | struct ref_reloc_sym *reloc_sym = NULL; |
2224 | struct symbol *sym; | 2223 | struct symbol *sym; |
2225 | struct rb_node *nd; | ||
2226 | struct probe_trace_event *tev; | 2224 | struct probe_trace_event *tev; |
2227 | struct perf_probe_point *pp = &pev->point; | 2225 | struct perf_probe_point *pp = &pev->point; |
2228 | struct probe_trace_point *tp; | 2226 | struct probe_trace_point *tp; |
2227 | int num_matched_functions; | ||
2229 | int ret, i; | 2228 | int ret, i; |
2230 | 2229 | ||
2231 | /* Init maps of given executable or kernel */ | 2230 | /* Init maps of given executable or kernel */ |
@@ -2242,10 +2241,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2242 | * Load matched symbols: Since the different local symbols may have | 2241 | * Load matched symbols: Since the different local symbols may have |
2243 | * same name but different addresses, this lists all the symbols. | 2242 | * same name but different addresses, this lists all the symbols. |
2244 | */ | 2243 | */ |
2245 | num_matched_functions = 0; | 2244 | num_matched_functions = find_probe_functions(map, pp->function); |
2246 | looking_function_name = pp->function; | 2245 | if (num_matched_functions == 0) { |
2247 | ret = map__load(map, probe_function_filter); | ||
2248 | if (ret || num_matched_functions == 0) { | ||
2249 | pr_err("Failed to find symbol %s in %s\n", pp->function, | 2246 | pr_err("Failed to find symbol %s in %s\n", pp->function, |
2250 | target ? : "kernel"); | 2247 | target ? : "kernel"); |
2251 | ret = -ENOENT; | 2248 | ret = -ENOENT; |
@@ -2257,7 +2254,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2257 | goto out; | 2254 | goto out; |
2258 | } | 2255 | } |
2259 | 2256 | ||
2260 | if (!pev->uprobes) { | 2257 | if (!pev->uprobes && !pp->retprobe) { |
2261 | kmap = map__kmap(map); | 2258 | kmap = map__kmap(map); |
2262 | reloc_sym = kmap->ref_reloc_sym; | 2259 | reloc_sym = kmap->ref_reloc_sym; |
2263 | if (!reloc_sym) { | 2260 | if (!reloc_sym) { |
@@ -2275,7 +2272,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2275 | } | 2272 | } |
2276 | 2273 | ||
2277 | ret = 0; | 2274 | ret = 0; |
2278 | map__for_each_symbol(map, sym, nd) { | 2275 | |
2276 | map__for_each_symbol_by_name(map, pp->function, sym) { | ||
2279 | tev = (*tevs) + ret; | 2277 | tev = (*tevs) + ret; |
2280 | tp = &tev->point; | 2278 | tp = &tev->point; |
2281 | if (ret == num_matched_functions) { | 2279 | if (ret == num_matched_functions) { |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c24c5b83156c..a194702a0a2f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -396,6 +396,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
396 | const char *name) | 396 | const char *name) |
397 | { | 397 | { |
398 | struct rb_node *n; | 398 | struct rb_node *n; |
399 | struct symbol_name_rb_node *s; | ||
399 | 400 | ||
400 | if (symbols == NULL) | 401 | if (symbols == NULL) |
401 | return NULL; | 402 | return NULL; |
@@ -403,7 +404,6 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
403 | n = symbols->rb_node; | 404 | n = symbols->rb_node; |
404 | 405 | ||
405 | while (n) { | 406 | while (n) { |
406 | struct symbol_name_rb_node *s; | ||
407 | int cmp; | 407 | int cmp; |
408 | 408 | ||
409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); | 409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); |
@@ -414,10 +414,24 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
414 | else if (cmp > 0) | 414 | else if (cmp > 0) |
415 | n = n->rb_right; | 415 | n = n->rb_right; |
416 | else | 416 | else |
417 | return &s->sym; | 417 | break; |
418 | } | 418 | } |
419 | 419 | ||
420 | return NULL; | 420 | if (n == NULL) |
421 | return NULL; | ||
422 | |||
423 | /* return first symbol that has same name (if any) */ | ||
424 | for (n = rb_prev(n); n; n = rb_prev(n)) { | ||
425 | struct symbol_name_rb_node *tmp; | ||
426 | |||
427 | tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); | ||
428 | if (strcmp(tmp->sym.name, s->sym.name)) | ||
429 | break; | ||
430 | |||
431 | s = tmp; | ||
432 | } | ||
433 | |||
434 | return &s->sym; | ||
421 | } | 435 | } |
422 | 436 | ||
423 | struct symbol *dso__find_symbol(struct dso *dso, | 437 | struct symbol *dso__find_symbol(struct dso *dso, |
@@ -436,6 +450,17 @@ struct symbol *dso__next_symbol(struct symbol *sym) | |||
436 | return symbols__next(sym); | 450 | return symbols__next(sym); |
437 | } | 451 | } |
438 | 452 | ||
453 | struct symbol *symbol__next_by_name(struct symbol *sym) | ||
454 | { | ||
455 | struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym); | ||
456 | struct rb_node *n = rb_next(&s->rb_node); | ||
457 | |||
458 | return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL; | ||
459 | } | ||
460 | |||
461 | /* | ||
462 | * Teturns first symbol that matched with @name. | ||
463 | */ | ||
439 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 464 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
440 | const char *name) | 465 | const char *name) |
441 | { | 466 | { |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 9d602e9c6f59..1650dcb3a67b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -231,6 +231,7 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | |||
231 | u64 addr); | 231 | u64 addr); |
232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
233 | const char *name); | 233 | const char *name); |
234 | struct symbol *symbol__next_by_name(struct symbol *sym); | ||
234 | 235 | ||
235 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | 236 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); |
236 | struct symbol *dso__next_symbol(struct symbol *sym); | 237 | struct symbol *dso__next_symbol(struct symbol *sym); |