~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/trace-event-read.c

Version: ~ [ linux-6.4-rc3 ] ~ [ linux-6.3.4 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.30 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.113 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.180 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.243 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.283 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.315 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
  4  */
  5 #include <dirent.h>
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <string.h>
  9 #include <stdarg.h>
 10 #include <sys/types.h>
 11 #include <sys/stat.h>
 12 #include <sys/wait.h>
 13 #include <sys/mman.h>
 14 #include <fcntl.h>
 15 #include <unistd.h>
 16 #include <errno.h>
 17 
 18 #include "../perf.h"
 19 #include "util.h"
 20 #include "trace-event.h"
 21 #include "debug.h"
 22 
 23 static int input_fd;
 24 
 25 static ssize_t trace_data_size;
 26 static bool repipe;
 27 
 28 static int __do_read(int fd, void *buf, int size)
 29 {
 30         int rsize = size;
 31 
 32         while (size) {
 33                 int ret = read(fd, buf, size);
 34 
 35                 if (ret <= 0)
 36                         return -1;
 37 
 38                 if (repipe) {
 39                         int retw = write(STDOUT_FILENO, buf, ret);
 40 
 41                         if (retw <= 0 || retw != ret) {
 42                                 pr_debug("repiping input file");
 43                                 return -1;
 44                         }
 45                 }
 46 
 47                 size -= ret;
 48                 buf += ret;
 49         }
 50 
 51         return rsize;
 52 }
 53 
 54 static int do_read(void *data, int size)
 55 {
 56         int r;
 57 
 58         r = __do_read(input_fd, data, size);
 59         if (r <= 0) {
 60                 pr_debug("reading input file (size expected=%d received=%d)",
 61                          size, r);
 62                 return -1;
 63         }
 64 
 65         trace_data_size += r;
 66 
 67         return r;
 68 }
 69 
 70 /* If it fails, the next read will report it */
 71 static void skip(int size)
 72 {
 73         char buf[BUFSIZ];
 74         int r;
 75 
 76         while (size) {
 77                 r = size > BUFSIZ ? BUFSIZ : size;
 78                 do_read(buf, r);
 79                 size -= r;
 80         };
 81 }
 82 
 83 static unsigned int read4(struct tep_handle *pevent)
 84 {
 85         unsigned int data;
 86 
 87         if (do_read(&data, 4) < 0)
 88                 return 0;
 89         return tep_read_number(pevent, &data, 4);
 90 }
 91 
 92 static unsigned long long read8(struct tep_handle *pevent)
 93 {
 94         unsigned long long data;
 95 
 96         if (do_read(&data, 8) < 0)
 97                 return 0;
 98         return tep_read_number(pevent, &data, 8);
 99 }
100 
101 static char *read_string(void)
102 {
103         char buf[BUFSIZ];
104         char *str = NULL;
105         int size = 0;
106         off_t r;
107         char c;
108 
109         for (;;) {
110                 r = read(input_fd, &c, 1);
111                 if (r < 0) {
112                         pr_debug("reading input file");
113                         goto out;
114                 }
115 
116                 if (!r) {
117                         pr_debug("no data");
118                         goto out;
119                 }
120 
121                 if (repipe) {
122                         int retw = write(STDOUT_FILENO, &c, 1);
123 
124                         if (retw <= 0 || retw != r) {
125                                 pr_debug("repiping input file string");
126                                 goto out;
127                         }
128                 }
129 
130                 buf[size++] = c;
131 
132                 if (!c)
133                         break;
134         }
135 
136         trace_data_size += size;
137 
138         str = malloc(size);
139         if (str)
140                 memcpy(str, buf, size);
141 out:
142         return str;
143 }
144 
145 static int read_proc_kallsyms(struct tep_handle *pevent)
146 {
147         unsigned int size;
148 
149         size = read4(pevent);
150         if (!size)
151                 return 0;
152         /*
153          * Just skip it, now that we configure libtraceevent to use the
154          * tools/perf/ symbol resolver.
155          *
156          * We need to skip it so that we can continue parsing old perf.data
157          * files, that contains this /proc/kallsyms payload.
158          *
159          * Newer perf.data files will have just the 4-bytes zeros "kallsyms
160          * payload", so that older tools can continue reading it and interpret
161          * it as "no kallsyms payload is present".
162          */
163         lseek(input_fd, size, SEEK_CUR);
164         trace_data_size += size;
165         return 0;
166 }
167 
168 static int read_ftrace_printk(struct tep_handle *pevent)
169 {
170         unsigned int size;
171         char *buf;
172 
173         /* it can have 0 size */
174         size = read4(pevent);
175         if (!size)
176                 return 0;
177 
178         buf = malloc(size + 1);
179         if (buf == NULL)
180                 return -1;
181 
182         if (do_read(buf, size) < 0) {
183                 free(buf);
184                 return -1;
185         }
186 
187         buf[size] = '\0';
188 
189         parse_ftrace_printk(pevent, buf, size);
190 
191         free(buf);
192         return 0;
193 }
194 
195 static int read_header_files(struct tep_handle *pevent)
196 {
197         unsigned long long size;
198         char *header_page;
199         char buf[BUFSIZ];
200         int ret = 0;
201 
202         if (do_read(buf, 12) < 0)
203                 return -1;
204 
205         if (memcmp(buf, "header_page", 12) != 0) {
206                 pr_debug("did not read header page");
207                 return -1;
208         }
209 
210         size = read8(pevent);
211 
212         header_page = malloc(size);
213         if (header_page == NULL)
214                 return -1;
215 
216         if (do_read(header_page, size) < 0) {
217                 pr_debug("did not read header page");
218                 free(header_page);
219                 return -1;
220         }
221 
222         if (!tep_parse_header_page(pevent, header_page, size,
223                                    tep_get_long_size(pevent))) {
224                 /*
225                  * The commit field in the page is of type long,
226                  * use that instead, since it represents the kernel.
227                  */
228                 tep_set_long_size(pevent, tep_get_header_page_size(pevent));
229         }
230         free(header_page);
231 
232         if (do_read(buf, 13) < 0)
233                 return -1;
234 
235         if (memcmp(buf, "header_event", 13) != 0) {
236                 pr_debug("did not read header event");
237                 return -1;
238         }
239 
240         size = read8(pevent);
241         skip(size);
242 
243         return ret;
244 }
245 
246 static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
247 {
248         int ret;
249         char *buf;
250 
251         buf = malloc(size);
252         if (buf == NULL) {
253                 pr_debug("memory allocation failure\n");
254                 return -1;
255         }
256 
257         ret = do_read(buf, size);
258         if (ret < 0) {
259                 pr_debug("error reading ftrace file.\n");
260                 goto out;
261         }
262 
263         ret = parse_ftrace_file(pevent, buf, size);
264         if (ret < 0)
265                 pr_debug("error parsing ftrace file.\n");
266 out:
267         free(buf);
268         return ret;
269 }
270 
271 static int read_event_file(struct tep_handle *pevent, char *sys,
272                            unsigned long long size)
273 {
274         int ret;
275         char *buf;
276 
277         buf = malloc(size);
278         if (buf == NULL) {
279                 pr_debug("memory allocation failure\n");
280                 return -1;
281         }
282 
283         ret = do_read(buf, size);
284         if (ret < 0)
285                 goto out;
286 
287         ret = parse_event_file(pevent, buf, size, sys);
288         if (ret < 0)
289                 pr_debug("error parsing event file.\n");
290 out:
291         free(buf);
292         return ret;
293 }
294 
295 static int read_ftrace_files(struct tep_handle *pevent)
296 {
297         unsigned long long size;
298         int count;
299         int i;
300         int ret;
301 
302         count = read4(pevent);
303 
304         for (i = 0; i < count; i++) {
305                 size = read8(pevent);
306                 ret = read_ftrace_file(pevent, size);
307                 if (ret)
308                         return ret;
309         }
310         return 0;
311 }
312 
313 static int read_event_files(struct tep_handle *pevent)
314 {
315         unsigned long long size;
316         char *sys;
317         int systems;
318         int count;
319         int i,x;
320         int ret;
321 
322         systems = read4(pevent);
323 
324         for (i = 0; i < systems; i++) {
325                 sys = read_string();
326                 if (sys == NULL)
327                         return -1;
328 
329                 count = read4(pevent);
330 
331                 for (x=0; x < count; x++) {
332                         size = read8(pevent);
333                         ret = read_event_file(pevent, sys, size);
334                         if (ret) {
335                                 free(sys);
336                                 return ret;
337                         }
338                 }
339                 free(sys);
340         }
341         return 0;
342 }
343 
344 static int read_saved_cmdline(struct tep_handle *pevent)
345 {
346         unsigned long long size;
347         char *buf;
348         int ret;
349 
350         /* it can have 0 size */
351         size = read8(pevent);
352         if (!size)
353                 return 0;
354 
355         buf = malloc(size + 1);
356         if (buf == NULL) {
357                 pr_debug("memory allocation failure\n");
358                 return -1;
359         }
360 
361         ret = do_read(buf, size);
362         if (ret < 0) {
363                 pr_debug("error reading saved cmdlines\n");
364                 goto out;
365         }
366 
367         parse_saved_cmdline(pevent, buf, size);
368         ret = 0;
369 out:
370         free(buf);
371         return ret;
372 }
373 
374 ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
375 {
376         char buf[BUFSIZ];
377         char test[] = { 23, 8, 68 };
378         char *version;
379         int show_version = 0;
380         int show_funcs = 0;
381         int show_printk = 0;
382         ssize_t size = -1;
383         int file_bigendian;
384         int host_bigendian;
385         int file_long_size;
386         int file_page_size;
387         struct tep_handle *pevent = NULL;
388         int err;
389 
390         repipe = __repipe;
391         input_fd = fd;
392 
393         if (do_read(buf, 3) < 0)
394                 return -1;
395         if (memcmp(buf, test, 3) != 0) {
396                 pr_debug("no trace data in the file");
397                 return -1;
398         }
399 
400         if (do_read(buf, 7) < 0)
401                 return -1;
402         if (memcmp(buf, "tracing", 7) != 0) {
403                 pr_debug("not a trace file (missing 'tracing' tag)");
404                 return -1;
405         }
406 
407         version = read_string();
408         if (version == NULL)
409                 return -1;
410         if (show_version)
411                 printf("version = %s\n", version);
412 
413         if (do_read(buf, 1) < 0) {
414                 free(version);
415                 return -1;
416         }
417         file_bigendian = buf[0];
418         host_bigendian = bigendian();
419 
420         if (trace_event__init(tevent)) {
421                 pr_debug("trace_event__init failed");
422                 goto out;
423         }
424 
425         pevent = tevent->pevent;
426 
427         tep_set_flag(pevent, TEP_NSEC_OUTPUT);
428         tep_set_file_bigendian(pevent, file_bigendian);
429         tep_set_local_bigendian(pevent, host_bigendian);
430 
431         if (do_read(buf, 1) < 0)
432                 goto out;
433         file_long_size = buf[0];
434 
435         file_page_size = read4(pevent);
436         if (!file_page_size)
437                 goto out;
438 
439         tep_set_long_size(pevent, file_long_size);
440         tep_set_page_size(pevent, file_page_size);
441 
442         err = read_header_files(pevent);
443         if (err)
444                 goto out;
445         err = read_ftrace_files(pevent);
446         if (err)
447                 goto out;
448         err = read_event_files(pevent);
449         if (err)
450                 goto out;
451         err = read_proc_kallsyms(pevent);
452         if (err)
453                 goto out;
454         err = read_ftrace_printk(pevent);
455         if (err)
456                 goto out;
457         if (atof(version) >= 0.6) {
458                 err = read_saved_cmdline(pevent);
459                 if (err)
460                         goto out;
461         }
462 
463         size = trace_data_size;
464         repipe = false;
465 
466         if (show_funcs) {
467                 tep_print_funcs(pevent);
468         } else if (show_printk) {
469                 tep_print_printk(pevent);
470         }
471 
472         pevent = NULL;
473 
474 out:
475         if (pevent)
476                 trace_event__cleanup(tevent);
477         free(version);
478         return size;
479 }
480 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp