lttng: Add Callstack View support for UST traces
authorAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Wed, 11 Sep 2013 14:46:08 +0000 (10:46 -0400)
committerAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Tue, 17 Sep 2013 22:19:00 +0000 (18:19 -0400)
UST traces using the lttng-ust-cyg-profile library will contain events
about function entries and exists. We can leverage(!) this information
to populate the generic TMF Callstack view.

For now it will only print the function addresses. Until the whole
function-names-in-the-trace debate is resolved upstream, we will provide
a mechanism to import a mapping file manually. This will come in a
separate commit.

Change-Id: I03b461ef9e863ddb6988907514e96bb3db3eaef9
Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Reviewed-on: https://git.eclipse.org/r/16394
Tested-by: Hudson CI
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
IP-Clean: Genevieve Bastien <gbastien+lttng@versatic.net>

org.eclipse.linuxtools.lttng2.ust.core/META-INF/MANIFEST.MF
org.eclipse.linuxtools.lttng2.ust.core/src/org/eclipse/linuxtools/internal/lttng2/ust/core/trace/callstack/LttngUstCallStackProvider.java [new file with mode: 0644]
org.eclipse.linuxtools.lttng2.ust.core/src/org/eclipse/linuxtools/lttng2/ust/core/trace/LttngUstTrace.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java

