tmf: Add function name mapping to the Callstack View
authorAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Tue, 29 Oct 2013 22:35:33 +0000 (18:35 -0400)
committerAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Sun, 17 Nov 2013 21:18:04 +0000 (16:18 -0500)
Initial version of the "function name mapper" for the Callstack View.
It currently only supports a text file listing addresses followed by
names, like the output of "nm [binary] > out.txt".

The next steps will be:
- Add support for reading the binary directly, by tapping into the
  relevant CDT components.
- Add a separate dialog that shows the currently imported file name(s).
- Add support for dynamically-loaded libraries. This will require some
  work on the tracer side.

Change-Id: Id622cce487965b8c770fc40218685ec7605924ff
Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Reviewed-on: https://git.eclipse.org/r/17978
Tested-by: Hudson CI
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
IP-Clean: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
org.eclipse.linuxtools.lttng2.ust.core.tests/src/org/eclipse/linuxtools/lttng2/ust/core/tests/trace/callstack/LttngUstCallStackProviderFastTest.java
org.eclipse.linuxtools.lttng2.ust.core.tests/src/org/eclipse/linuxtools/lttng2/ust/core/tests/trace/callstack/LttngUstCallStackProviderTest.java
org.eclipse.linuxtools.lttng2.ust.core/src/org/eclipse/linuxtools/internal/lttng2/ust/core/trace/callstack/LttngUstCallStackProvider.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java
org.eclipse.linuxtools.tmf.ui/build.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/Messages.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/messages.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/callstack/CallStackPresentationProvider.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/callstack/CallStackView.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/callstack/FunctionNameMapper.java [new file with mode: 0644]

index 89715eeaa3a668009801207a4fc489c0a03587c9..06a2196566963c13eb417fcbda2a962a66bf91b9 100644 (file)
@@ -107,7 +107,7 @@ public class LttngUstCallStackProviderFastTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, start);
         assertEquals(1, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
+        assertEquals("40472b", cs[0]);
     }
 
     /**
@@ -118,8 +118,8 @@ public class LttngUstCallStackProviderFastTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1379361250310000000L);
         assertEquals(2, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x403d60", cs[1]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("403d60", cs[1]);
     }
 
     /**
@@ -130,9 +130,9 @@ public class LttngUstCallStackProviderFastTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1379361250498400000L);
         assertEquals(3, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x403b14", cs[1]);
-        assertEquals("0x401b23", cs[2]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("403b14", cs[1]);
+        assertEquals("401b23", cs[2]);
     }
 
     /**
@@ -143,10 +143,10 @@ public class LttngUstCallStackProviderFastTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1379361250499759000L);
         assertEquals(4, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x4045c8", cs[1]);
-        assertEquals("0x403760", cs[2]);
-        assertEquals("0x401aac", cs[3]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("4045c8", cs[1]);
+        assertEquals("403760", cs[2]);
+        assertEquals("401aac", cs[3]);
     }
 
     /**
@@ -158,8 +158,8 @@ public class LttngUstCallStackProviderFastTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, end);
         assertEquals(3, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x4045c8", cs[1]);
-        assertEquals("0x403760", cs[2]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("4045c8", cs[1]);
+        assertEquals("403760", cs[2]);
     }
 }
index d04fc824bf538e56bac97c55637221ea6ff9590e..8e86fa8cb14be75bab6ed4aa2d5e9d2629550ce1 100644 (file)
@@ -140,7 +140,7 @@ public class LttngUstCallStackProviderTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, start);
         assertEquals(1, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
+        assertEquals("40472b", cs[0]);
     }
 
     /**
@@ -151,8 +151,8 @@ public class LttngUstCallStackProviderTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1378850463600000000L);
         assertEquals(2, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x403d60", cs[1]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("403d60", cs[1]);
     }
 
     /**
@@ -163,9 +163,9 @@ public class LttngUstCallStackProviderTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1378850463770000000L);
         assertEquals(3, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x403b14", cs[1]);
-        assertEquals("0x401b23", cs[2]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("403b14", cs[1]);
+        assertEquals("401b23", cs[2]);
     }
 
     /**
@@ -176,10 +176,10 @@ public class LttngUstCallStackProviderTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, 1378850463868753000L);
         assertEquals(4, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x4045c8", cs[1]);
-        assertEquals("0x403760", cs[2]);
-        assertEquals("0x401aac", cs[3]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("4045c8", cs[1]);
+        assertEquals("403760", cs[2]);
+        assertEquals("401aac", cs[3]);
     }
 
     /**
@@ -191,8 +191,8 @@ public class LttngUstCallStackProviderTest {
         String[] cs = TestUtils.getCallStack(fixture, PROCNAME, end);
         assertEquals(3, cs.length);
 
-        assertEquals("0x40472b", cs[0]);
-        assertEquals("0x4045c8", cs[1]);
-        assertEquals("0x403760", cs[2]);
+        assertEquals("40472b", cs[0]);
+        assertEquals("4045c8", cs[1]);
+        assertEquals("403760", cs[2]);
     }
 }
index 3be120963f78d92e76dcfa8d40273a28c501fdb6..ae77fb4ce86afbaca6d7459762a6458321001509 100644 (file)
@@ -64,6 +64,12 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
         FUNC_EXIT_EVENTS.add("lttng_ust_cyg_profile_fast:func_exit"); //$NON-NLS-1$
     }
 
+    /**
+     * Version number of this state provider. Please bump this if you modify
+     * the contents of the generated state history in some way.
+     */
+    private static final int VERSION = 1;
+
     // ------------------------------------------------------------------------
     // Constructor
     // ------------------------------------------------------------------------
