lttng.ust: Implement a symbol provider for LTTng-UST traces
authorAlexandre Montplaisir <alexmonthy@efficios.com>
Wed, 23 Mar 2016 01:37:36 +0000 (21:37 -0400)
committerAlexandre Montplaisir <alexmonthy@efficios.com>
Thu, 28 Apr 2016 17:32:57 +0000 (13:32 -0400)
This new symbol provider will make use of the "Debug Info"
analysis, which means it will only be available for traces
taken with LTTng-UST >= 2.8.

It will call into the existing BinaryCallsite and SourceCallsite
aspects to get the function name of a given address.

The provider's configuration page will allow specifying the
"root directory" of a target image. This is useful in cases
where a trace is taken on a remote target, and an image of that
target is available locally.

Since paths are found directly in the trace, this means that a
trace with the proper information taken on the same system
should show the function names in the Callstack View without
the need for the user to configure anything!

Possible future improvements:
- Split the symbol provider extension point in core and ui parts
- Merge the FileOffsetMapper logic with the core parts of the
  symbol provider.
- Move the "current path prefix" configuration from the trace
  object to the core symbol provider.

References bug 484042

Change-Id: Ia346c1eab2b54a54ddf672c7ffafd0655a47ee34
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/69973
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
13 files changed:
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryAspect.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoSourceAspect.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/trace/LttngUstTrace.java
lttng/org.eclipse.tracecompass.lttng2.ust.ui/META-INF/MANIFEST.MF
lttng/org.eclipse.tracecompass.lttng2.ust.ui/plugin.xml
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/Messages.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProvider.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderFactory.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderPreferencePage.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/messages.properties [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/package-info.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/symbols/BasicSymbolProviderFactory.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/symbols/ISymbolProviderFactory.java

index c2fc6206bbf8dc6ea841d2fe1149d32672bb4746..4bb345e2dd3310f283c8f4ced7a3e24695057350 100644 (file)
@@ -53,8 +53,9 @@ public class UstDebugInfoBinaryAspect implements ITmfEventAspect<BinaryCallsite>
         if (!(event.getTrace() instanceof LttngUstTrace)) {
             return null;
         }
+        LttngUstTrace trace = (LttngUstTrace) event.getTrace();
 
-        ILttngUstEventLayout layout = ((LttngUstTrace) event.getTrace()).getEventLayout();
+        ILttngUstEventLayout layout = trace.getEventLayout();
 
         /* We need both the vpid and ip contexts */
         ITmfEventField vpidField = event.getContent().getField(layout.contextVpid());
@@ -64,13 +65,33 @@ public class UstDebugInfoBinaryAspect implements ITmfEventAspect<BinaryCallsite>
         }
         Long vpid = (Long) vpidField.getValue();
         Long ip = (Long) ipField.getValue();
+        long ts = event.getTimestamp().toNanos();
 
