0001
0002
0003
0004
0005 #include <dirent.h>
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 #include <stdarg.h>
0010 #include <sys/types.h>
0011 #include <sys/stat.h>
0012 #include <sys/wait.h>
0013 #include <sys/mman.h>
0014 #include <fcntl.h>
0015 #include <unistd.h>
0016 #include <errno.h>
0017
0018 #include "trace-event.h"
0019 #include "debug.h"
0020
0021 static int input_fd;
0022
0023 static ssize_t trace_data_size;
0024 static bool repipe;
0025
0026 static int __do_read(int fd, void *buf, int size)
0027 {
0028 int rsize = size;
0029
0030 while (size) {
0031 int ret = read(fd, buf, size);
0032
0033 if (ret <= 0)
0034 return -1;
0035
0036 if (repipe) {
0037 int retw = write(STDOUT_FILENO, buf, ret);
0038
0039 if (retw <= 0 || retw != ret) {
0040 pr_debug("repiping input file");
0041 return -1;
0042 }
0043 }
0044
0045 size -= ret;
0046 buf += ret;
0047 }
0048
0049 return rsize;
0050 }
0051
0052 static int do_read(void *data, int size)
0053 {
0054 int r;
0055
0056 r = __do_read(input_fd, data, size);
0057 if (r <= 0) {
0058 pr_debug("reading input file (size expected=%d received=%d)",
0059 size, r);
0060 return -1;
0061 }
0062
0063 trace_data_size += r;
0064
0065 return r;
0066 }
0067
0068
0069 static void skip(int size)
0070 {
0071 char buf[BUFSIZ];
0072 int r;
0073
0074 while (size) {
0075 r = size > BUFSIZ ? BUFSIZ : size;
0076 do_read(buf, r);
0077 size -= r;
0078 }
0079 }
0080
0081 static unsigned int read4(struct tep_handle *pevent)
0082 {
0083 unsigned int data;
0084
0085 if (do_read(&data, 4) < 0)
0086 return 0;
0087 return tep_read_number(pevent, &data, 4);
0088 }
0089
0090 static unsigned long long read8(struct tep_handle *pevent)
0091 {
0092 unsigned long long data;
0093
0094 if (do_read(&data, 8) < 0)
0095 return 0;
0096 return tep_read_number(pevent, &data, 8);
0097 }
0098
0099 static char *read_string(void)
0100 {
0101 char buf[BUFSIZ];
0102 char *str = NULL;
0103 int size = 0;
0104 off_t r;
0105 char c;
0106
0107 for (;;) {
0108 r = read(input_fd, &c, 1);
0109 if (r < 0) {
0110 pr_debug("reading input file");
0111 goto out;
0112 }
0113
0114 if (!r) {
0115 pr_debug("no data");
0116 goto out;
0117 }
0118
0119 if (repipe) {
0120 int retw = write(STDOUT_FILENO, &c, 1);
0121
0122 if (retw <= 0 || retw != r) {
0123 pr_debug("repiping input file string");
0124 goto out;
0125 }
0126 }
0127
0128 buf[size++] = c;
0129
0130 if (!c)
0131 break;
0132 }
0133
0134 trace_data_size += size;
0135
0136 str = malloc(size);
0137 if (str)
0138 memcpy(str, buf, size);
0139 out:
0140 return str;
0141 }
0142
0143 static int read_proc_kallsyms(struct tep_handle *pevent)
0144 {
0145 unsigned int size;
0146
0147 size = read4(pevent);
0148 if (!size)
0149 return 0;
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 lseek(input_fd, size, SEEK_CUR);
0162 trace_data_size += size;
0163 return 0;
0164 }
0165
0166 static int read_ftrace_printk(struct tep_handle *pevent)
0167 {
0168 unsigned int size;
0169 char *buf;
0170
0171
0172 size = read4(pevent);
0173 if (!size)
0174 return 0;
0175
0176 buf = malloc(size + 1);
0177 if (buf == NULL)
0178 return -1;
0179
0180 if (do_read(buf, size) < 0) {
0181 free(buf);
0182 return -1;
0183 }
0184
0185 buf[size] = '\0';
0186
0187 parse_ftrace_printk(pevent, buf, size);
0188
0189 free(buf);
0190 return 0;
0191 }
0192
0193 static int read_header_files(struct tep_handle *pevent)
0194 {
0195 unsigned long long size;
0196 char *header_page;
0197 char buf[BUFSIZ];
0198 int ret = 0;
0199
0200 if (do_read(buf, 12) < 0)
0201 return -1;
0202
0203 if (memcmp(buf, "header_page", 12) != 0) {
0204 pr_debug("did not read header page");
0205 return -1;
0206 }
0207
0208 size = read8(pevent);
0209
0210 header_page = malloc(size);
0211 if (header_page == NULL)
0212 return -1;
0213
0214 if (do_read(header_page, size) < 0) {
0215 pr_debug("did not read header page");
0216 free(header_page);
0217 return -1;
0218 }
0219
0220 if (!tep_parse_header_page(pevent, header_page, size,
0221 tep_get_long_size(pevent))) {
0222
0223
0224
0225
0226 tep_set_long_size(pevent, tep_get_header_page_size(pevent));
0227 }
0228 free(header_page);
0229
0230 if (do_read(buf, 13) < 0)
0231 return -1;
0232
0233 if (memcmp(buf, "header_event", 13) != 0) {
0234 pr_debug("did not read header event");
0235 return -1;
0236 }
0237
0238 size = read8(pevent);
0239 skip(size);
0240
0241 return ret;
0242 }
0243
0244 static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
0245 {
0246 int ret;
0247 char *buf;
0248
0249 buf = malloc(size);
0250 if (buf == NULL) {
0251 pr_debug("memory allocation failure\n");
0252 return -1;
0253 }
0254
0255 ret = do_read(buf, size);
0256 if (ret < 0) {
0257 pr_debug("error reading ftrace file.\n");
0258 goto out;
0259 }
0260
0261 ret = parse_ftrace_file(pevent, buf, size);
0262 if (ret < 0)
0263 pr_debug("error parsing ftrace file.\n");
0264 out:
0265 free(buf);
0266 return ret;
0267 }
0268
0269 static int read_event_file(struct tep_handle *pevent, char *sys,
0270 unsigned long long size)
0271 {
0272 int ret;
0273 char *buf;
0274
0275 buf = malloc(size);
0276 if (buf == NULL) {
0277 pr_debug("memory allocation failure\n");
0278 return -1;
0279 }
0280
0281 ret = do_read(buf, size);
0282 if (ret < 0)
0283 goto out;
0284
0285 ret = parse_event_file(pevent, buf, size, sys);
0286 if (ret < 0)
0287 pr_debug("error parsing event file.\n");
0288 out:
0289 free(buf);
0290 return ret;
0291 }
0292
0293 static int read_ftrace_files(struct tep_handle *pevent)
0294 {
0295 unsigned long long size;
0296 int count;
0297 int i;
0298 int ret;
0299
0300 count = read4(pevent);
0301
0302 for (i = 0; i < count; i++) {
0303 size = read8(pevent);
0304 ret = read_ftrace_file(pevent, size);
0305 if (ret)
0306 return ret;
0307 }
0308 return 0;
0309 }
0310
0311 static int read_event_files(struct tep_handle *pevent)
0312 {
0313 unsigned long long size;
0314 char *sys;
0315 int systems;
0316 int count;
0317 int i,x;
0318 int ret;
0319
0320 systems = read4(pevent);
0321
0322 for (i = 0; i < systems; i++) {
0323 sys = read_string();
0324 if (sys == NULL)
0325 return -1;
0326
0327 count = read4(pevent);
0328
0329 for (x=0; x < count; x++) {
0330 size = read8(pevent);
0331 ret = read_event_file(pevent, sys, size);
0332 if (ret) {
0333 free(sys);
0334 return ret;
0335 }
0336 }
0337 free(sys);
0338 }
0339 return 0;
0340 }
0341
0342 static int read_saved_cmdline(struct tep_handle *pevent)
0343 {
0344 unsigned long long size;
0345 char *buf;
0346 int ret;
0347
0348
0349 size = read8(pevent);
0350 if (!size)
0351 return 0;
0352
0353 buf = malloc(size + 1);
0354 if (buf == NULL) {
0355 pr_debug("memory allocation failure\n");
0356 return -1;
0357 }
0358
0359 ret = do_read(buf, size);
0360 if (ret < 0) {
0361 pr_debug("error reading saved cmdlines\n");
0362 goto out;
0363 }
0364 buf[ret] = '\0';
0365
0366 parse_saved_cmdline(pevent, buf, size);
0367 ret = 0;
0368 out:
0369 free(buf);
0370 return ret;
0371 }
0372
0373 ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
0374 {
0375 char buf[BUFSIZ];
0376 char test[] = { 23, 8, 68 };
0377 char *version;
0378 int show_version = 0;
0379 int show_funcs = 0;
0380 int show_printk = 0;
0381 ssize_t size = -1;
0382 int file_bigendian;
0383 int host_bigendian;
0384 int file_long_size;
0385 int file_page_size;
0386 struct tep_handle *pevent = NULL;
0387 int err;
0388
0389 repipe = __repipe;
0390 input_fd = fd;
0391
0392 if (do_read(buf, 3) < 0)
0393 return -1;
0394 if (memcmp(buf, test, 3) != 0) {
0395 pr_debug("no trace data in the file");
0396 return -1;
0397 }
0398
0399 if (do_read(buf, 7) < 0)
0400 return -1;
0401 if (memcmp(buf, "tracing", 7) != 0) {
0402 pr_debug("not a trace file (missing 'tracing' tag)");
0403 return -1;
0404 }
0405
0406 version = read_string();
0407 if (version == NULL)
0408 return -1;
0409 if (show_version)
0410 printf("version = %s\n", version);
0411
0412 if (do_read(buf, 1) < 0) {
0413 free(version);
0414 return -1;
0415 }
0416 file_bigendian = buf[0];
0417 host_bigendian = bigendian();
0418
0419 if (trace_event__init(tevent)) {
0420 pr_debug("trace_event__init failed");
0421 goto out;
0422 }
0423
0424 pevent = tevent->pevent;
0425
0426 tep_set_flag(pevent, TEP_NSEC_OUTPUT);
0427 tep_set_file_bigendian(pevent, file_bigendian);
0428 tep_set_local_bigendian(pevent, host_bigendian);
0429
0430 if (do_read(buf, 1) < 0)
0431 goto out;
0432 file_long_size = buf[0];
0433
0434 file_page_size = read4(pevent);
0435 if (!file_page_size)
0436 goto out;
0437
0438 tep_set_long_size(pevent, file_long_size);
0439 tep_set_page_size(pevent, file_page_size);
0440
0441 err = read_header_files(pevent);
0442 if (err)
0443 goto out;
0444 err = read_ftrace_files(pevent);
0445 if (err)
0446 goto out;
0447 err = read_event_files(pevent);
0448 if (err)
0449 goto out;
0450 err = read_proc_kallsyms(pevent);
0451 if (err)
0452 goto out;
0453 err = read_ftrace_printk(pevent);
0454 if (err)
0455 goto out;
0456 if (atof(version) >= 0.6) {
0457 err = read_saved_cmdline(pevent);
0458 if (err)
0459 goto out;
0460 }
0461
0462 size = trace_data_size;
0463 repipe = false;
0464
0465 if (show_funcs) {
0466 tep_print_funcs(pevent);
0467 } else if (show_printk) {
0468 tep_print_printk(pevent);
0469 }
0470
0471 pevent = NULL;
0472
0473 out:
0474 if (pevent)
0475 trace_event__cleanup(tevent);
0476 free(version);
0477 return size;
0478 }