builtin-trace.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "builtin.h"
  2. #include "util/util.h"
  3. #include "util/cache.h"
  4. #include "util/symbol.h"
  5. #include "util/thread.h"
  6. #include "util/header.h"
  7. #include "util/parse-options.h"
  8. #include "perf.h"
  9. #include "util/debug.h"
  10. #include "util/trace-event.h"
  11. #include "util/data_map.h"
  12. static char const *input_name = "perf.data";
  13. static unsigned long total = 0;
  14. static unsigned long total_comm = 0;
  15. static struct perf_header *header;
  16. static u64 sample_type;
  17. static char *cwd;
  18. static int cwdlen;
  19. static int
  20. process_comm_event(event_t *event, unsigned long offset, unsigned long head)
  21. {
  22. struct thread *thread = threads__findnew(event->comm.pid);
  23. dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
  24. (void *)(offset + head),
  25. (void *)(long)(event->header.size),
  26. event->comm.comm, event->comm.pid);
  27. if (thread == NULL ||
  28. thread__set_comm(thread, event->comm.comm)) {
  29. dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
  30. return -1;
  31. }
  32. total_comm++;
  33. return 0;
  34. }
  35. static int
  36. process_sample_event(event_t *event, unsigned long offset, unsigned long head)
  37. {
  38. u64 ip = event->ip.ip;
  39. u64 timestamp = -1;
  40. u32 cpu = -1;
  41. u64 period = 1;
  42. void *more_data = event->ip.__more_data;
  43. struct thread *thread = threads__findnew(event->ip.pid);
  44. if (sample_type & PERF_SAMPLE_TIME) {
  45. timestamp = *(u64 *)more_data;
  46. more_data += sizeof(u64);
  47. }
  48. if (sample_type & PERF_SAMPLE_CPU) {
  49. cpu = *(u32 *)more_data;
  50. more_data += sizeof(u32);
  51. more_data += sizeof(u32); /* reserved */
  52. }
  53. if (sample_type & PERF_SAMPLE_PERIOD) {
  54. period = *(u64 *)more_data;
  55. more_data += sizeof(u64);
  56. }
  57. dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
  58. (void *)(offset + head),
  59. (void *)(long)(event->header.size),
  60. event->header.misc,
  61. event->ip.pid, event->ip.tid,
  62. (void *)(long)ip,
  63. (long long)period);
  64. if (thread == NULL) {
  65. pr_debug("problem processing %d event, skipping it.\n",
  66. event->header.type);
  67. return -1;
  68. }
  69. dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
  70. if (sample_type & PERF_SAMPLE_RAW) {
  71. struct {
  72. u32 size;
  73. char data[0];
  74. } *raw = more_data;
  75. /*
  76. * FIXME: better resolve from pid from the struct trace_entry
  77. * field, although it should be the same than this perf
  78. * event pid
  79. */
  80. print_event(cpu, raw->data, raw->size, timestamp, thread->comm);
  81. }
  82. total += period;
  83. return 0;
  84. }
  85. static int sample_type_check(u64 type)
  86. {
  87. sample_type = type;
  88. if (!(sample_type & PERF_SAMPLE_RAW)) {
  89. fprintf(stderr,
  90. "No trace sample to read. Did you call perf record "
  91. "without -R?");
  92. return -1;
  93. }
  94. return 0;
  95. }
  96. static struct perf_file_handler file_handler = {
  97. .process_sample_event = process_sample_event,
  98. .process_comm_event = process_comm_event,
  99. .sample_type_check = sample_type_check,
  100. };
  101. static int __cmd_trace(void)
  102. {
  103. register_idle_thread();
  104. register_perf_file_handler(&file_handler);
  105. return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
  106. }
  107. static const char * const annotate_usage[] = {
  108. "perf trace [<options>] <command>",
  109. NULL
  110. };
  111. static const struct option options[] = {
  112. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
  113. "dump raw trace in ASCII"),
  114. OPT_BOOLEAN('v', "verbose", &verbose,
  115. "be more verbose (show symbol address, etc)"),
  116. OPT_BOOLEAN('l', "latency", &latency_format,
  117. "show latency attributes (irqs/preemption disabled, etc)"),
  118. OPT_END()
  119. };
  120. int cmd_trace(int argc, const char **argv, const char *prefix __used)
  121. {
  122. symbol__init(0);
  123. argc = parse_options(argc, argv, options, annotate_usage, 0);
  124. if (argc) {
  125. /*
  126. * Special case: if there's an argument left then assume tha
  127. * it's a symbol filter:
  128. */
  129. if (argc > 1)
  130. usage_with_options(annotate_usage, options);
  131. }
  132. setup_pager();
  133. return __cmd_trace();
  134. }