Contributed symbol provider extension point.
Contributed BasicSymbolProvider to symbol provider extension point.
Switched CallStackView to symbol provider.
Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=487978
Change-Id: Ic40c272c2dbc0074fc170e9ff0d2ee0e9f230559
Signed-off-by: Robert Kiss <robert.kiss@gmail.com>
Reviewed-on: https://git.eclipse.org/r/67442
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Tested-by: Alexandre Montplaisir <alexmonthy@efficios.com>
/** Tooltips of the toolbar buttons */
private static final @NonNull String ALIGN_VIEWS = "Align Views";
- private static final @NonNull String IMPORT_BINARY = "Import a binary file containing debugging symbols";
- private static final @NonNull String IMPORT_TEXT = "Import a text file containing the mapping between addresses and function names";
+ private static final @NonNull String CONFIGURE_SYMBOL_PROVIDERS = "Configure how the addresses are mapped to function names";
// Separator
private static final @NonNull String SORT_BY_NAME = "Sort threads by thread name";
private static final @NonNull String SORT_BY_ID = "Sort threads by thread id";
// Separator
private static final String PIN_VIEW = "Pin View";
private static final List<String> TOOLBAR_BUTTONS_TOOLTIPS = ImmutableList.of(
- ALIGN_VIEWS, IMPORT_BINARY, IMPORT_TEXT,
+ ALIGN_VIEWS, CONFIGURE_SYMBOL_PROVIDERS,
"",
SORT_BY_NAME, SORT_BY_ID, SORT_BY_START,
"",
# Extension points
extensionpoint.trace_type_ui.name = Tmf Trace Type UI Elements
extensionpoint.sequence_diagram_loader.name = TMF UML 2 Sequence Diagram Loader
+extensionpoint.symbol_provider.name = TMF Symbol provider extension
# Perspective and Views names
perspective.category.name = Tracing
<plugin>
<extension-point id="org.eclipse.linuxtools.tmf.ui.uml2SDLoader" name="%extensionpoint.sequence_diagram_loader.name" schema="schema/org.eclipse.linuxtools.tmf.ui.uml2SDLoader.exsd"/>
<extension-point id="org.eclipse.linuxtools.tmf.ui.tracetypeui" name="%extensionpoint.trace_type_ui.name" schema="schema/org.eclipse.linuxtools.tmf.ui.tracetypeui.exsd"/>
+ <extension-point id="org.eclipse.tracecompass.tmf.ui.symbolProvider" name="%extensionpoint.symbol_provider.name" schema="schema/org.eclipse.tracecompass.tmf.ui.symbolProvider.exsd"/>
<extension
point="org.eclipse.ui.perspectives">
</description>
</colorDefinition>
</extension>
+ <extension
+ point="org.eclipse.tracecompass.tmf.ui.symbolProvider">
+ <providerFactory
+ class="org.eclipse.tracecompass.internal.tmf.ui.symbols.BasicSymbolProviderFactory"
+ id="org.eclipse.tracecompass.tmf.ui.providerFactory1"
+ priority="0">
+ </providerFactory>
+ </extension>
</plugin>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.tracecompass.tmf.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.tracecompass.tmf.ui" id="symbolProvider" name="TMF Symbol provider extension"/>
+ </appinfo>
+ <documentation>
+ This extension point can be used to transform from symbol addresses that might be found inside a TmfTrace into human readable texts, for example function names.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="providerFactory" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="providerFactory">
+ <annotation>
+ <documentation>
+ A symbol provider factory can be used to translate symbol addresses that can be found inside traces into symbol names.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ The ID of the extension
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The name of the class responsible to create an ISymbolProvider
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderFactory"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="priority" type="string" use="default" value="50">
+ <annotation>
+ <documentation>
+ Specify the priority of this factory relativ to the other. It should be an integer number. If not defined or not a valid integer it will be assumed to be zero.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ 2.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ Since 2.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ Copyright (c) 2016 Movidius 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 <a
+href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ </documentation>
+ </annotation>
+
+</schema>
public static String CallStackView_SortByThreadName;
public static String CallStackView_SortByThreadId;
public static String CallStackView_SortByThreadTime;
- public static String CallStackView_ImportMappingButtonText;
- public static String CallStackView_ImportMappingButtonTooltip;
- public static String CallStackView_ImportMappingDialogTitle;
- public static String CallStackView_ImportMappingJobName;
- public static String CallStackView_ImportBinaryFileButtonText;
- public static String CallStackView_ImportBinaryFileButtonTooltip;
- public static String CallStackView_ImportBinaryFileDialogTitle;
+ public static String CallStackView_ConfigureSymbolProvidersText;
+ public static String CallStackView_ConfigureSymbolProvidersTooltip;
public static String CopyToClipboardOperation_TaskName;
public static String CopyToClipboardOperation_OutOfMemoryErrorTitle;
public static String ExportToTextJob_Export_trace_to;
public static String ExportToTextJob_Unable_to_export_trace;
+ public static String SymbolProviderConfigDialog_title;
+ public static String SymbolProviderConfigDialog_message;
+
+ public static String BasicSymbolProviderPrefPage_radioBinaryFile_text;
+ public static String BasicSymbolProviderPrefPage_radioBinaryFile_tooltip;
+ public static String BasicSymbolProviderPrefPage_radioMappingFile_text;
+ public static String BasicSymbolProviderPrefPage_radioMappingFile_tooltip;
+ public static String BasicSymbolProviderPrefPage_btnBrowse;
+ public static String BasicSymbolProviderPrefPage_description;
+ public static String BasicSymbolProviderPrefPage_ImportMappingDialogTitle;
+ public static String BasicSymbolProviderPrefPage_ImportBinaryFileDialogTitle;
+ public static String BasicSymbolProviderPrefPage_errorFileDoesNotExists;
+ public static String BasicSymbolProviderPrefPage_errorSpecifyFile;
+ public static String BasicSymbolProviderPrefPage_loadingConfigurations;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
CallStackView_SortByThreadName=Sort threads by thread name
CallStackView_SortByThreadId=Sort threads by thread id
CallStackView_SortByThreadTime=Sort threads by start time
-CallStackView_ImportMappingButtonText=Import mapping file...
-CallStackView_ImportMappingButtonTooltip=Import a text file containing the mapping between addresses and function names
-CallStackView_ImportMappingDialogTitle=Select Mapping File
-CallStackView_ImportMappingJobName=Updating Call Stack view function mapping
-CallStackView_ImportBinaryFileButtonText=Import binary file...
-CallStackView_ImportBinaryFileButtonTooltip=Import a binary file containing debugging symbols
-CallStackView_ImportBinaryFileDialogTitle=Select Binary File
+CallStackView_ConfigureSymbolProvidersText=Configure symbol providers
+CallStackView_ConfigureSymbolProvidersTooltip=Configure how the addresses are mapped to function names
CopyToClipboardOperation_TaskName=Copying to Clipboard
CopyToClipboardOperation_OutOfMemoryErrorTitle=Out Of Memory Error
ExportToTextJob_Export_to=Export to {0}...
ExportToTextJob_Export_trace_to=Export trace to {0}
ExportToTextJob_Unable_to_export_trace=Unable to export trace to {0}
+
+#Symbol providers
+SymbolProviderConfigDialog_title = Symbol mapping
+SymbolProviderConfigDialog_message = Configure how symbols are resolved
+
+BasicSymbolProviderPrefPage_radioBinaryFile_text=Select a binary file
+BasicSymbolProviderPrefPage_radioBinaryFile_tooltip=Select a binary file, executable or library,\nthat was used to produce the selected trace
+BasicSymbolProviderPrefPage_radioMappingFile_text=Select a mapping file
+BasicSymbolProviderPrefPage_radioMappingFile_tooltip=Select a symbol to address mapping file of the binary used\n\
+to produce the selected trace.\n\
+Such a file can be generated using the 'nm' tool.
+BasicSymbolProviderPrefPage_btnBrowse=Browse...
+BasicSymbolProviderPrefPage_description=Symbol provider configuration for trace "{0}"
+BasicSymbolProviderPrefPage_ImportMappingDialogTitle=Select Mapping File
+BasicSymbolProviderPrefPage_ImportBinaryFileDialogTitle=Select Binary File
+BasicSymbolProviderPrefPage_errorFileDoesNotExists=The current path is not a file or it does not exist
+BasicSymbolProviderPrefPage_errorSpecifyFile=Please specify a valid binary or mapping file
+BasicSymbolProviderPrefPage_loadingConfigurations=Loading configurations...
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.core.callstack.FunctionNameMapper;
+import org.eclipse.tracecompass.tmf.core.event.lookup.ITmfCallsite;
+import org.eclipse.tracecompass.tmf.core.event.lookup.TmfCallsite;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
+
+/**
+ * The {@link BasicSymbolProvider} can use either an executable or a simple
+ * symbol mapping file to resolve symbols.
+ *
+ * @author Robert Kiss
+ *
+ */
+public class BasicSymbolProvider implements ISymbolProvider {
+
+ private final @NonNull ITmfTrace fTrace;
+
+ private @NonNull Map<String, String> fMapping = Collections.emptyMap();
+
+ private String fSource;
+
+ private @NonNull SourceKind fKind = SourceKind.BINARY;
+
+ private boolean fConfigured;
+
+ /**
+ * The kind of source this provider is configured with
+ *
+ */
+ public static enum SourceKind {
+ /**
+ * Literal for binary configuration
+ */
+ BINARY,
+
+ /**
+ * Literal for mapping configuration
+ */
+ MAPPING;
+ }
+
+ /**
+ * Create a new {@link BasicSymbolProvider} for the given trace
+ *
+ * @param trace
+ * A non-null trace
+ */
+ public BasicSymbolProvider(@NonNull ITmfTrace trace) {
+ fTrace = trace;
+ }
+
+ /**
+ *
+ * @return the configured source
+ */
+ public String getConfiguredSource() {
+ return fSource;
+ }
+
+ /**
+ * @return the configured source kind
+ */
+ public @NonNull SourceKind getConfiguredSourceKind() {
+ return fKind;
+ }
+
+ /**
+ * Set the configuration to the given source and kind.
+ *
+ * @param fileSource
+ * File path to either a binary file or a mapping file.
+ * @param kind
+ * the type of the referenced file
+ */
+ public void setConfiguredSource(String fileSource, @NonNull SourceKind kind) {
+ fSource = fileSource;
+ fKind = kind;
+ fConfigured = false;
+ }
+
+ @Override
+ public @NonNull ITmfTrace getTrace() {
+ return fTrace;
+ }
+
+ @Override
+ public void loadConfiguration(IProgressMonitor monitor) {
+ if (!fConfigured) {
+ synchronized (this) {
+ if (!fConfigured) {
+ try {
+ fMapping = Collections.emptyMap();
+ if (fSource != null) {
+ File file = new File(fSource);
+ if (file.isFile()) {
+ Map<String, String> result;
+ if (fKind == SourceKind.BINARY) {
+ result = FunctionNameMapper.mapFromBinaryFile(file);
+ } else {
+ result = FunctionNameMapper.mapFromNmTextFile(file);
+ }
+ if (result != null) {
+ fMapping = result;
+ }
+ }
+ }
+ } finally {
+ fConfigured = true;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public @Nullable String getSymbolText(long address) {
+ loadConfiguration(null);
+ return fMapping.get(Long.toHexString(address));
+ }
+
+ @Override
+ public @Nullable ITmfCallsite getSymbolInfo(long address) {
+ loadConfiguration(null);
+ String symbolText = getSymbolText(address);
+ if (symbolText != null) {
+ return new TmfCallsite(null, symbolText, -1);
+ }
+ return null;
+ }
+
+ @Override
+ public ISymbolProviderPreferencePage createPreferencePage() {
+ return new BasicSymbolProviderPreferencePage(this);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderFactory;
+
+/**
+ * Basic symbol provider factory that can handle any trace. It will create a
+ * {@link BasicSymbolProvider}.
+ *
+ * @author Robert Kiss
+ *
+ */
+@NonNullByDefault
+public class BasicSymbolProviderFactory implements ISymbolProviderFactory {
+
+ @Override
+ public ISymbolProvider createProvider(ITmfTrace trace) {
+ return new BasicSymbolProvider(trace);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import java.io.File;
+import java.text.MessageFormat;
+
+import org.eclipse.jdt.annotation.NonNull;
+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.FileDialog;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.tracecompass.internal.tmf.ui.Messages;
+import org.eclipse.tracecompass.internal.tmf.ui.symbols.BasicSymbolProvider.SourceKind;
+import org.eclipse.tracecompass.tmf.ui.symbols.AbstractSymbolProviderPreferencePage;
+
+/**
+ * Preference page that allows the user to configure a
+ * {@link BasicSymbolProvider}
+ *
+ * @author Robert Kiss
+ *
+ */
+public class BasicSymbolProviderPreferencePage extends AbstractSymbolProviderPreferencePage {
+
+ private Button fRadioBinaryFile;
+ private Text fTextBinaryFile;
+ private Button fButtonBrowseBinary;
+ private Button fRadioMappingFile;
+ private Text fTextMappingFile;
+ private Button fButtonBrowseMapping;
+
+ /**
+ * Creates a new object for the given provider
+ *
+ * @param provider
+ * a non-null provider
+ */
+ public BasicSymbolProviderPreferencePage(@NonNull BasicSymbolProvider provider) {
+ super(provider);
+ setDescription(MessageFormat.format(Messages.BasicSymbolProviderPrefPage_description, provider.getTrace().getName()));
+ setValid(true);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ composite.setLayout(new GridLayout(3, false));
+
+ fRadioBinaryFile = new Button(composite, SWT.RADIO);
+ fRadioBinaryFile.setText(Messages.BasicSymbolProviderPrefPage_radioBinaryFile_text);
+ fRadioBinaryFile.setToolTipText(Messages.BasicSymbolProviderPrefPage_radioBinaryFile_tooltip);
+ fRadioBinaryFile.setSelection(true);
+ fRadioBinaryFile.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ switchToSourceKind(SourceKind.BINARY, true);
+ }
+ });
+
+ fTextBinaryFile = new Text(composite, SWT.BORDER);
+ fTextBinaryFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fTextBinaryFile.setEditable(false);
+
+ fButtonBrowseBinary = new Button(composite, SWT.NONE);
+ fButtonBrowseBinary.setText(Messages.BasicSymbolProviderPrefPage_btnBrowse);
+ fButtonBrowseBinary.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ browseForFile(fTextBinaryFile, Messages.BasicSymbolProviderPrefPage_ImportBinaryFileDialogTitle);
+ }
+ });
+
+ fRadioMappingFile = new Button(composite, SWT.RADIO);
+ fRadioMappingFile.setText(Messages.BasicSymbolProviderPrefPage_radioMappingFile_text);
+ fRadioMappingFile.setToolTipText(Messages.BasicSymbolProviderPrefPage_radioMappingFile_tooltip);
+ fRadioMappingFile.setSelection(false);
+ fRadioMappingFile.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ switchToSourceKind(SourceKind.MAPPING, true);
+ }
+ });
+
+ fTextMappingFile = new Text(composite, SWT.BORDER);
+ fTextMappingFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fTextMappingFile.setEnabled(false);
+ fTextMappingFile.setEditable(false);
+
+ fButtonBrowseMapping = new Button(composite, SWT.NONE);
+ fButtonBrowseMapping.setText(Messages.BasicSymbolProviderPrefPage_btnBrowse);
+ fButtonBrowseMapping.setEnabled(false);
+ fButtonBrowseMapping.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ browseForFile(fTextMappingFile, Messages.BasicSymbolProviderPrefPage_ImportMappingDialogTitle);
+ }
+ });
+
+ loadProviderSettings();
+
+ return composite;
+ }
+
+ private void browseForFile(Text fileField, String dialogTitle) {
+ FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
+ fileDialog.setText(dialogTitle);
+ String filePath = fileDialog.open();
+ if (filePath != null) {
+ fileField.setText(filePath);
+ broadcastChanges();
+ }
+
+ }
+
+ private void loadProviderSettings() {
+ BasicSymbolProvider provider = (BasicSymbolProvider) getSymbolProvider();
+ String source = provider.getConfiguredSource();
+ SourceKind sourceKind = provider.getConfiguredSourceKind();
+ if (source != null) {
+ if (sourceKind == SourceKind.BINARY) {
+ fTextBinaryFile.setText(source);
+ } else {
+ fTextMappingFile.setText(source);
+ }
+ }
+
+ switchToSourceKind(sourceKind, false);
+ broadcastChanges();
+ }
+
+ private void switchToSourceKind(@NonNull SourceKind kind, boolean broadcastChanges) {
+ fRadioBinaryFile.setSelection(kind == SourceKind.BINARY);
+ fTextBinaryFile.setEnabled(kind == SourceKind.BINARY);
+ fButtonBrowseBinary.setEnabled(kind == SourceKind.BINARY);
+
+ fRadioMappingFile.setSelection(kind == SourceKind.MAPPING);
+ fTextMappingFile.setEnabled(kind == SourceKind.MAPPING);
+ fButtonBrowseMapping.setEnabled(kind == SourceKind.MAPPING);
+ if (broadcastChanges) {
+ broadcastChanges();
+ }
+ }
+
+ @Override
+ public void saveConfiguration() {
+ BasicSymbolProvider provider = (BasicSymbolProvider) getSymbolProvider();
+ provider.setConfiguredSource(getCurrentSource(), getCurrentSourceKind());
+ }
+
+ private @NonNull SourceKind getCurrentSourceKind() {
+ if (fRadioBinaryFile.getSelection()) {
+ return SourceKind.BINARY;
+ }
+ return SourceKind.MAPPING;
+ }
+
+ private String getCurrentSource() {
+ if (fRadioBinaryFile.getSelection()) {
+ return fTextBinaryFile.getText();
+ }
+ return fTextMappingFile.getText();
+ }
+
+ private void broadcastChanges() {
+ String filePath = getCurrentSource();
+ String errorMessage = null;
+ if (filePath != null && filePath.length() > 0) {
+ File file = new File(filePath);
+ if (!file.isFile()) {
+ errorMessage = Messages.BasicSymbolProviderPrefPage_errorFileDoesNotExists;
+ }
+ } else {
+ errorMessage = Messages.BasicSymbolProviderPrefPage_errorSpecifyFile;
+ }
+ setErrorMessage(errorMessage);
+ setValid(errorMessage == null);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jface.preference.PreferencePage;
+
+/**
+ * Abstract implementation of the {@link ISymbolProviderPreferencePage}. Instead
+ * of implementing the interface one should extend this class.
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ */
+@NonNullByDefault
+public abstract class AbstractSymbolProviderPreferencePage extends PreferencePage implements ISymbolProviderPreferencePage {
+
+ private final ISymbolProvider fProvider;
+
+ /**
+ * Create a new instance that knows how to configure the given provider
+ *
+ * @param provider
+ * the {@link ISymbolProvider} to configure
+ */
+ public AbstractSymbolProviderPreferencePage(ISymbolProvider provider) {
+ fProvider = provider;
+ setTitle(provider.getTrace().getName());
+ noDefaultAndApplyButton();
+ }
+
+ @Override
+ public ISymbolProvider getSymbolProvider() {
+ return fProvider;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.core.event.lookup.ITmfCallsite;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * A default implementation of the {@link ISymbolProvider} which return a hex
+ * format representation of the symbol address
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ *
+ */
+@NonNullByDefault
+public class DefaultSymbolProvider implements ISymbolProvider {
+
+ private final ITmfTrace fTrace;
+
+ /**
+ * Create a new provider for the given trace
+ *
+ * @param trace
+ * the trace
+ */
+ public DefaultSymbolProvider(ITmfTrace trace) {
+ fTrace = trace;
+ }
+
+ @Override
+ public void loadConfiguration(@Nullable IProgressMonitor monitor) {
+ // no configuration here
+ }
+
+ @Override
+ public ITmfTrace getTrace() {
+ return fTrace;
+ }
+
+ /**
+ * Return a hex formated representation of the given address
+ *
+ * @param address
+ * the symbol address
+ * @return the hex representation of the given address
+ */
+ @Override
+ public @NonNull String getSymbolText(long address) {
+ if ((address & (0xFFFFFFFF << 32)) == 0) {
+ return String.format("%08x", address); //$NON-NLS-1$
+ }
+ return String.format("%016x", address); //$NON-NLS-1$
+ }
+
+ /**
+ * The default symbol provider will return null for this method
+ *
+ * @param address
+ * the symbol address
+ * @return always null
+ */
+ @Override
+ public @Nullable ITmfCallsite getSymbolInfo(long address) {
+ return null;
+ }
+
+ /**
+ * @return null because the default symbol provider doesn't support
+ * configuration
+ */
+ @Override
+ public @Nullable ISymbolProviderPreferencePage createPreferencePage() {
+ return null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.core.event.lookup.ITmfCallsite;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
+
+/**
+ * An ISymbolProvider is used to map symbol addresses that might be found inside
+ * an {@link TmfTrace} into human readable strings.
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ * @see ISymbolProviderFactory
+ *
+ */
+public interface ISymbolProvider {
+
+ /**
+ * @return the trace that this class resolves symbols for
+ */
+ @NonNull ITmfTrace getTrace();
+
+ /**
+ * Some providers might have configurations that take some time to load. All
+ * the CPU intensive load operations shall be done in this method. The
+ * adopters shall call this method at an opportune moment when cancellation
+ * and UI feedback is possible. However, the implementors of this interface
+ * shall not assume that this method has been called.
+ *
+ * @param monitor
+ * The progress monitor to use, can be null
+ */
+ void loadConfiguration(IProgressMonitor monitor);
+
+ /**
+ * Return the symbol text corresponding to the given address or null if
+ * there is no such symbol
+ *
+ * @param address
+ * the address of the symbol
+ * @return the symbol text or null if the symbol cannot be found
+ */
+ @Nullable String getSymbolText(long address);
+
+ /**
+ * Return additional information regarding the symbol from the given address
+ * or null if the symbol cannot be found
+ *
+ * @param address
+ * the address of the symbol
+ * @return the symbol {@link ITmfCallsite} information or null if the symbol
+ * cannot be found
+ */
+ @Nullable ITmfCallsite getSymbolInfo(long address);
+
+ /**
+ * Create the {@link ISymbolProviderPreferencePage} that can be used to
+ * configure this {@link ISymbolProvider}
+ *
+ * @return the {@link ISymbolProviderPreferencePage} or null if this symbol
+ * provider does not offer a configuration UI
+ */
+ @Nullable ISymbolProviderPreferencePage createPreferencePage();
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * Instance of this interface can be contributed using the
+ * <code>org.eclipse.tracecompass.tmf.ui.symbolProvider</code> extension and is
+ * used to create instances of {@link ISymbolProvider}
+ *
+ * @author Robert Kiss
+ *
+ * @since 2.0
+ */
+public interface ISymbolProviderFactory {
+
+ /**
+ * Create a provider for the given trace. If this factory does not know how
+ * to handle the given trace it will return null;
+ *
+ * @param trace
+ * A non-null trace
+ * @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);
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jface.preference.IPreferencePage;
+
+/**
+ * Allow the user to configure a {@link ISymbolProvider}
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ *
+ */
+@NonNullByDefault
+public interface ISymbolProviderPreferencePage extends IPreferencePage {
+
+ /**
+ * Return the {@link ISymbolProvider} associated with this preference page
+ *
+ * @return the associated {@link ISymbolProvider}
+ */
+ ISymbolProvider getSymbolProvider();
+
+ /**
+ * Save the configuration that is currently in UI into the corresponding
+ * {@link ISymbolProvider}.
+ */
+ void saveConfiguration();
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.preference.IPreferencePageContainer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.Messages;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * This class shall be used to configure one or more {@link ISymbolProvider}. It
+ * receives an array of {@link ISymbolProviderPreferencePage} and creates a
+ * dialog that can be used to configure the corresponding providers. If the
+ * {@link #open()} method exits with {@link IDialogConstants#OK_ID} the caller
+ * shall assume that the corresponding {@link ISymbolProvider}'s have a new
+ * configuration.
+ *
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ *
+ */
+public class SymbolProviderConfigDialog extends TitleAreaDialog implements IPreferencePageContainer {
+
+ private ISymbolProviderPreferencePage[] fPreferencePages;
+ private CTabItem[] fPageTabs;
+ private CTabFolder fTabFolder;
+
+ private IRunnableWithProgress configJob = (monitor) -> {
+ // saving the configuration is fast and need UI access
+ SymbolProviderConfigDialog.this.getContents().getDisplay().syncExec(() -> {
+ for (int i = 0; i < fPreferencePages.length; i++) {
+ ISymbolProviderPreferencePage page = fPreferencePages[i];
+ page.saveConfiguration();
+ }
+ });
+ monitor.beginTask(Messages.BasicSymbolProviderPrefPage_loadingConfigurations, fPreferencePages.length * 100);
+ try {
+ for (int i = 0; i < fPreferencePages.length; i++) {
+ ISymbolProviderPreferencePage page = fPreferencePages[i];
+ page.getSymbolProvider().loadConfiguration(monitor);
+ monitor.worked(100);
+ }
+ } finally {
+ monitor.done();
+ }
+ };
+
+ /**
+ * Create a new dialog that will use the given shall and preference pages.
+ *
+ * @param parentShell
+ * The parent shell
+ * @param pages
+ * the pages that provides the configuration UI for
+ * {@link ISymbolProvider}'s. The array shall not be empty and
+ * shall not contain null elements.
+ *
+ */
+ public SymbolProviderConfigDialog(Shell parentShell, ISymbolProviderPreferencePage... pages) {
+ super(parentShell);
+ fPreferencePages = pages;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ getShell().setText(Messages.SymbolProviderConfigDialog_title);
+ setTitle(Messages.SymbolProviderConfigDialog_title);
+ setMessage(Messages.SymbolProviderConfigDialog_message);
+
+ Composite composite = (Composite) super.createDialogArea(parent);
+ composite.setLayout(new GridLayout());
+
+ // if we have one single provider that we don't need a tab
+ if (fPreferencePages.length == 1) {
+ attachPreference(composite, fPreferencePages[0]);
+ updateMessage(0);
+ } else {
+ fTabFolder = new CTabFolder(composite, SWT.NONE);
+ fTabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fPageTabs = new CTabItem[fPreferencePages.length];
+ for (int i = 0; i < fPreferencePages.length; i++) {
+ ISymbolProviderPreferencePage page = fPreferencePages[i];
+ fPageTabs[i] = new CTabItem(fTabFolder, SWT.NONE);
+ fPageTabs[i].setText(page.getTitle());
+ Composite child = new Composite(fTabFolder, SWT.NONE);
+ child.setLayout(new GridLayout());
+ child.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
+ fPageTabs[i].setControl(child);
+ attachPreference(child, page);
+ updateMessage(i);
+ }
+ fTabFolder.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateMessage(fTabFolder.indexOf((CTabItem) e.item));
+ }
+ });
+ }
+ return composite;
+ }
+
+ @Override
+ public boolean isHelpAvailable() {
+ return false;
+ }
+
+ private void attachPreference(Composite composite, ISymbolProviderPreferencePage page) {
+ page.setContainer(this);
+ page.createControl(composite);
+ page.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+ }
+
+ @Override
+ public IPreferenceStore getPreferenceStore() {
+ // not used
+ return null;
+ }
+
+ @Override
+ public void updateTitle() {
+ // not used
+ }
+
+ @Override
+ public void updateButtons() {
+ // nothing to do
+ }
+
+ @Override
+ protected void okPressed() {
+ boolean cancel = false;
+ try {
+ new ProgressMonitorDialog(getShell()).run(true, false, configJob);
+ } catch (InvocationTargetException e) {
+ setMessage(e.getMessage(), IMessageProvider.ERROR);
+ cancel = true;
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ if (!cancel) {
+ super.okPressed();
+ }
+ }
+
+ @Override
+ public void updateMessage() {
+ if (fTabFolder == null) {
+ updateMessage(0);
+ } else {
+ updateMessage(fTabFolder.getSelectionIndex());
+ }
+ }
+
+ private void updateMessage(int pageIndex) {
+ ISymbolProviderPreferencePage currentPage = fPreferencePages[pageIndex];
+ String message = currentPage.getMessage();
+ String errorMessage = currentPage.getErrorMessage();
+ int messageType = IMessageProvider.NONE;
+
+ if (errorMessage != null) {
+ message = errorMessage;
+ messageType = IMessageProvider.ERROR;
+ }
+ setMessage(message, messageType);
+
+ if (fPreferencePages.length > 1) {
+ // update the corresponding tab icon
+ if (messageType == IMessageProvider.ERROR) {
+ fPageTabs[pageIndex].setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK));
+ } else {
+ fPageTabs[pageIndex].setImage(null);
+ }
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 Movidius 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.tmf.ui.symbols;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * This class offer services around the
+ * <code>org.eclipse.tracecompass.tmf.ui.symbolProvider</code> extension point.
+ *
+ * @author Robert Kiss
+ * @since 2.0
+ *
+ */
+public final class SymbolProviderManager {
+
+ /**
+ * The singleton instance of this manager
+ */
+ private static SymbolProviderManager INSTANCE;
+
+ private static final String EXTENSION_POINT_ID = "org.eclipse.tracecompass.tmf.ui.symbolProvider"; //$NON-NLS-1$
+ private static final String ELEM_NAME_PROVIDER = "providerFactory"; //$NON-NLS-1$
+ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+ private static final String ATTR_PRIORITY = "priority"; //$NON-NLS-1$
+
+ private final List<SymbolProviderFactoryWrapper> fProviders;
+
+ private final Map<ITmfTrace, WeakReference<ISymbolProvider>> fInstances = new WeakHashMap<>();
+
+ /**
+ * Internal class used to store extension point information
+ *
+ */
+ private static class SymbolProviderFactoryWrapper {
+
+ public final ISymbolProviderFactory factory;
+ public final int priority;
+
+ private SymbolProviderFactoryWrapper(ISymbolProviderFactory factory, int priority) {
+ this.factory = factory;
+ this.priority = priority;
+
+ }
+
+ }
+
+ /**
+ *
+ * @return the singleton instance of this class
+ */
+ @SuppressWarnings("null")
+ public static synchronized @NonNull SymbolProviderManager getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new SymbolProviderManager();
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * The private constructor of this manager
+ */
+ private SymbolProviderManager() {
+ fProviders = new ArrayList<>();
+ IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID);
+ for (IConfigurationElement element : configElements) {
+ if (ELEM_NAME_PROVIDER.equals(element.getName())) {
+ try {
+ Object extension = element.createExecutableExtension(ATTR_CLASS);
+ int priority = 0;
+ try {
+ priority = Integer.parseInt(element.getAttribute(ATTR_PRIORITY));
+ } catch (NumberFormatException e) {
+ // safe to ignore
+ }
+ fProviders.add(new SymbolProviderFactoryWrapper((ISymbolProviderFactory) extension, priority));
+ } catch (CoreException | ClassCastException e) {
+ Activator.getDefault().logError("Exception while loading extensions", e); //$NON-NLS-1$
+ }
+ }
+ }
+ // Those with a higher priority need to be on top
+ fProviders.sort(Comparator.comparingLong(o -> -o.priority));
+ }
+
+ /**
+ * Locate an {@link ISymbolProvider} capable to resolve symbols from the
+ * given trace. If no such provider is defined an instance of
+ * {@link DefaultSymbolProvider} will be returned
+ *
+ * @param trace
+ * The trace to create a provider for
+ * @return a valid {@link ISymbolProvider}, never null
+ */
+ public @NonNull ISymbolProvider getSymbolProvider(@NonNull ITmfTrace trace) {
+ // Check to see if we already have a provider for this trace
+ synchronized (fInstances) {
+ WeakReference<ISymbolProvider> reference = fInstances.get(trace);
+ if (reference != null) {
+ ISymbolProvider provider = reference.get();
+ if (provider != null) {
+ return provider;
+ }
+ }
+ // we don't have yet an instance, build one
+ for (SymbolProviderFactoryWrapper wrapper : fProviders) {
+ ISymbolProviderFactory factory = wrapper.factory;
+ ISymbolProvider provider = factory.createProvider(trace);
+ if (provider != null) {
+ fInstances.put(trace, new WeakReference<>(provider));
+ return provider;
+ }
+ }
+ }
+ // No provider found, return the default one
+ return new DefaultSymbolProvider(trace);
+ }
+
+}
try {
ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue();
if (!value.isNull()) {
- String address = value.toString();
- return fView.getFunctionName(address);
+ return fView.getFunctionName(entry.getTrace(), value);
}
} catch (AttributeNotFoundException e) {
Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
try {
ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue();
if (!value.isNull()) {
- String address = value.toString();
- String name = fView.getFunctionName(address);
+ String name = fView.getFunctionName(entry.getTrace(), value);
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
Utils.drawText(gc, name, bounds.x, bounds.y, bounds.width, bounds.height, true, true);
}
package org.eclipse.tracecompass.tmf.ui.views.callstack;
-import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
-import org.eclipse.tracecompass.internal.tmf.core.callstack.FunctionNameMapper;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderConfigDialog;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderManager;
import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
- private static final String IMPORT_MAPPING_ICON_PATH = "icons/etool16/import.gif"; //$NON-NLS-1$
private static final String IMPORT_BINARY_ICON_PATH = "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
// Fields
// ------------------------------------------------------------------------
- /** The map to map function addresses to function names */
- private Map<String, String> fNameMapping;
+ private final Map<ITmfTrace, ISymbolProvider> fSymbolProviders = new HashMap<>();
// The next event action
private Action fNextEventAction;
// The previous item action
private Action fPreviousItemAction;
- // The action to import a function-name mapping file
- private Action fImportMappingAction;
-
// The action to import a binary file mapping */
- private Action fImportBinaryFileMappingAction;
+ private Action fConfigureSymbolsAction;
// The saved time sync. signal used when switching off the pinning of a view
private TmfSelectionRangeUpdatedSignal fSavedTimeSyncSignal;
// Internal
// ------------------------------------------------------------------------
+ @Override
+ @TmfSignalHandler
+ public void traceClosed(TmfTraceClosedSignal signal) {
+ super.traceClosed(signal);
+ synchronized(fSymbolProviders){
+ for(ITmfTrace trace : getTracesToBuild(signal.getTrace())){
+ fSymbolProviders.remove(trace);
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ protected void refresh() {
+ super.refresh();
+ updateConfigureSymbolsAction();
+ }
+
@Override
protected void buildEventList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
if (monitor.isCanceled()) {
if (start == end && !complete) { // when complete execute one last time regardless of end time
continue;
}
+
+ ISymbolProvider provider = fSymbolProviders.get(trace);
+ if (provider == null) {
+ provider = SymbolProviderManager.getInstance().getSymbolProvider(trace);
+ provider.loadConfiguration(monitor);
+ fSymbolProviders.put(trace, provider);
+ }
+
+ getConfigureSymbolsAction().setEnabled(true);
+
List<Integer> threadQuarks = ss.getQuarks(threadPaths);
TraceEntry traceEntry = traceEntryMap.get(trace);
if (traceEntry == null) {
}
for (ITimeGraphEntry child : threadEntry.getChildren()) {
CallStackEntry callStackEntry = (CallStackEntry) child;
+ ITmfTrace trace = callStackEntry.getTrace();
try {
ITmfStateInterval stackLevelInterval = ss.querySingleState(time, callStackEntry.getQuark());
ITmfStateValue nameValue = stackLevelInterval.getStateValue();
- String name = ""; //$NON-NLS-1$
- try {
- if (nameValue.getType() == Type.STRING) {
- String address = nameValue.unboxStr();
- name = getFunctionName(address);
- } else if (nameValue.getType() == Type.INTEGER) {
- name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
- } else if (nameValue.getType() == Type.LONG) {
- name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
- }
- } catch (StateValueTypeException e) {
- }
+ String name = getFunctionName(trace, nameValue);
callStackEntry.setFunctionName(name);
if (name.length() > 0) {
callStackEntry.setFunctionEntryTime(stackLevelInterval.getStartTime());
}
}
+ String getFunctionName(ITmfTrace trace, ITmfStateValue nameValue) {
+ long address = Long.MAX_VALUE;
+ String name = ""; //$NON-NLS-1$
+ try {
+ if (nameValue.getType() == Type.STRING) {
+ name = nameValue.unboxStr();
+ try {
+ address = Long.parseLong(name, 16);
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ } else if (nameValue.getType() == Type.INTEGER) {
+ name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
+ address = nameValue.unboxInt();
+ } else if (nameValue.getType() == Type.LONG) {
+ name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
+ address = nameValue.unboxLong();
+ }
+ } catch (StateValueTypeException e) {
+ }
+ if (address != Long.MAX_VALUE) {
+ ISymbolProvider provider = fSymbolProviders.get(trace);
+ if (provider != null) {
+ String symbol = provider.getSymbolText(address);
+ if (symbol != null) {
+ name = symbol;
+ }
+ }
+ }
+ return name;
+ }
+
private void makeActions() {
fPreviousItemAction = getTimeGraphViewer().getPreviousItemAction();
fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
@Override
protected void fillLocalToolBar(IToolBarManager manager) {
makeActions();
- manager.add(getImportBinaryAction());
- manager.add(getImportMappingAction());
+ manager.add(getConfigureSymbolsAction());
manager.add(new Separator());
manager.add(getSortByNameAction());
manager.add(getSortByIdAction());
// Methods related to function name mapping
// ------------------------------------------------------------------------
- /**
- * Common code for all import file mapping actions
- */
- private abstract class AbstractImportFileMappingAction extends Action {
- private final String fDialogTitle;
-
- private AbstractImportFileMappingAction(String dialogTitle) {
- fDialogTitle = dialogTitle;
- }
-
- @Override
- public void run() {
- FileDialog dialog = new FileDialog(getViewSite().getShell());
- dialog.setText(fDialogTitle);
- final String filePath = dialog.open();
- if (filePath == null) {
- /* No file was selected, don't change anything */
- return;
- }
-
- /*
- * Start the mapping import in a separate thread (we do not want to
- * UI thread to do this).
- */
- Job job = new Job(Messages.CallStackView_ImportMappingJobName) {
- @Override
- public IStatus run(IProgressMonitor monitor) {
- fNameMapping = doMapping(new File(filePath));
-
- /* Refresh call stack entries and event labels */
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- synchingToTime(getTimeGraphViewer().getSelectionBegin());
- }
- });
- return Status.OK_STATUS;
- }
- };
- job.schedule();
- }
-
- abstract Map<String, String> doMapping(File file);
- }
-
- /**
- * Toolbar icon to import the function address-to-name mapping file.
- */
- private Action getImportMappingAction() {
- if (fImportMappingAction != null) {
- return fImportMappingAction;
- }
- fImportMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportMappingDialogTitle) {
- @Override
- Map<String, String> doMapping(File file) {
- return FunctionNameMapper.mapFromNmTextFile(file);
- }
- };
-
- fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
- fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
- fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
-
- return fImportMappingAction;
- }
-
private Action getSortByNameAction() {
if (fSortByNameAction == null) {
fSortByNameAction = new Action(Messages.CallStackView_SortByThreadName, IAction.AS_CHECK_BOX) {
refresh();
}
- /**
- * Toolbar icon to import the function address-to-name mapping binary file.
- */
- private Action getImportBinaryAction() {
- if (fImportBinaryFileMappingAction != null) {
- return fImportBinaryFileMappingAction;
+ private Action getConfigureSymbolsAction() {
+ if (fConfigureSymbolsAction != null) {
+ return fConfigureSymbolsAction;
}
- fImportBinaryFileMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportBinaryFileDialogTitle) {
+ fConfigureSymbolsAction = new Action(Messages.CallStackView_ConfigureSymbolProvidersText) {
@Override
- Map<String, String> doMapping(File file) {
- return FunctionNameMapper.mapFromBinaryFile(file);
+ public void run() {
+ SymbolProviderConfigDialog dialog = new SymbolProviderConfigDialog(getSite().getShell(), getProviderPages());
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ refresh();
+ }
}
};
- fImportBinaryFileMappingAction.setText(Messages.CallStackView_ImportBinaryFileButtonText);
- fImportBinaryFileMappingAction.setToolTipText(Messages.CallStackView_ImportBinaryFileButtonTooltip);
- fImportBinaryFileMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
+ fConfigureSymbolsAction.setToolTipText(Messages.CallStackView_ConfigureSymbolProvidersTooltip);
+ fConfigureSymbolsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
+ fConfigureSymbolsAction.setEnabled(false);
- return fImportBinaryFileMappingAction;
+ return fConfigureSymbolsAction;
}
- String getFunctionName(String address) {
- if (fNameMapping == null) {
- /* No mapping available, just print the addresses */
- return address;
- }
- String ret = fNameMapping.get(address);
- if (ret == null) {
- /*
- * We didn't find this address in the mapping file, just use the
- * address
- */
- return address;
+ /**
+ * @return an array of {@link ISymbolProviderPreferencePage} that will
+ * configure the current traces
+ */
+ private ISymbolProviderPreferencePage[] getProviderPages() {
+ List<ISymbolProviderPreferencePage> pages = new ArrayList<>();
+ ITmfTrace trace = getTrace();
+ if (trace != null) {
+ for (ITmfTrace subTrace : getTracesToBuild(trace)) {
+ ISymbolProvider provider = fSymbolProviders.get(subTrace);
+ if (provider != null) {
+ ISymbolProviderPreferencePage page = provider.createPreferencePage();
+ if (page != null) {
+ pages.add(page);
+ }
+ }
+ }
}
- return ret;
+ return pages.toArray(new ISymbolProviderPreferencePage[pages.size()]);
+ }
+
+ /**
+ * Update the enable status of the configure symbols action
+ */
+ private void updateConfigureSymbolsAction() {
+ ISymbolProviderPreferencePage[] providerPages = getProviderPages();
+ getConfigureSymbolsAction().setEnabled(providerPages.length > 0);
}
}