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

Configure Feed

Select the types of activity you want to include in your feed.

perf inject: Add a command line option to specify build ids.

This commit adds the option --known-build-ids to perf inject.
It allows the user to explicitly specify the build id for a given
path, instead of retrieving it from the current system. This is
useful in cases where a perf.data file is processed on a different
system from where it was collected, or if some of the binaries are
no longer available.

The build ids and paths are specified in pairs in the command line.
Using the file:// specifier, build ids can be loaded from a file
directly generated by perf buildid-list. This is convenient to copy
build ids from one perf.data file to another.

** Example: In this example we use perf record to create two
perf.data files, one with build ids and another without, and use
perf buildid-list and perf inject to copy the build ids from the
first file to the second.

$ perf record ls /tmp
$ perf record --no-buildid -o perf.data.no-buildid ls /tmp
$ perf buildid-list > build-ids.txt
$ perf inject -b --known-build-ids='file://build-ids.txt' \
-i perf.data.no-buildid -o perf.data.buildid

Signed-off-by: Raul Silvera <rsilvera@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220815225922.2118745-1-rsilvera@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Raul Silvera and committed by
Arnaldo Carvalho de Melo
8012243e 725737e7

+91 -1
+6 -1
tools/perf/Documentation/perf-inject.txt
··· 27 27 --build-ids:: 28 28 Inject build-ids into the output stream 29 29 30 - --buildid-all: 30 + --buildid-all:: 31 31 Inject build-ids of all DSOs into the output stream 32 + 33 + --known-build-ids=:: 34 + Override build-ids to inject using these comma-separated pairs of 35 + build-id and path. Understands file://filename to read these pairs 36 + from a file, which can be generated with perf buildid-list. 32 37 33 38 -v:: 34 39 --verbose::
+85
tools/perf/builtin-inject.c
··· 21 21 #include "util/data.h" 22 22 #include "util/auxtrace.h" 23 23 #include "util/jit.h" 24 + #include "util/string2.h" 24 25 #include "util/symbol.h" 25 26 #include "util/synthetic-events.h" 26 27 #include "util/thread.h" ··· 39 38 #include <linux/string.h> 40 39 #include <linux/zalloc.h> 41 40 #include <linux/hash.h> 41 + #include <ctype.h> 42 42 #include <errno.h> 43 43 #include <signal.h> 44 44 #include <inttypes.h> ··· 125 123 char event_copy[PERF_SAMPLE_MAX_SIZE]; 126 124 struct perf_file_section secs[HEADER_FEAT_BITS]; 127 125 struct guest_session guest_session; 126 + struct strlist *known_build_ids; 128 127 }; 129 128 130 129 struct event_entry { ··· 637 634 return dso->has_build_id ? 0 : -1; 638 635 } 639 636 637 + static struct strlist *perf_inject__parse_known_build_ids( 638 + const char *known_build_ids_string) 639 + { 640 + struct str_node *pos, *tmp; 641 + struct strlist *known_build_ids; 642 + int bid_len; 643 + 644 + known_build_ids = strlist__new(known_build_ids_string, NULL); 645 + if (known_build_ids == NULL) 646 + return NULL; 647 + strlist__for_each_entry_safe(pos, tmp, known_build_ids) { 648 + const char *build_id, *dso_name; 649 + 650 + build_id = skip_spaces(pos->s); 651 + dso_name = strchr(build_id, ' '); 652 + if (dso_name == NULL) { 653 + strlist__remove(known_build_ids, pos); 654 + continue; 655 + } 656 + bid_len = dso_name - pos->s; 657 + dso_name = skip_spaces(dso_name); 658 + if (bid_len % 2 != 0 || bid_len >= SBUILD_ID_SIZE) { 659 + strlist__remove(known_build_ids, pos); 660 + continue; 661 + } 662 + for (int ix = 0; 2 * ix + 1 < bid_len; ++ix) { 663 + if (!isxdigit(build_id[2 * ix]) || 664 + !isxdigit(build_id[2 * ix + 1])) { 665 + strlist__remove(known_build_ids, pos); 666 + break; 667 + } 668 + } 669 + } 670 + return known_build_ids; 671 + } 672 + 673 + static bool perf_inject__lookup_known_build_id(struct perf_inject *inject, 674 + struct dso *dso) 675 + { 676 + struct str_node *pos; 677 + int bid_len; 678 + 679 + strlist__for_each_entry(pos, inject->known_build_ids) { 680 + const char *build_id, *dso_name; 681 + 682 + build_id = skip_spaces(pos->s); 683 + dso_name = strchr(build_id, ' '); 684 + bid_len = dso_name - pos->s; 685 + dso_name = skip_spaces(dso_name); 686 + if (strcmp(dso->long_name, dso_name)) 687 + continue; 688 + for (int ix = 0; 2 * ix + 1 < bid_len; ++ix) { 689 + dso->bid.data[ix] = (hex(build_id[2 * ix]) << 4 | 690 + hex(build_id[2 * ix + 1])); 691 + } 692 + dso->bid.size = bid_len / 2; 693 + dso->has_build_id = 1; 694 + return true; 695 + } 696 + return false; 697 + } 698 + 640 699 static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, 641 700 struct machine *machine, u8 cpumode, u32 flags) 642 701 { 702 + struct perf_inject *inject = container_of(tool, struct perf_inject, 703 + tool); 643 704 int err; 644 705 645 706 if (is_anon_memory(dso->long_name) || flags & MAP_HUGETLB) 646 707 return 0; 647 708 if (is_no_dso_memory(dso->long_name)) 648 709 return 0; 710 + 711 + if (inject->known_build_ids != NULL && 712 + perf_inject__lookup_known_build_id(inject, dso)) 713 + return 1; 649 714 650 715 if (dso__read_build_id(dso) < 0) { 651 716 pr_debug("no build_id found for %s\n", dso->long_name); ··· 2183 2112 }; 2184 2113 int ret; 2185 2114 bool repipe = true; 2115 + const char *known_build_ids = NULL; 2186 2116 2187 2117 struct option options[] = { 2188 2118 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 2189 2119 "Inject build-ids into the output stream"), 2190 2120 OPT_BOOLEAN(0, "buildid-all", &inject.build_id_all, 2191 2121 "Inject build-ids of all DSOs into the output stream"), 2122 + OPT_STRING(0, "known-build-ids", &known_build_ids, 2123 + "buildid path [,buildid path...]", 2124 + "build-ids to use for given paths"), 2192 2125 OPT_STRING('i', "input", &inject.input_name, "file", 2193 2126 "input file name"), 2194 2127 OPT_STRING('o', "output", &inject.output.path, "file", ··· 2332 2257 */ 2333 2258 inject.tool.ordered_events = true; 2334 2259 inject.tool.ordering_requires_timestamps = true; 2260 + if (known_build_ids != NULL) { 2261 + inject.known_build_ids = 2262 + perf_inject__parse_known_build_ids(known_build_ids); 2263 + 2264 + if (inject.known_build_ids == NULL) { 2265 + pr_err("Couldn't parse known build ids.\n"); 2266 + goto out_delete; 2267 + } 2268 + } 2335 2269 } 2336 2270 2337 2271 if (inject.sched_stat) { ··· 2369 2285 guest_session__exit(&inject.guest_session); 2370 2286 2371 2287 out_delete: 2288 + strlist__delete(inject.known_build_ids); 2372 2289 zstd_fini(&(inject.session->zstd_data)); 2373 2290 perf_session__delete(inject.session); 2374 2291 out_close_output: