1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 * 2005 Mathieu Desnoyers
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;
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.
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,
22 * Event printing routines.
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>
36 #include <lttv/stats.h>
37 #include <lttv/filter.h>
39 #include <lttv/print.h>
41 #include <ltt/event.h>
42 #include <ltt/trace.h>
45 #include <ltt/ltt-private.h>
46 #include <babeltrace/ctf/events.h>
49 #include <lttv/event.h>
50 #include <lttv/traceset.h>
52 static inline void print_enum_events(LttEvent
*e
, struct marker_field
*f
,
53 guint64 value
, GString
*s
, LttvTracefileState
*tfs
)
55 LttvTraceState
*ts
= (LttvTraceState
*)(tfs
->parent
.t_context
);
56 LttvNameTables
*nt
= ts
->name_tables
;
58 if (tf
->name
== LTT_CHANNEL_KERNEL
) {
59 if (info
->name
== LTT_EVENT_SYSCALL_ENTRY
60 && f
->name
== LTT_FIELD_SYSCALL_ID
) {
61 g_string_append_printf(s
, " [%s]",
62 g_quark_to_string(nt
->syscall_names
[value
]));
63 } else if ((info
->name
== LTT_EVENT_SOFT_IRQ_ENTRY
64 || info
->name
== LTT_EVENT_SOFT_IRQ_EXIT
65 || info
->name
== LTT_EVENT_SOFT_IRQ_RAISE
)
66 && f
->name
== LTT_FIELD_SOFT_IRQ_ID
) {
67 g_string_append_printf(s
, " [%s]",
68 g_quark_to_string(nt
->soft_irq_names
[value
]));
69 } else if (info
->name
== LTT_EVENT_KPROBE
70 && f
->name
== LTT_FIELD_IP
) {
71 #if (__WORDSIZE == 32)
72 GQuark symbol
= (GQuark
)g_hash_table_lookup(nt
->kprobe_hash
,
73 (gconstpointer
)&value
);
75 GQuark symbol
= (GQuark
)(unsigned long)g_hash_table_lookup(nt
->kprobe_hash
,
76 (gconstpointer
)value
);
79 g_string_append_printf(s
, " [%s]", g_quark_to_string(symbol
));
84 void lttv_print_field(LttEvent
*e
, struct marker_field
*f
, GString
*s
,
85 gboolean field_names
, LttvTracefileState
*tfs
)
93 case LTT_TYPE_SIGNED_INT
:
97 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
99 value
= ltt_event_get_long_int(e
,f
);
100 //g_string_append_printf(s, "%lld", value);
101 g_string_append_printf(s
, f
->fmt
->str
, value
);
102 //g_string_append_printf(s, type->fmt, ltt_event_get_long_int(e,f));
103 print_enum_events(e
, f
, value
, s
, tfs
);
106 case LTT_TYPE_UNSIGNED_INT
:
110 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
112 value
= ltt_event_get_long_unsigned(e
,f
);
113 //g_string_append_printf(s, "%llu", value);
114 g_string_append_printf(s
, f
->fmt
->str
, value
);
115 print_enum_events(e
, f
, value
, s
, tfs
);
116 //g_string_append_printf(s, type->fmt, ltt_event_get_long_unsigned(e,f));
123 unsigned car
= ltt_event_get_unsigned(e
,f
);
125 name
= ltt_field_name(f
);
127 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
131 name
= ltt_field_name(f
);
133 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
135 //g_string_append_printf(s, "%c", car);
136 g_string_append_printf(s
, type
->fmt
, car
);
138 g_string_append_printf(s
, "\\%x", car
);
144 name
= ltt_field_name(f
);
146 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
148 //g_string_append_printf(s, "%g", ltt_event_get_double(e,f));
149 g_string_append_printf(s
, type
->fmt
, ltt_event_get_double(e
,f
));
153 case LTT_TYPE_POINTER
:
157 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
159 g_string_append_printf(s
, "0x%" PRIx64
, ltt_event_get_long_unsigned(e
,f
));
160 //g_string_append_printf(s, type->fmt, ltt_event_get_long_unsigned(e,f));
163 case LTT_TYPE_STRING
:
167 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
169 g_string_append_printf(s
, "\"%s\"", ltt_event_get_string(e
,f
));
175 GQuark value
= ltt_enum_string_get(type
, ltt_event_get_unsigned(e
,f
));
177 name
= ltt_field_name(f
);
179 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
182 g_string_append_printf(s
, "%s", g_quark_to_string(value
));
184 g_string_append_printf(s
, "%lld", ltt_event_get_long_int(e
,f
));
191 name
= ltt_field_name(f
);
193 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
195 // g_string_append_printf(s, "{ ");
197 g_string_append_printf(s
, type
->header
);//tested, works fine.
200 nb
= ltt_event_field_element_number(e
,f
);
201 for(i
= 0 ; i
< nb
; i
++) {
202 LttField
*child
= ltt_event_field_element_select(e
,f
,i
);
203 lttv_print_field(e
, child
, s
, field_names
, i
);
205 g_string_append_printf(s
,type
->separator
);
207 //g_string_append_printf(s, " }");
209 g_string_append_printf(s
, type
->footer
);//tested, works fine.
214 name
= ltt_field_name(f
);
216 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
218 // g_string_append_printf(s, "{ ");
220 g_string_append_printf(s
, type
->header
);
222 nb
= ltt_type_member_number(type
);
223 for(i
= 0 ; i
< nb
; i
++) {
225 element
= ltt_field_member(f
,i
);
226 lttv_print_field(e
, element
, s
, field_names
, i
);
228 g_string_append_printf(s
,type
->separator
);
230 //g_string_append_printf(s, " }");
232 g_string_append_printf(s
, type
->footer
);
237 name
= ltt_field_name(f
);
239 g_string_append_printf(s
, "%s = ", g_quark_to_string(name
));
241 // g_string_append_printf(s, "{ ");
242 g_string_append_printf(s
, type
->header
);
244 nb
= ltt_type_member_number(type
);
245 for(i
= 0 ; i
< nb
; i
++) {
247 element
= ltt_field_member(f
,i
);
248 lttv_print_field(e
, element
, s
, field_names
, i
);
250 g_string_append_printf(s
, type
->separator
);
252 // g_string_append_printf(s, " }");
253 g_string_append_printf(s
, type
->footer
);
256 case LTT_TYPE_COMPACT
:
257 g_error("compact type printing not implemented");
264 int getProcessInfosFromEvent(LttvEvent
*event
, GString
* processInfos
)
266 int pid
=0, tid
=0, ppid
=0;
268 struct definition
*scope
;
269 unsigned long timestamp
;
273 gboolean noError
= TRUE
;
276 LttvTraceState
*state
= event
->state
;
277 LttvProcessState
*process
;
278 struct bt_ctf_event
*ctf_event
= event
->bt_event
;
280 cpu
= lttv_traceset_get_cpuid_from_event(event
);
282 process
= state
->running_process
[cpu
];
284 timestamp
= bt_ctf_get_timestamp(ctf_event
);
288 ppid
= process
->ppid
;
289 procname
= g_quark_to_string(process
->name
);
290 if (timestamp
== -1ULL) {
295 scope
= bt_ctf_get_top_level_scope(ctf_event
, BT_STREAM_EVENT_CONTEXT
);
296 if (bt_ctf_field_get_error()) {
301 pid
= bt_ctf_get_int64(bt_ctf_get_field(ctf_event
, scope
, "_pid"));
302 if (bt_ctf_field_get_error()) {
307 tid
= bt_ctf_get_int64(bt_ctf_get_field(ctf_event
, scope
, "_tid"));
308 if (bt_ctf_field_get_error()) {
313 ppid
= bt_ctf_get_int64(bt_ctf_get_field(ctf_event
, scope
, "_ppid"));
314 if (bt_ctf_field_get_error()) {
319 procname
= bt_ctf_get_char_array(bt_ctf_get_field(ctf_event
, scope
, "_procname"));
320 if (bt_ctf_field_get_error()) {
326 g_string_append_printf(processInfos
, "%u, %u, %s, %u", pid
, tid
, procname
, ppid
);
336 int getCPUIdFromEvent(LttvEvent
*event
, GString
* cpuId_str
)
340 cpuid
= lttv_traceset_get_cpuid_from_event(event
);
344 g_string_append_printf(cpuId_str
, "%u", cpuid
);
348 int getFields(struct bt_ctf_event
*ctf_event
, struct definition
const *fields
, GString
* fieldsStr
)
350 enum ctf_type_id fieldType
= bt_ctf_field_type(fields
);
351 int ret
= 0, isSigned
= -1, len
= 0, i
= 0;
352 struct definition
*index_def
;
354 case CTF_TYPE_INTEGER
:
355 isSigned
= bt_ctf_get_int_signedness(fields
);
357 g_string_append_printf(fieldsStr
, "%lu", bt_ctf_get_int64(fields
));
359 else if (isSigned
== 0) {
360 g_string_append_printf(fieldsStr
, "%llu", bt_ctf_get_uint64(fields
));
363 case CTF_TYPE_STRING
:
364 g_string_append_printf(fieldsStr
, "%s", bt_ctf_get_string(fields
));
368 g_string_append_printf(fieldsStr
, "[ ");
369 len
= bt_ctf_get_array_len(fields
);
370 if (index_def
= bt_ctf_get_index(ctf_event
, fields
, i
)) {
371 for (i
= 0; i
< len
; i
++) {
373 g_string_append_printf(fieldsStr
, ", ");
375 bt_ctf_field_type(bt_ctf_get_index(ctf_event
, fields
, i
));
376 g_string_append_printf(fieldsStr
, " ");
377 g_string_append_printf(fieldsStr
, "[%d] = ");
378 getFields(ctf_event
, bt_ctf_get_index(ctf_event
, fields
, i
), fieldsStr
);
382 g_string_append_printf(fieldsStr
, "%s", bt_ctf_get_char_array(fields
));
384 g_string_append_printf(fieldsStr
, " ]");
387 case CTF_TYPE_UNKNOWN
:
394 int getFieldsFromEvent(struct bt_ctf_event
*ctf_event
, GString
* fields
, gboolean field_names
)
396 struct definition
const * const *list
= NULL
;
398 int i
= 0, j
= 0, ret
= 0;
399 gboolean noError
= TRUE
;
400 struct definition
*scope
;
401 scope
= bt_ctf_get_top_level_scope(ctf_event
, BT_EVENT_FIELDS
);
407 ret
= bt_ctf_get_field_list(ctf_event
, scope
, &list
, &count
);
412 for (i
= 0; i
< count
; i
++) {
414 g_string_append_printf(fields
, ", ");
416 const char *name
= bt_ctf_field_name(list
[i
]);
418 g_string_append_printf(fields
, "%s = ", name
);
420 getFields(ctf_event
, list
[i
] ,fields
);
421 if (bt_ctf_field_get_error()) {
433 void lttv_event_to_string(LttvEvent
*event
, GString
*a_string
,
434 gboolean field_names
, gboolean long_version
)
436 GString
* processInfos
= g_string_new("");
437 GString
* fields
= g_string_new("");
438 GString
* cpuId_str
= g_string_new("");
440 getProcessInfosFromEvent(event
, processInfos
);
441 getFieldsFromEvent(event
->bt_event
, fields
, field_names
);
442 getCPUIdFromEvent(event
, cpuId_str
);
444 g_string_set_size(a_string
,0);
446 g_string_append_printf(a_string
, "%llu %s: ",
447 bt_ctf_get_timestamp(event
->bt_event
),
448 bt_ctf_event_name(event
->bt_event
));
450 g_string_append_printf(a_string
, "{ %s }", cpuId_str
->str
);
452 if (strcmp("", processInfos
->str
) < 0) {
453 g_string_append_printf(a_string
, ", { %s }", processInfos
->str
);
455 if (strcmp("", fields
->str
) < 0) {
456 g_string_append_printf(a_string
, ", { %s }", fields
->str
);
459 g_string_free(fields
, TRUE
);
460 g_string_free(processInfos
, TRUE
);
461 g_string_free(cpuId_str
, TRUE
);
463 void lttv_event_get_name(LttvEvent
*event
,GString
*a_string
)
465 g_string_set_size(a_string
,0);
466 g_string_append_printf(a_string
, " %s", bt_ctf_event_name(event
->bt_event
));
469 void lttv_event_to_string(LttEvent
*e
, GString
*s
, gboolean mandatory_fields
,
470 gboolean field_names
, LttvTracefileState
*tfs
)
472 struct marker_field
*field
;
473 struct marker_info
*info
;
477 guint cpu
= tfs
->cpu
;
478 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
479 LttvProcessState
*process
= ts
->running_process
[cpu
];
481 s
= g_string_set_size(s
,0);
483 info
= marker_get_info_from_id(tfs
->parent
.tf
->mdata
, e
->event_id
);
485 if(mandatory_fields
) {
486 time
= ltt_event_time(e
);
487 g_string_append_printf(s
,"%s.%s: %ld.%09ld (%s/%s_%u)",
488 g_quark_to_string(ltt_tracefile_name(tfs
->parent
.tf
)),
489 g_quark_to_string(info
->name
), (long)time
.tv_sec
, time
.tv_nsec
,
491 ltt_trace_name(ltt_tracefile_get_trace(tfs
->parent
.tf
))),
492 g_quark_to_string(ltt_tracefile_name(tfs
->parent
.tf
)), cpu
);
493 /* Print the process id and the state/interrupt type of the process */
494 g_string_append_printf(s
,", %u, %u, %s, %s, %u, 0x%" PRIx64
", %s",
497 g_quark_to_string(process
->name
),
498 g_quark_to_string(process
->brand
),
500 process
->current_function
,
501 g_quark_to_string(process
->state
->t
));
504 if(marker_get_num_fields(info
) == 0) return;
505 g_string_append_printf(s
, " ");
506 g_string_append_printf(s
, "{ ");
507 for (field
= marker_get_field(info
, 0);
508 field
!= marker_get_field(info
, marker_get_num_fields(info
));
510 if(field
!= marker_get_field(info
, 0))
511 g_string_append_printf(s
, ", ");
512 lttv_print_field(e
, field
, s
, field_names
, tfs
);
514 g_string_append_printf(s
, " }");
516 #endif /* BABEL_CLEANUP */
522 static void destroy()
526 LTTV_MODULE("print", "Print events", \
527 "Produce a detailed text printout of events", \