index 06ecec5654570989f5fab63e5d3eed5df3f743a2..4759022595cb6b8e81d1a1d3e2d44d498f8e752f 100644 (file)
@@ -9,6 +9,7 @@ Bundle-Activator: org.eclipse.linuxtools.internal.lttng2.ust.core.Activator
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Export-Package: org.eclipse.linuxtools.internal.lttng2.ust.core;x-internal:=true,
+ org.eclipse.linuxtools.internal.lttng2.ust.core.trace.callstack;x-internal:=true,
  org.eclipse.linuxtools.lttng2.ust.core.trace
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.core.resources,
diff --git a/org.eclipse.linuxtools.lttng2.ust.core/src/org/eclipse/linuxtools/internal/lttng2/ust/core/trace/callstack/LttngUstCallStackProvider.java b/org.eclipse.linuxtools.lttng2.ust.core/src/org/eclipse/linuxtools/internal/lttng2/ust/core/trace/callstack/LttngUstCallStackProvider.java
new file mode 100644 (file)
index 0000000..3be1209
--- /dev/null
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Alexandre Montplaisir - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.lttng2.ust.core.trace.callstack;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.linuxtools.lttng2.ust.core.trace.LttngUstTrace;
+import org.eclipse.linuxtools.tmf.core.callstack.CallStackStateProvider;
+import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
+
+/**
+ * Callstack provider for LTTng-UST traces.
+ *
+ * If the traces contains 'func_entry' and 'func_exit' event (see the
+ * lttng-ust-cyg-profile manpage), AND contains vtid and procname contexts, we
+ * can use this information to populate the TMF Callstack View.
+ *
+ * Granted, most UST traces will not contain this information. In this case,
+ * this will simply build an empty state system, and the view will remain
+ * unavailable.
+ *
+ * @author Alexandre Montplaisir
+ */
+public class LttngUstCallStackProvider extends CallStackStateProvider {
+
+    // ------------------------------------------------------------------------
+    // Event strings
+    // ------------------------------------------------------------------------
+
+    /** Name of the fake field for the vtid contexts */
+    private static final String CONTEXT_VTID = "context._vtid"; //$NON-NLS-1$
+
+    /** Name of the fake field for the procname context */
+    private static final String CONTEXT_PROCNAME = "context._procname"; //$NON-NLS-1$
+
+    /** Field name for the target function address */
+    private static final String FIELD_ADDR = "addr"; //$NON-NLS-1$
+
+    /** Event names indicating function entry */
+    private static final Set<String> FUNC_ENTRY_EVENTS = new HashSet<String>();
+
+    /** Event names indicating function exit */
+    private static final Set<String> FUNC_EXIT_EVENTS = new HashSet<String>();
+
+    static {
+        /* This seems overkill, but it will be checked every event. Gotta go FAST! */
+        FUNC_ENTRY_EVENTS.add("lttng_ust_cyg_profile:func_entry"); //$NON-NLS-1$
+        FUNC_ENTRY_EVENTS.add("lttng_ust_cyg_profile_fast:func_entry"); //$NON-NLS-1$
+
+        FUNC_EXIT_EVENTS.add("lttng_ust_cyg_profile:func_exit"); //$NON-NLS-1$
+        FUNC_EXIT_EVENTS.add("lttng_ust_cyg_profile_fast:func_exit"); //$NON-NLS-1$
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructor
+     *
+     * @param trace
+     *            The UST trace
+     */
+    public LttngUstCallStackProvider(LttngUstTrace trace) {
+        super(trace);
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods from AbstractTmfStateProvider
+    // ------------------------------------------------------------------------
+
+    @Override
+    public LttngUstTrace getTrace() {
+        /* Type is enforced by the constructor */
+        return (LttngUstTrace) super.getTrace();
+    }
+
+    @Override
+    public LttngUstCallStackProvider getNewInstance() {
+        return new LttngUstCallStackProvider(getTrace());
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods from CallStackStateProvider
+    // ------------------------------------------------------------------------
+
+    /**
+     * Check that this event contains the required information we need to be
+     * used in the call stack view. We need at least the "procname" and "vtid"
+     * contexts.
+     */
+    @Override
+    protected boolean considerEvent(ITmfEvent event) {
+        if (!(event instanceof CtfTmfEvent)) {
+            return false;
+        }
+        ITmfEventField content = ((CtfTmfEvent) event).getContent();
+        if (content.getField(CONTEXT_VTID) == null ||
+                content.getField(CONTEXT_PROCNAME) == null) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String functionEntry(ITmfEvent event) {
+        String eventName = ((CtfTmfEvent) event).getEventName();
+        if (!FUNC_ENTRY_EVENTS.contains(eventName)) {
+            return null;
+        }
+        Long address = (Long) event.getContent().getField(FIELD_ADDR).getValue();
+        return getFunctionNameFromAddress(address.longValue());
+    }
+
+    @Override
+    public String functionExit(ITmfEvent event) {
+        String eventName = ((CtfTmfEvent) event).getEventName();
+        if (!FUNC_EXIT_EVENTS.contains(eventName)) {
+            return null;
+        }
+        /*
+         * The 'addr' field may or may not be present in func_exit events,
+         * depending on if cyg-profile.so or cyg-profile-fast.so was used.
+         */
+        ITmfEventField field = event.getContent().getField(FIELD_ADDR);
+        if (field == null) {
+            return CallStackStateProvider.UNDEFINED;
+        }
+        Long address = (Long) field.getValue();
+        return getFunctionNameFromAddress(address.longValue());
+    }
+
+    @Override
+    public String getThreadName(ITmfEvent event) {
+        /* Class type and content was already checked if we get called here */
+        ITmfEventField content = ((CtfTmfEvent) event).getContent();
+        String procName = (String) content.getField(CONTEXT_PROCNAME).getValue();
+        Long vtid = (Long) content.getField(CONTEXT_VTID).getValue();
+
+        if (procName == null || vtid == null) {
+            throw new IllegalStateException();
+        }
+
+        return new String(procName + '-' + vtid.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Internal helper methods
+    // ------------------------------------------------------------------------
+
+    private static String getFunctionNameFromAddress(long address) {
+        /*
+         * We do not support getting the real function name yet, just print the
+         * hex string.
+         */
+        return new String("0x" + Long.toHexString(address)); //$NON-NLS-1$
+    }
+}
index 9305dab40a00f5789d7ba05a498dd35f44de6ed9..fd87ac97309471a864a855ac99a2d8b27e67216b 100644 (file)
@@ -8,17 +8,27 @@
  *
  * Contributors:
  *   Matthew Khouzam - Initial API and implementation
+ *   Alexandre Montplaisir - Add UST callstack state system
  **********************************************************************/
 
 package org.eclipse.linuxtools.lttng2.ust.core.trace;
 
+import java.io.File;
+
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
 import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
 import org.eclipse.linuxtools.internal.lttng2.ust.core.Activator;
+import org.eclipse.linuxtools.internal.lttng2.ust.core.trace.callstack.LttngUstCallStackProvider;
+import org.eclipse.linuxtools.tmf.core.callstack.CallStackStateProvider;
 import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace;
+import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
+import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemFactory;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
 
 /**
  * Class to contain LTTng-UST traces
@@ -28,6 +38,9 @@ import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace;
  */
 public class LttngUstTrace extends CtfTmfTrace {
 
+    /** Name of the history file for the callstack state system */
+    private static final String CALLSTACK_FILENAME = "ust-callstack.ht"; //$NON-NLS-1$
+
     /**
      * Default constructor
      */
@@ -59,4 +72,26 @@ public class LttngUstTrace extends CtfTmfTrace {
         status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.LttngUstTrace_DomainError);
         return status;
     }
+
+    @Override
+    public IStatus buildStateSystem() {
+        super.buildStateSystem();
+
+        /*
+         * Build the state system for the UST Callstack (will be empty if the
+         * required events are not present).
+         */
+        String directory = TmfTraceManager.getSupplementaryFileDir(this);
+        final File htFile = new File(directory + CALLSTACK_FILENAME);
+        ITmfStateProvider csInput = new LttngUstCallStackProvider(this);
+
+        try {
+            ITmfStateSystem ss = TmfStateSystemFactory.newFullHistory(htFile, csInput, false);
+            registerStateSystem(CallStackStateProvider.ID, ss);
+        }  catch (TmfTraceException e) {
+            return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
+        }
+
+        return Status.OK_STATUS;
+    }
 }
index ea3f7b59f41e1af5ede9060cf549613cc292426c..5810801fe64ca18b45a4b2e9f4cd56a9e85d030e 100644 (file)
@@ -290,9 +290,6 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     /**
      * Build the state system(s) associated with this trace type.
      *
-     * Suppressing the warning, because the 'throws' will usually happen in
-     * sub-classes.
-     *
      * @return An IStatus indicating if the state system could be build
      *         successfully or not.
      * @since 3.0
This page took 0.031846 seconds and 5 git commands to generate.