Please ignore this patch. A new one will come soon. Thanks.
Selon Vincent Attard <[email protected]>: > This new plugin prints a formated output of each events in a trace. The > output format is defined as a parameter with printf like syntax.It provides > a default format easy to read and the original textDump format for backward > compatibility. > Updated: Use glib functions for solving buffer overflow problem and correct > indentation. Add another format called "strace-like". > > Signed-off-by: Vincent Attard <[email protected]> > Reviewed-by: Yannick Brosseau <[email protected]> > --- > lttv/modules/text/Makefile.am | 3 +- > lttv/modules/text/formattedDump.c | 381 > +++++++++++++++++++++++++++++++++++++ > 2 files changed, 383 insertions(+), 1 deletions(-) > create mode 100644 lttv/modules/text/formattedDump.c > > diff --git a/lttv/modules/text/Makefile.am b/lttv/modules/text/Makefile.am > index 29e8990..4f11cb6 100644 > --- a/lttv/modules/text/Makefile.am > +++ b/lttv/modules/text/Makefile.am > @@ -3,7 +3,7 @@ AM_LDFLAGS = $(MODULE_LDFLAGS) > > libdir = ${lttvplugindir} > > -lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la > libprecomputeState.la libdepanalysis.la libsync_chain_batch.la > +lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la > libprecomputeState.la libdepanalysis.la libsync_chain_batch.la > libformattedDump.la > > libtextDump_la_SOURCES = textDump.c > libbatchAnalysis_la_SOURCES = batchAnalysis.c > @@ -11,6 +11,7 @@ libtextFilter_la_SOURCES = textFilter.c > libprecomputeState_la_SOURCES = precomputeState.c > libdepanalysis_la_SOURCES = depanalysis.c sstack.c > libsync_chain_batch_la_SOURCES = sync_chain_batch.c > +libformattedDump_la_SOURCES = formattedDump.c > > noinst_HEADERS = \ > batchanalysis.h \ > diff --git a/lttv/modules/text/formattedDump.c > b/lttv/modules/text/formattedDump.c > new file mode 100644 > index 0000000..a5c40f4 > --- /dev/null > +++ b/lttv/modules/text/formattedDump.c > @@ -0,0 +1,381 @@ > +/* This file is part of the Linux Trace Toolkit viewer > + * Copyright (C) 2003-2004 Michel Dagenais > + * 2005 Mathieu Desnoyers > + * 2011 Vincent Attard <[email protected]> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License Version 2 as > + * published by the Free Software Foundation; > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, > + * MA 02111-1307, USA. > + */ > + > +/* > + * Formatted dump plugin prints a formatted output of each events in a > trace. > + * The output format is defined as a parameter. It provides a default format > + * easy to read, a "strace-like" format and the original textDump format for > + * backward compatibility. > + */ > + > +#ifdef HAVE_CONFIG_H > +#include <config.h> > +#endif > + > +#include <lttv/lttv.h> > +#include <lttv/option.h> > +#include <lttv/module.h> > +#include <lttv/hook.h> > +#include <lttv/attribute.h> > +#include <lttv/iattribute.h> > +#include <lttv/stats.h> > +#include <lttv/filter.h> > +#include <lttv/print.h> > +#include <ltt/ltt.h> > +#include <ltt/event.h> > +#include <ltt/trace.h> > +#include <stdio.h> > +#include <inttypes.h> > +#include <string.h> > +#include <stdlib.h> > + > +static gboolean a_no_field_names; > +static gboolean a_state; > +static gboolean a_text; > +static gboolean a_strace; > + > +static char *a_file_name = NULL; > +static char *a_format = NULL; > + > +static LttvHooks *before_traceset; > +static LttvHooks *event_hook; > + > +static const char default_format[] = > + "channel:%c event:%e timestamp:%t elapsed:%l cpu:%u pid:%d > ppid:%i " > + "tgpid:%g process:%p brand:%b state:%a payload:{ %m }"; > +static const char textDump_format[] = > + "%c.%e: %s.%n (%r/%c_%u), %d, %g, %p, %b, %i, %y, %a { %m }"; > +static const char strace_format[] = "%e(%m) %s.%n"; > + > +static FILE *a_file; > + > +static GString *a_string; > + > +static gboolean open_output_file(void *hook_data, void *call_data) > +{ > + g_info("Open the output file"); > + if (a_file_name == NULL) { > + a_file = stdout; > + } else { > + a_file = fopen(a_file_name, "w"); > + } > + if (a_file == NULL) { > + g_error("cannot open file %s", a_file_name); > + } > + return FALSE; > +} > + > +static int write_event_content(void *hook_data, void *call_data) > +{ > + gboolean result; > + > + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); > + > + LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; > + > + LttvTracefileState *tfs = (LttvTracefileState *)call_data; > + > + LttEvent *e; > + > + LttvAttributeValue value_filter; > + > + LttvFilter *filter; > + > + guint cpu = tfs->cpu; > + LttvTraceState *ts = (LttvTraceState *)tfc->t_context; > + LttvProcessState *process = ts->running_process[cpu]; > + > + e = ltt_tracefile_get_event(tfc->tf); > + > + result = lttv_iattribute_find_by_path(attributes, "filter/lttv_filter", > + LTTV_POINTER, &value_filter); > + g_assert(result); > + filter = (LttvFilter *)*(value_filter.v_pointer); > + > + /* > + * call to the filter if available > + */ > + if (filter->head != NULL) > + if (!lttv_filter_tree_parse(filter->head, e, tfc->tf, > + tfc->t_context->t, tfc, NULL, NULL)) > + return FALSE; > + > + lttv_event_to_string(e, a_string, TRUE, !a_no_field_names, tfs); > + > + if (a_state) { > + g_string_append_printf(a_string, "%s ", > + g_quark_to_string(process->state->s)); > + } > + > + g_string_append_printf(a_string, "\n"); > + > + fputs(a_string->str, a_file); > + return FALSE; > +} > + > +void lttv_event_to_string(LttEvent *e, GString *string_buffer, gboolean > mandatory_fields, > + gboolean field_names, LttvTracefileState *tfs) > +{ > + struct marker_field *field; > + struct marker_info *info; > + LttTime time; > + > + static LttTime time_prev = {0, 0}; > + /* TODO: > + * Added this static value into state.c and reset each time you do a > + * seek for using it in the GUI. > + */ > + LttTime elapse; > + const char *fmt; > + int i; > + > + guint cpu = tfs->cpu; > + LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context; > + LttvProcessState *process = ts->running_process[cpu]; > + > + info = marker_get_info_from_id(tfs->parent.tf->mdata, e->event_id); > + if (mandatory_fields) { > + time = ltt_event_time(e); > + /* Calculate elapsed time between current and previous event */ > + if (time_prev.tv_sec == 0 && time_prev.tv_nsec == 0) { > + time_prev = ltt_event_time(e); > + elapse.tv_sec = 0; > + elapse.tv_nsec = 0; > + /* TODO: > + * Keep in mind that you should add the ability to restore the previous > + * event time to state.c if you want to reuse this code into the GUI. > + */ > + } else { > + elapse = ltt_time_sub(time, time_prev); > + time_prev = time; > + } > + } > + if (a_text) { > + /* textDump format (used with -T command option) */ > + fmt = textDump_format; > + } else if (a_strace) { > + /* strace-like format (used with -S command option) */ > + fmt = strace_format; > + } else if (!a_format) { > + /* Default format (used if no option) */ > + fmt = default_format; > + } else { > + /* > + * formattedDump format > + * (used with -F command option following by the desired format) > + */ > + fmt = a_format; > + } > + > + g_string_set_size(string_buffer, 0); > + /* > + * Switch case: > + * all '%-' are replaced by the desired value in 'string_buffer' > + */ > + int len; > + len = strlen(fmt); > + for (i = 0; i < len; i++) { > + if (fmt[i] == '%') { > + switch (fmt[++i]) { > + case 't': > + g_string_append_printf(string_buffer, > + > "%ld:%02ld:%02ld.%09ld", > + > time.tv_sec/3600, > + > (time.tv_sec%3600)/60, > + > time.tv_sec%60, > + > time.tv_nsec); > + break; > + case 'c': > + /*if (ltt_tracefile_name(tfs->parent.tf) == 1) { > + goto end; > + }*/ > + g_string_append(string_buffer, > + > g_quark_to_string(ltt_tracefile_name(tfs->parent.tf))); > + break; > + case 'e': > + g_string_append(string_buffer, > + g_quark_to_string(info->name)); > + break; > + case 'd': > + g_string_append_printf(string_buffer, "%u", > process->pid); > + break; > + case 's': > + g_string_append_printf(string_buffer, "%ld", > time.tv_sec); > + break; > + case 'n': > + g_string_append_printf(string_buffer, "%ld", > time.tv_nsec); > + break; > + case 'i': > + g_string_append_printf(string_buffer, "%u", > process->ppid); > + break; > + case 'g': > + g_string_append_printf(string_buffer, "%u", > process->tgid); > + break; > + case 'p': > + g_string_append(string_buffer, > + > g_quark_to_string(process->name)); > + break; > + case 'b': > + g_string_append_printf(string_buffer, "%u", > process->brand); > + break; > + case 'u': > + g_string_append_printf(string_buffer, "%u", > cpu); > + break; > + case 'l': > + g_string_append_printf(string_buffer, > "%ld.%09ld", > + elapse.tv_sec, elapse.tv_nsec); > + break; > + case 'a': > + g_string_append(string_buffer, > + > g_quark_to_string(process->state->t)); > + break; > + case 'm': > + { > + /* > + * Get and print markers and > tracepoints fields into > + * 'string_buffer' > + */ > + if (marker_get_num_fields(info) == 0) > + break; > + for (field = marker_get_field(info, 0); > + field != > marker_get_field(info, marker_get_num_fields(info)); > + field++) { > + if (field != > marker_get_field(info, 0)) { > + > g_string_append(string_buffer, ", "); > + } > + > + lttv_print_field(e, field, > string_buffer, field_names, tfs); > + } > + } > + break; > + case 'r': > + g_string_append(string_buffer, > g_quark_to_string( > + > ltt_trace_name(ltt_tracefile_get_trace(tfs->parent.tf)))); > + break; > + case '%': > + g_string_append_c(string_buffer, '%'); > + break; > + case 'y': > + g_string_append_printf(string_buffer, "0x%" > PRIx64, > + process->current_function); > + break; > + } > + } else > + /* Copy every character if not equals to '%' */ > + g_string_append_c(string_buffer, fmt[i]); > + } > +} > + > +static void init() > +{ > + gboolean result; > + > + LttvAttributeValue value; > + > + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); > + > + g_info("Init formattedDump.c"); > + > + a_string = g_string_new(""); > + > + a_file_name = NULL; > + lttv_option_add("output", 'o', > + "output file where the text is written", > + "file name", > + LTTV_OPT_STRING, &a_file_name, NULL, NULL); > + > + a_text = FALSE; > + lttv_option_add("text", 'T', > + "output the textDump format", > + "", > + LTTV_OPT_NONE, &a_text, NULL, NULL); > + > + a_strace = FALSE; > + lttv_option_add("strace", 'S', > + "output a \"strace-like\" format", > + "", > + LTTV_OPT_NONE, &a_strace, NULL, NULL); > + > + a_format = NULL; > + lttv_option_add("format", 'F', > + "output the desired format\n" > + " FORMAT controls the output. > Interpreted sequences are:\n" > + "\n" > + " %c channel name\n" > + " %p process name\n" > + " %e event name\n" > + " %r path to trace\n" > + " %t timestamp (e.g., > 2:08:54.025684145)\n" > + " %s seconds\n" > + " %n nanoseconds\n" > + " %l elapsed time with the previous > event\n" > + " %d pid\n" > + " %i ppid\n" > + " %g tgid\n" > + " %u cpu\n" > + " %b brand\n" > + " %a state\n" > + " %y memory address\n" > + " %m markers and tracepoints fields\n", > + "format string (e.g., \"channel:%c event:%e > process:%p\")", > + LTTV_OPT_STRING, &a_format, NULL, NULL); > + > + result = lttv_iattribute_find_by_path(attributes, "hooks/event", > + LTTV_POINTER, &value); > + g_assert(result); > + event_hook = *(value.v_pointer); > + g_assert(event_hook); > + lttv_hooks_add(event_hook, write_event_content, NULL, > LTTV_PRIO_DEFAULT); > + > + result = lttv_iattribute_find_by_path(attributes, > "hooks/traceset/before", > + LTTV_POINTER, &value); > + g_assert(result); > + before_traceset = *(value.v_pointer); > + g_assert(before_traceset); > + lttv_hooks_add(before_traceset, open_output_file, NULL, > + LTTV_PRIO_DEFAULT); > + > +} > + > +static void destroy() > +{ > + g_info("Destroy formattedDump"); > + > + lttv_option_remove("format"); > + > + lttv_option_remove("output"); > + > + lttv_option_remove("text"); > + > + lttv_option_remove("strace"); > + > + g_string_free(a_string, TRUE); > + > + lttv_hooks_remove_data(event_hook, write_event_content, NULL); > + > + lttv_hooks_remove_data(before_traceset, open_output_file, NULL); > + > +} > + > + > +LTTV_MODULE("formattedDump", "Print events with desired format in a file", \ > + "Produce a detailed formatted text printout of a trace", \ > + init, destroy, "batchAnalysis", "option") > + > -- > 1.7.0.4 > > _______________________________________________ ltt-dev mailing list [email protected] http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
