Commit | Line | Data |
---|---|---|
c34984b2 ACM |
1 | /* |
2 | * builtin-buildid-list.c | |
3 | * | |
4 | * Builtin buildid-list command: list buildids in perf.data | |
5 | * | |
6 | * Copyright (C) 2009, Red Hat Inc. | |
7 | * Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com> | |
8 | */ | |
9 | #include "builtin.h" | |
10 | #include "perf.h" | |
11 | #include "util/cache.h" | |
12 | #include "util/data_map.h" | |
13 | #include "util/debug.h" | |
14 | #include "util/header.h" | |
15 | #include "util/parse-options.h" | |
16 | #include "util/symbol.h" | |
17 | ||
18 | static char const *input_name = "perf.data"; | |
19 | static int force; | |
20 | ||
21 | static const char *const buildid_list_usage[] = { | |
22 | "perf report [<options>]", | |
23 | NULL | |
24 | }; | |
25 | ||
26 | static const struct option options[] = { | |
27 | OPT_STRING('i', "input", &input_name, "file", | |
28 | "input file name"), | |
29 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), | |
30 | OPT_BOOLEAN('v', "verbose", &verbose, | |
31 | "be more verbose (show counter open errors, etc)"), | |
32 | OPT_END() | |
33 | }; | |
34 | ||
35 | static int perf_file_section__process_buildids(struct perf_file_section *self, | |
36 | int feat, int fd) | |
37 | { | |
38 | if (feat != HEADER_BUILD_ID) | |
39 | return 0; | |
40 | ||
41 | if (lseek(fd, self->offset, SEEK_SET) < 0) { | |
42 | pr_warning("Failed to lseek to %Ld offset for buildids!\n", | |
43 | self->offset); | |
44 | return -1; | |
45 | } | |
46 | ||
47 | if (perf_header__read_build_ids(fd, self->offset, self->size)) { | |
48 | pr_warning("Failed to read buildids!\n"); | |
49 | return -1; | |
50 | } | |
51 | ||
52 | return 0; | |
53 | } | |
54 | ||
55 | static int __cmd_buildid_list(void) | |
56 | { | |
57 | int err = -1; | |
58 | struct perf_header *header; | |
59 | struct perf_file_header f_header; | |
60 | struct stat input_stat; | |
61 | int input = open(input_name, O_RDONLY); | |
62 | ||
63 | if (input < 0) { | |
64 | pr_err("failed to open file: %s", input_name); | |
65 | if (!strcmp(input_name, "perf.data")) | |
66 | pr_err(" (try 'perf record' first)"); | |
67 | pr_err("\n"); | |
68 | goto out; | |
69 | } | |
70 | ||
71 | err = fstat(input, &input_stat); | |
72 | if (err < 0) { | |
73 | perror("failed to stat file"); | |
74 | goto out_close; | |
75 | } | |
76 | ||
77 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { | |
78 | pr_err("file %s not owned by current user or root\n", | |
79 | input_name); | |
80 | goto out_close; | |
81 | } | |
82 | ||
83 | if (!input_stat.st_size) { | |
84 | pr_info("zero-sized file, nothing to do!\n"); | |
85 | goto out_close; | |
86 | } | |
87 | ||
88 | err = -1; | |
89 | header = perf_header__new(); | |
90 | if (header == NULL) | |
91 | goto out_close; | |
92 | ||
93 | if (perf_file_header__read(&f_header, header, input) < 0) { | |
94 | pr_warning("incompatible file format"); | |
95 | goto out_close; | |
96 | } | |
97 | ||
98 | err = perf_header__process_sections(header, input, | |
99 | perf_file_section__process_buildids); | |
100 | ||
101 | if (err < 0) | |
102 | goto out_close; | |
103 | ||
104 | dsos__fprintf_buildid(stdout); | |
105 | out_close: | |
106 | close(input); | |
107 | out: | |
108 | return err; | |
109 | } | |
110 | ||
111 | int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) | |
112 | { | |
113 | argc = parse_options(argc, argv, options, buildid_list_usage, 0); | |
114 | setup_pager(); | |
115 | return __cmd_buildid_list(); | |
116 | } |