18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * builtin-buildid-list.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Builtin buildid-list command: list buildids in perf.data, in the running
58c2ecf20Sopenharmony_ci * kernel and in ELF files.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (C) 2009, Red Hat Inc.
88c2ecf20Sopenharmony_ci * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#include "builtin.h"
118c2ecf20Sopenharmony_ci#include "perf.h"
128c2ecf20Sopenharmony_ci#include "util/build-id.h"
138c2ecf20Sopenharmony_ci#include "util/debug.h"
148c2ecf20Sopenharmony_ci#include "util/dso.h"
158c2ecf20Sopenharmony_ci#include <subcmd/pager.h>
168c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h>
178c2ecf20Sopenharmony_ci#include "util/session.h"
188c2ecf20Sopenharmony_ci#include "util/symbol.h"
198c2ecf20Sopenharmony_ci#include "util/data.h"
208c2ecf20Sopenharmony_ci#include <errno.h>
218c2ecf20Sopenharmony_ci#include <linux/err.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic int sysfs__fprintf_build_id(FILE *fp)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	char sbuild_id[SBUILD_ID_SIZE];
268c2ecf20Sopenharmony_ci	int ret;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	ret = sysfs__sprintf_build_id("/", sbuild_id);
298c2ecf20Sopenharmony_ci	if (ret != sizeof(sbuild_id))
308c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EINVAL;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	return fprintf(fp, "%s\n", sbuild_id);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int filename__fprintf_build_id(const char *name, FILE *fp)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	char sbuild_id[SBUILD_ID_SIZE];
388c2ecf20Sopenharmony_ci	int ret;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	ret = filename__sprintf_build_id(name, sbuild_id);
418c2ecf20Sopenharmony_ci	if (ret != sizeof(sbuild_id))
428c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EINVAL;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	return fprintf(fp, "%s\n", sbuild_id);
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic bool dso__skip_buildid(struct dso *dso, int with_hits)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	return with_hits && !dso->hit;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic int perf_session__list_build_ids(bool force, bool with_hits)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	struct perf_session *session;
558c2ecf20Sopenharmony_ci	struct perf_data data = {
568c2ecf20Sopenharmony_ci		.path  = input_name,
578c2ecf20Sopenharmony_ci		.mode  = PERF_DATA_MODE_READ,
588c2ecf20Sopenharmony_ci		.force = force,
598c2ecf20Sopenharmony_ci	};
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	symbol__elf_init();
628c2ecf20Sopenharmony_ci	/*
638c2ecf20Sopenharmony_ci	 * See if this is an ELF file first:
648c2ecf20Sopenharmony_ci	 */
658c2ecf20Sopenharmony_ci	if (filename__fprintf_build_id(input_name, stdout) > 0)
668c2ecf20Sopenharmony_ci		goto out;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	session = perf_session__new(&data, false, &build_id__mark_dso_hit_ops);
698c2ecf20Sopenharmony_ci	if (IS_ERR(session))
708c2ecf20Sopenharmony_ci		return PTR_ERR(session);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/*
738c2ecf20Sopenharmony_ci	 * We take all buildids when the file contains AUX area tracing data
748c2ecf20Sopenharmony_ci	 * because we do not decode the trace because it would take too long.
758c2ecf20Sopenharmony_ci	 */
768c2ecf20Sopenharmony_ci	if (!perf_data__is_pipe(&data) &&
778c2ecf20Sopenharmony_ci	    perf_header__has_feat(&session->header, HEADER_AUXTRACE))
788c2ecf20Sopenharmony_ci		with_hits = false;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/*
818c2ecf20Sopenharmony_ci	 * in pipe-mode, the only way to get the buildids is to parse
828c2ecf20Sopenharmony_ci	 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
838c2ecf20Sopenharmony_ci	 */
848c2ecf20Sopenharmony_ci	if (with_hits || perf_data__is_pipe(&data))
858c2ecf20Sopenharmony_ci		perf_session__process_events(session);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
888c2ecf20Sopenharmony_ci	perf_session__delete(session);
898c2ecf20Sopenharmony_ciout:
908c2ecf20Sopenharmony_ci	return 0;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ciint cmd_buildid_list(int argc, const char **argv)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	bool show_kernel = false;
968c2ecf20Sopenharmony_ci	bool with_hits = false;
978c2ecf20Sopenharmony_ci	bool force = false;
988c2ecf20Sopenharmony_ci	const struct option options[] = {
998c2ecf20Sopenharmony_ci	OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
1008c2ecf20Sopenharmony_ci	OPT_STRING('i', "input", &input_name, "file", "input file name"),
1018c2ecf20Sopenharmony_ci	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1028c2ecf20Sopenharmony_ci	OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
1038c2ecf20Sopenharmony_ci	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1048c2ecf20Sopenharmony_ci	OPT_END()
1058c2ecf20Sopenharmony_ci	};
1068c2ecf20Sopenharmony_ci	const char * const buildid_list_usage[] = {
1078c2ecf20Sopenharmony_ci		"perf buildid-list [<options>]",
1088c2ecf20Sopenharmony_ci		NULL
1098c2ecf20Sopenharmony_ci	};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	argc = parse_options(argc, argv, options, buildid_list_usage, 0);
1128c2ecf20Sopenharmony_ci	setup_pager();
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	if (show_kernel)
1158c2ecf20Sopenharmony_ci		return !(sysfs__fprintf_build_id(stdout) > 0);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	return perf_session__list_build_ids(force, with_hits);
1188c2ecf20Sopenharmony_ci}
119