9731b3ed37f505fe2fb6bcb47b2dd24260f720b6
[lttv.git] / lttv / lttv / print.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 * 2005 Mathieu Desnoyers
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17 * MA 02111-1307, USA.
18 */
19
20 /* print.c
21 *
22 * Event printing routines.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <lttv/lttv.h>
30 #include <lttv/option.h>
31 #include <lttv/module.h>
32 #include <lttv/hook.h>
33 #include <lttv/attribute.h>
34 #include <lttv/iattribute.h>
35 #include <lttv/stats.h>
36 #include <lttv/filter.h>
37 #include <lttv/print.h>
38 #include <ltt/ltt.h>
39 #include <ltt/event.h>
40 #include <ltt/trace.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <ltt/ltt-private.h>
44 #include <babeltrace/ctf/events.h>
45 #include <string.h>
46 #include <inttypes.h>
47
48 static inline void print_enum_events(LttEvent *e, struct marker_field *f,
49 guint64 value, GString *s, LttvTracefileState *tfs)
50 {
51 LttTracefile *tf = tfs->parent.tf;
52 struct marker_info *info = marker_get_info_from_id(tf->mdata, e->event_id);
53 LttvTraceState *ts = (LttvTraceState*)(tfs->parent.t_context);
54 LttvNameTables *nt = ts->name_tables;
55
56 if (tf->name == LTT_CHANNEL_KERNEL) {
57 if (info->name == LTT_EVENT_SYSCALL_ENTRY
58 && f->name == LTT_FIELD_SYSCALL_ID) {
59 g_string_append_printf(s, " [%s]",
60 g_quark_to_string(nt->syscall_names[value]));
61 } else if ((info->name == LTT_EVENT_SOFT_IRQ_ENTRY
62 || info->name == LTT_EVENT_SOFT_IRQ_EXIT
63 || info->name == LTT_EVENT_SOFT_IRQ_RAISE)
64 && f->name == LTT_FIELD_SOFT_IRQ_ID) {
65 g_string_append_printf(s, " [%s]",
66 g_quark_to_string(nt->soft_irq_names[value]));
67 } else if (info->name == LTT_EVENT_KPROBE
68 && f->name == LTT_FIELD_IP) {
69 #if (__WORDSIZE == 32)
70 GQuark symbol = (GQuark)g_hash_table_lookup(nt->kprobe_hash,
71 (gconstpointer)&value);
72 #else
73 GQuark symbol = (GQuark)(unsigned long)g_hash_table_lookup(nt->kprobe_hash,
74 (gconstpointer)value);
75 #endif
76 if (symbol)
77 g_string_append_printf(s, " [%s]", g_quark_to_string(symbol));
78 }
79 }
80 }
81
82 void lttv_print_field(LttEvent *e, struct marker_field *f, GString *s,
83 gboolean field_names, LttvTracefileState *tfs)
84 {
85 GQuark name;
86 guint64 value;
87
88 //int nb, i;
89
90 switch(f->type) {
91 case LTT_TYPE_SIGNED_INT:
92 if(field_names) {
93 name = f->name;
94 if(name)
95 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
96 }
97 value = ltt_event_get_long_int(e,f);
98 //g_string_append_printf(s, "%lld", value);
99 g_string_append_printf(s, f->fmt->str, value);
100 //g_string_append_printf(s, type->fmt, ltt_event_get_long_int(e,f));
101 print_enum_events(e, f, value, s, tfs);
102 break;
103
104 case LTT_TYPE_UNSIGNED_INT:
105 if(field_names) {
106 name = f->name;
107 if(name)
108 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
109 }
110 value = ltt_event_get_long_unsigned(e,f);
111 //g_string_append_printf(s, "%llu", value);
112 g_string_append_printf(s, f->fmt->str, value);
113 print_enum_events(e, f, value, s, tfs);
114 //g_string_append_printf(s, type->fmt, ltt_event_get_long_unsigned(e,f));
115 break;
116
117 #if 0
118 case LTT_CHAR:
119 case LTT_UCHAR:
120 {
121 unsigned car = ltt_event_get_unsigned(e,f);
122 if(field_names) {
123 name = ltt_field_name(f);
124 if(name)
125 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
126 }
127 if(isprint(car)) {
128 if(field_names) {
129 name = ltt_field_name(f);
130 if(name)
131 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
132 }
133 //g_string_append_printf(s, "%c", car);
134 g_string_append_printf(s, type->fmt, car);
135 } else {
136 g_string_append_printf(s, "\\%x", car);
137 }
138 }
139 break;
140 case LTT_FLOAT:
141 if(field_names) {
142 name = ltt_field_name(f);
143 if(name)
144 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
145 }
146 //g_string_append_printf(s, "%g", ltt_event_get_double(e,f));
147 g_string_append_printf(s, type->fmt, ltt_event_get_double(e,f));
148 break;
149 #endif
150
151 case LTT_TYPE_POINTER:
152 if(field_names) {
153 name = f->name;
154 if(name)
155 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
156 }
157 g_string_append_printf(s, "0x%" PRIx64, ltt_event_get_long_unsigned(e,f));
158 //g_string_append_printf(s, type->fmt, ltt_event_get_long_unsigned(e,f));
159 break;
160
161 case LTT_TYPE_STRING:
162 if(field_names) {
163 name = f->name;
164 if(name)
165 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
166 }
167 g_string_append_printf(s, "\"%s\"", ltt_event_get_string(e,f));
168 break;
169
170 #if 0
171 case LTT_ENUM:
172 {
173 GQuark value = ltt_enum_string_get(type, ltt_event_get_unsigned(e,f));
174 if(field_names) {
175 name = ltt_field_name(f);
176 if(name)
177 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
178 }
179 if(value)
180 g_string_append_printf(s, "%s", g_quark_to_string(value));
181 else
182 g_string_append_printf(s, "%lld", ltt_event_get_long_int(e,f));
183 }
184 break;
185
186 case LTT_ARRAY:
187 case LTT_SEQUENCE:
188 if(field_names) {
189 name = ltt_field_name(f);
190 if(name)
191 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
192 }
193 // g_string_append_printf(s, "{ ");
194 //Insert header
195 g_string_append_printf(s, type->header);//tested, works fine.
196
197
198 nb = ltt_event_field_element_number(e,f);
199 for(i = 0 ; i < nb ; i++) {
200 LttField *child = ltt_event_field_element_select(e,f,i);
201 lttv_print_field(e, child, s, field_names, i);
202 if(i<nb-1)
203 g_string_append_printf(s,type->separator);
204 }
205 //g_string_append_printf(s, " }");
206 //Insert footer
207 g_string_append_printf(s, type->footer);//tested, works fine.
208 break;
209
210 case LTT_STRUCT:
211 if(field_names) {
212 name = ltt_field_name(f);
213 if(name)
214 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
215 }
216 // g_string_append_printf(s, "{ ");
217 //Insert header
218 g_string_append_printf(s, type->header);
219
220 nb = ltt_type_member_number(type);
221 for(i = 0 ; i < nb ; i++) {
222 LttField *element;
223 element = ltt_field_member(f,i);
224 lttv_print_field(e, element, s, field_names, i);
225 if(i < nb-1)
226 g_string_append_printf(s,type->separator);
227 }
228 //g_string_append_printf(s, " }");
229 //Insert footer
230 g_string_append_printf(s, type->footer);
231 break;
232
233 case LTT_UNION:
234 if(field_names) {
235 name = ltt_field_name(f);
236 if(name)
237 g_string_append_printf(s, "%s = ", g_quark_to_string(name));
238 }
239 // g_string_append_printf(s, "{ ");
240 g_string_append_printf(s, type->header);
241
242 nb = ltt_type_member_number(type);
243 for(i = 0 ; i < nb ; i++) {
244 LttField *element;
245 element = ltt_field_member(f,i);
246 lttv_print_field(e, element, s, field_names, i);
247 if(i<nb-1)
248 g_string_append_printf(s, type->separator);
249 }
250 // g_string_append_printf(s, " }");
251 g_string_append_printf(s, type->footer);
252 break;
253 #endif
254 case LTT_TYPE_COMPACT:
255 g_error("compact type printing not implemented");
256 break;
257 case LTT_TYPE_NONE:
258 break;
259 }
260 }
261
262 int getProcessInfosFromEvent(struct bt_ctf_event *ctf_event, GString* processInfos)
263 {
264 int pid, tid, ppid;
265 char *procname;
266 struct definition *scope;
267 unsigned long timestamp;
268
269 int ret = 0;
270
271 gboolean noError = TRUE;
272
273 timestamp = bt_ctf_get_timestamp(ctf_event);
274 if (timestamp == -1ULL) {
275 noError = FALSE;
276 }
277 if (noError) {
278 scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_EVENT_CONTEXT);
279 if (bt_ctf_field_get_error()) {
280 noError = FALSE;
281 }
282 }
283 if (noError) {
284 pid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_pid"));
285 if (bt_ctf_field_get_error()) {
286 noError = FALSE;
287 }
288 }
289 if (noError) {
290 tid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_tid"));
291 if (bt_ctf_field_get_error()) {
292 noError = FALSE;
293 }
294 }
295 if (noError) {
296 ppid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_ppid"));
297 if (bt_ctf_field_get_error()) {
298 noError = FALSE;
299 }
300 }
301 if (noError) {
302 procname = bt_ctf_get_char_array(bt_ctf_get_field(ctf_event, scope, "_procname"));
303 if (bt_ctf_field_get_error()) {
304 noError = FALSE;
305 }
306 }
307
308 if (noError) {
309 g_string_append_printf(processInfos, "%u, %u, %s, %u", pid, tid, procname, ppid);
310 }
311 else {
312 ret = -1;
313 }
314
315 return ret;
316 }
317
318
319 int getCPUIdFromEvent(struct bt_ctf_event *ctf_event, GString* cpuId_str)
320 {
321 struct definition *scope;
322 unsigned long timestamp;
323 unsigned int cpu_id;
324 int ret = 0;
325
326 gboolean noError = TRUE;
327
328 timestamp = bt_ctf_get_timestamp(ctf_event);
329 if (timestamp == -1ULL) {
330 noError = FALSE;
331 }
332 if (noError) {
333 scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT);
334 if (bt_ctf_field_get_error()) {
335 noError = FALSE;
336 }
337 }
338 if (noError) {
339 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id"));
340 if (bt_ctf_field_get_error()) {
341 noError = FALSE;
342 }
343 else {
344 g_string_append_printf(cpuId_str, "%u", cpu_id);
345 }
346 }
347
348 if (!noError) {
349 ret = -1;
350 }
351
352 return ret;
353 }
354
355 int getFields(struct bt_ctf_event *ctf_event, struct definition const *fields, GString* fieldsStr)
356 {
357 enum ctf_type_id fieldType = bt_ctf_field_type(fields);
358 int ret = 0, isSigned = -1, len = 0, i = 0;
359 struct definition *index_def;
360 switch (fieldType) {
361 case CTF_TYPE_INTEGER:
362 isSigned = bt_ctf_get_int_signedness(fields);
363 if (isSigned == 1) {
364 g_string_append_printf(fieldsStr, "%lu", bt_ctf_get_int64(fields));
365 }
366 else if (isSigned == 0) {
367 g_string_append_printf(fieldsStr, "%llu", bt_ctf_get_uint64(fields));
368 }
369 break;
370 case CTF_TYPE_STRING:
371 g_string_append_printf(fieldsStr, "%s", bt_ctf_get_string(fields));
372 break;
373
374 case CTF_TYPE_ARRAY:
375 g_string_append_printf(fieldsStr, "[ ");
376 len = bt_ctf_get_array_len(fields);
377 if (index_def = bt_ctf_get_index(ctf_event, fields, i)) {
378 for (i = 0; i < len; i++) {
379 if (i > 0) {
380 g_string_append_printf(fieldsStr, ", ");
381 }
382 bt_ctf_field_type(bt_ctf_get_index(ctf_event, fields, i));
383 g_string_append_printf(fieldsStr, " ");
384 g_string_append_printf(fieldsStr, "[%d] = ");
385 getFields(ctf_event, bt_ctf_get_index(ctf_event, fields, i), fieldsStr);
386 }
387 }
388 else {
389 g_string_append_printf(fieldsStr, "%s", bt_ctf_get_char_array(fields));
390 }
391 g_string_append_printf(fieldsStr, " ]");
392
393 break;
394 case CTF_TYPE_UNKNOWN:
395 default:
396 break;
397 }
398 return ret;
399 }
400
401 int getFieldsFromEvent(struct bt_ctf_event *ctf_event, GString* fields, gboolean field_names)
402 {
403 struct definition const * const *list = NULL;
404 unsigned int count;
405 int i = 0, j = 0, ret = 0;
406 gboolean noError = TRUE;
407 struct definition *scope;
408 scope = bt_ctf_get_top_level_scope(ctf_event, BT_EVENT_FIELDS);
409
410 if (!scope) {
411 noError = FALSE;
412 }
413 if (noError) {
414 ret = bt_ctf_get_field_list(ctf_event, scope, &list, &count);
415 if (ret < 0) {
416 noError = TRUE;
417 }
418 else {
419 for (i = 0; i < count; i++) {
420 if (i > 0) {
421 g_string_append_printf(fields, ", ");
422 }
423 const char *name = bt_ctf_field_name(list[i]);
424 if (field_names) {
425 g_string_append_printf(fields, "%s = ", name);
426 }
427 getFields(ctf_event, list[i] ,fields);
428 if (bt_ctf_field_get_error()) {
429 continue;
430 }
431 }
432 }
433 }
434 if (!noError) {
435 ret = -1;
436 }
437 return ret;
438 }
439
440 void lttv_event_to_string(struct bt_ctf_event *event, GString *a_string, gboolean field_names)
441 {
442 GString* processInfos = g_string_new("");
443 GString* fields = g_string_new("");
444 GString* cpuId_str = g_string_new("");
445
446 getProcessInfosFromEvent(event, processInfos);
447 getFieldsFromEvent(event, fields, field_names);
448 getCPUIdFromEvent(event, cpuId_str);
449
450 g_string_set_size(a_string,0);
451
452 g_string_append_printf(a_string, "%llu %s: { %s }", bt_ctf_get_timestamp(event), bt_ctf_event_name(event), cpuId_str->str);
453 if (strcmp("", processInfos->str) < 0) {
454 g_string_append_printf(a_string, ", { %s }", processInfos->str);
455 }
456 if (strcmp("", fields->str) < 0) {
457 g_string_append_printf(a_string, ", { %s }", fields->str);
458 }
459
460 g_string_free(fields, TRUE);
461 g_string_free(processInfos, TRUE);
462 g_string_free(cpuId_str, TRUE);
463 }
464
465 #ifdef BABEL_CLEANUP
466 void lttv_event_to_string(LttEvent *e, GString *s, gboolean mandatory_fields,
467 gboolean field_names, LttvTracefileState *tfs)
468 {
469 struct marker_field *field;
470 struct marker_info *info;
471
472 LttTime time;
473
474 guint cpu = tfs->cpu;
475 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
476 LttvProcessState *process = ts->running_process[cpu];
477
478 s = g_string_set_size(s,0);
479
480 info = marker_get_info_from_id(tfs->parent.tf->mdata, e->event_id);
481
482 if(mandatory_fields) {
483 time = ltt_event_time(e);
484 g_string_append_printf(s,"%s.%s: %ld.%09ld (%s/%s_%u)",
485 g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)),
486 g_quark_to_string(info->name), (long)time.tv_sec, time.tv_nsec,
487 g_quark_to_string(
488 ltt_trace_name(ltt_tracefile_get_trace(tfs->parent.tf))),
489 g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)), cpu);
490 /* Print the process id and the state/interrupt type of the process */
491 g_string_append_printf(s,", %u, %u, %s, %s, %u, 0x%" PRIx64", %s",
492 process->pid,
493 process->tgid,
494 g_quark_to_string(process->name),
495 g_quark_to_string(process->brand),
496 process->ppid,
497 process->current_function,
498 g_quark_to_string(process->state->t));
499 }
500
501 if(marker_get_num_fields(info) == 0) return;
502 g_string_append_printf(s, " ");
503 g_string_append_printf(s, "{ ");
504 for (field = marker_get_field(info, 0);
505 field != marker_get_field(info, marker_get_num_fields(info));
506 field++) {
507 if(field != marker_get_field(info, 0))
508 g_string_append_printf(s, ", ");
509 lttv_print_field(e, field, s, field_names, tfs);
510 }
511 g_string_append_printf(s, " }");
512 }
513 #endif /* BABEL_CLEANUP */
514
515 static void init()
516 {
517 }
518
519 static void destroy()
520 {
521 }
522
523 LTTV_MODULE("print", "Print events", \
524 "Produce a detailed text printout of events", \
525 init, destroy)
526
This page took 0.038714 seconds and 3 git commands to generate.