@@ -93,6 +99,11 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
         return new LttngUstCallStackProvider(getTrace());
     }
 
+    @Override
+    public int getVersion() {
+        return VERSION;
+    }
+
     // ------------------------------------------------------------------------
     // Methods from CallStackStateProvider
     // ------------------------------------------------------------------------
@@ -122,7 +133,7 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
             return null;
         }
         Long address = (Long) event.getContent().getField(FIELD_ADDR).getValue();
-        return getFunctionNameFromAddress(address.longValue());
+        return Long.toHexString(address);
     }
 
     @Override
@@ -140,7 +151,7 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
             return CallStackStateProvider.UNDEFINED;
         }
         Long address = (Long) field.getValue();
-        return getFunctionNameFromAddress(address.longValue());
+        return Long.toHexString(address);
     }
 
     @Override
@@ -156,16 +167,4 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
 
         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 7284635fc9649310c4010402162ad02db719a92f..9341b6953e6e548a71db96b42e4e3bc3a8ad39cc 100644 (file)
@@ -76,12 +76,6 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
     /** Dummy function name for when no function is expected */
     private static final String NO_FUNCTION = "no function"; //$NON-NLS-1$
 
-    /**
-     * Version number of this state provider. Please bump this if you modify
-     * the contents of the generated state history in some way.
-     */
-    private static final int VERSION = 0;
-
     /**
      * Default constructor
      *
@@ -92,11 +86,6 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
         super(trace, ITmfEvent.class, ID);
     }
 
-    @Override
-    public int getVersion() {
-        return VERSION;
-    }
-
     @Override
     protected void eventHandle(ITmfEvent event) {
         if (!considerEvent(event)) {
index 0081f8f2780c6e6b9b18bc662fb3ce79be46b817..9ed841f5f1a9c5dc3d4039d168f13d9a157f184d 100644 (file)
@@ -21,3 +21,5 @@ bin.includes = META-INF/,\
                schema/
 src.includes = about.html,\
                schema/
+additional.bundles = org.eclipse.jdt.annotation
+jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation
index 84e5e34b7e5eec7f0daeb905d19032005b9fbb30..92ba8ec777f3da1b175716d3ec223a4996c20fd0 100644 (file)
@@ -297,6 +297,11 @@ public class Messages extends NLS {
     public static String CallStackView_DurationColumn;
     public static String CallStackView_StackInfoNotAvailable;
 
+    public static String CallStackView_ImportMappingButtonText;
+    public static String CallStackView_ImportMappingButtonTooltip;
+    public static String CallStackView_ImportMappingDialogTitle;
+    public static String CallStackView_ImportMappingJobName;
+
     static {
         // initialize resource bundle
         NLS.initializeMessages(BUNDLE_NAME, Messages.class);
index 34865bf9369e56656f7c980f10c49fc0bc97aa42..194fab27cde5e363deef97ac4f3db170217fe180 100644 (file)
@@ -290,9 +290,15 @@ FilterViewer_ValueLabel=value:
 TmfView_PinActionNameText=Pin View
 TmfView_PinActionToolTipText=Pin View
 
+# Call Stack View
 CallStackView_FunctionColumn=Function
 CallStackView_DepthColumn=Depth
 CallStackView_EntryTimeColumn=Entry time
 CallStackView_ExitTimeColumn=Exit time
 CallStackView_DurationColumn=Duration
 CallStackView_StackInfoNotAvailable=Stack info not available
+
+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
index 0d1c2c6b06a7004702c4eb6a08c4c97ab0a0cf83..14297d08356cbfd8979b0cddf223591be49d458f 100644 (file)
@@ -17,7 +17,6 @@ import org.eclipse.linuxtools.tmf.core.callstack.CallStackStateProvider;
 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem;
@@ -43,6 +42,8 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider
     /** Number of colors used for call stack events */
     public static final int NUM_COLORS = 360;
 