+        return getBinaryCallsite(trace, vpid.intValue(), ts, ip.longValue());
+    }
+
+    /**
+     * Get the binary callsite (which means binary file and offset in this file)
+     * corresponding to the given instruction pointer, for the given PID and
+     * timetamp.
+     *
+     * @param trace
+     *            The trace, from which we will get the debug info analysis
+     * @param pid
+     *            The PID for which we want the symbol
+     * @param ts
+     *            The timestamp of the query
+     * @param ip
+     *            The instruction pointer address
+     * @return The {@link BinaryCallsite} object with the relevant information
+     */
+    public static @Nullable BinaryCallsite getBinaryCallsite(LttngUstTrace trace, int pid, long ts, long ip) {
         /*
          * First match the IP to the correct binary or library, by using the
          * UstDebugInfoAnalysis.
          */
         UstDebugInfoAnalysisModule module =
-                TmfTraceUtils.getAnalysisModuleOfClass(event.getTrace(),
+                TmfTraceUtils.getAnalysisModuleOfClass(trace,
                         UstDebugInfoAnalysisModule.class, UstDebugInfoAnalysisModule.ID);
         if (module == null) {
             /*
@@ -79,27 +100,29 @@ public class UstDebugInfoBinaryAspect implements ITmfEventAspect<BinaryCallsite>
              */
             return null;
         }
-        long ts = event.getTimestamp().getValue();
-        UstDebugInfoLoadedBinaryFile file = module.getMatchingFile(ts, vpid, ip);
+        UstDebugInfoLoadedBinaryFile file = module.getMatchingFile(ts, pid, ip);
         if (file == null) {
             return null;
         }
 
+        /* Apply the path prefix defined by the trace, if any */
+        String fullPath = (trace.getSymbolProviderConfig().getActualRootDirPath() + file.getFilePath());
+
         long offset;
-        if (isPIC(file)) {
-            offset = (ip.longValue() - file.getBaseAddress());
+        if (isPIC(fullPath)) {
+            offset = (ip - file.getBaseAddress());
         } else {
             /*
              * In the case of the object being the main binary (loaded at a very
              * low address), we must pass the actual ip address to addr2line.
              */
-            offset = ip.longValue();
+            offset = ip;
         }
 
         // TODO If the binary is present on the current file system, we could
         // try to get the symbol name from it.
 
-        return new BinaryCallsite(file.getFilePath(), EMPTY_STRING, offset);
+        return new BinaryCallsite(fullPath, EMPTY_STRING, offset);
     }
 
     /**
@@ -107,13 +130,12 @@ public class UstDebugInfoBinaryAspect implements ITmfEventAspect<BinaryCallsite>
      * or not. This indicates if addr2line considers the addresses as absolute
      * addresses or as offsets.
      */
-    private static boolean isPIC(UstDebugInfoLoadedBinaryFile file) {
+    private static boolean isPIC(String filePath) {
         /*
          * Ghetto binary/library identification for now. It would be possible to
          * parse the ELF binary to check if it is position-independent
          * (-fPIC/-fPIE) or not.
          */
-        String filePath = file.getFilePath();
         return (filePath.endsWith(".so") || filePath.contains(".so.")); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
index 8f947bcf8016aa7e737466171e9f368e79fb0a69..fbeed9c4760e844f0e3928fb4159d5109466dfb7 100644 (file)
@@ -52,6 +52,7 @@ public class UstDebugInfoSourceAspect implements ITmfEventAspect<TmfCallsite> {
         if (!(event.getTrace() instanceof LttngUstTrace)) {
             return null;
         }
+        LttngUstTrace trace = (LttngUstTrace) event.getTrace();
 
         /*
          * Resolve the binary callsite first, from there we can use the file's
@@ -62,6 +63,21 @@ public class UstDebugInfoSourceAspect implements ITmfEventAspect<TmfCallsite> {
             return null;
         }
 
+        return getSourceCallsite(trace, bc);
+    }
+
+    /**
+     * Get the source callsite (the full {@link TmfCallsite} information) from a
+     * binary callsite.
+     *
+     * @param trace
+     *            The trace, which may contain trace-specific configuration
+     * @param bc
+     *            The binary callsite
+     * @return The source callsite, which sould include file name, function name
+     *         and line number
+     */
+    public static @Nullable TmfCallsite getSourceCallsite(LttngUstTrace trace, BinaryCallsite bc) {
         Iterable<TmfCallsite> callsites = FileOffsetMapper.getCallsiteFromOffset(new File(bc.getBinaryFilePath()), bc.getOffset());
 
         if (callsites == null || Iterables.isEmpty(callsites)) {
@@ -72,6 +88,18 @@ public class UstDebugInfoSourceAspect implements ITmfEventAspect<TmfCallsite> {
          * We will take the "deepest" one in the stack, which should refer to
          * the initial, non-inlined location.
          */
-        return Iterables.getLast(callsites);
+        TmfCallsite callsite = Iterables.getLast(callsites);
+
+        /*
+         * Apply the path prefix again, this time on the path given from
+         * addr2line. If applicable.
+         */
+        String pathPrefix = trace.getSymbolProviderConfig().getActualRootDirPath();
+        if (pathPrefix.isEmpty()) {
+            return callsite;
+        }
+
+        String fullFileName = (pathPrefix + callsite.getFileName());
+        return new TmfCallsite(fullFileName, callsite.getFunctionName(), callsite.getLineNumber());
     }
 }
index 32bf54e99e098eb47e6a76da596177d26457ffb4..de923a12ecb7c69044e9d0b84e04997c28bb6ea7 100644 (file)
@@ -145,4 +145,96 @@ public class LttngUstTrace extends CtfTmfTrace {
         }
         return status;
     }
+
+    // ------------------------------------------------------------------------
+    // Fields/methods bridging the Debug-info symbol provider
+    // ------------------------------------------------------------------------
+
+    /*
+     * FIXME Once the symbol provider is split in core/ui components, the
+     * UstDebugInfoSymbolProvider should be moved to the core plugin, and this
+     * here can be removed.
+     */
+
+    /**
+     * Configuration of the symbol provider.
+     *
+     * @since 2.0
+     */
+    public static class SymbolProviderConfig {
+
+        private final boolean fUseCustomRootDir;
+        private final @NonNull String fCustomRootDirPath;
+
+        /**
+         * Constructor
+         *
+         * Note that a path can be specified even if 'useCustomRootDir' is
+         * false. This will keep the setting in the text field even when it is
+         * grayed out.
+         *
+         * @param useCustomRootDir
+         *            Should a custom directory be used
+         * @param rootDirPath
+         *            Custom directory path
+         */
+        public SymbolProviderConfig(boolean useCustomRootDir, @NonNull String rootDirPath) {
+            fUseCustomRootDir = useCustomRootDir;
+            fCustomRootDirPath = rootDirPath;
+        }
+
+        /**
+         * @return Should a custom directory be used
+         */
+        public boolean useCustomRootDir() {
+            return fUseCustomRootDir;
+        }
+
+        /**
+         * @return The configured root directory
+         */
+        public String getCustomRootDirPath() {
+            return fCustomRootDirPath;
+        }
+
+        /**
+         * Return the "real" path to use for symbol resolution. This is a
+         * convenience method that avoids having to check the state of
+         * {@link #useCustomRootDir()} separately.
+         *
+         * @return The actual root directory to use
+         */
+        public String getActualRootDirPath() {
+            if (fUseCustomRootDir) {
+                return fCustomRootDirPath;
+            }
+            return ""; //$NON-NLS-1$
+        }
+    }
+
+    private @NonNull SymbolProviderConfig fCurrentProviderConfig =
+            /* Default settings for new traces */
+            new SymbolProviderConfig(false, ""); //$NON-NLS-1$
+
+
+    /**
+     * Get the current symbol provider configuration for this trace.
+     *
+     * @return The current symbol provider configuration
+     * @since 2.0
+     */
+    public @NonNull SymbolProviderConfig getSymbolProviderConfig() {
+        return fCurrentProviderConfig;
+    }
+
+    /**
+     * Set the symbol provider configuration for this trace.
+     *
+     * @param config
+     *            The new symbol provider configuration to use
+     * @since 2.0
+     */
+    public void setSymbolProviderConfig(@NonNull SymbolProviderConfig config) {
+        fCurrentProviderConfig = config;
+    }
 }
index d5c9704e779edfe2761b4e6d7b73c03067384b7d..c4154ad14d707b8e8600ae62cf14df827f98c25c 100644 (file)
@@ -18,6 +18,7 @@ Require-Bundle: org.eclipse.core.resources,
  org.eclipse.tracecompass.tmf.ctf.core
 Export-Package: org.eclipse.tracecompass.internal.lttng2.ust.ui;x-friends:="org.eclipse.tracecompass.lttng2.ust.ui.tests",
  org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.callstack;x-friends:="org.eclipse.tracecompass.lttng2.ust.ui.tests",
+ org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;x-internal:=true,
  org.eclipse.tracecompass.internal.lttng2.ust.ui.views.memusage;x-friends:="org.eclipse.tracecompass.lttng2.ust.ui.tests,org.eclipse.tracecompass.lttng2.ust.ui.swtbot.tests",
  org.eclipse.tracecompass.lttng2.ust.ui.analysis.callstack
 Import-Package: com.google.common.base,
index 7abcd7192e20c50d7226f2a8b5c88ae3f6236c57..801eb4b559df1cbdbe7f20694466416f080ac8eb 100644 (file)
          </analysisId>
       </output>
    </extension>
+   <extension
+         point="org.eclipse.tracecompass.tmf.ui.symbolProvider">
+      <providerFactory
+            class="org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo.UstDebugInfoSymbolProviderFactory"
+            id="org.eclipse.tracecompass.lttng2.ust.ui.analysis.debuginfo.providerFactory"
+            priority="50">
+      </providerFactory>
+   </extension>
 </plugin>
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/Messages.java b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/Messages.java
new file mode 100644 (file)
index 0000000..30a2865
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. and others
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Message bundle
+ *
+ * @noreference Messages class
+ */
+@NonNullByDefault({})
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+
+    private Messages() {}
+
+    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo.messages"; //$NON-NLS-1$
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    public static String PreferencePage_WindowDescription;
+
+    public static String PreferencePage_CheckboxLabel;
+    public static String PreferencePage_CheckboxTooltip;
+
+    public static String PreferencePage_ButtonBrowse;
+    public static String PreferencePage_ButtonClear;
+
+    public static String PreferencePage_BrowseDialogTitle;
+    public static String PreferencePage_ErrorDirectoryDoesNotExists;
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProvider.java b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProvider.java
new file mode 100644 (file)
index 0000000..8ca91fd
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. and others
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.BinaryCallsite;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoAnalysisModule;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryAspect;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoSourceAspect;
+import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
+import org.eclipse.tracecompass.tmf.core.event.lookup.TmfCallsite;
+import org.eclipse.tracecompass.tmf.ui.symbols.DefaultSymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
+
+/**
+ * Symbol provider for UST traces with debug information.
+ *
+ * @author Alexandre Montplaisir
+ * @see UstDebugInfoAnalysisModule
+ */
+public class UstDebugInfoSymbolProvider extends DefaultSymbolProvider {
+
+    /**
+     * Create a new {@link UstDebugInfoSymbolProvider} for the given trace
+     *
+     * @param trace
+     *            A non-null trace
+     */
+    public UstDebugInfoSymbolProvider(LttngUstTrace trace) {
+        super(trace);
+    }
+
+    /**
+     * Sets the configured path prefix. Usually called from the preferences
+     * page.
+     *
+     * @param newPathPrefix
+     *            The new path prefix to use
+     */
+    void setConfiguredPathPrefix(LttngUstTrace.SymbolProviderConfig newConfig) {
+        getTrace().setSymbolProviderConfig(newConfig);
+    }
+
+    @Override
+    public @NonNull LttngUstTrace getTrace() {
+        /* Type enforced at constructor */
+        return (LttngUstTrace) super.getTrace();
+    }
+
+    @Override
+    public @Nullable String getSymbolText(int pid, long timestamp, long address) {
+        TmfCallsite callsite = getSymbolInfo(pid, timestamp, address);
+        return (callsite == null ? null : callsite.getFunctionName());
+    }
+
+    @Override
+    public @Nullable TmfCallsite getSymbolInfo(int pid, long timestamp, long address) {
+        BinaryCallsite bc = UstDebugInfoBinaryAspect.getBinaryCallsite(getTrace(), pid, timestamp, address);
+        if (bc == null) {
+            return null;
+        }
+
+        return UstDebugInfoSourceAspect.getSourceCallsite(getTrace(), bc);
+    }
+
+    @Override
+    public @NonNull ISymbolProviderPreferencePage createPreferencePage() {
+        return new UstDebugInfoSymbolProviderPreferencePage(this);
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderFactory.java b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderFactory.java
new file mode 100644 (file)
index 0000000..c43126d
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. and others
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoAnalysisModule;
+import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderFactory;
+
+/**
+ * Factory to create {@link UstDebugInfoSymbolProvider}. Provided to TMF via
+ * the extension point. Only works with LTTng-UST traces.
+ *
+ * @author Alexandre Montplaisir
+ */
+public class UstDebugInfoSymbolProviderFactory implements ISymbolProviderFactory {
+
+    @Override
+    public @Nullable ISymbolProvider createProvider(ITmfTrace trace) {
+        /*
+         * This applies only to UST traces that fulfill the DebugInfo analysis
+         * requirements.
+         */
+        UstDebugInfoAnalysisModule module = TmfTraceUtils.getAnalysisModuleOfClass(trace,
+                UstDebugInfoAnalysisModule.class, UstDebugInfoAnalysisModule.ID);
+
+        if (module != null && trace instanceof LttngUstTrace) {
+            return new UstDebugInfoSymbolProvider((LttngUstTrace) trace);
+        }
+        return null;
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderPreferencePage.java b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/UstDebugInfoSymbolProviderPreferencePage.java
new file mode 100644 (file)
index 0000000..5fdac62
--- /dev/null
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. and others
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
+import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace.SymbolProviderConfig;
+import org.eclipse.tracecompass.tmf.ui.symbols.AbstractSymbolProviderPreferencePage;
+
+/**
+ * Preference page to configure a path prefix from which to resolve all the
+ * paths found the binary file's debug information.
+ *
+ * @author Alexandre Montplaisir
+ */
+public class UstDebugInfoSymbolProviderPreferencePage extends AbstractSymbolProviderPreferencePage {
+
+    private @Nullable Button fUseCustomDirectoryCheckbox;
+    private @Nullable Text fCustomDirectoryPath;
+    private @Nullable Button fBrowseButton;
+    private @Nullable Button fClearButton;
+
+    /**
+     * Creates a new object for the given provider
+     *
+     * @param provider
+     *            a non-null provider
+     */
+    public UstDebugInfoSymbolProviderPreferencePage(UstDebugInfoSymbolProvider provider) {
+        super(provider);
+        setDescription(MessageFormat.format(Messages.PreferencePage_WindowDescription, provider.getTrace().getName()));
+        setValid(true);
+    }
+
+    @Override
+    public UstDebugInfoSymbolProvider getSymbolProvider() {
+        /* Type enforced at constructor */
+        return (UstDebugInfoSymbolProvider) super.getSymbolProvider();
+    }
+
+    @Override
+    protected Control createContents(@Nullable Composite parent) {
+        /*
+         * We will use a grid layout with 3 columns :
+         *
+         * [checkbox+label][][]
+         *
+         * [text field][Browse][Clear]
+         */
+        Composite composite = new Composite(parent, SWT.BORDER);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        composite.setLayout(new GridLayout(3, false));
+
+        /* The first row: checkbox and itslabel */
+        Button checkBox = new Button(composite, SWT.CHECK);
+        checkBox.setText(Messages.PreferencePage_CheckboxLabel);
+        checkBox.setToolTipText(Messages.PreferencePage_CheckboxTooltip);
+        checkBox.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(@Nullable SelectionEvent e) {
+                updateContents();
+            }
+        });
+        fUseCustomDirectoryCheckbox = checkBox;
+
+        /* Nothing in the two following cells */
+        new Label(composite, SWT.NONE);
+        new Label(composite, SWT.NONE);
+
+        /* Second row: The text input box */
+        Text text =  new Text(composite, SWT.BORDER);
+        text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        text.setEditable(false);
+        text.setToolTipText(Messages.PreferencePage_CheckboxTooltip);
+        fCustomDirectoryPath = text;
+
+        /* The "Browse..." button */
+        Button browseButton = new Button(composite, SWT.NONE);
+        browseButton.setText(Messages.PreferencePage_ButtonBrowse);
+        browseButton.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(@Nullable SelectionEvent e) {
+                browseDirectory(checkNotNull(fCustomDirectoryPath), Messages.PreferencePage_BrowseDialogTitle);
+            }
+        });
+        fBrowseButton = browseButton;
+
+        /* The "Clear" button */
+        Button clearButton = new Button(composite, SWT.NONE);
+        clearButton.setText(Messages.PreferencePage_ButtonClear);
+        clearButton.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(@Nullable SelectionEvent e) {
+                checkNotNull(fCustomDirectoryPath).setText(""); //$NON-NLS-1$
+                updateContents();
+            }
+        });
+        fClearButton = clearButton;
+
+        /* Load existing preferences */
+        loadCurrentSettings();
+
+        return composite;
+    }
+
+    private void browseDirectory(Text textField, @Nullable String dialogTitle) {
+        DirectoryDialog dialog = new DirectoryDialog(getShell());
+        dialog.setText(dialogTitle);
+        String dirPath = dialog.open();
+        if (dirPath != null) {
+            textField.setText(dirPath);
+            updateContents();
+        }
+    }
+
+    private void loadCurrentSettings() {
+        /* The settings are currently stored in the trace object */
+        LttngUstTrace trace = getSymbolProvider().getTrace();
+        SymbolProviderConfig config = trace.getSymbolProviderConfig();
+
+        checkNotNull(fUseCustomDirectoryCheckbox).setSelection(config.useCustomRootDir());
+        checkNotNull(fCustomDirectoryPath).setText(config.getCustomRootDirPath());
+
+        updateContents();
+    }
+
+    @Override
+    public void saveConfiguration() {
+        SymbolProviderConfig config =
+                new SymbolProviderConfig(getCurrentCheckBoxState(), getCurrentPathPrefix());
+
+        LttngUstTrace trace = getSymbolProvider().getTrace();
+        trace.setSymbolProviderConfig(config);
+    }
+
+    private boolean getCurrentCheckBoxState() {
+        return (checkNotNull(fUseCustomDirectoryCheckbox).getSelection());
+    }
+
+    private String getCurrentPathPrefix() {
+        return nullToEmptyString(checkNotNull(fCustomDirectoryPath).getText());
+    }
+
+    /**
+     * Grey out the relevant controls if the checkbox is unchecked, and vice
+     * versa. Also verify if the current settings are valid, and update the
+     * window error message if needed.
+     */
+    private void updateContents() {
+        boolean useCustomDirEnabled = getCurrentCheckBoxState();
+        checkNotNull(fCustomDirectoryPath).setEnabled(useCustomDirEnabled);
+        checkNotNull(fBrowseButton).setEnabled(useCustomDirEnabled);
+        checkNotNull(fClearButton).setEnabled(useCustomDirEnabled);
+
+        String errorMessage = null;
+
+        if (useCustomDirEnabled) {
+            String pathPrefix = getCurrentPathPrefix();
+            Path path = Paths.get(pathPrefix);
+            if (pathPrefix.equals("") || !Files.isDirectory(path)) { //$NON-NLS-1$
+                errorMessage = Messages.PreferencePage_ErrorDirectoryDoesNotExists;
+            }
+        }
+        setErrorMessage(errorMessage);
+        setValid(errorMessage == null);
+    }
+
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/messages.properties b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/messages.properties
new file mode 100644 (file)
index 0000000..5f34065
--- /dev/null
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2016 EfficiOS Inc. and others
+#
+# 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
+###############################################################################
+
+PreferencePage_WindowDescription=Multi-binary symbol mapping configuration for LTTng-UST 2.8+ trace "{0}"
+
+PreferencePage_CheckboxLabel = Use custom target root directory
+PreferencePage_CheckboxTooltip = \
+By default, paths to binaries and libraries found in the trace will be resolved as-is on the current system.\n\
+You can specify a path here to use as a \"prefix\" for all path resolutions.\n\
+For example, if the trace comes from a different target, and you have a local \
+image of the binaries of that target, you can specify the root location of this image here.
+
+PreferencePage_ButtonBrowse = Browse...
+PreferencePage_ButtonClear = Clear
+
+PreferencePage_BrowseDialogTitle=Select a target root directory
+PreferencePage_ErrorDirectoryDoesNotExists=The current path is missing or is not a directory.
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/package-info.java b/lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/debuginfo/package-info.java
new file mode 100644 (file)
index 0000000..5ca65d5
--- /dev/null
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. and others
+ *
+ * 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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.debuginfo;
index 860d607b02b87d7371e4911b6f0de6097bafb975..6fc01be3ab237409bfa9623bb01eb4a5caa1aee3 100644 (file)
@@ -10,6 +10,7 @@
 
 package org.eclipse.tracecompass.internal.tmf.ui.symbols;
 
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
@@ -26,7 +27,8 @@ import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderFactory;
 public class BasicSymbolProviderFactory implements ISymbolProviderFactory {
 
     @Override
-    public ISymbolProvider createProvider(ITmfTrace trace) {
+    public @NonNull ISymbolProvider createProvider(ITmfTrace trace) {
+        /* This provider can apply to any trace */
         return new BasicSymbolProvider(trace);
     }
 
index 217c4cd0b2e5ff2cb5d10d56539001e72a3af4ca..6d1cefc1acf7c25492470e9f116deb165b300b59 100644 (file)
@@ -11,6 +11,7 @@
 package org.eclipse.tracecompass.tmf.ui.symbols;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 
 /**
@@ -33,6 +34,6 @@ public interface ISymbolProviderFactory {
      * @return A newly created provider that can resolve symbols from the given
      *         trace or null if no such provider can be created by this factory
      */
-    ISymbolProvider createProvider(@NonNull ITmfTrace trace);
+    @Nullable ISymbolProvider createProvider(@NonNull ITmfTrace trace);
 
 }
This page took 0.038377 seconds and 5 git commands to generate.