root/tools/perf/util/trace-event-read.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __do_read
  2. do_read
  3. skip
  4. read4
  5. read8
  6. read_string
  7. read_proc_kallsyms
  8. read_ftrace_printk
  9. read_header_files
  10. read_ftrace_file
  11. read_event_file
  12. read_ftrace_files
  13. read_event_files
  14. read_saved_cmdline
  15. trace_report

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

/* [<][>][^][v][top][bottom][index][help] */