1538bafb5SSteven Rostedt /* 2538bafb5SSteven Rostedt * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> 3538bafb5SSteven Rostedt * 4538bafb5SSteven Rostedt * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5538bafb5SSteven Rostedt * 6538bafb5SSteven Rostedt * This program is free software; you can redistribute it and/or modify 7538bafb5SSteven Rostedt * it under the terms of the GNU General Public License as published by 8538bafb5SSteven Rostedt * the Free Software Foundation; version 2 of the License (not later!) 9538bafb5SSteven Rostedt * 10538bafb5SSteven Rostedt * This program is distributed in the hope that it will be useful, 11538bafb5SSteven Rostedt * but WITHOUT ANY WARRANTY; without even the implied warranty of 12538bafb5SSteven Rostedt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13538bafb5SSteven Rostedt * GNU General Public License for more details. 14538bafb5SSteven Rostedt * 15538bafb5SSteven Rostedt * You should have received a copy of the GNU General Public License 16538bafb5SSteven Rostedt * along with this program; if not, write to the Free Software 17538bafb5SSteven Rostedt * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18538bafb5SSteven Rostedt * 19538bafb5SSteven Rostedt * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20538bafb5SSteven Rostedt */ 21f887f301SXiao Guangrong #define _FILE_OFFSET_BITS 64 22538bafb5SSteven Rostedt 23538bafb5SSteven Rostedt #include <dirent.h> 24538bafb5SSteven Rostedt #include <stdio.h> 25538bafb5SSteven Rostedt #include <stdlib.h> 26538bafb5SSteven Rostedt #include <string.h> 27538bafb5SSteven Rostedt #include <getopt.h> 28538bafb5SSteven Rostedt #include <stdarg.h> 29538bafb5SSteven Rostedt #include <sys/types.h> 30538bafb5SSteven Rostedt #include <sys/stat.h> 31538bafb5SSteven Rostedt #include <sys/wait.h> 32538bafb5SSteven Rostedt #include <sys/mman.h> 33538bafb5SSteven Rostedt #include <pthread.h> 34538bafb5SSteven Rostedt #include <fcntl.h> 35538bafb5SSteven Rostedt #include <unistd.h> 36538bafb5SSteven Rostedt #include <errno.h> 37538bafb5SSteven Rostedt 381ef2ed10SFrederic Weisbecker #include "../perf.h" 39538bafb5SSteven Rostedt #include "util.h" 40538bafb5SSteven Rostedt #include "trace-event.h" 41538bafb5SSteven Rostedt 42538bafb5SSteven Rostedt static int input_fd; 43538bafb5SSteven Rostedt 44538bafb5SSteven Rostedt static int read_page; 45538bafb5SSteven Rostedt 46538bafb5SSteven Rostedt int file_bigendian; 47538bafb5SSteven Rostedt int host_bigendian; 48538bafb5SSteven Rostedt static int long_size; 49538bafb5SSteven Rostedt 50538bafb5SSteven Rostedt static unsigned long page_size; 51538bafb5SSteven Rostedt 529215545eSTom Zanussi static ssize_t calc_data_size; 53454c407eSTom Zanussi static bool repipe; 549215545eSTom Zanussi 55aaf045f7SSteven Rostedt static void *malloc_or_die(int size) 56aaf045f7SSteven Rostedt { 57aaf045f7SSteven Rostedt void *ret; 58aaf045f7SSteven Rostedt 59aaf045f7SSteven Rostedt ret = malloc(size); 60aaf045f7SSteven Rostedt if (!ret) 61aaf045f7SSteven Rostedt die("malloc"); 62aaf045f7SSteven Rostedt return ret; 63aaf045f7SSteven Rostedt } 64aaf045f7SSteven Rostedt 659215545eSTom Zanussi static int do_read(int fd, void *buf, int size) 669215545eSTom Zanussi { 679215545eSTom Zanussi int rsize = size; 689215545eSTom Zanussi 699215545eSTom Zanussi while (size) { 709215545eSTom Zanussi int ret = read(fd, buf, size); 719215545eSTom Zanussi 729215545eSTom Zanussi if (ret <= 0) 739215545eSTom Zanussi return -1; 749215545eSTom Zanussi 75454c407eSTom Zanussi if (repipe) { 76454c407eSTom Zanussi int retw = write(STDOUT_FILENO, buf, ret); 77454c407eSTom Zanussi 78454c407eSTom Zanussi if (retw <= 0 || retw != ret) 79454c407eSTom Zanussi die("repiping input file"); 80454c407eSTom Zanussi } 81454c407eSTom Zanussi 829215545eSTom Zanussi size -= ret; 839215545eSTom Zanussi buf += ret; 849215545eSTom Zanussi } 859215545eSTom Zanussi 869215545eSTom Zanussi return rsize; 879215545eSTom Zanussi } 889215545eSTom Zanussi 89538bafb5SSteven Rostedt static int read_or_die(void *data, int size) 90538bafb5SSteven Rostedt { 91538bafb5SSteven Rostedt int r; 92538bafb5SSteven Rostedt 939215545eSTom Zanussi r = do_read(input_fd, data, size); 949215545eSTom Zanussi if (r <= 0) 95538bafb5SSteven Rostedt die("reading input file (size expected=%d received=%d)", 96538bafb5SSteven Rostedt size, r); 979215545eSTom Zanussi 989215545eSTom Zanussi if (calc_data_size) 999215545eSTom Zanussi calc_data_size += r; 1009215545eSTom Zanussi 101538bafb5SSteven Rostedt return r; 102538bafb5SSteven Rostedt } 103538bafb5SSteven Rostedt 104cbb5cf7fSTom Zanussi /* If it fails, the next read will report it */ 105cbb5cf7fSTom Zanussi static void skip(int size) 106cbb5cf7fSTom Zanussi { 107cbb5cf7fSTom Zanussi char buf[BUFSIZ]; 108cbb5cf7fSTom Zanussi int r; 109cbb5cf7fSTom Zanussi 110cbb5cf7fSTom Zanussi while (size) { 111cbb5cf7fSTom Zanussi r = size > BUFSIZ ? BUFSIZ : size; 112cbb5cf7fSTom Zanussi read_or_die(buf, r); 113cbb5cf7fSTom Zanussi size -= r; 114cbb5cf7fSTom Zanussi }; 115cbb5cf7fSTom Zanussi } 116cbb5cf7fSTom Zanussi 117538bafb5SSteven Rostedt static unsigned int read4(void) 118538bafb5SSteven Rostedt { 119538bafb5SSteven Rostedt unsigned int data; 120538bafb5SSteven Rostedt 121538bafb5SSteven Rostedt read_or_die(&data, 4); 122aaf045f7SSteven Rostedt return __data2host4(perf_pevent, data); 123538bafb5SSteven Rostedt } 124538bafb5SSteven Rostedt 125538bafb5SSteven Rostedt static unsigned long long read8(void) 126538bafb5SSteven Rostedt { 127538bafb5SSteven Rostedt unsigned long long data; 128538bafb5SSteven Rostedt 129538bafb5SSteven Rostedt read_or_die(&data, 8); 130aaf045f7SSteven Rostedt return __data2host8(perf_pevent, data); 131538bafb5SSteven Rostedt } 132538bafb5SSteven Rostedt 133538bafb5SSteven Rostedt static char *read_string(void) 134538bafb5SSteven Rostedt { 135538bafb5SSteven Rostedt char buf[BUFSIZ]; 136538bafb5SSteven Rostedt char *str = NULL; 137538bafb5SSteven Rostedt int size = 0; 138f887f301SXiao Guangrong off_t r; 1399215545eSTom Zanussi char c; 140538bafb5SSteven Rostedt 141538bafb5SSteven Rostedt for (;;) { 1429215545eSTom Zanussi r = read(input_fd, &c, 1); 143538bafb5SSteven Rostedt if (r < 0) 144538bafb5SSteven Rostedt die("reading input file"); 145538bafb5SSteven Rostedt 146538bafb5SSteven Rostedt if (!r) 147538bafb5SSteven Rostedt die("no data"); 148538bafb5SSteven Rostedt 149454c407eSTom Zanussi if (repipe) { 150454c407eSTom Zanussi int retw = write(STDOUT_FILENO, &c, 1); 151454c407eSTom Zanussi 152454c407eSTom Zanussi if (retw <= 0 || retw != r) 153454c407eSTom Zanussi die("repiping input file string"); 154454c407eSTom Zanussi } 155454c407eSTom Zanussi 1569215545eSTom Zanussi buf[size++] = c; 1579215545eSTom Zanussi 1589215545eSTom Zanussi if (!c) 159538bafb5SSteven Rostedt break; 160538bafb5SSteven Rostedt } 161538bafb5SSteven Rostedt 1629215545eSTom Zanussi if (calc_data_size) 1639215545eSTom Zanussi calc_data_size += size; 1649215545eSTom Zanussi 165538bafb5SSteven Rostedt str = malloc_or_die(size); 166538bafb5SSteven Rostedt memcpy(str, buf, size); 167538bafb5SSteven Rostedt 168538bafb5SSteven Rostedt return str; 169538bafb5SSteven Rostedt } 170538bafb5SSteven Rostedt 171538bafb5SSteven Rostedt static void read_proc_kallsyms(void) 172538bafb5SSteven Rostedt { 173538bafb5SSteven Rostedt unsigned int size; 174538bafb5SSteven Rostedt char *buf; 175538bafb5SSteven Rostedt 176538bafb5SSteven Rostedt size = read4(); 177538bafb5SSteven Rostedt if (!size) 178538bafb5SSteven Rostedt return; 179538bafb5SSteven Rostedt 1807691b1ecSOGAWA Hirofumi buf = malloc_or_die(size + 1); 181538bafb5SSteven Rostedt read_or_die(buf, size); 1827691b1ecSOGAWA Hirofumi buf[size] = '\0'; 183538bafb5SSteven Rostedt 184538bafb5SSteven Rostedt parse_proc_kallsyms(buf, size); 185538bafb5SSteven Rostedt 186538bafb5SSteven Rostedt free(buf); 187538bafb5SSteven Rostedt } 188538bafb5SSteven Rostedt 189538bafb5SSteven Rostedt static void read_ftrace_printk(void) 190538bafb5SSteven Rostedt { 191538bafb5SSteven Rostedt unsigned int size; 192538bafb5SSteven Rostedt char *buf; 193538bafb5SSteven Rostedt 194538bafb5SSteven Rostedt size = read4(); 195538bafb5SSteven Rostedt if (!size) 196538bafb5SSteven Rostedt return; 197538bafb5SSteven Rostedt 198538bafb5SSteven Rostedt buf = malloc_or_die(size); 199538bafb5SSteven Rostedt read_or_die(buf, size); 200538bafb5SSteven Rostedt 201538bafb5SSteven Rostedt parse_ftrace_printk(buf, size); 202538bafb5SSteven Rostedt 203538bafb5SSteven Rostedt free(buf); 204538bafb5SSteven Rostedt } 205538bafb5SSteven Rostedt 206538bafb5SSteven Rostedt static void read_header_files(void) 207538bafb5SSteven Rostedt { 208538bafb5SSteven Rostedt unsigned long long size; 209538bafb5SSteven Rostedt char *header_event; 210538bafb5SSteven Rostedt char buf[BUFSIZ]; 211538bafb5SSteven Rostedt 212538bafb5SSteven Rostedt read_or_die(buf, 12); 213538bafb5SSteven Rostedt 214538bafb5SSteven Rostedt if (memcmp(buf, "header_page", 12) != 0) 215538bafb5SSteven Rostedt die("did not read header page"); 216538bafb5SSteven Rostedt 217538bafb5SSteven Rostedt size = read8(); 218d00a47ccSFrederic Weisbecker skip(size); 219538bafb5SSteven Rostedt 220538bafb5SSteven Rostedt /* 221538bafb5SSteven Rostedt * The size field in the page is of type long, 222538bafb5SSteven Rostedt * use that instead, since it represents the kernel. 223538bafb5SSteven Rostedt */ 224538bafb5SSteven Rostedt long_size = header_page_size_size; 225538bafb5SSteven Rostedt 226538bafb5SSteven Rostedt read_or_die(buf, 13); 227538bafb5SSteven Rostedt if (memcmp(buf, "header_event", 13) != 0) 228538bafb5SSteven Rostedt die("did not read header event"); 229538bafb5SSteven Rostedt 230538bafb5SSteven Rostedt size = read8(); 231538bafb5SSteven Rostedt header_event = malloc_or_die(size); 232538bafb5SSteven Rostedt read_or_die(header_event, size); 233538bafb5SSteven Rostedt free(header_event); 234538bafb5SSteven Rostedt } 235538bafb5SSteven Rostedt 236538bafb5SSteven Rostedt static void read_ftrace_file(unsigned long long size) 237538bafb5SSteven Rostedt { 238538bafb5SSteven Rostedt char *buf; 239538bafb5SSteven Rostedt 240538bafb5SSteven Rostedt buf = malloc_or_die(size); 241538bafb5SSteven Rostedt read_or_die(buf, size); 242538bafb5SSteven Rostedt parse_ftrace_file(buf, size); 243538bafb5SSteven Rostedt free(buf); 244538bafb5SSteven Rostedt } 245538bafb5SSteven Rostedt 246538bafb5SSteven Rostedt static void read_event_file(char *sys, unsigned long long size) 247538bafb5SSteven Rostedt { 248538bafb5SSteven Rostedt char *buf; 249538bafb5SSteven Rostedt 250538bafb5SSteven Rostedt buf = malloc_or_die(size); 251538bafb5SSteven Rostedt read_or_die(buf, size); 252538bafb5SSteven Rostedt parse_event_file(buf, size, sys); 253538bafb5SSteven Rostedt free(buf); 254538bafb5SSteven Rostedt } 255538bafb5SSteven Rostedt 256538bafb5SSteven Rostedt static void read_ftrace_files(void) 257538bafb5SSteven Rostedt { 258538bafb5SSteven Rostedt unsigned long long size; 259538bafb5SSteven Rostedt int count; 260538bafb5SSteven Rostedt int i; 261538bafb5SSteven Rostedt 262538bafb5SSteven Rostedt count = read4(); 263538bafb5SSteven Rostedt 264538bafb5SSteven Rostedt for (i = 0; i < count; i++) { 265538bafb5SSteven Rostedt size = read8(); 266538bafb5SSteven Rostedt read_ftrace_file(size); 267538bafb5SSteven Rostedt } 268538bafb5SSteven Rostedt } 269538bafb5SSteven Rostedt 270538bafb5SSteven Rostedt static void read_event_files(void) 271538bafb5SSteven Rostedt { 272538bafb5SSteven Rostedt unsigned long long size; 273538bafb5SSteven Rostedt char *sys; 274538bafb5SSteven Rostedt int systems; 275538bafb5SSteven Rostedt int count; 276538bafb5SSteven Rostedt int i,x; 277538bafb5SSteven Rostedt 278538bafb5SSteven Rostedt systems = read4(); 279538bafb5SSteven Rostedt 280538bafb5SSteven Rostedt for (i = 0; i < systems; i++) { 281538bafb5SSteven Rostedt sys = read_string(); 282538bafb5SSteven Rostedt 283538bafb5SSteven Rostedt count = read4(); 284538bafb5SSteven Rostedt for (x=0; x < count; x++) { 285538bafb5SSteven Rostedt size = read8(); 286538bafb5SSteven Rostedt read_event_file(sys, size); 287538bafb5SSteven Rostedt } 288538bafb5SSteven Rostedt } 289538bafb5SSteven Rostedt } 290538bafb5SSteven Rostedt 291538bafb5SSteven Rostedt struct cpu_data { 292538bafb5SSteven Rostedt unsigned long long offset; 293538bafb5SSteven Rostedt unsigned long long size; 294538bafb5SSteven Rostedt unsigned long long timestamp; 295538bafb5SSteven Rostedt struct record *next; 296538bafb5SSteven Rostedt char *page; 297538bafb5SSteven Rostedt int cpu; 298538bafb5SSteven Rostedt int index; 299538bafb5SSteven Rostedt int page_size; 300538bafb5SSteven Rostedt }; 301538bafb5SSteven Rostedt 302538bafb5SSteven Rostedt static struct cpu_data *cpu_data; 303538bafb5SSteven Rostedt 304538bafb5SSteven Rostedt static void update_cpu_data_index(int cpu) 305538bafb5SSteven Rostedt { 306538bafb5SSteven Rostedt cpu_data[cpu].offset += page_size; 307538bafb5SSteven Rostedt cpu_data[cpu].size -= page_size; 308538bafb5SSteven Rostedt cpu_data[cpu].index = 0; 309538bafb5SSteven Rostedt } 310538bafb5SSteven Rostedt 311538bafb5SSteven Rostedt static void get_next_page(int cpu) 312538bafb5SSteven Rostedt { 313f887f301SXiao Guangrong off_t save_seek; 314f887f301SXiao Guangrong off_t ret; 315538bafb5SSteven Rostedt 316538bafb5SSteven Rostedt if (!cpu_data[cpu].page) 317538bafb5SSteven Rostedt return; 318538bafb5SSteven Rostedt 319538bafb5SSteven Rostedt if (read_page) { 320538bafb5SSteven Rostedt if (cpu_data[cpu].size <= page_size) { 321538bafb5SSteven Rostedt free(cpu_data[cpu].page); 322538bafb5SSteven Rostedt cpu_data[cpu].page = NULL; 323538bafb5SSteven Rostedt return; 324538bafb5SSteven Rostedt } 325538bafb5SSteven Rostedt 326538bafb5SSteven Rostedt update_cpu_data_index(cpu); 327538bafb5SSteven Rostedt 328538bafb5SSteven Rostedt /* other parts of the code may expect the pointer to not move */ 329f887f301SXiao Guangrong save_seek = lseek(input_fd, 0, SEEK_CUR); 330538bafb5SSteven Rostedt 331f887f301SXiao Guangrong ret = lseek(input_fd, cpu_data[cpu].offset, SEEK_SET); 332f887f301SXiao Guangrong if (ret == (off_t)-1) 333538bafb5SSteven Rostedt die("failed to lseek"); 334538bafb5SSteven Rostedt ret = read(input_fd, cpu_data[cpu].page, page_size); 335538bafb5SSteven Rostedt if (ret < 0) 336538bafb5SSteven Rostedt die("failed to read page"); 337538bafb5SSteven Rostedt 338538bafb5SSteven Rostedt /* reset the file pointer back */ 339f887f301SXiao Guangrong lseek(input_fd, save_seek, SEEK_SET); 340538bafb5SSteven Rostedt 341538bafb5SSteven Rostedt return; 342538bafb5SSteven Rostedt } 343538bafb5SSteven Rostedt 344538bafb5SSteven Rostedt munmap(cpu_data[cpu].page, page_size); 345538bafb5SSteven Rostedt cpu_data[cpu].page = NULL; 346538bafb5SSteven Rostedt 347538bafb5SSteven Rostedt if (cpu_data[cpu].size <= page_size) 348538bafb5SSteven Rostedt return; 349538bafb5SSteven Rostedt 350538bafb5SSteven Rostedt update_cpu_data_index(cpu); 351538bafb5SSteven Rostedt 352538bafb5SSteven Rostedt cpu_data[cpu].page = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, 353538bafb5SSteven Rostedt input_fd, cpu_data[cpu].offset); 354538bafb5SSteven Rostedt if (cpu_data[cpu].page == MAP_FAILED) 355538bafb5SSteven Rostedt die("failed to mmap cpu %d at offset 0x%llx", 356538bafb5SSteven Rostedt cpu, cpu_data[cpu].offset); 357538bafb5SSteven Rostedt } 358538bafb5SSteven Rostedt 359538bafb5SSteven Rostedt static unsigned int type_len4host(unsigned int type_len_ts) 360538bafb5SSteven Rostedt { 361538bafb5SSteven Rostedt if (file_bigendian) 362538bafb5SSteven Rostedt return (type_len_ts >> 27) & ((1 << 5) - 1); 363538bafb5SSteven Rostedt else 364538bafb5SSteven Rostedt return type_len_ts & ((1 << 5) - 1); 365538bafb5SSteven Rostedt } 366538bafb5SSteven Rostedt 367538bafb5SSteven Rostedt static unsigned int ts4host(unsigned int type_len_ts) 368538bafb5SSteven Rostedt { 369538bafb5SSteven Rostedt if (file_bigendian) 370538bafb5SSteven Rostedt return type_len_ts & ((1 << 27) - 1); 371538bafb5SSteven Rostedt else 372538bafb5SSteven Rostedt return type_len_ts >> 5; 373538bafb5SSteven Rostedt } 374538bafb5SSteven Rostedt 375538bafb5SSteven Rostedt static int calc_index(void *ptr, int cpu) 376538bafb5SSteven Rostedt { 377538bafb5SSteven Rostedt return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; 378538bafb5SSteven Rostedt } 379538bafb5SSteven Rostedt 380538bafb5SSteven Rostedt struct record *trace_peek_data(int cpu) 381538bafb5SSteven Rostedt { 382538bafb5SSteven Rostedt struct record *data; 383538bafb5SSteven Rostedt void *page = cpu_data[cpu].page; 384538bafb5SSteven Rostedt int idx = cpu_data[cpu].index; 385538bafb5SSteven Rostedt void *ptr = page + idx; 386538bafb5SSteven Rostedt unsigned long long extend; 387538bafb5SSteven Rostedt unsigned int type_len_ts; 388538bafb5SSteven Rostedt unsigned int type_len; 389538bafb5SSteven Rostedt unsigned int delta; 390538bafb5SSteven Rostedt unsigned int length = 0; 391538bafb5SSteven Rostedt 392538bafb5SSteven Rostedt if (cpu_data[cpu].next) 393538bafb5SSteven Rostedt return cpu_data[cpu].next; 394538bafb5SSteven Rostedt 395538bafb5SSteven Rostedt if (!page) 396538bafb5SSteven Rostedt return NULL; 397538bafb5SSteven Rostedt 398538bafb5SSteven Rostedt if (!idx) { 399538bafb5SSteven Rostedt /* FIXME: handle header page */ 400538bafb5SSteven Rostedt if (header_page_ts_size != 8) 401538bafb5SSteven Rostedt die("expected a long long type for timestamp"); 402aaf045f7SSteven Rostedt cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr); 403538bafb5SSteven Rostedt ptr += 8; 404538bafb5SSteven Rostedt switch (header_page_size_size) { 405538bafb5SSteven Rostedt case 4: 406aaf045f7SSteven Rostedt cpu_data[cpu].page_size = data2host4(perf_pevent, ptr); 407538bafb5SSteven Rostedt ptr += 4; 408538bafb5SSteven Rostedt break; 409538bafb5SSteven Rostedt case 8: 410aaf045f7SSteven Rostedt cpu_data[cpu].page_size = data2host8(perf_pevent, ptr); 411538bafb5SSteven Rostedt ptr += 8; 412538bafb5SSteven Rostedt break; 413538bafb5SSteven Rostedt default: 414538bafb5SSteven Rostedt die("bad long size"); 415538bafb5SSteven Rostedt } 416538bafb5SSteven Rostedt ptr = cpu_data[cpu].page + header_page_data_offset; 417538bafb5SSteven Rostedt } 418538bafb5SSteven Rostedt 419538bafb5SSteven Rostedt read_again: 420538bafb5SSteven Rostedt idx = calc_index(ptr, cpu); 421538bafb5SSteven Rostedt 422538bafb5SSteven Rostedt if (idx >= cpu_data[cpu].page_size) { 423538bafb5SSteven Rostedt get_next_page(cpu); 424538bafb5SSteven Rostedt return trace_peek_data(cpu); 425538bafb5SSteven Rostedt } 426538bafb5SSteven Rostedt 427aaf045f7SSteven Rostedt type_len_ts = data2host4(perf_pevent, ptr); 428538bafb5SSteven Rostedt ptr += 4; 429538bafb5SSteven Rostedt 430538bafb5SSteven Rostedt type_len = type_len4host(type_len_ts); 431538bafb5SSteven Rostedt delta = ts4host(type_len_ts); 432538bafb5SSteven Rostedt 433538bafb5SSteven Rostedt switch (type_len) { 434538bafb5SSteven Rostedt case RINGBUF_TYPE_PADDING: 435538bafb5SSteven Rostedt if (!delta) 436538bafb5SSteven Rostedt die("error, hit unexpected end of page"); 437aaf045f7SSteven Rostedt length = data2host4(perf_pevent, ptr); 438538bafb5SSteven Rostedt ptr += 4; 439538bafb5SSteven Rostedt length *= 4; 440538bafb5SSteven Rostedt ptr += length; 441538bafb5SSteven Rostedt goto read_again; 442538bafb5SSteven Rostedt 443538bafb5SSteven Rostedt case RINGBUF_TYPE_TIME_EXTEND: 444aaf045f7SSteven Rostedt extend = data2host4(perf_pevent, ptr); 445538bafb5SSteven Rostedt ptr += 4; 446538bafb5SSteven Rostedt extend <<= TS_SHIFT; 447538bafb5SSteven Rostedt extend += delta; 448538bafb5SSteven Rostedt cpu_data[cpu].timestamp += extend; 449538bafb5SSteven Rostedt goto read_again; 450538bafb5SSteven Rostedt 451538bafb5SSteven Rostedt case RINGBUF_TYPE_TIME_STAMP: 452538bafb5SSteven Rostedt ptr += 12; 453538bafb5SSteven Rostedt break; 454538bafb5SSteven Rostedt case 0: 455aaf045f7SSteven Rostedt length = data2host4(perf_pevent, ptr); 456538bafb5SSteven Rostedt ptr += 4; 457538bafb5SSteven Rostedt die("here! length=%d", length); 458538bafb5SSteven Rostedt break; 459538bafb5SSteven Rostedt default: 460538bafb5SSteven Rostedt length = type_len * 4; 461538bafb5SSteven Rostedt break; 462538bafb5SSteven Rostedt } 463538bafb5SSteven Rostedt 464538bafb5SSteven Rostedt cpu_data[cpu].timestamp += delta; 465538bafb5SSteven Rostedt 466538bafb5SSteven Rostedt data = malloc_or_die(sizeof(*data)); 467538bafb5SSteven Rostedt memset(data, 0, sizeof(*data)); 468538bafb5SSteven Rostedt 469538bafb5SSteven Rostedt data->ts = cpu_data[cpu].timestamp; 470538bafb5SSteven Rostedt data->size = length; 471538bafb5SSteven Rostedt data->data = ptr; 472538bafb5SSteven Rostedt ptr += length; 473538bafb5SSteven Rostedt 474538bafb5SSteven Rostedt cpu_data[cpu].index = calc_index(ptr, cpu); 475538bafb5SSteven Rostedt cpu_data[cpu].next = data; 476538bafb5SSteven Rostedt 477538bafb5SSteven Rostedt return data; 478538bafb5SSteven Rostedt } 479538bafb5SSteven Rostedt 480538bafb5SSteven Rostedt struct record *trace_read_data(int cpu) 481538bafb5SSteven Rostedt { 482538bafb5SSteven Rostedt struct record *data; 483538bafb5SSteven Rostedt 484538bafb5SSteven Rostedt data = trace_peek_data(cpu); 485538bafb5SSteven Rostedt cpu_data[cpu].next = NULL; 486538bafb5SSteven Rostedt 487538bafb5SSteven Rostedt return data; 488538bafb5SSteven Rostedt } 489538bafb5SSteven Rostedt 490454c407eSTom Zanussi ssize_t trace_report(int fd, bool __repipe) 491538bafb5SSteven Rostedt { 492538bafb5SSteven Rostedt char buf[BUFSIZ]; 493538bafb5SSteven Rostedt char test[] = { 23, 8, 68 }; 494538bafb5SSteven Rostedt char *version; 495d9340c1dSIngo Molnar int show_version = 0; 496538bafb5SSteven Rostedt int show_funcs = 0; 497538bafb5SSteven Rostedt int show_printk = 0; 4989215545eSTom Zanussi ssize_t size; 4999215545eSTom Zanussi 5009215545eSTom Zanussi calc_data_size = 1; 501454c407eSTom Zanussi repipe = __repipe; 502538bafb5SSteven Rostedt 50303456a15SFrederic Weisbecker input_fd = fd; 504538bafb5SSteven Rostedt 505538bafb5SSteven Rostedt read_or_die(buf, 3); 506538bafb5SSteven Rostedt if (memcmp(buf, test, 3) != 0) 507e2561368SArnaldo Carvalho de Melo die("no trace data in the file"); 508538bafb5SSteven Rostedt 509538bafb5SSteven Rostedt read_or_die(buf, 7); 510538bafb5SSteven Rostedt if (memcmp(buf, "tracing", 7) != 0) 511e2561368SArnaldo Carvalho de Melo die("not a trace file (missing 'tracing' tag)"); 512538bafb5SSteven Rostedt 513538bafb5SSteven Rostedt version = read_string(); 514d9340c1dSIngo Molnar if (show_version) 515538bafb5SSteven Rostedt printf("version = %s\n", version); 516538bafb5SSteven Rostedt free(version); 517538bafb5SSteven Rostedt 518538bafb5SSteven Rostedt read_or_die(buf, 1); 519538bafb5SSteven Rostedt file_bigendian = buf[0]; 520538bafb5SSteven Rostedt host_bigendian = bigendian(); 521538bafb5SSteven Rostedt 522aaf045f7SSteven Rostedt read_trace_init(file_bigendian, host_bigendian); 523aaf045f7SSteven Rostedt 524538bafb5SSteven Rostedt read_or_die(buf, 1); 525538bafb5SSteven Rostedt long_size = buf[0]; 526538bafb5SSteven Rostedt 527538bafb5SSteven Rostedt page_size = read4(); 528538bafb5SSteven Rostedt 529538bafb5SSteven Rostedt read_header_files(); 530538bafb5SSteven Rostedt 531538bafb5SSteven Rostedt read_ftrace_files(); 532538bafb5SSteven Rostedt read_event_files(); 533538bafb5SSteven Rostedt read_proc_kallsyms(); 534538bafb5SSteven Rostedt read_ftrace_printk(); 535538bafb5SSteven Rostedt 5369215545eSTom Zanussi size = calc_data_size - 1; 5379215545eSTom Zanussi calc_data_size = 0; 538454c407eSTom Zanussi repipe = false; 5399215545eSTom Zanussi 540538bafb5SSteven Rostedt if (show_funcs) { 541aaf045f7SSteven Rostedt pevent_print_funcs(perf_pevent); 5429215545eSTom Zanussi return size; 543538bafb5SSteven Rostedt } 544538bafb5SSteven Rostedt if (show_printk) { 545aaf045f7SSteven Rostedt pevent_print_printk(perf_pevent); 5469215545eSTom Zanussi return size; 547538bafb5SSteven Rostedt } 548538bafb5SSteven Rostedt 5499215545eSTom Zanussi return size; 550538bafb5SSteven Rostedt } 551