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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ 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 <traceevent/event-parse.h>
 15 #include <fcntl.h>
 16 #include <unistd.h>
 17 #include <errno.h>
 18 
 19 #include "trace-event.h"
 20 #include "debug.h"
 21 #include "util.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         buf[ret] = '\0';
367 
368         parse_saved_cmdline(pevent, buf, size);
369         ret = 0;
370 out:
371         free(buf);
372         return ret;
373 }
374 
375 ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
376 {
377         char buf[BUFSIZ];
378         char test[] = { 23, 8, 68 };
379         char *version;
380         int show_version = 0;
381         int show_funcs = 0;
382         int show_printk = 0;
383         ssize_t size = -1;
384         int file_bigendian;
385         int host_bigendian;
386         int file_long_size;
387         int file_page_size;
388         struct tep_handle *pevent = NULL;
389         int err;
390 
391         repipe = __repipe;
392         input_fd = fd;
393 
394         if (do_read(buf, 3) < 0)
395                 return -1;
396         if (memcmp(buf, test, 3) != 0) {
397                 pr_debug("no trace data in the file");
398                 return -1;
399         }
400 
401         if (do_read(buf, 7) < 0)
402                 return -1;
403         if (memcmp(buf, "tracing", 7) != 0) {
404                 pr_debug("not a trace file (missing 'tracing' tag)");
405                 return -1;
406         }
407 
408         version = read_string();
409         if (version == NULL)
410                 return -1;
411         if (show_version)
412                 printf("version = %s\n", version);
413 
414         if (do_read(buf, 1) < 0) {
415                 free(version);
416                 return -1;
417         }
418         file_bigendian = buf[0];
419         host_bigendian = host_is_bigendian() ? 1 : 0;
420 
421         if (trace_event__init(tevent)) {
422                 pr_debug("trace_event__init failed");
423                 goto out;
424         }
425 
426         pevent = tevent->pevent;
427 
428         tep_set_flag(pevent, TEP_NSEC_OUTPUT);
429         tep_set_file_bigendian(pevent, file_bigendian);
430         tep_set_local_bigendian(pevent, host_bigendian);
431 
432         if (do_read(buf, 1) < 0)
433                 goto out;
434         file_long_size = buf[0];
435 
436         file_page_size = read4(pevent);
437         if (!file_page_size)
438                 goto out;
439 
440         tep_set_long_size(pevent, file_long_size);
441         tep_set_page_size(pevent, file_page_size);
442 
443         err = read_header_files(pevent);
444         if (err)
445                 goto out;
446         err = read_ftrace_files(pevent);
447         if (err)
448                 goto out;
449         err = read_event_files(pevent);
450         if (err)
451                 goto out;
452         err = read_proc_kallsyms(pevent);
453         if (err)
454                 goto out;
455         err = read_ftrace_printk(pevent);
456         if (err)
457                 goto out;
458         if (atof(version) >= 0.6) {
459                 err = read_saved_cmdline(pevent);
460                 if (err)
461                         goto out;
462         }
463 
464         size = trace_data_size;
465         repipe = false;
466 
467         if (show_funcs) {
468                 tep_print_funcs(pevent);
469         } else if (show_printk) {
470                 tep_print_printk(pevent);
471         }
472 
473         pevent = NULL;
474 
475 out:
476         if (pevent)
477                 trace_event__cleanup(tevent);
478         free(version);
479         return size;
480 }
481 

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php