From nobody Mon Apr 13 11:48:06 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0DAEC19F2C for ; Tue, 16 Aug 2022 05:53:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231159AbiHPFxo (ORCPT ); Tue, 16 Aug 2022 01:53:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53464 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230480AbiHPFx0 (ORCPT ); Tue, 16 Aug 2022 01:53:26 -0400 Received: from mail-io1-xd4a.google.com (mail-io1-xd4a.google.com [IPv6:2607:f8b0:4864:20::d4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E2DD375FD5 for ; Mon, 15 Aug 2022 15:59:40 -0700 (PDT) Received: by mail-io1-xd4a.google.com with SMTP id k22-20020a6bf716000000b0068898c0b395so975671iog.3 for ; Mon, 15 Aug 2022 15:59:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:mime-version:message-id:date:from:to:cc; bh=qjxTwNs46mBErQ+98eCyfxk5QZmIEb2cOA8EBrFu9oc=; b=tWMtvPeknQYFBSL7spt7SaiV96nFguiXlCt/bQ7nMaSfG0Ja6ya07XtqMamEMvhd1W 4bSb8u8+o/lu8KhKDgL81BN8gcBFGQCbuW4AKcGObZznNTP8Myhij12FwXjx63XmzpVv UO5s0LWwv0gezIKQ4fMMdr1H7nGxLd1Idz+jwZbwXlLlIeGGN40yAffJjtUZLXvyJuDq UouPrm2CJArWx3SxGMKo64k/QuDSC1DRp9YXUNc5B+gMH2fusgPg9+iuMHz4SUW+cOLi tE8xZsxM4ZXJM2hEROEE9SQuFD9JQa+eflvKrMNcZSI05x8Rkmo77Tqlsdn+Z2Em9b1N ZRRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:mime-version:message-id:date:x-gm-message-state :from:to:cc; bh=qjxTwNs46mBErQ+98eCyfxk5QZmIEb2cOA8EBrFu9oc=; b=0brMCCCvehY7nSJX+xtL3wmLaMCQ42P1neZiqmqc9AUPh/RZzZzzSezOjg5oTBEbjC Vq5/F1GVmO4eGAfu6p5z7BtuzhZNWbw8msjFgMJEvYZMlpD7He7rdJNl8qIYW7qmJea2 XdmGWI5aA7UKcFcNmrSlVA4inQwdZGm4VqxACHkSUJY/mxz98d46bkLd/VVL6VdIUpMy EH//SVTahRMAjEkFEQ6KP8Ls3Gg3luY6GpholcPpkmKH4Veu9rbKcldXHzssuHqLZfFr aW87qpoEnWBhw/qaE9wCWXtr6yhAyDkso+NftPUCxHj5kqkveaHMbr570kRbzArp2DJF /zwQ== X-Gm-Message-State: ACgBeo3Xhv8H+puiQJRUsie1ntqrcTkbG/ye5VCcXf7iD6E1B5wlJteU WMPs/6QmjBIEU1TdrrfBo2qKbai3Eiy2PQ== X-Google-Smtp-Source: AA6agR43YtkaciFxA5o18koQqVw4sEaVs9oQNrp2PsIfD5FgZeY7kwnbEQ2XUNzLjISkxrXBhtslS3mC6VvyoQ== X-Received: from riochico.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:b3e]) (user=rsilvera job=sendgmr) by 2002:a92:9506:0:b0:2e0:ed70:ea7d with SMTP id y6-20020a929506000000b002e0ed70ea7dmr8114959ilh.207.1660604380104; Mon, 15 Aug 2022 15:59:40 -0700 (PDT) Date: Mon, 15 Aug 2022 22:59:22 +0000 Message-Id: <20220815225922.2118745-1-rsilvera@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.37.1.595.g718a3a8f04-goog Subject: [PATCH v4] perf inject: Add a command line option to specify build ids. From: Raul Silvera To: Namhyung Kim , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa Cc: Adrian Hunter , James Clark , Raul Silvera , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=3D'file://build-ids.txt' \ -i perf.data.no-buildid -o perf.data.buildid Signed-off-by: Raul Silvera Acked-by: Namhyung Kim --- V3 -> V4: Perform upfront validation of build ids V2 -> V3: Added documentation and removed unnecessary temps V1 -> V2: Cleaned up patch description, deleted the strlist during cleanup, and updated validation of the build id strings =20 tools/perf/Documentation/perf-inject.txt | 7 +- tools/perf/builtin-inject.c | 85 ++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Document= ation/perf-inject.txt index ffc293fdf61d..70e2ac3cc91a 100644 --- a/tools/perf/Documentation/perf-inject.txt +++ b/tools/perf/Documentation/perf-inject.txt @@ -27,9 +27,14 @@ OPTIONS --build-ids:: Inject build-ids into the output stream =20 ---buildid-all: +--buildid-all:: Inject build-ids of all DSOs into the output stream =20 +--known-build-ids=3D:: + Override build-ids to inject using these comma-separated pairs of + build-id and path. Understands file://filename to read these pairs + from a file, which can be generated with perf buildid-list. + -v:: --verbose:: Be more verbose. diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 2a0f992ca0be..8ec955402488 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -21,6 +21,7 @@ #include "util/data.h" #include "util/auxtrace.h" #include "util/jit.h" +#include "util/string2.h" #include "util/symbol.h" #include "util/synthetic-events.h" #include "util/thread.h" @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +125,7 @@ struct perf_inject { char event_copy[PERF_SAMPLE_MAX_SIZE]; struct perf_file_section secs[HEADER_FEAT_BITS]; struct guest_session guest_session; + struct strlist *known_build_ids; }; =20 struct event_entry { @@ -634,9 +637,73 @@ static int dso__read_build_id(struct dso *dso) return dso->has_build_id ? 0 : -1; } =20 +static struct strlist *perf_inject__parse_known_build_ids( + const char *known_build_ids_string) +{ + struct str_node *pos, *tmp; + struct strlist *known_build_ids; + int bid_len; + + known_build_ids =3D strlist__new(known_build_ids_string, NULL); + if (known_build_ids =3D=3D NULL) + return NULL; + strlist__for_each_entry_safe(pos, tmp, known_build_ids) { + const char *build_id, *dso_name; + + build_id =3D skip_spaces(pos->s); + dso_name =3D strchr(build_id, ' '); + if (dso_name =3D=3D NULL) { + strlist__remove(known_build_ids, pos); + continue; + } + bid_len =3D dso_name - pos->s; + dso_name =3D skip_spaces(dso_name); + if (bid_len % 2 !=3D 0 || bid_len >=3D SBUILD_ID_SIZE) { + strlist__remove(known_build_ids, pos); + continue; + } + for (int ix =3D 0; 2 * ix + 1 < bid_len; ++ix) { + if (!isxdigit(build_id[2 * ix]) || + !isxdigit(build_id[2 * ix + 1])) { + strlist__remove(known_build_ids, pos); + break; + } + } + } + return known_build_ids; +} + +static bool perf_inject__lookup_known_build_id(struct perf_inject *inject, + struct dso *dso) +{ + struct str_node *pos; + int bid_len; + + strlist__for_each_entry(pos, inject->known_build_ids) { + const char *build_id, *dso_name; + + build_id =3D skip_spaces(pos->s); + dso_name =3D strchr(build_id, ' '); + bid_len =3D dso_name - pos->s; + dso_name =3D skip_spaces(dso_name); + if (strcmp(dso->long_name, dso_name)) + continue; + for (int ix =3D 0; 2 * ix + 1 < bid_len; ++ix) { + dso->bid.data[ix] =3D (hex(build_id[2 * ix]) << 4 | + hex(build_id[2 * ix + 1])); + } + dso->bid.size =3D bid_len / 2; + dso->has_build_id =3D 1; + return true; + } + return false; +} + static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool, struct machine *machine, u8 cpumode, u32 flags) { + struct perf_inject *inject =3D container_of(tool, struct perf_inject, + tool); int err; =20 if (is_anon_memory(dso->long_name) || flags & MAP_HUGETLB) @@ -644,6 +711,10 @@ static int dso__inject_build_id(struct dso *dso, struc= t perf_tool *tool, if (is_no_dso_memory(dso->long_name)) return 0; =20 + if (inject->known_build_ids !=3D NULL && + perf_inject__lookup_known_build_id(inject, dso)) + return 1; + if (dso__read_build_id(dso) < 0) { pr_debug("no build_id found for %s\n", dso->long_name); return -1; @@ -2112,12 +2183,16 @@ int cmd_inject(int argc, const char **argv) }; int ret; bool repipe =3D true; + const char *known_build_ids =3D NULL; =20 struct option options[] =3D { OPT_BOOLEAN('b', "build-ids", &inject.build_ids, "Inject build-ids into the output stream"), OPT_BOOLEAN(0, "buildid-all", &inject.build_id_all, "Inject build-ids of all DSOs into the output stream"), + OPT_STRING(0, "known-build-ids", &known_build_ids, + "buildid path [,buildid path...]", + "build-ids to use for given paths"), OPT_STRING('i', "input", &inject.input_name, "file", "input file name"), OPT_STRING('o', "output", &inject.output.path, "file", @@ -2257,6 +2332,15 @@ int cmd_inject(int argc, const char **argv) */ inject.tool.ordered_events =3D true; inject.tool.ordering_requires_timestamps =3D true; + if (known_build_ids !=3D NULL) { + inject.known_build_ids =3D + perf_inject__parse_known_build_ids(known_build_ids); + + if (inject.known_build_ids =3D=3D NULL) { + pr_err("Couldn't parse known build ids.\n"); + goto out_delete; + } + } } =20 if (inject.sched_stat) { @@ -2285,6 +2369,7 @@ int cmd_inject(int argc, const char **argv) guest_session__exit(&inject.guest_session); =20 out_delete: + strlist__delete(inject.known_build_ids); zstd_fini(&(inject.session->zstd_data)); perf_session__delete(inject.session); out_close_output: --=20 2.37.1.595.g718a3a8f04-goog