0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "builtin.h"
0011 #include "perf.h"
0012 #include "util/build-id.h"
0013 #include "util/debug.h"
0014 #include "util/dso.h"
0015 #include "util/map.h"
0016 #include <subcmd/pager.h>
0017 #include <subcmd/parse-options.h>
0018 #include "util/session.h"
0019 #include "util/symbol.h"
0020 #include "util/data.h"
0021 #include <errno.h>
0022 #include <inttypes.h>
0023 #include <linux/err.h>
0024
0025 static int buildid__map_cb(struct map *map, void *arg __maybe_unused)
0026 {
0027 const struct dso *dso = map->dso;
0028 char bid_buf[SBUILD_ID_SIZE];
0029
0030 memset(bid_buf, 0, sizeof(bid_buf));
0031 if (dso->has_build_id)
0032 build_id__sprintf(&dso->bid, bid_buf);
0033 printf("%s %16" PRIx64 " %16" PRIx64, bid_buf, map->start, map->end);
0034 if (dso->long_name != NULL) {
0035 printf(" %s", dso->long_name);
0036 } else if (dso->short_name != NULL) {
0037 printf(" %s", dso->short_name);
0038 }
0039 printf("\n");
0040
0041 return 0;
0042 }
0043
0044 static void buildid__show_kernel_maps(void)
0045 {
0046 struct machine *machine;
0047
0048 machine = machine__new_host();
0049 machine__for_each_kernel_map(machine, buildid__map_cb, NULL);
0050 machine__delete(machine);
0051 }
0052
0053 static int sysfs__fprintf_build_id(FILE *fp)
0054 {
0055 char sbuild_id[SBUILD_ID_SIZE];
0056 int ret;
0057
0058 ret = sysfs__sprintf_build_id("/", sbuild_id);
0059 if (ret != sizeof(sbuild_id))
0060 return ret < 0 ? ret : -EINVAL;
0061
0062 return fprintf(fp, "%s\n", sbuild_id);
0063 }
0064
0065 static int filename__fprintf_build_id(const char *name, FILE *fp)
0066 {
0067 char sbuild_id[SBUILD_ID_SIZE];
0068 int ret;
0069
0070 ret = filename__sprintf_build_id(name, sbuild_id);
0071 if (ret != sizeof(sbuild_id))
0072 return ret < 0 ? ret : -EINVAL;
0073
0074 return fprintf(fp, "%s\n", sbuild_id);
0075 }
0076
0077 static bool dso__skip_buildid(struct dso *dso, int with_hits)
0078 {
0079 return with_hits && !dso->hit;
0080 }
0081
0082 static int perf_session__list_build_ids(bool force, bool with_hits)
0083 {
0084 struct perf_session *session;
0085 struct perf_data data = {
0086 .path = input_name,
0087 .mode = PERF_DATA_MODE_READ,
0088 .force = force,
0089 };
0090
0091 symbol__elf_init();
0092
0093
0094
0095 if (filename__fprintf_build_id(input_name, stdout) > 0)
0096 goto out;
0097
0098 session = perf_session__new(&data, &build_id__mark_dso_hit_ops);
0099 if (IS_ERR(session))
0100 return PTR_ERR(session);
0101
0102
0103
0104
0105
0106 if (!perf_data__is_pipe(&data) &&
0107 perf_header__has_feat(&session->header, HEADER_AUXTRACE))
0108 with_hits = false;
0109
0110 if (!perf_header__has_feat(&session->header, HEADER_BUILD_ID))
0111 with_hits = true;
0112
0113 if (zstd_init(&(session->zstd_data), 0) < 0)
0114 pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
0115
0116
0117
0118
0119
0120 if (with_hits || perf_data__is_pipe(&data))
0121 perf_session__process_events(session);
0122
0123 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
0124 perf_session__delete(session);
0125 out:
0126 return 0;
0127 }
0128
0129 int cmd_buildid_list(int argc, const char **argv)
0130 {
0131 bool show_kernel = false;
0132 bool show_kernel_maps = false;
0133 bool with_hits = false;
0134 bool force = false;
0135 const struct option options[] = {
0136 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
0137 OPT_STRING('i', "input", &input_name, "file", "input file name"),
0138 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
0139 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
0140 OPT_BOOLEAN('m', "kernel-maps", &show_kernel_maps,
0141 "Show build id of current kernel + modules"),
0142 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
0143 OPT_END()
0144 };
0145 const char * const buildid_list_usage[] = {
0146 "perf buildid-list [<options>]",
0147 NULL
0148 };
0149
0150 argc = parse_options(argc, argv, options, buildid_list_usage, 0);
0151 setup_pager();
0152
0153 if (show_kernel) {
0154 return !(sysfs__fprintf_build_id(stdout) > 0);
0155 } else if (show_kernel_maps) {
0156 buildid__show_kernel_maps();
0157 return 0;
0158 }
0159
0160 return perf_session__list_build_ids(force, with_hits);
0161 }