trace-event-read.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
  3. *
  4. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; version 2 of the License (not later!)
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  20. */
  21. #include <dirent.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <getopt.h>
  26. #include <stdarg.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/wait.h>
  30. #include <sys/mman.h>
  31. #include <pthread.h>
  32. #include <fcntl.h>
  33. #include <unistd.h>
  34. #include <errno.h>
  35. #include "../perf.h"
  36. #include "util.h"
  37. #include "trace-event.h"
  38. static int input_fd;
  39. int file_bigendian;
  40. int host_bigendian;
  41. static int long_size;
  42. static ssize_t trace_data_size;
  43. static bool repipe;
  44. static int __do_read(int fd, void *buf, int size)
  45. {
  46. int rsize = size;
  47. while (size) {
  48. int ret = read(fd, buf, size);
  49. if (ret <= 0)
  50. return -1;
  51. if (repipe) {
  52. int retw = write(STDOUT_FILENO, buf, ret);
  53. if (retw <= 0 || retw != ret) {
  54. pr_debug("repiping input file");
  55. return -1;
  56. }
  57. }
  58. size -= ret;
  59. buf += ret;
  60. }
  61. return rsize;
  62. }
  63. static int do_read(void *data, int size)
  64. {
  65. int r;
  66. r = __do_read(input_fd, data, size);
  67. if (r <= 0) {
  68. pr_debug("reading input file (size expected=%d received=%d)",
  69. size, r);
  70. return -1;
  71. }
  72. trace_data_size += r;
  73. return r;
  74. }
  75. /* If it fails, the next read will report it */
  76. static void skip(int size)
  77. {
  78. char buf[BUFSIZ];
  79. int r;
  80. while (size) {
  81. r = size > BUFSIZ ? BUFSIZ : size;
  82. do_read(buf, r);
  83. size -= r;
  84. };
  85. }
  86. static unsigned int read4(struct pevent *pevent)
  87. {
  88. unsigned int data;
  89. if (do_read(&data, 4) < 0)
  90. return 0;
  91. return __data2host4(pevent, data);
  92. }
  93. static unsigned long long read8(struct pevent *pevent)
  94. {
  95. unsigned long long data;
  96. if (do_read(&data, 8) < 0)
  97. return 0;
  98. return __data2host8(pevent, data);
  99. }
  100. static char *read_string(void)
  101. {
  102. char buf[BUFSIZ];
  103. char *str = NULL;
  104. int size = 0;
  105. off_t r;
  106. char c;
  107. for (;;) {
  108. r = read(input_fd, &c, 1);
  109. if (r < 0) {
  110. pr_debug("reading input file");
  111. goto out;
  112. }
  113. if (!r) {
  114. pr_debug("no data");
  115. goto out;
  116. }
  117. if (repipe) {
  118. int retw = write(STDOUT_FILENO, &c, 1);
  119. if (retw <= 0 || retw != r) {
  120. pr_debug("repiping input file string");
  121. goto out;
  122. }
  123. }
  124. buf[size++] = c;
  125. if (!c)
  126. break;
  127. }
  128. trace_data_size += size;
  129. str = malloc(size);
  130. if (str)
  131. memcpy(str, buf, size);
  132. out:
  133. return str;
  134. }
  135. static int read_proc_kallsyms(struct pevent *pevent)
  136. {
  137. unsigned int size;
  138. char *buf;
  139. size = read4(pevent);
  140. if (!size)
  141. return 0;
  142. buf = malloc(size + 1);
  143. if (buf == NULL)
  144. return -1;
  145. if (do_read(buf, size) < 0) {
  146. free(buf);
  147. return -1;
  148. }
  149. buf[size] = '\0';
  150. parse_proc_kallsyms(pevent, buf, size);
  151. free(buf);
  152. return 0;
  153. }
  154. static int read_ftrace_printk(struct pevent *pevent)
  155. {
  156. unsigned int size;
  157. char *buf;
  158. /* it can have 0 size */
  159. size = read4(pevent);
  160. if (!size)
  161. return 0;
  162. buf = malloc(size);
  163. if (buf == NULL)
  164. return -1;
  165. if (do_read(buf, size) < 0) {
  166. free(buf);
  167. return -1;
  168. }
  169. parse_ftrace_printk(pevent, buf, size);
  170. free(buf);
  171. return 0;
  172. }
  173. static int read_header_files(struct pevent *pevent)
  174. {
  175. unsigned long long size;
  176. char *header_event;
  177. char buf[BUFSIZ];
  178. int ret = 0;
  179. if (do_read(buf, 12) < 0)
  180. return -1;
  181. if (memcmp(buf, "header_page", 12) != 0) {
  182. pr_debug("did not read header page");
  183. return -1;
  184. }
  185. size = read8(pevent);
  186. skip(size);
  187. /*
  188. * The size field in the page is of type long,
  189. * use that instead, since it represents the kernel.
  190. */
  191. long_size = header_page_size_size;
  192. if (do_read(buf, 13) < 0)
  193. return -1;
  194. if (memcmp(buf, "header_event", 13) != 0) {
  195. pr_debug("did not read header event");
  196. return -1;
  197. }
  198. size = read8(pevent);
  199. header_event = malloc(size);
  200. if (header_event == NULL)
  201. return -1;
  202. if (do_read(header_event, size) < 0)
  203. ret = -1;
  204. free(header_event);
  205. return ret;
  206. }
  207. static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
  208. {
  209. char *buf;
  210. buf = malloc(size);
  211. if (buf == NULL)
  212. return -1;
  213. if (do_read(buf, size) < 0) {
  214. free(buf);
  215. return -1;
  216. }
  217. parse_ftrace_file(pevent, buf, size);
  218. free(buf);
  219. return 0;
  220. }
  221. static int read_event_file(struct pevent *pevent, char *sys,
  222. unsigned long long size)
  223. {
  224. char *buf;
  225. buf = malloc(size);
  226. if (buf == NULL)
  227. return -1;
  228. if (do_read(buf, size) < 0) {
  229. free(buf);
  230. return -1;
  231. }
  232. parse_event_file(pevent, buf, size, sys);
  233. free(buf);
  234. return 0;
  235. }
  236. static int read_ftrace_files(struct pevent *pevent)
  237. {
  238. unsigned long long size;
  239. int count;
  240. int i;
  241. int ret;
  242. count = read4(pevent);
  243. for (i = 0; i < count; i++) {
  244. size = read8(pevent);
  245. ret = read_ftrace_file(pevent, size);
  246. if (ret)
  247. return ret;
  248. }
  249. return 0;
  250. }
  251. static int read_event_files(struct pevent *pevent)
  252. {
  253. unsigned long long size;
  254. char *sys;
  255. int systems;
  256. int count;
  257. int i,x;
  258. int ret;
  259. systems = read4(pevent);
  260. for (i = 0; i < systems; i++) {
  261. sys = read_string();
  262. if (sys == NULL)
  263. return -1;
  264. count = read4(pevent);
  265. for (x=0; x < count; x++) {
  266. size = read8(pevent);
  267. ret = read_event_file(pevent, sys, size);
  268. if (ret)
  269. return ret;
  270. }
  271. }
  272. return 0;
  273. }
  274. ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
  275. {
  276. char buf[BUFSIZ];
  277. char test[] = { 23, 8, 68 };
  278. char *version;
  279. int show_version = 0;
  280. int show_funcs = 0;
  281. int show_printk = 0;
  282. ssize_t size = -1;
  283. struct pevent *pevent;
  284. int err;
  285. *ppevent = NULL;
  286. repipe = __repipe;
  287. input_fd = fd;
  288. if (do_read(buf, 3) < 0)
  289. return -1;
  290. if (memcmp(buf, test, 3) != 0) {
  291. pr_debug("no trace data in the file");
  292. return -1;
  293. }
  294. if (do_read(buf, 7) < 0)
  295. return -1;
  296. if (memcmp(buf, "tracing", 7) != 0) {
  297. pr_debug("not a trace file (missing 'tracing' tag)");
  298. return -1;
  299. }
  300. version = read_string();
  301. if (version == NULL)
  302. return -1;
  303. if (show_version)
  304. printf("version = %s\n", version);
  305. free(version);
  306. if (do_read(buf, 1) < 0)
  307. return -1;
  308. file_bigendian = buf[0];
  309. host_bigendian = bigendian();
  310. pevent = read_trace_init(file_bigendian, host_bigendian);
  311. if (pevent == NULL) {
  312. pr_debug("read_trace_init failed");
  313. goto out;
  314. }
  315. if (do_read(buf, 1) < 0)
  316. goto out;
  317. long_size = buf[0];
  318. page_size = read4(pevent);
  319. if (!page_size)
  320. goto out;
  321. err = read_header_files(pevent);
  322. if (err)
  323. goto out;
  324. err = read_ftrace_files(pevent);
  325. if (err)
  326. goto out;
  327. err = read_event_files(pevent);
  328. if (err)
  329. goto out;
  330. err = read_proc_kallsyms(pevent);
  331. if (err)
  332. goto out;
  333. err = read_ftrace_printk(pevent);
  334. if (err)
  335. goto out;
  336. size = trace_data_size;
  337. repipe = false;
  338. if (show_funcs) {
  339. pevent_print_funcs(pevent);
  340. } else if (show_printk) {
  341. pevent_print_printk(pevent);
  342. }
  343. *ppevent = pevent;
  344. pevent = NULL;
  345. out:
  346. if (pevent)
  347. pevent_free(pevent);
  348. return size;
  349. }