Commit e742f3dc0886a92403d578e8ac771e5e33d06d08
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/g…
…it/acme/linux into perf/urgent Pull perf/urgent fixes from Arnaldo Carvalho de Melo: " User visible fixes: - Fix probing at function return (Namhyumg Kim) Developer visible fixes: - Symbol processing changes necessary for fixing support for kretprobes in 'perf probe' (Namhyung Kim, Arnaldo Carvalho de Melo) - Annotation memory leaks and instruction parsing fixes (Rabin Vincent) - Fix perl build on ARM64 (Wang Nam) " Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Showing 7 changed files Side-by-side Diff
tools/perf/scripts/perl/Perf-Trace-Util/Context.c
tools/perf/util/annotate.c
... | ... | @@ -177,14 +177,17 @@ |
177 | 177 | goto out_free_ops; |
178 | 178 | |
179 | 179 | ops->locked.ins = ins__find(name); |
180 | + free(name); | |
181 | + | |
180 | 182 | if (ops->locked.ins == NULL) |
181 | 183 | goto out_free_ops; |
182 | 184 | |
183 | 185 | if (!ops->locked.ins->ops) |
184 | 186 | return 0; |
185 | 187 | |
186 | - if (ops->locked.ins->ops->parse) | |
187 | - ops->locked.ins->ops->parse(ops->locked.ops); | |
188 | + if (ops->locked.ins->ops->parse && | |
189 | + ops->locked.ins->ops->parse(ops->locked.ops) < 0) | |
190 | + goto out_free_ops; | |
188 | 191 | |
189 | 192 | return 0; |
190 | 193 | |
... | ... | @@ -208,6 +211,13 @@ |
208 | 211 | |
209 | 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 | 221 | zfree(&ops->locked.ops); |
212 | 222 | zfree(&ops->target.raw); |
213 | 223 | zfree(&ops->target.name); |
... | ... | @@ -531,8 +541,8 @@ |
531 | 541 | if (!dl->ins->ops) |
532 | 542 | return; |
533 | 543 | |
534 | - if (dl->ins->ops->parse) | |
535 | - dl->ins->ops->parse(&dl->ops); | |
544 | + if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) | |
545 | + dl->ins = NULL; | |
536 | 546 | } |
537 | 547 | |
538 | 548 | static int disasm_line__parse(char *line, char **namep, char **rawp) |
tools/perf/util/evlist.c
... | ... | @@ -1445,7 +1445,7 @@ |
1445 | 1445 | case ENOENT: |
1446 | 1446 | scnprintf(buf, size, "%s", |
1447 | 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 | 1449 | "Hint:\tIs the debugfs filesystem mounted?\n" |
1450 | 1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); |
1451 | 1451 | break; |
tools/perf/util/map.h
... | ... | @@ -116,6 +116,22 @@ |
116 | 116 | #define map__for_each_symbol(map, pos, n) \ |
117 | 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 | 135 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); |
120 | 136 | |
121 | 137 | void map__init(struct map *map, enum map_type type, |
tools/perf/util/probe-event.c
... | ... | @@ -446,7 +446,7 @@ |
446 | 446 | } |
447 | 447 | |
448 | 448 | for (i = 0; i < ntevs; i++) { |
449 | - if (tevs[i].point.address) { | |
449 | + if (tevs[i].point.address && !tevs[i].point.retprobe) { | |
450 | 450 | tmp = strdup(reloc_sym->name); |
451 | 451 | if (!tmp) |
452 | 452 | return -ENOMEM; |
453 | 453 | |
454 | 454 | |
... | ... | @@ -2193,18 +2193,17 @@ |
2193 | 2193 | return ret; |
2194 | 2194 | } |
2195 | 2195 | |
2196 | -static char *looking_function_name; | |
2197 | -static int num_matched_functions; | |
2198 | - | |
2199 | -static int probe_function_filter(struct map *map __maybe_unused, | |
2200 | - struct symbol *sym) | |
2196 | +static int find_probe_functions(struct map *map, char *name) | |
2201 | 2197 | { |
2202 | - if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && | |
2203 | - strcmp(looking_function_name, sym->name) == 0) { | |
2204 | - num_matched_functions++; | |
2205 | - return 0; | |
2198 | + int found = 0; | |
2199 | + struct symbol *sym; | |
2200 | + | |
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 | 2209 | #define strdup_or_goto(str, label) \ |
2211 | 2210 | |
... | ... | @@ -2222,10 +2221,10 @@ |
2222 | 2221 | struct kmap *kmap = NULL; |
2223 | 2222 | struct ref_reloc_sym *reloc_sym = NULL; |
2224 | 2223 | struct symbol *sym; |
2225 | - struct rb_node *nd; | |
2226 | 2224 | struct probe_trace_event *tev; |
2227 | 2225 | struct perf_probe_point *pp = &pev->point; |
2228 | 2226 | struct probe_trace_point *tp; |
2227 | + int num_matched_functions; | |
2229 | 2228 | int ret, i; |
2230 | 2229 | |
2231 | 2230 | /* Init maps of given executable or kernel */ |
... | ... | @@ -2242,10 +2241,8 @@ |
2242 | 2241 | * Load matched symbols: Since the different local symbols may have |
2243 | 2242 | * same name but different addresses, this lists all the symbols. |
2244 | 2243 | */ |
2245 | - num_matched_functions = 0; | |
2246 | - looking_function_name = pp->function; | |
2247 | - ret = map__load(map, probe_function_filter); | |
2248 | - if (ret || num_matched_functions == 0) { | |
2244 | + num_matched_functions = find_probe_functions(map, pp->function); | |
2245 | + if (num_matched_functions == 0) { | |
2249 | 2246 | pr_err("Failed to find symbol %s in %s\n", pp->function, |
2250 | 2247 | target ? : "kernel"); |
2251 | 2248 | ret = -ENOENT; |
... | ... | @@ -2257,7 +2254,7 @@ |
2257 | 2254 | goto out; |
2258 | 2255 | } |
2259 | 2256 | |
2260 | - if (!pev->uprobes) { | |
2257 | + if (!pev->uprobes && !pp->retprobe) { | |
2261 | 2258 | kmap = map__kmap(map); |
2262 | 2259 | reloc_sym = kmap->ref_reloc_sym; |
2263 | 2260 | if (!reloc_sym) { |
... | ... | @@ -2275,7 +2272,8 @@ |
2275 | 2272 | } |
2276 | 2273 | |
2277 | 2274 | ret = 0; |
2278 | - map__for_each_symbol(map, sym, nd) { | |
2275 | + | |
2276 | + map__for_each_symbol_by_name(map, pp->function, sym) { | |
2279 | 2277 | tev = (*tevs) + ret; |
2280 | 2278 | tp = &tev->point; |
2281 | 2279 | if (ret == num_matched_functions) { |
tools/perf/util/symbol.c
... | ... | @@ -396,6 +396,7 @@ |
396 | 396 | const char *name) |
397 | 397 | { |
398 | 398 | struct rb_node *n; |
399 | + struct symbol_name_rb_node *s; | |
399 | 400 | |
400 | 401 | if (symbols == NULL) |
401 | 402 | return NULL; |
... | ... | @@ -403,7 +404,6 @@ |
403 | 404 | n = symbols->rb_node; |
404 | 405 | |
405 | 406 | while (n) { |
406 | - struct symbol_name_rb_node *s; | |
407 | 407 | int cmp; |
408 | 408 | |
409 | 409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); |
410 | 410 | |
... | ... | @@ -414,10 +414,24 @@ |
414 | 414 | else if (cmp > 0) |
415 | 415 | n = n->rb_right; |
416 | 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 | 437 | struct symbol *dso__find_symbol(struct dso *dso, |
... | ... | @@ -436,6 +450,17 @@ |
436 | 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 | 464 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
440 | 465 | const char *name) |
441 | 466 | { |
tools/perf/util/symbol.h
... | ... | @@ -231,6 +231,7 @@ |
231 | 231 | u64 addr); |
232 | 232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
233 | 233 | const char *name); |
234 | +struct symbol *symbol__next_by_name(struct symbol *sym); | |
234 | 235 | |
235 | 236 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); |
236 | 237 | struct symbol *dso__next_symbol(struct symbol *sym); |