diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | trace-cmd.h | 5 | ||||
-rw-r--r-- | trace-input.c | 293 | ||||
-rw-r--r-- | trace-read.c | 259 |
4 files changed, 306 insertions, 253 deletions
@@ -35,7 +35,7 @@ libparsevent.so: $(PEVENT_LIB_OBJS) | |||
35 | libparsevent.a: $(PEVENT_LIB_OBJS) | 35 | libparsevent.a: $(PEVENT_LIB_OBJS) |
36 | $(RM) $@; $(AR) rcs $@ $^ | 36 | $(RM) $@; $(AR) rcs $@ $^ |
37 | 37 | ||
38 | TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o | 38 | TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o |
39 | 39 | ||
40 | libtracecmd.a: $(TCMD_LIB_OBJS) | 40 | libtracecmd.a: $(TCMD_LIB_OBJS) |
41 | $(RM) $@; $(AR) rcs $@ $^ | 41 | $(RM) $@; $(AR) rcs $@ $^ |
diff --git a/trace-cmd.h b/trace-cmd.h index 667ab3e..4e1d900 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -33,4 +33,9 @@ enum { | |||
33 | #define TS_SHIFT 27 | 33 | #define TS_SHIFT 27 |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | struct tracecmd_handle; | ||
37 | |||
38 | struct tracecmd_handle *tracecmd_open(int fd); | ||
39 | int tracecmd_read_headers(struct tracecmd_handle *handle); | ||
40 | |||
36 | #endif /* _TRACE_CMD_H */ | 41 | #endif /* _TRACE_CMD_H */ |
diff --git a/trace-input.c b/trace-input.c new file mode 100644 index 0000000..e2c089b --- /dev/null +++ b/trace-input.c | |||
@@ -0,0 +1,293 @@ | |||
1 | #define _LARGEFILE64_SOURCE | ||
2 | #define _GNU_SOURCE | ||
3 | #include <dirent.h> | ||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <string.h> | ||
7 | #include <getopt.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <sys/types.h> | ||
10 | #include <sys/stat.h> | ||
11 | #include <sys/wait.h> | ||
12 | #include <sys/mman.h> | ||
13 | #include <pthread.h> | ||
14 | #include <fcntl.h> | ||
15 | #include <unistd.h> | ||
16 | #include <ctype.h> | ||
17 | #include <errno.h> | ||
18 | |||
19 | #include "trace-cmd.h" | ||
20 | |||
21 | extern int show_events; | ||
22 | |||
23 | struct tracecmd_handle { | ||
24 | int fd; | ||
25 | }; | ||
26 | |||
27 | int file_bigendian; | ||
28 | int host_bigendian; | ||
29 | int long_size; | ||
30 | |||
31 | int read_or_die(void *data, int size) | ||
32 | { | ||
33 | int r; | ||
34 | |||
35 | r = read(input_fd, data, size); | ||
36 | if (r != size) | ||
37 | die("reading input file (size expected=%d received=%d)", | ||
38 | size, r); | ||
39 | return r; | ||
40 | } | ||
41 | |||
42 | static char *read_string(void) | ||
43 | { | ||
44 | char buf[BUFSIZ]; | ||
45 | char *str = NULL; | ||
46 | int size = 0; | ||
47 | int i; | ||
48 | int r; | ||
49 | |||
50 | for (;;) { | ||
51 | r = read(input_fd, buf, BUFSIZ); | ||
52 | if (r < 0) | ||
53 | die("reading input file"); | ||
54 | |||
55 | if (!r) | ||
56 | die("no data"); | ||
57 | |||
58 | for (i = 0; i < r; i++) { | ||
59 | if (!buf[i]) | ||
60 | break; | ||
61 | } | ||
62 | if (i < r) | ||
63 | break; | ||
64 | |||
65 | if (str) { | ||
66 | size += BUFSIZ; | ||
67 | str = realloc(str, size); | ||
68 | if (!str) | ||
69 | die("malloc of size %d", size); | ||
70 | memcpy(str + (size - BUFSIZ), buf, BUFSIZ); | ||
71 | } else { | ||
72 | size = BUFSIZ; | ||
73 | str = malloc_or_die(size); | ||
74 | memcpy(str, buf, size); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /* move the file descriptor to the end of the string */ | ||
79 | r = lseek(input_fd, -(r - (i+1)), SEEK_CUR); | ||
80 | if (r < 0) | ||
81 | die("lseek"); | ||
82 | |||
83 | if (str) { | ||
84 | size += i + 1; | ||
85 | str = realloc(str, size); | ||
86 | if (!str) | ||
87 | die("malloc of size %d", size); | ||
88 | memcpy(str + (size - i), buf, i); | ||
89 | str[size] = 0; | ||
90 | } else { | ||
91 | size = i + 1; | ||
92 | str = malloc_or_die(i); | ||
93 | memcpy(str, buf, i); | ||
94 | str[i] = 0; | ||
95 | } | ||
96 | |||
97 | return str; | ||
98 | } | ||
99 | |||
100 | unsigned int read4(void) | ||
101 | { | ||
102 | unsigned int data; | ||
103 | |||
104 | read_or_die(&data, 4); | ||
105 | return __data2host4(data); | ||
106 | } | ||
107 | |||
108 | unsigned long long read8(void) | ||
109 | { | ||
110 | unsigned long long data; | ||
111 | |||
112 | read_or_die(&data, 8); | ||
113 | return __data2host8(data); | ||
114 | } | ||
115 | |||
116 | static void read_header_files(void) | ||
117 | { | ||
118 | unsigned long long size; | ||
119 | char *header_page; | ||
120 | char *header_event; | ||
121 | char buf[BUFSIZ]; | ||
122 | |||
123 | read_or_die(buf, 12); | ||
124 | if (memcmp(buf, "header_page", 12) != 0) | ||
125 | die("did not read header page"); | ||
126 | |||
127 | size = read8(); | ||
128 | header_page = malloc_or_die(size); | ||
129 | read_or_die(header_page, size); | ||
130 | pevent_parse_header_page(header_page, size); | ||
131 | free(header_page); | ||
132 | |||
133 | /* | ||
134 | * The size field in the page is of type long, | ||
135 | * use that instead, since it represents the kernel. | ||
136 | */ | ||
137 | long_size = header_page_size_size; | ||
138 | |||
139 | read_or_die(buf, 13); | ||
140 | if (memcmp(buf, "header_event", 13) != 0) | ||
141 | die("did not read header event"); | ||
142 | |||
143 | size = read8(); | ||
144 | header_event = malloc_or_die(size); | ||
145 | read_or_die(header_event, size); | ||
146 | free(header_event); | ||
147 | } | ||
148 | |||
149 | static void read_ftrace_file(unsigned long long size) | ||
150 | { | ||
151 | char *buf; | ||
152 | |||
153 | buf = malloc_or_die(size); | ||
154 | read_or_die(buf, size); | ||
155 | pevent_parse_event(buf, size, "ftrace"); | ||
156 | free(buf); | ||
157 | } | ||
158 | |||
159 | static void read_event_file(char *system, unsigned long long size) | ||
160 | { | ||
161 | char *buf; | ||
162 | |||
163 | buf = malloc_or_die(size+1); | ||
164 | read_or_die(buf, size); | ||
165 | buf[size] = 0; | ||
166 | if (show_events) | ||
167 | printf("%s\n", buf); | ||
168 | pevent_parse_event(buf, size, system); | ||
169 | free(buf); | ||
170 | } | ||
171 | |||
172 | static void read_ftrace_files(void) | ||
173 | { | ||
174 | unsigned long long size; | ||
175 | int count; | ||
176 | int i; | ||
177 | |||
178 | count = read4(); | ||
179 | |||
180 | for (i = 0; i < count; i++) { | ||
181 | size = read8(); | ||
182 | read_ftrace_file(size); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static void read_event_files(void) | ||
187 | { | ||
188 | unsigned long long size; | ||
189 | char *system; | ||
190 | int systems; | ||
191 | int count; | ||
192 | int i,x; | ||
193 | |||
194 | systems = read4(); | ||
195 | |||
196 | for (i = 0; i < systems; i++) { | ||
197 | system = read_string(); | ||
198 | |||
199 | count = read4(); | ||
200 | for (x=0; x < count; x++) { | ||
201 | size = read8(); | ||
202 | read_event_file(system, size); | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void read_proc_kallsyms(void) | ||
208 | { | ||
209 | unsigned int size; | ||
210 | char *buf; | ||
211 | |||
212 | size = read4(); | ||
213 | if (!size) | ||
214 | return; | ||
215 | |||
216 | buf = malloc_or_die(size); | ||
217 | read_or_die(buf, size); | ||
218 | |||
219 | parse_proc_kallsyms(buf, size); | ||
220 | |||
221 | free(buf); | ||
222 | } | ||
223 | |||
224 | static void read_ftrace_printk(void) | ||
225 | { | ||
226 | unsigned int size; | ||
227 | char *buf; | ||
228 | |||
229 | size = read4(); | ||
230 | if (!size) | ||
231 | return; | ||
232 | |||
233 | buf = malloc_or_die(size); | ||
234 | read_or_die(buf, size); | ||
235 | |||
236 | parse_ftrace_printk(buf, size); | ||
237 | |||
238 | free(buf); | ||
239 | } | ||
240 | |||
241 | int read_trace_files(void) | ||
242 | { | ||
243 | read_header_files(); | ||
244 | read_ftrace_files(); | ||
245 | read_event_files(); | ||
246 | read_proc_kallsyms(); | ||
247 | read_ftrace_printk(); | ||
248 | |||
249 | trace_load_plugins(); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | struct tracecmd_handle *tracecmd_open(int fd) | ||
255 | { | ||
256 | struct tracecmd_handle *handle; | ||
257 | char test[] = { 23, 8, 68 }; | ||
258 | char *version; | ||
259 | char buf[BUFSIZ]; | ||
260 | |||
261 | handle = malloc(sizeof(*handle)); | ||
262 | if (!handle) | ||
263 | return NULL; | ||
264 | |||
265 | handle->fd = fd; | ||
266 | |||
267 | input_fd = open(input_file, O_RDONLY); | ||
268 | if (input_fd < 0) | ||
269 | die("opening '%s'\n", input_file); | ||
270 | |||
271 | read_or_die(buf, 3); | ||
272 | if (memcmp(buf, test, 3) != 0) | ||
273 | die("not an trace data file"); | ||
274 | |||
275 | read_or_die(buf, 7); | ||
276 | if (memcmp(buf, "tracing", 7) != 0) | ||
277 | die("not a trace file (missing tracing)"); | ||
278 | |||
279 | version = read_string(); | ||
280 | printf("version = %s\n", version); | ||
281 | free(version); | ||
282 | |||
283 | read_or_die(buf, 1); | ||
284 | file_bigendian = buf[0]; | ||
285 | host_bigendian = bigendian(); | ||
286 | |||
287 | read_or_die(buf, 1); | ||
288 | long_size = buf[0]; | ||
289 | |||
290 | page_size = read4(); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
diff --git a/trace-read.c b/trace-read.c index cb358b0..395eeef 100644 --- a/trace-read.c +++ b/trace-read.c | |||
@@ -43,224 +43,10 @@ const char *input_file = "trace.dat"; | |||
43 | 43 | ||
44 | static int read_page; | 44 | static int read_page; |
45 | 45 | ||
46 | int file_bigendian; | 46 | int show_events = 0; |
47 | int host_bigendian; | ||
48 | static int long_size; | ||
49 | |||
50 | static int show_events = 0; | ||
51 | 47 | ||
52 | static int filter_cpu = -1; | 48 | static int filter_cpu = -1; |
53 | 49 | ||
54 | static int read_or_die(void *data, int size) | ||
55 | { | ||
56 | int r; | ||
57 | |||
58 | r = read(input_fd, data, size); | ||
59 | if (r != size) | ||
60 | die("reading input file (size expected=%d received=%d)", | ||
61 | size, r); | ||
62 | return r; | ||
63 | } | ||
64 | |||
65 | static unsigned int read4(void) | ||
66 | { | ||
67 | unsigned int data; | ||
68 | |||
69 | read_or_die(&data, 4); | ||
70 | return __data2host4(data); | ||
71 | } | ||
72 | |||
73 | static unsigned long long read8(void) | ||
74 | { | ||
75 | unsigned long long data; | ||
76 | |||
77 | read_or_die(&data, 8); | ||
78 | return __data2host8(data); | ||
79 | } | ||
80 | |||
81 | static char *read_string(void) | ||
82 | { | ||
83 | char buf[BUFSIZ]; | ||
84 | char *str = NULL; | ||
85 | int size = 0; | ||
86 | int i; | ||
87 | int r; | ||
88 | |||
89 | for (;;) { | ||
90 | r = read(input_fd, buf, BUFSIZ); | ||
91 | if (r < 0) | ||
92 | die("reading input file"); | ||
93 | |||
94 | if (!r) | ||
95 | die("no data"); | ||
96 | |||
97 | for (i = 0; i < r; i++) { | ||
98 | if (!buf[i]) | ||
99 | break; | ||
100 | } | ||
101 | if (i < r) | ||
102 | break; | ||
103 | |||
104 | if (str) { | ||
105 | size += BUFSIZ; | ||
106 | str = realloc(str, size); | ||
107 | if (!str) | ||
108 | die("malloc of size %d", size); | ||
109 | memcpy(str + (size - BUFSIZ), buf, BUFSIZ); | ||
110 | } else { | ||
111 | size = BUFSIZ; | ||
112 | str = malloc_or_die(size); | ||
113 | memcpy(str, buf, size); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* move the file descriptor to the end of the string */ | ||
118 | r = lseek(input_fd, -(r - (i+1)), SEEK_CUR); | ||
119 | if (r < 0) | ||
120 | die("lseek"); | ||
121 | |||
122 | if (str) { | ||
123 | size += i + 1; | ||
124 | str = realloc(str, size); | ||
125 | if (!str) | ||
126 | die("malloc of size %d", size); | ||
127 | memcpy(str + (size - i), buf, i); | ||
128 | str[size] = 0; | ||
129 | } else { | ||
130 | size = i + 1; | ||
131 | str = malloc_or_die(i); | ||
132 | memcpy(str, buf, i); | ||
133 | str[i] = 0; | ||
134 | } | ||
135 | |||
136 | return str; | ||
137 | } | ||
138 | |||
139 | static void read_proc_kallsyms(void) | ||
140 | { | ||
141 | unsigned int size; | ||
142 | char *buf; | ||
143 | |||
144 | size = read4(); | ||
145 | if (!size) | ||
146 | return; | ||
147 | |||
148 | buf = malloc_or_die(size); | ||
149 | read_or_die(buf, size); | ||
150 | |||
151 | parse_proc_kallsyms(buf, size); | ||
152 | |||
153 | free(buf); | ||
154 | } | ||
155 | |||
156 | static void read_ftrace_printk(void) | ||
157 | { | ||
158 | unsigned int size; | ||
159 | char *buf; | ||
160 | |||
161 | size = read4(); | ||
162 | if (!size) | ||
163 | return; | ||
164 | |||
165 | buf = malloc_or_die(size); | ||
166 | read_or_die(buf, size); | ||
167 | |||
168 | parse_ftrace_printk(buf, size); | ||
169 | |||
170 | free(buf); | ||
171 | } | ||
172 | |||
173 | static void read_header_files(void) | ||
174 | { | ||
175 | unsigned long long size; | ||
176 | char *header_page; | ||
177 | char *header_event; | ||
178 | char buf[BUFSIZ]; | ||
179 | |||
180 | read_or_die(buf, 12); | ||
181 | if (memcmp(buf, "header_page", 12) != 0) | ||
182 | die("did not read header page"); | ||
183 | |||
184 | size = read8(); | ||
185 | header_page = malloc_or_die(size); | ||
186 | read_or_die(header_page, size); | ||
187 | pevent_parse_header_page(header_page, size); | ||
188 | free(header_page); | ||
189 | |||
190 | /* | ||
191 | * The size field in the page is of type long, | ||
192 | * use that instead, since it represents the kernel. | ||
193 | */ | ||
194 | long_size = header_page_size_size; | ||
195 | |||
196 | read_or_die(buf, 13); | ||
197 | if (memcmp(buf, "header_event", 13) != 0) | ||
198 | die("did not read header event"); | ||
199 | |||
200 | size = read8(); | ||
201 | header_event = malloc_or_die(size); | ||
202 | read_or_die(header_event, size); | ||
203 | free(header_event); | ||
204 | } | ||
205 | |||
206 | static void read_ftrace_file(unsigned long long size) | ||
207 | { | ||
208 | char *buf; | ||
209 | |||
210 | buf = malloc_or_die(size); | ||
211 | read_or_die(buf, size); | ||
212 | pevent_parse_event(buf, size, "ftrace"); | ||
213 | free(buf); | ||
214 | } | ||
215 | |||
216 | static void read_event_file(char *system, unsigned long long size) | ||
217 | { | ||
218 | char *buf; | ||
219 | |||
220 | buf = malloc_or_die(size+1); | ||
221 | read_or_die(buf, size); | ||
222 | buf[size] = 0; | ||
223 | if (show_events) | ||
224 | printf("%s\n", buf); | ||
225 | pevent_parse_event(buf, size, system); | ||
226 | free(buf); | ||
227 | } | ||
228 | |||
229 | static void read_ftrace_files(void) | ||
230 | { | ||
231 | unsigned long long size; | ||
232 | int count; | ||
233 | int i; | ||
234 | |||
235 | count = read4(); | ||
236 | |||
237 | for (i = 0; i < count; i++) { | ||
238 | size = read8(); | ||
239 | read_ftrace_file(size); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void read_event_files(void) | ||
244 | { | ||
245 | unsigned long long size; | ||
246 | char *system; | ||
247 | int systems; | ||
248 | int count; | ||
249 | int i,x; | ||
250 | |||
251 | systems = read4(); | ||
252 | |||
253 | for (i = 0; i < systems; i++) { | ||
254 | system = read_string(); | ||
255 | |||
256 | count = read4(); | ||
257 | for (x=0; x < count; x++) { | ||
258 | size = read8(); | ||
259 | read_event_file(system, size); | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | struct cpu_data { | 50 | struct cpu_data { |
265 | unsigned long long offset; | 51 | unsigned long long offset; |
266 | unsigned long long size; | 52 | unsigned long long size; |
@@ -629,6 +415,11 @@ static void read_rest(void) | |||
629 | } while (r > 0); | 415 | } while (r > 0); |
630 | } | 416 | } |
631 | 417 | ||
418 | unsigned int read4(void); | ||
419 | unsigned long long read8(void); | ||
420 | int read_or_die(void *data, int size); | ||
421 | extern int long_size; | ||
422 | |||
632 | static void read_data_info(void) | 423 | static void read_data_info(void) |
633 | { | 424 | { |
634 | unsigned long long ts; | 425 | unsigned long long ts; |
@@ -695,47 +486,11 @@ static void read_data_info(void) | |||
695 | 486 | ||
696 | int read_trace_header(void) | 487 | int read_trace_header(void) |
697 | { | 488 | { |
698 | char test[] = { 23, 8, 68 }; | ||
699 | char *version; | ||
700 | char buf[BUFSIZ]; | ||
701 | |||
702 | input_fd = open(input_file, O_RDONLY); | 489 | input_fd = open(input_file, O_RDONLY); |
703 | if (input_fd < 0) | 490 | if (input_fd < 0) |
704 | die("opening '%s'\n", input_file); | 491 | die("opening '%s'\n", input_file); |
705 | 492 | ||
706 | read_or_die(buf, 3); | 493 | tracecmd_open(input_fd); |
707 | if (memcmp(buf, test, 3) != 0) | ||
708 | die("not an trace data file"); | ||
709 | |||
710 | read_or_die(buf, 7); | ||
711 | if (memcmp(buf, "tracing", 7) != 0) | ||
712 | die("not a trace file (missing tracing)"); | ||
713 | |||
714 | version = read_string(); | ||
715 | printf("version = %s\n", version); | ||
716 | free(version); | ||
717 | |||
718 | read_or_die(buf, 1); | ||
719 | file_bigendian = buf[0]; | ||
720 | host_bigendian = bigendian(); | ||
721 | |||
722 | read_or_die(buf, 1); | ||
723 | long_size = buf[0]; | ||
724 | |||
725 | page_size = read4(); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | int read_trace_files(void) | ||
731 | { | ||
732 | read_header_files(); | ||
733 | read_ftrace_files(); | ||
734 | read_event_files(); | ||
735 | read_proc_kallsyms(); | ||
736 | read_ftrace_printk(); | ||
737 | |||
738 | trace_load_plugins(); | ||
739 | 494 | ||
740 | return 0; | 495 | return 0; |
741 | } | 496 | } |