Commit e742f3dc0886a92403d578e8ac771e5e33d06d08

Authored by Ingo Molnar

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
... ... @@ -5,7 +5,10 @@
5 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 12 #line 1 "Context.xs"
10 13 /*
11 14 * Context.xs. XS interfaces for perf script.
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);