rasd: Add event format parsing

Parse the events format from debugfs entry, i.e.
(debugfs)/tracing/events/<sys>/<name>/format.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Link: http://lkml.kernel.org/r/1412933690-25576-9-git-send-email-jean.pihet@linaro.org
Signed-off-by: Borislav Petkov <bp@suse.de>
diff --git a/include/trace_event.h b/include/trace_event.h
new file mode 100644
index 0000000..83cefdb
--- /dev/null
+++ b/include/trace_event.h
@@ -0,0 +1,10 @@
+#include <linux/perf_event.h>
+
+#include "ras.h"
+
+struct trace_event {
+	struct pevent		*pevent;
+	struct plugin_list	*plugin_list;
+};
+
+struct event_format *trace_event__tp_format(const char *sys, const char *name);
diff --git a/src/Makefile b/src/Makefile
index 523e8ef..fa0aee6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -34,6 +34,7 @@
 HEADERS += $(HPFX)/symbol.h
 HEADERS += $(HPFX)/target.h
 HEADERS += $(HPFX)/thread_map.h
+HEADERS += $(HPFX)/trace_event.h
 HEADERS += $(HPFX)/trace_seq.h
 HEADERS += $(HPFX)/xyarray.h
 
@@ -51,6 +52,7 @@
 OBJS += rbtree.o
 OBJS += strlist.o
 OBJS += thread_map.o
+OBJS += trace_event.o
 OBJS += trace-seq.o
 OBJS += util.o
 OBJS += xyarray.o
diff --git a/src/evsel.c b/src/evsel.c
index ef4e888..8e46e8f 100644
--- a/src/evsel.c
+++ b/src/evsel.c
@@ -2,6 +2,7 @@
 #include "cpumap.h"
 #include "debug.h"
 #include "evsel.h"
+#include "trace_event.h"
 #include "xyarray.h"
 
 int __perf_evsel__sample_size(u64 sample_type)
@@ -176,11 +177,9 @@
 		if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
 			goto out_free;
 
-		/*
 		evsel->tp_format = trace_event__tp_format(sys, name);
 		if (evsel->tp_format == NULL)
 			goto out_free;
-			*/
 
 		event_attr_init(&attr);
 		/*
diff --git a/src/trace_event.c b/src/trace_event.c
new file mode 100644
index 0000000..5ea2556
--- /dev/null
+++ b/src/trace_event.c
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <linux/kernel.h>
+
+#include "event-parse.h"
+#include "trace_event.h"
+
+#define PATH_MAX		4096
+
+char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
+
+/*
+ * global trace_event object used by trace_event__tp_format
+ *
+ * TODO There's no cleanup call for this. Add some sort of
+ * __exit function support and call trace_event__cleanup
+ * there.
+ */
+static struct trace_event tevent;
+
+int trace_event__init(struct trace_event *t)
+{
+	struct pevent *pevent = pevent_alloc();
+
+	if (pevent) {
+		/*t->plugin_list = traceevent_load_plugins(pevent);*/
+		t->pevent  = pevent;
+	}
+
+	return pevent ? 0 : -1;
+}
+
+void trace_event__cleanup(struct trace_event *t)
+{
+	/*traceevent_unload_plugins(t->plugin_list, t->pevent);*/
+	pevent_free(t->pevent);
+}
+
+static struct event_format*
+tp_format(const char *sys, const char *name)
+{
+	struct pevent *pevent = tevent.pevent;
+	struct event_format *event = NULL;
+	char path[PATH_MAX];
+	size_t size;
+	char *data;
+
+	scnprintf(path, PATH_MAX, "%s/%s/%s/format",
+		  tracing_events_path, sys, name);
+
+	if (filename__read_str(path, &data, &size))
+		return NULL;
+
+	pevent_parse_format(pevent, &event, data, size, sys);
+
+	free(data);
+	return event;
+}
+
+struct event_format*
+trace_event__tp_format(const char *sys, const char *name)
+{
+	static bool initialized;
+
+	if (!initialized) {
+		int be = traceevent_host_bigendian();
+		struct pevent *pevent;
+
+		if (trace_event__init(&tevent))
+			return NULL;
+
+		pevent = tevent.pevent;
+		pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+		pevent_set_file_bigendian(pevent, be);
+		pevent_set_host_bigendian(pevent, be);
+		initialized = true;
+	}
+
+	return tp_format(sys, name);
+}