xref: /linux/tools/perf/builtin-buildid-list.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
1c34984b2SArnaldo Carvalho de Melo /*
2c34984b2SArnaldo Carvalho de Melo  * builtin-buildid-list.c
3c34984b2SArnaldo Carvalho de Melo  *
47a6f205dSArnaldo Carvalho de Melo  * Builtin buildid-list command: list buildids in perf.data, in the running
57a6f205dSArnaldo Carvalho de Melo  * kernel and in ELF files.
6c34984b2SArnaldo Carvalho de Melo  *
7c34984b2SArnaldo Carvalho de Melo  * Copyright (C) 2009, Red Hat Inc.
8c34984b2SArnaldo Carvalho de Melo  * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com>
9c34984b2SArnaldo Carvalho de Melo  */
10c34984b2SArnaldo Carvalho de Melo #include "builtin.h"
117b2567c1SArnaldo Carvalho de Melo #include "util/build-id.h"
12c34984b2SArnaldo Carvalho de Melo #include "util/debug.h"
134a3cec84SArnaldo Carvalho de Melo #include "util/dso.h"
14a6bd98c4SBlake Jones #include "util/map.h"
15fa0d9846SArnaldo Carvalho de Melo #include <subcmd/pager.h>
164b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1794c744b6SArnaldo Carvalho de Melo #include "util/session.h"
18c34984b2SArnaldo Carvalho de Melo #include "util/symbol.h"
19f5fc1412SJiri Olsa #include "util/data.h"
20f12ad272SIan Rogers #include "util/util.h"
21a43783aeSArnaldo Carvalho de Melo #include <errno.h>
22a6bd98c4SBlake Jones #include <inttypes.h>
236ef81c55SMamatha Inamdar #include <linux/err.h>
24c34984b2SArnaldo Carvalho de Melo 
25a6bd98c4SBlake Jones static int buildid__map_cb(struct map *map, void *arg __maybe_unused)
26a6bd98c4SBlake Jones {
2763df0e4bSIan Rogers 	const struct dso *dso = map__dso(map);
28a6bd98c4SBlake Jones 	char bid_buf[SBUILD_ID_SIZE];
29*ee756ef7SIan Rogers 	const char *dso_long_name = dso__long_name(dso);
30*ee756ef7SIan Rogers 	const char *dso_short_name = dso__short_name(dso);
31a6bd98c4SBlake Jones 
32a6bd98c4SBlake Jones 	memset(bid_buf, 0, sizeof(bid_buf));
33*ee756ef7SIan Rogers 	if (dso__has_build_id(dso))
34*ee756ef7SIan Rogers 		build_id__sprintf(dso__bid_const(dso), bid_buf);
35e5116f46SIan Rogers 	printf("%s %16" PRIx64 " %16" PRIx64, bid_buf, map__start(map), map__end(map));
36*ee756ef7SIan Rogers 	if (dso_long_name != NULL)
37*ee756ef7SIan Rogers 		printf(" %s", dso_long_name);
38*ee756ef7SIan Rogers 	else if (dso_short_name != NULL)
39*ee756ef7SIan Rogers 		printf(" %s", dso_short_name);
40*ee756ef7SIan Rogers 
41a6bd98c4SBlake Jones 	printf("\n");
42a6bd98c4SBlake Jones 
43a6bd98c4SBlake Jones 	return 0;
44a6bd98c4SBlake Jones }
45a6bd98c4SBlake Jones 
46a6bd98c4SBlake Jones static void buildid__show_kernel_maps(void)
47a6bd98c4SBlake Jones {
48a6bd98c4SBlake Jones 	struct machine *machine;
49a6bd98c4SBlake Jones 
50a6bd98c4SBlake Jones 	machine = machine__new_host();
51a6bd98c4SBlake Jones 	machine__for_each_kernel_map(machine, buildid__map_cb, NULL);
52a6bd98c4SBlake Jones 	machine__delete(machine);
53a6bd98c4SBlake Jones }
54a6bd98c4SBlake Jones 
55f2add9cdSArnaldo Carvalho de Melo static int sysfs__fprintf_build_id(FILE *fp)
56f2add9cdSArnaldo Carvalho de Melo {
57d77fac7fSMasami Hiramatsu 	char sbuild_id[SBUILD_ID_SIZE];
580b5a7935SMasami Hiramatsu 	int ret;
59f2add9cdSArnaldo Carvalho de Melo 
600b5a7935SMasami Hiramatsu 	ret = sysfs__sprintf_build_id("/", sbuild_id);
610b5a7935SMasami Hiramatsu 	if (ret != sizeof(sbuild_id))
620b5a7935SMasami Hiramatsu 		return ret < 0 ? ret : -EINVAL;
63f2add9cdSArnaldo Carvalho de Melo 
640b5a7935SMasami Hiramatsu 	return fprintf(fp, "%s\n", sbuild_id);
65f2add9cdSArnaldo Carvalho de Melo }
66f2add9cdSArnaldo Carvalho de Melo 
677a6f205dSArnaldo Carvalho de Melo static int filename__fprintf_build_id(const char *name, FILE *fp)
687a6f205dSArnaldo Carvalho de Melo {
69d77fac7fSMasami Hiramatsu 	char sbuild_id[SBUILD_ID_SIZE];
700b5a7935SMasami Hiramatsu 	int ret;
717a6f205dSArnaldo Carvalho de Melo 
720b5a7935SMasami Hiramatsu 	ret = filename__sprintf_build_id(name, sbuild_id);
730b5a7935SMasami Hiramatsu 	if (ret != sizeof(sbuild_id))
740b5a7935SMasami Hiramatsu 		return ret < 0 ? ret : -EINVAL;
757a6f205dSArnaldo Carvalho de Melo 
767a6f205dSArnaldo Carvalho de Melo 	return fprintf(fp, "%s\n", sbuild_id);
777a6f205dSArnaldo Carvalho de Melo }
787a6f205dSArnaldo Carvalho de Melo 
79417c2ff6SArnaldo Carvalho de Melo static bool dso__skip_buildid(struct dso *dso, int with_hits)
80417c2ff6SArnaldo Carvalho de Melo {
81*ee756ef7SIan Rogers 	return with_hits && !dso__hit(dso);
82417c2ff6SArnaldo Carvalho de Melo }
83417c2ff6SArnaldo Carvalho de Melo 
8470cb4e96SFeng Tang static int perf_session__list_build_ids(bool force, bool with_hits)
851b549504SRobert Richter {
861b549504SRobert Richter 	struct perf_session *session;
878ceb41d7SJiri Olsa 	struct perf_data data = {
88f5fc1412SJiri Olsa 		.path  = input_name,
89f5fc1412SJiri Olsa 		.mode  = PERF_DATA_MODE_READ,
90f5fc1412SJiri Olsa 		.force = force,
91f5fc1412SJiri Olsa 	};
921b549504SRobert Richter 
93166ccc9cSNamhyung Kim 	symbol__elf_init();
94f0bf9107SArnaldo Carvalho de Melo 	/*
95f0bf9107SArnaldo Carvalho de Melo 	 * See if this is an ELF file first:
96f0bf9107SArnaldo Carvalho de Melo 	 */
970b5a7935SMasami Hiramatsu 	if (filename__fprintf_build_id(input_name, stdout) > 0)
98f0bf9107SArnaldo Carvalho de Melo 		goto out;
99efad1415SRobert Richter 
1002681bd85SNamhyung Kim 	session = perf_session__new(&data, &build_id__mark_dso_hit_ops);
1016ef81c55SMamatha Inamdar 	if (IS_ERR(session))
1026ef81c55SMamatha Inamdar 		return PTR_ERR(session);
103cd10b289SAdrian Hunter 
104cd10b289SAdrian Hunter 	/*
105cd10b289SAdrian Hunter 	 * We take all buildids when the file contains AUX area tracing data
106cd10b289SAdrian Hunter 	 * because we do not decode the trace because it would take too long.
107cd10b289SAdrian Hunter 	 */
1088ceb41d7SJiri Olsa 	if (!perf_data__is_pipe(&data) &&
109cd10b289SAdrian Hunter 	    perf_header__has_feat(&session->header, HEADER_AUXTRACE))
110cd10b289SAdrian Hunter 		with_hits = false;
111cd10b289SAdrian Hunter 
112d176db95SJiri Olsa 	if (!perf_header__has_feat(&session->header, HEADER_BUILD_ID))
113d176db95SJiri Olsa 		with_hits = true;
114d176db95SJiri Olsa 
115c67d7349SMilian Wolff 	if (zstd_init(&(session->zstd_data), 0) < 0)
116c67d7349SMilian Wolff 		pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
117c67d7349SMilian Wolff 
118299c3452SStephane Eranian 	/*
119299c3452SStephane Eranian 	 * in pipe-mode, the only way to get the buildids is to parse
120299c3452SStephane Eranian 	 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
121299c3452SStephane Eranian 	 */
1228ceb41d7SJiri Olsa 	if (with_hits || perf_data__is_pipe(&data))
123b7b61cbeSArnaldo Carvalho de Melo 		perf_session__process_events(session);
1241b549504SRobert Richter 
125417c2ff6SArnaldo Carvalho de Melo 	perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
1261b549504SRobert Richter 	perf_session__delete(session);
127f0bf9107SArnaldo Carvalho de Melo out:
1281b549504SRobert Richter 	return 0;
1291b549504SRobert Richter }
1301b549504SRobert Richter 
131b0ad8ea6SArnaldo Carvalho de Melo int cmd_buildid_list(int argc, const char **argv)
132c34984b2SArnaldo Carvalho de Melo {
1336ee41497SArnaldo Carvalho de Melo 	bool show_kernel = false;
134a6bd98c4SBlake Jones 	bool show_kernel_maps = false;
1356ee41497SArnaldo Carvalho de Melo 	bool with_hits = false;
1366ee41497SArnaldo Carvalho de Melo 	bool force = false;
1376ee41497SArnaldo Carvalho de Melo 	const struct option options[] = {
1386ee41497SArnaldo Carvalho de Melo 	OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
1396ee41497SArnaldo Carvalho de Melo 	OPT_STRING('i', "input", &input_name, "file", "input file name"),
1406ee41497SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1416ee41497SArnaldo Carvalho de Melo 	OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
142a6bd98c4SBlake Jones 	OPT_BOOLEAN('m', "kernel-maps", &show_kernel_maps,
143a6bd98c4SBlake Jones 	    "Show build id of current kernel + modules"),
1446ee41497SArnaldo Carvalho de Melo 	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1456ee41497SArnaldo Carvalho de Melo 	OPT_END()
1466ee41497SArnaldo Carvalho de Melo 	};
1476ee41497SArnaldo Carvalho de Melo 	const char * const buildid_list_usage[] = {
1486ee41497SArnaldo Carvalho de Melo 		"perf buildid-list [<options>]",
1496ee41497SArnaldo Carvalho de Melo 		NULL
1506ee41497SArnaldo Carvalho de Melo 	};
1516ee41497SArnaldo Carvalho de Melo 
152c34984b2SArnaldo Carvalho de Melo 	argc = parse_options(argc, argv, options, buildid_list_usage, 0);
153c34984b2SArnaldo Carvalho de Melo 	setup_pager();
1546ee41497SArnaldo Carvalho de Melo 
155a6bd98c4SBlake Jones 	if (show_kernel) {
156c8319c9dSMichael Petlan 		return !(sysfs__fprintf_build_id(stdout) > 0);
157a6bd98c4SBlake Jones 	} else if (show_kernel_maps) {
158a6bd98c4SBlake Jones 		buildid__show_kernel_maps();
159a6bd98c4SBlake Jones 		return 0;
160a6bd98c4SBlake Jones 	}
1616ee41497SArnaldo Carvalho de Melo 
16270cb4e96SFeng Tang 	return perf_session__list_build_ids(force, with_hits);
163c34984b2SArnaldo Carvalho de Melo }
164