+    private final CallStackView fView;
+
     private enum State {
         MULTIPLE (new RGB(100, 100, 100)),
         EXEC     (new RGB(0, 200, 0));
@@ -54,6 +55,16 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider
         }
     }
 
+    /**
+     * Constructor
+     *
+     * @param view
+     *            The callstack view that will contain the time events
+     */
+    public CallStackPresentationProvider(CallStackView view) {
+        fView = view;
+    }
+
     @Override
     public String getStateTypeName() {
         // Empty string since no generic name
@@ -95,10 +106,10 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider
             CallStackEntry entry = (CallStackEntry) event.getEntry();
             ITmfStateSystem ss = entry.getTrace().getStateSystems().get(CallStackStateProvider.ID);
             try {
-                ITmfStateInterval value = ss.querySingleState(event.getTime(), entry.getQuark());
-                if (!value.getStateValue().isNull()) {
-                    ITmfStateValue state = value.getStateValue();
-                    return state.toString();
+                ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue();
+                if (!value.isNull()) {
+                    String address = value.toString();
+                    return fView.getFunctionName(address);
                 }
             } catch (AttributeNotFoundException e) {
                 Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
@@ -123,11 +134,12 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider
         CallStackEntry entry = (CallStackEntry) event.getEntry();
         ITmfStateSystem ss = entry.getTrace().getStateSystems().get(CallStackStateProvider.ID);
         try {
-            ITmfStateInterval value = ss.querySingleState(event.getTime(), entry.getQuark());
-            if (!value.getStateValue().isNull()) {
-                ITmfStateValue state = value.getStateValue();
+            ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue();
+            if (!value.isNull()) {
+                String address = value.toString();
+                String name = fView.getFunctionName(address);
                 gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
-                Utils.drawText(gc, state.toString(), bounds.x, bounds.y - 2, bounds.width, true, true);
+                Utils.drawText(gc, name, bounds.x, bounds.y - 2, bounds.width, true, true);
             }
         } catch (AttributeNotFoundException e) {
             Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
index 8c0acf345ee2449404d53003f2cef81418dc99e7..903aae72497c0d42b50fae2a826cce7ad74ba381 100644 (file)
@@ -13,6 +13,7 @@
 
 package org.eclipse.linuxtools.tmf.ui.views.callstack;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -20,7 +21,10 @@ import java.util.List;
 import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IStatusLineManager;
@@ -84,6 +88,7 @@ import org.eclipse.swt.events.MouseEvent;
 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.ui.IActionBars;
 import org.eclipse.ui.IEditorPart;
 
@@ -129,6 +134,8 @@ public class CallStackView extends TmfView {
     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$
+
     // ------------------------------------------------------------------------
     // Fields
     // ------------------------------------------------------------------------
@@ -151,6 +158,9 @@ public class CallStackView extends TmfView {
     // The trace to build thread hash map
     private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<ITmfTrace, BuildThread>();
 
+    /** The map to map function addresses to function names */
+    private Map<String, String> fNameMapping;
+
     // The start time
     private long fStartTime;
 
@@ -172,6 +182,9 @@ public class CallStackView extends TmfView {
     // The previous item action
     private Action fPreviousItemAction;
 
+    /** The action to import a function-name mapping file */
+    private Action fImportMappingAction;
+
     // The zoom thread
     private ZoomThread fZoomThread;
 
@@ -488,7 +501,7 @@ public class CallStackView extends TmfView {
         fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS[3]);
         fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS[4]);
 
-        fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider());
+        fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
         fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
 
         fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
@@ -743,6 +756,7 @@ public class CallStackView extends TmfView {
     // ------------------------------------------------------------------------
     // Internal
     // ------------------------------------------------------------------------
+
     private void loadTrace() {
         synchronized (fEntryListMap) {
             fEntryList = fEntryListMap.get(fTrace);
@@ -911,7 +925,8 @@ public class CallStackView extends TmfView {
                     String name = ""; //$NON-NLS-1$
                     try {
                         if (nameValue.getType() == Type.STRING) {
-                            name = nameValue.unboxStr();
+                            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) {
@@ -1039,6 +1054,7 @@ public class CallStackView extends TmfView {
     }
 
     private void fillLocalToolBar(IToolBarManager manager) {
+        manager.add(getImportMappingAction());
         manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
         manager.add(getPreviousEventAction());
         manager.add(getNextEventAction());
@@ -1150,4 +1166,74 @@ public class CallStackView extends TmfView {
         return fPrevEventAction;
     }
 
+    // ------------------------------------------------------------------------
+    // Methods related to function name mapping
+    // ------------------------------------------------------------------------
+
+    /**
+     * Toolbar icon to import the function address-to-name mapping file.
+     */
+    private Action getImportMappingAction() {
+        if (fImportMappingAction != null) {
+            return fImportMappingAction;
+        }
+        fImportMappingAction = new Action() {
+            @Override
+            public void run() {
+                FileDialog dialog = new FileDialog(getViewSite().getShell());
+                dialog.setText(Messages.CallStackView_ImportMappingDialogTitle);
+                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 ImportMappingJob(new File(filePath));
+                job.schedule();
+            }
+        };
+
+        fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
+        fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
+        fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
+
+        return fImportMappingAction;
+    }
+
+    private class ImportMappingJob extends Job {
+        private final File fMappingFile;
+
+        public ImportMappingJob(File mappingFile) {
+            super(Messages.CallStackView_ImportMappingJobName);
+            fMappingFile = mappingFile;
+        }
+
+        @Override
+        public IStatus run(IProgressMonitor monitor) {
+            fNameMapping = FunctionNameMapper.mapFromNmTextFile(fMappingFile);
+
+            /* Refresh the time graph and the list of entries */
+            buildThreadList(fTrace, new NullProgressMonitor());
+            redraw();
+
+            return Status.OK_STATUS;
+        }
+    }
+
+    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 ret;
+    }
+
 }
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/callstack/FunctionNameMapper.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/callstack/FunctionNameMapper.java
new file mode 100644 (file)
index 0000000..cf88239
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.tmf.ui.views.callstack;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Class containing the different methods to import an address->name mapping.
+ *
+ * @author Alexandre Montplaisir
+ */
+class FunctionNameMapper {
+
+    public static @Nullable Map<String, String> mapFromNmTextFile(File mappingFile) {
+        Map<String, String> map = new HashMap<String, String>();
+
+        FileReader fr;
+        try {
+            fr = new FileReader(mappingFile);
+        } catch (FileNotFoundException e) {
+            return null;
+        }
+        BufferedReader reader = new BufferedReader(fr);
+
+        try {
+            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+                String[] elems = line.split(" "); //$NON-NLS-1$
+                /* Only lines with 3 elements contain addresses */
+                if (elems.length == 3) {
+                    /* Strip the leading zeroes from the address */
+                    String address = elems[0].replaceFirst("^0+(?!$)", ""); //$NON-NLS-1$ //$NON-NLS-2$;
+                    String name = elems[elems.length - 1];
+                    map.put(address, name);
+                }
+            }
+
+        } catch (IOException e) {
+            /* Stop reading the file at this point */
+        } finally {
+            try {
+                reader.close();
+            } catch (IOException e) {}
+        }
+
+        if (map.isEmpty()) {
+            return null;
+        }
+        return Collections.unmodifiableMap(map);
+    }
+
+}
This page took 0.041989 seconds and 5 git commands to generate.