diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/data_map.c | 71 | ||||
-rw-r--r-- | tools/perf/util/data_map.h | 9 | ||||
-rw-r--r-- | tools/perf/util/header.c | 28 | ||||
-rw-r--r-- | tools/perf/util/header.h | 4 | ||||
-rw-r--r-- | tools/perf/util/session.c | 80 | ||||
-rw-r--r-- | tools/perf/util/session.h | 16 |
6 files changed, 118 insertions, 90 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index 59b65d0bd7c1..6d46dda53a29 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c | |||
@@ -129,23 +129,16 @@ out: | |||
129 | return err; | 129 | return err; |
130 | } | 130 | } |
131 | 131 | ||
132 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 132 | int perf_session__process_events(struct perf_session *self, |
133 | const char *input_name, | 133 | int full_paths, int *cwdlen, char **cwd) |
134 | int force, | ||
135 | int full_paths, | ||
136 | int *cwdlen, | ||
137 | char **cwd) | ||
138 | { | 134 | { |
139 | int err; | 135 | int err; |
140 | struct perf_header *header; | ||
141 | unsigned long head, shift; | 136 | unsigned long head, shift; |
142 | unsigned long offset = 0; | 137 | unsigned long offset = 0; |
143 | struct stat input_stat; | ||
144 | size_t page_size; | 138 | size_t page_size; |
145 | u64 sample_type; | 139 | u64 sample_type; |
146 | event_t *event; | 140 | event_t *event; |
147 | uint32_t size; | 141 | uint32_t size; |
148 | int input; | ||
149 | char *buf; | 142 | char *buf; |
150 | 143 | ||
151 | if (curr_handler == NULL) { | 144 | if (curr_handler == NULL) { |
@@ -155,56 +148,19 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, | |||
155 | 148 | ||
156 | page_size = getpagesize(); | 149 | page_size = getpagesize(); |
157 | 150 | ||
158 | input = open(input_name, O_RDONLY); | 151 | head = self->header.data_offset; |
159 | if (input < 0) { | 152 | sample_type = perf_header__sample_type(&self->header); |
160 | pr_err("Failed to open file: %s", input_name); | ||
161 | if (!strcmp(input_name, "perf.data")) | ||
162 | pr_err(" (try 'perf record' first)"); | ||
163 | pr_err("\n"); | ||
164 | return -errno; | ||
165 | } | ||
166 | |||
167 | if (fstat(input, &input_stat) < 0) { | ||
168 | pr_err("failed to stat file"); | ||
169 | err = -errno; | ||
170 | goto out_close; | ||
171 | } | ||
172 | |||
173 | err = -EACCES; | ||
174 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { | ||
175 | pr_err("file: %s not owned by current user or root\n", | ||
176 | input_name); | ||
177 | goto out_close; | ||
178 | } | ||
179 | |||
180 | if (input_stat.st_size == 0) { | ||
181 | pr_info("zero-sized file, nothing to do!\n"); | ||
182 | goto done; | ||
183 | } | ||
184 | |||
185 | err = -ENOMEM; | ||
186 | header = perf_header__new(); | ||
187 | if (header == NULL) | ||
188 | goto out_close; | ||
189 | |||
190 | err = perf_header__read(header, input); | ||
191 | if (err < 0) | ||
192 | goto out_delete; | ||
193 | *pheader = header; | ||
194 | head = header->data_offset; | ||
195 | |||
196 | sample_type = perf_header__sample_type(header); | ||
197 | 153 | ||
198 | err = -EINVAL; | 154 | err = -EINVAL; |
199 | if (curr_handler->sample_type_check && | 155 | if (curr_handler->sample_type_check && |
200 | curr_handler->sample_type_check(sample_type) < 0) | 156 | curr_handler->sample_type_check(sample_type) < 0) |
201 | goto out_delete; | 157 | goto out_err; |
202 | 158 | ||
203 | if (!full_paths) { | 159 | if (!full_paths) { |
204 | if (getcwd(__cwd, sizeof(__cwd)) == NULL) { | 160 | if (getcwd(__cwd, sizeof(__cwd)) == NULL) { |
205 | pr_err("failed to get the current directory\n"); | 161 | pr_err("failed to get the current directory\n"); |
206 | err = -errno; | 162 | err = -errno; |
207 | goto out_delete; | 163 | goto out_err; |
208 | } | 164 | } |
209 | *cwd = __cwd; | 165 | *cwd = __cwd; |
210 | *cwdlen = strlen(*cwd); | 166 | *cwdlen = strlen(*cwd); |
@@ -219,11 +175,11 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, | |||
219 | 175 | ||
220 | remap: | 176 | remap: |
221 | buf = mmap(NULL, page_size * mmap_window, PROT_READ, | 177 | buf = mmap(NULL, page_size * mmap_window, PROT_READ, |
222 | MAP_SHARED, input, offset); | 178 | MAP_SHARED, self->fd, offset); |
223 | if (buf == MAP_FAILED) { | 179 | if (buf == MAP_FAILED) { |
224 | pr_err("failed to mmap file\n"); | 180 | pr_err("failed to mmap file\n"); |
225 | err = -errno; | 181 | err = -errno; |
226 | goto out_delete; | 182 | goto out_err; |
227 | } | 183 | } |
228 | 184 | ||
229 | more: | 185 | more: |
@@ -273,19 +229,14 @@ more: | |||
273 | 229 | ||
274 | head += size; | 230 | head += size; |
275 | 231 | ||
276 | if (offset + head >= header->data_offset + header->data_size) | 232 | if (offset + head >= self->header.data_offset + self->header.data_size) |
277 | goto done; | 233 | goto done; |
278 | 234 | ||
279 | if (offset + head < (unsigned long)input_stat.st_size) | 235 | if (offset + head < self->size) |
280 | goto more; | 236 | goto more; |
281 | 237 | ||
282 | done: | 238 | done: |
283 | err = 0; | 239 | err = 0; |
284 | out_close: | 240 | out_err: |
285 | close(input); | ||
286 | |||
287 | return err; | 241 | return err; |
288 | out_delete: | ||
289 | perf_header__delete(header); | ||
290 | goto out_close; | ||
291 | } | 242 | } |
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index 258a87bcc4fb..98c5b823388c 100644 --- a/tools/perf/util/data_map.h +++ b/tools/perf/util/data_map.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include "event.h" | 4 | #include "event.h" |
5 | #include "header.h" | 5 | #include "header.h" |
6 | #include "session.h" | ||
6 | 7 | ||
7 | typedef int (*event_type_handler_t)(event_t *); | 8 | typedef int (*event_type_handler_t)(event_t *); |
8 | 9 | ||
@@ -21,12 +22,8 @@ struct perf_file_handler { | |||
21 | }; | 22 | }; |
22 | 23 | ||
23 | void register_perf_file_handler(struct perf_file_handler *handler); | 24 | void register_perf_file_handler(struct perf_file_handler *handler); |
24 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 25 | int perf_session__process_events(struct perf_session *self, |
25 | const char *input_name, | 26 | int full_paths, int *cwdlen, char **cwd); |
26 | int force, | ||
27 | int full_paths, | ||
28 | int *cwdlen, | ||
29 | char **cwd); | ||
30 | int perf_header__read_build_ids(int input, u64 offset, u64 file_size); | 27 | int perf_header__read_build_ids(int input, u64 offset, u64 file_size); |
31 | 28 | ||
32 | #endif | 29 | #endif |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 59a9c0b3033e..f2e8d8715111 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -58,35 +58,19 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* | 61 | int perf_header__init(struct perf_header *self) |
62 | * Create new perf.data header: | ||
63 | */ | ||
64 | struct perf_header *perf_header__new(void) | ||
65 | { | 62 | { |
66 | struct perf_header *self = zalloc(sizeof(*self)); | 63 | self->size = 1; |
67 | 64 | self->attr = malloc(sizeof(void *)); | |
68 | if (self != NULL) { | 65 | return self->attr == NULL ? -ENOMEM : 0; |
69 | self->size = 1; | ||
70 | self->attr = malloc(sizeof(void *)); | ||
71 | |||
72 | if (self->attr == NULL) { | ||
73 | free(self); | ||
74 | self = NULL; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | return self; | ||
79 | } | 66 | } |
80 | 67 | ||
81 | void perf_header__delete(struct perf_header *self) | 68 | void perf_header__exit(struct perf_header *self) |
82 | { | 69 | { |
83 | int i; | 70 | int i; |
84 | |||
85 | for (i = 0; i < self->attrs; ++i) | 71 | for (i = 0; i < self->attrs; ++i) |
86 | perf_header_attr__delete(self->attr[i]); | 72 | perf_header_attr__delete(self->attr[i]); |
87 | |||
88 | free(self->attr); | 73 | free(self->attr); |
89 | free(self); | ||
90 | } | 74 | } |
91 | 75 | ||
92 | int perf_header__add_attr(struct perf_header *self, | 76 | int perf_header__add_attr(struct perf_header *self, |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index d1dbe2b79c42..d118d05d3abe 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -55,8 +55,8 @@ struct perf_header { | |||
55 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); | 55 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct perf_header *perf_header__new(void); | 58 | int perf_header__init(struct perf_header *self); |
59 | void perf_header__delete(struct perf_header *self); | 59 | void perf_header__exit(struct perf_header *self); |
60 | 60 | ||
61 | int perf_header__read(struct perf_header *self, int fd); | 61 | int perf_header__read(struct perf_header *self, int fd); |
62 | int perf_header__write(struct perf_header *self, int fd, bool at_exit); | 62 | int perf_header__write(struct perf_header *self, int fd, bool at_exit); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c new file mode 100644 index 000000000000..707ce1cb1621 --- /dev/null +++ b/tools/perf/util/session.c | |||
@@ -0,0 +1,80 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | |||
3 | #include <unistd.h> | ||
4 | #include <sys/types.h> | ||
5 | |||
6 | #include "session.h" | ||
7 | #include "util.h" | ||
8 | |||
9 | static int perf_session__open(struct perf_session *self, bool force) | ||
10 | { | ||
11 | struct stat input_stat; | ||
12 | |||
13 | self->fd = open(self->filename, O_RDONLY); | ||
14 | if (self->fd < 0) { | ||
15 | pr_err("failed to open file: %s", self->filename); | ||
16 | if (!strcmp(self->filename, "perf.data")) | ||
17 | pr_err(" (try 'perf record' first)"); | ||
18 | pr_err("\n"); | ||
19 | return -errno; | ||
20 | } | ||
21 | |||
22 | if (fstat(self->fd, &input_stat) < 0) | ||
23 | goto out_close; | ||
24 | |||
25 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { | ||
26 | pr_err("file %s not owned by current user or root\n", | ||
27 | self->filename); | ||
28 | goto out_close; | ||
29 | } | ||
30 | |||
31 | if (!input_stat.st_size) { | ||
32 | pr_info("zero-sized file (%s), nothing to do!\n", | ||
33 | self->filename); | ||
34 | goto out_close; | ||
35 | } | ||
36 | |||
37 | if (perf_header__read(&self->header, self->fd) < 0) { | ||
38 | pr_err("incompatible file format"); | ||
39 | goto out_close; | ||
40 | } | ||
41 | |||
42 | self->size = input_stat.st_size; | ||
43 | return 0; | ||
44 | |||
45 | out_close: | ||
46 | close(self->fd); | ||
47 | self->fd = -1; | ||
48 | return -1; | ||
49 | } | ||
50 | |||
51 | struct perf_session *perf_session__new(const char *filename, int mode, bool force) | ||
52 | { | ||
53 | size_t len = strlen(filename) + 1; | ||
54 | struct perf_session *self = zalloc(sizeof(*self) + len); | ||
55 | |||
56 | if (self == NULL) | ||
57 | goto out; | ||
58 | |||
59 | if (perf_header__init(&self->header) < 0) | ||
60 | goto out_delete; | ||
61 | |||
62 | memcpy(self->filename, filename, len); | ||
63 | |||
64 | if (mode == O_RDONLY && perf_session__open(self, force) < 0) { | ||
65 | perf_session__delete(self); | ||
66 | self = NULL; | ||
67 | } | ||
68 | out: | ||
69 | return self; | ||
70 | out_delete: | ||
71 | free(self); | ||
72 | return NULL; | ||
73 | } | ||
74 | |||
75 | void perf_session__delete(struct perf_session *self) | ||
76 | { | ||
77 | perf_header__exit(&self->header); | ||
78 | close(self->fd); | ||
79 | free(self); | ||
80 | } | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h new file mode 100644 index 000000000000..f3699c8c8ed4 --- /dev/null +++ b/tools/perf/util/session.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __PERF_SESSION_H | ||
2 | #define __PERF_SESSION_H | ||
3 | |||
4 | #include "header.h" | ||
5 | |||
6 | struct perf_session { | ||
7 | struct perf_header header; | ||
8 | unsigned long size; | ||
9 | int fd; | ||
10 | char filename[0]; | ||
11 | }; | ||
12 | |||
13 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); | ||
14 | void perf_session__delete(struct perf_session *self); | ||
15 | |||
16 | #endif /* __PERF_SESSION_H */ | ||