Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools lib traceevent: Allow setting an alternative symbol resolver

The perf tools have a symbol resolver that includes solving kernel
symbols using either kallsyms or ELF symtabs, and it also is using
libtraceevent to format the trace events fields, including via
subsystem specific plugins, like the "timer" one.

To solve fields like "timer:hrtimer_start"'s "function", libtraceevent
needs a way to map from its value to a function name and addr.

This patch provides a way for tools that already have symbol resolving
facilities to ask libtraceevent to use it when needing to resolve
kernel symbols.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Acked-by: David Ahern <dsahern@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-fdx1fazols17w5py26ia3bwh@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+75 -1
+67 -1
tools/lib/traceevent/event-parse.c
··· 418 418 } 419 419 420 420 static struct func_map * 421 - find_func(struct pevent *pevent, unsigned long long addr) 421 + __find_func(struct pevent *pevent, unsigned long long addr) 422 422 { 423 423 struct func_map *func; 424 424 struct func_map key; ··· 432 432 sizeof(*pevent->func_map), func_bcmp); 433 433 434 434 return func; 435 + } 436 + 437 + struct func_resolver { 438 + pevent_func_resolver_t *func; 439 + void *priv; 440 + struct func_map map; 441 + }; 442 + 443 + /** 444 + * pevent_set_function_resolver - set an alternative function resolver 445 + * @pevent: handle for the pevent 446 + * @resolver: function to be used 447 + * @priv: resolver function private state. 448 + * 449 + * Some tools may have already a way to resolve kernel functions, allow them to 450 + * keep using it instead of duplicating all the entries inside 451 + * pevent->funclist. 452 + */ 453 + int pevent_set_function_resolver(struct pevent *pevent, 454 + pevent_func_resolver_t *func, void *priv) 455 + { 456 + struct func_resolver *resolver = malloc(sizeof(*resolver)); 457 + 458 + if (resolver == NULL) 459 + return -1; 460 + 461 + resolver->func = func; 462 + resolver->priv = priv; 463 + 464 + free(pevent->func_resolver); 465 + pevent->func_resolver = resolver; 466 + 467 + return 0; 468 + } 469 + 470 + /** 471 + * pevent_reset_function_resolver - reset alternative function resolver 472 + * @pevent: handle for the pevent 473 + * 474 + * Stop using whatever alternative resolver was set, use the default 475 + * one instead. 476 + */ 477 + void pevent_reset_function_resolver(struct pevent *pevent) 478 + { 479 + free(pevent->func_resolver); 480 + pevent->func_resolver = NULL; 481 + } 482 + 483 + static struct func_map * 484 + find_func(struct pevent *pevent, unsigned long long addr) 485 + { 486 + struct func_map *map; 487 + 488 + if (!pevent->func_resolver) 489 + return __find_func(pevent, addr); 490 + 491 + map = &pevent->func_resolver->map; 492 + map->mod = NULL; 493 + map->addr = addr; 494 + map->func = pevent->func_resolver->func(pevent->func_resolver->priv, 495 + &map->addr, &map->mod); 496 + if (map->func == NULL) 497 + return NULL; 498 + 499 + return map; 435 500 } 436 501 437 502 /** ··· 6629 6564 free(pevent->trace_clock); 6630 6565 free(pevent->events); 6631 6566 free(pevent->sort_events); 6567 + free(pevent->func_resolver); 6632 6568 6633 6569 free(pevent); 6634 6570 }
+8
tools/lib/traceevent/event-parse.h
··· 453 453 struct func_map; 454 454 struct func_list; 455 455 struct event_handler; 456 + struct func_resolver; 457 + 458 + typedef char *(pevent_func_resolver_t)(void *priv, 459 + unsigned long long *addrp, char **modp); 456 460 457 461 struct pevent { 458 462 int ref_count; ··· 485 481 int cmdline_count; 486 482 487 483 struct func_map *func_map; 484 + struct func_resolver *func_resolver; 488 485 struct func_list *funclist; 489 486 unsigned int func_count; 490 487 ··· 616 611 TRACE_FLAG_SOFTIRQ = 0x10, 617 612 }; 618 613 614 + int pevent_set_function_resolver(struct pevent *pevent, 615 + pevent_func_resolver_t *func, void *priv); 616 + void pevent_reset_function_resolver(struct pevent *pevent); 619 617 int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 620 618 int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock); 621 619 int pevent_register_function(struct pevent *pevent, char *name,