1 /*******************************************************************************
2 * Copyright (c) 2013, 2016 Ericsson and others.
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Patrick Tasse - Initial API and implementation
11 * Bernd Hufmann - Updated signal handling
12 * Marc-Andre Laperle - Map from binary file
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.callstack
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Collections
;
20 import java
.util
.Comparator
;
21 import java
.util
.HashMap
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
26 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
27 import org
.eclipse
.core
.runtime
.IStatus
;
28 import org
.eclipse
.core
.runtime
.Status
;
29 import org
.eclipse
.core
.runtime
.jobs
.Job
;
30 import org
.eclipse
.jdt
.annotation
.NonNull
;
31 import org
.eclipse
.jdt
.annotation
.Nullable
;
32 import org
.eclipse
.jface
.action
.Action
;
33 import org
.eclipse
.jface
.action
.GroupMarker
;
34 import org
.eclipse
.jface
.action
.IAction
;
35 import org
.eclipse
.jface
.action
.IToolBarManager
;
36 import org
.eclipse
.jface
.action
.MenuManager
;
37 import org
.eclipse
.jface
.action
.Separator
;
38 import org
.eclipse
.jface
.dialogs
.IDialogSettings
;
39 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
40 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
41 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
42 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
43 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
44 import org
.eclipse
.jface
.viewers
.ISelection
;
45 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
46 import org
.eclipse
.jface
.viewers
.TreeViewer
;
47 import org
.eclipse
.swt
.SWT
;
48 import org
.eclipse
.swt
.events
.MouseAdapter
;
49 import org
.eclipse
.swt
.events
.MouseEvent
;
50 import org
.eclipse
.swt
.graphics
.Image
;
51 import org
.eclipse
.swt
.widgets
.Composite
;
52 import org
.eclipse
.swt
.widgets
.Display
;
53 import org
.eclipse
.swt
.widgets
.FileDialog
;
54 import org
.eclipse
.swt
.widgets
.Menu
;
55 import org
.eclipse
.swt
.widgets
.Tree
;
56 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.callstack
.FunctionNameMapper
;
57 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
58 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.ITmfImageConstants
;
59 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Messages
;
60 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
61 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
62 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
63 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
64 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
65 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
66 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
67 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
68 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
.Type
;
69 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
70 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
71 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
72 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
73 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
74 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfNanoTimestamp
;
75 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
76 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
77 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestampDelta
;
78 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
79 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
80 import org
.eclipse
.tracecompass
.tmf
.ui
.editors
.ITmfTraceEditor
;
81 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
82 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.ITimeGraphTimeListener
;
83 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphContentProvider
;
84 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
85 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
86 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
87 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
88 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.NullTimeEvent
;
89 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
90 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
91 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
92 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphSelection
;
93 import org
.eclipse
.ui
.IEditorPart
;
94 import org
.eclipse
.ui
.IWorkbenchActionConstants
;
97 * Main implementation for the Call Stack view
99 * @author Patrick Tasse
101 public class CallStackView
extends AbstractTimeGraphView
{
103 // ------------------------------------------------------------------------
105 // ------------------------------------------------------------------------
108 public static final String ID
= "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
110 private static final String
[] COLUMN_NAMES
= new String
[] {
111 Messages
.CallStackView_FunctionColumn
,
112 Messages
.CallStackView_DepthColumn
,
113 Messages
.CallStackView_EntryTimeColumn
,
114 Messages
.CallStackView_ExitTimeColumn
,
115 Messages
.CallStackView_DurationColumn
118 private static final String
[] FILTER_COLUMN_NAMES
= new String
[] {
119 Messages
.CallStackView_ThreadColumn
122 /** Timeout between updates in the build thread in ms */
123 private static final long BUILD_UPDATE_TIMEOUT
= 500;
125 // Fraction of a function duration to be added as spacing
126 private static final double SPACING_RATIO
= 0.01;
128 private static final Image THREAD_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
129 private static final Image STACKFRAME_IMAGE
= Activator
.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
131 private static final String IMPORT_MAPPING_ICON_PATH
= "icons/etool16/import.gif"; //$NON-NLS-1$
132 private static final String IMPORT_BINARY_ICON_PATH
= "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
134 private static final ImageDescriptor SORT_BY_NAME_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
135 private static final ImageDescriptor SORT_BY_NAME_REV_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha_rev.gif"); //$NON-NLS-1$
136 private static final ImageDescriptor SORT_BY_ID_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_num.gif"); //$NON-NLS-1$
137 private static final ImageDescriptor SORT_BY_ID_REV_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_num_rev.gif"); //$NON-NLS-1$
138 private static final ImageDescriptor SORT_BY_TIME_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_time.gif"); //$NON-NLS-1$
139 private static final ImageDescriptor SORT_BY_TIME_REV_ICON
= Activator
.getDefault().getImageDescripterFromPath("icons/etool16/sort_time_rev.gif"); //$NON-NLS-1$
140 private static final String SORT_OPTION_KEY
= "sort.option"; //$NON-NLS-1$
142 private enum SortOption
{
143 BY_NAME
, BY_NAME_REV
, BY_ID
, BY_ID_REV
, BY_TIME
, BY_TIME_REV
146 private @NonNull SortOption fSortOption
= SortOption
.BY_NAME
;
147 private @NonNull Comparator
<ITimeGraphEntry
> fThreadComparator
= new ThreadNameComparator(false);
148 private Action fSortByNameAction
;
149 private Action fSortByIdAction
;
150 private Action fSortByTimeAction
;
152 // ------------------------------------------------------------------------
154 // ------------------------------------------------------------------------
156 /** The map to map function addresses to function names */
157 private Map
<String
, String
> fNameMapping
;
159 // The next event action
160 private Action fNextEventAction
;
162 // The previous event action
163 private Action fPrevEventAction
;
165 // The next item action
166 private Action fNextItemAction
;
168 // The previous item action
169 private Action fPreviousItemAction
;
171 // The action to import a function-name mapping file
172 private Action fImportMappingAction
;
174 // The action to import a binary file mapping */
175 private Action fImportBinaryFileMappingAction
;
177 // The saved time sync. signal used when switching off the pinning of a view
178 private TmfSelectionRangeUpdatedSignal fSavedTimeSyncSignal
;
180 // The saved window range signal used when switching off the pinning of
182 private TmfWindowRangeUpdatedSignal fSavedRangeSyncSignal
;
184 // ------------------------------------------------------------------------
186 // ------------------------------------------------------------------------
188 private static class TraceEntry
extends TimeGraphEntry
{
189 public TraceEntry(String name
, long startTime
, long endTime
) {
190 super(name
, startTime
, endTime
);
194 public boolean hasTimeEvents() {
199 private static class ThreadEntry
extends TimeGraphEntry
{
200 // The call stack quark
201 private final int fCallStackQuark
;
202 // The state system from which this entry comes
203 private final ITmfStateSystem fSS
;
205 private final long fThreadId
;
207 public ThreadEntry(ITmfStateSystem ss
, String name
, long threadId
, int callStackQuark
, long startTime
, long endTime
) {
208 super(name
, startTime
, endTime
);
209 fCallStackQuark
= callStackQuark
;
210 fThreadId
= threadId
;
215 public boolean hasTimeEvents() {
219 public int getCallStackQuark() {
220 return fCallStackQuark
;
223 public long getThreadId() {
228 public ITmfStateSystem
getStateSystem() {
233 private class CallStackComparator
implements Comparator
<ITimeGraphEntry
> {
235 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
236 if (o1
instanceof ThreadEntry
&& o2
instanceof ThreadEntry
) {
237 return fThreadComparator
.compare(o1
, o2
);
243 private static class ThreadNameComparator
implements Comparator
<ITimeGraphEntry
> {
244 private boolean reverse
;
246 public ThreadNameComparator(boolean reverse
) {
247 this.reverse
= reverse
;
251 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
252 return reverse ? o2
.getName().compareTo(o1
.getName()) :
253 o1
.getName().compareTo(o2
.getName());
257 private static class ThreadIdComparator
implements Comparator
<ITimeGraphEntry
> {
258 private boolean reverse
;
260 public ThreadIdComparator(boolean reverse
) {
261 this.reverse
= reverse
;
265 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
266 ThreadEntry t1
= (ThreadEntry
) o1
;
267 ThreadEntry t2
= (ThreadEntry
) o2
;
268 return reverse ? Long
.compare(t2
.getThreadId(), t1
.getThreadId()) :
269 Long
.compare(t1
.getThreadId(), t2
.getThreadId());
273 private static class ThreadTimeComparator
implements Comparator
<ITimeGraphEntry
> {
274 private boolean reverse
;
276 public ThreadTimeComparator(boolean reverse
) {
277 this.reverse
= reverse
;
281 public int compare(ITimeGraphEntry o1
, ITimeGraphEntry o2
) {
282 return reverse ? Long
.compare(o2
.getStartTime(), o1
.getStartTime()) :
283 Long
.compare(o1
.getStartTime(), o2
.getStartTime());
287 private static class CallStackTreeLabelProvider
extends TreeLabelProvider
{
290 public Image
getColumnImage(Object element
, int columnIndex
) {
291 if (columnIndex
== 0) {
292 if (element
instanceof ThreadEntry
) {
294 } else if (element
instanceof CallStackEntry
) {
295 CallStackEntry entry
= (CallStackEntry
) element
;
296 if (entry
.getFunctionName().length() > 0) {
297 return STACKFRAME_IMAGE
;
305 public String
getColumnText(Object element
, int columnIndex
) {
306 if (element
instanceof CallStackEntry
) {
307 CallStackEntry entry
= (CallStackEntry
) element
;
308 if (columnIndex
== 0) {
309 return entry
.getFunctionName();
310 } else if (columnIndex
== 1 && entry
.getFunctionName().length() > 0) {
311 int depth
= entry
.getStackLevel();
312 return Integer
.toString(depth
);
313 } else if (columnIndex
== 2 && entry
.getFunctionName().length() > 0) {
314 ITmfTimestamp ts
= new TmfTimestamp(entry
.getFunctionEntryTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
315 return ts
.toString();
316 } else if (columnIndex
== 3 && entry
.getFunctionName().length() > 0) {
317 ITmfTimestamp ts
= new TmfTimestamp(entry
.getFunctionExitTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
318 return ts
.toString();
319 } else if (columnIndex
== 4 && entry
.getFunctionName().length() > 0) {
320 ITmfTimestamp ts
= new TmfTimestampDelta(entry
.getFunctionExitTime() - entry
.getFunctionEntryTime(), ITmfTimestamp
.NANOSECOND_SCALE
);
321 return ts
.toString();
323 } else if (element
instanceof ITimeGraphEntry
) {
324 if (columnIndex
== 0) {
325 return ((ITimeGraphEntry
) element
).getName();
328 return ""; //$NON-NLS-1$
333 private class CallStackFilterContentProvider
extends TimeGraphContentProvider
{
335 public boolean hasChildren(Object element
) {
336 if (element
instanceof TraceEntry
) {
337 return super.hasChildren(element
);
343 public ITimeGraphEntry
[] getChildren(Object parentElement
) {
344 if (parentElement
instanceof TraceEntry
) {
345 return super.getChildren(parentElement
);
347 return new ITimeGraphEntry
[0];
351 // ------------------------------------------------------------------------
353 // ------------------------------------------------------------------------
356 * Default constructor
358 public CallStackView() {
359 super(ID
, new CallStackPresentationProvider());
360 ((CallStackPresentationProvider
) getPresentationProvider()).setCallStackView(this);
361 setTreeColumns(COLUMN_NAMES
);
362 setTreeLabelProvider(new CallStackTreeLabelProvider());
363 setEntryComparator(new CallStackComparator());
364 setFilterColumns(FILTER_COLUMN_NAMES
);
365 setFilterContentProvider(new CallStackFilterContentProvider());
366 setFilterLabelProvider(new CallStackTreeLabelProvider());
369 // ------------------------------------------------------------------------
371 // ------------------------------------------------------------------------
374 public void createPartControl(Composite parent
) {
375 super.createPartControl(parent
);
377 getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
379 public void timeSelected(TimeGraphTimeEvent event
) {
380 synchingToTime(event
.getBeginTime());
384 getTimeGraphCombo().getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
386 public void doubleClick(DoubleClickEvent event
) {
387 Object selection
= ((IStructuredSelection
) event
.getSelection()).getFirstElement();
388 if (selection
instanceof CallStackEntry
) {
389 CallStackEntry entry
= (CallStackEntry
) selection
;
390 if (entry
.getFunctionName().length() > 0) {
391 long entryTime
= entry
.getFunctionEntryTime();
392 long exitTime
= entry
.getFunctionExitTime();
393 long spacingTime
= (long) ((exitTime
- entryTime
) * SPACING_RATIO
);
394 entryTime
-= spacingTime
;
395 exitTime
+= spacingTime
;
396 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(entryTime
), new TmfNanoTimestamp(exitTime
));
397 broadcast(new TmfWindowRangeUpdatedSignal(CallStackView
.this, range
));
398 getTimeGraphViewer().setStartFinishTime(entryTime
, exitTime
);
399 startZoomThread(entryTime
, exitTime
);
405 getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
407 public void mouseDoubleClick(MouseEvent e
) {
408 TimeGraphControl timeGraphControl
= getTimeGraphViewer().getTimeGraphControl();
409 ISelection selection
= timeGraphControl
.getSelection();
410 if (selection
instanceof TimeGraphSelection
) {
411 Object o
= ((TimeGraphSelection
) selection
).getFirstElement();
412 if (o
instanceof CallStackEvent
) {
413 CallStackEvent event
= (CallStackEvent
) o
;
414 long startTime
= event
.getTime();
415 long endTime
= startTime
+ event
.getDuration();
416 long spacingTime
= (long) ((endTime
- startTime
) * SPACING_RATIO
);
417 startTime
-= spacingTime
;
418 endTime
+= spacingTime
;
419 TmfTimeRange range
= new TmfTimeRange(new TmfNanoTimestamp(startTime
), new TmfNanoTimestamp(endTime
));
420 broadcast(new TmfWindowRangeUpdatedSignal(CallStackView
.this, range
));
421 getTimeGraphViewer().setStartFinishTime(startTime
, endTime
);
422 startZoomThread(startTime
, endTime
);
428 contributeToActionBars();
432 IEditorPart editor
= getSite().getPage().getActiveEditor();
433 if (editor
instanceof ITmfTraceEditor
) {
434 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
436 traceSelected(new TmfTraceSelectedSignal(this, trace
));
442 * Handler for the selection range signal.
445 * The incoming signal
450 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
452 fSavedTimeSyncSignal
= isPinned() ?
new TmfSelectionRangeUpdatedSignal(signal
.getSource(), signal
.getBeginTime(), signal
.getEndTime()) : null;
454 if (signal
.getSource() == this || getTrace() == null || isPinned()) {
457 final long beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
458 final long endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
459 Display
.getDefault().asyncExec(new Runnable() {
462 if (getTimeGraphCombo().isDisposed()) {
465 if (beginTime
== endTime
) {
466 getTimeGraphViewer().setSelectedTime(beginTime
, true);
468 getTimeGraphViewer().setSelectionRange(beginTime
, endTime
, true);
470 synchingToTime(beginTime
);
471 startZoomThread(getTimeGraphViewer().getTime0(), getTimeGraphViewer().getTime1());
472 List
<TimeGraphEntry
> entryList
= getEntryList(getTrace());
473 if (entryList
== null) {
476 TimeGraphViewer viewer
= getTimeGraphViewer();
477 for (TimeGraphEntry traceEntry
: entryList
) {
478 for (ITimeGraphEntry child
: traceEntry
.getChildren()) {
479 ThreadEntry threadEntry
= (ThreadEntry
) child
;
480 ITmfStateSystem ss
= threadEntry
.getStateSystem();
481 if (ss
== null || beginTime
< ss
.getStartTime() || beginTime
> ss
.getCurrentEndTime()) {
485 int quark
= threadEntry
.getCallStackQuark();
486 ITmfStateInterval stackInterval
= ss
.querySingleState(beginTime
, quark
);
487 if (beginTime
== stackInterval
.getStartTime()) {
488 int stackLevel
= stackInterval
.getStateValue().unboxInt();
489 ITimeGraphEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
490 getTimeGraphCombo().setSelection(selectedEntry
);
491 viewer
.getTimeGraphControl().fireSelectionChanged();
494 } catch (AttributeNotFoundException
| TimeRangeException
| StateSystemDisposedException
| StateValueTypeException e
) {
495 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
503 // ------------------------------------------------------------------------
505 // ------------------------------------------------------------------------
508 protected void buildEventList(final ITmfTrace trace
, final ITmfTrace parentTrace
, final IProgressMonitor monitor
) {
509 if (monitor
.isCanceled()) {
512 AbstractCallStackAnalysis module
= getCallStackModule(trace
);
513 if (module
== null) {
514 addUnavailableEntry(trace
, parentTrace
);
517 ITmfStateSystem ss
= module
.getStateSystem();
519 addUnavailableEntry(trace
, parentTrace
);
523 Map
<ITmfTrace
, TraceEntry
> traceEntryMap
= new HashMap
<>();
524 Map
<Integer
, ThreadEntry
> threadEntryMap
= new HashMap
<>();
525 String
[] threadPaths
= module
.getThreadsPattern();
527 long start
= ss
.getStartTime();
529 boolean complete
= false;
531 if (monitor
.isCanceled()) {
534 complete
= ss
.waitUntilBuilt(BUILD_UPDATE_TIMEOUT
);
535 if (ss
.isCancelled()) {
538 long end
= ss
.getCurrentEndTime();
539 if (start
== end
&& !complete
) { // when complete execute one last time regardless of end time
542 List
<Integer
> threadQuarks
= ss
.getQuarks(threadPaths
);
543 TraceEntry traceEntry
= traceEntryMap
.get(trace
);
544 if (traceEntry
== null) {
545 traceEntry
= new TraceEntry(trace
.getName(), start
, end
+ 1);
546 traceEntryMap
.put(trace
, traceEntry
);
547 traceEntry
.sortChildren(fThreadComparator
);
548 addToEntryList(parentTrace
, Collections
.singletonList(traceEntry
));
550 traceEntry
.updateEndTime(end
);
552 for (int i
= 0; i
< threadQuarks
.size(); i
++) {
553 if (monitor
.isCanceled()) {
556 int threadQuark
= threadQuarks
.get(i
);
558 String
[] callStackPath
= module
.getCallStackPath();
559 int callStackQuark
= ss
.getQuarkRelative(threadQuark
, callStackPath
);
560 String threadName
= ss
.getAttributeName(threadQuark
);
561 long threadEnd
= end
+ 1;
562 ITmfStateInterval endInterval
= ss
.querySingleState(ss
.getCurrentEndTime(), callStackQuark
);
563 if (endInterval
.getStateValue().isNull() && endInterval
.getStartTime() != ss
.getStartTime()) {
564 threadEnd
= endInterval
.getStartTime();
566 ThreadEntry threadEntry
= threadEntryMap
.get(threadQuark
);
567 if (threadEntry
== null) {
568 long threadId
= ss
.querySingleState(ss
.getCurrentEndTime(), threadQuark
).getStateValue().unboxLong();
569 long threadStart
= start
;
570 ITmfStateInterval startInterval
= ss
.querySingleState(start
, callStackQuark
);
571 if (startInterval
.getStateValue().isNull()) {
572 threadStart
= Math
.min(startInterval
.getEndTime() + 1, end
+ 1);
574 threadEntry
= new ThreadEntry(ss
, threadName
, threadId
, callStackQuark
, threadStart
, threadEnd
);
575 threadEntryMap
.put(threadQuark
, threadEntry
);
576 traceEntry
.addChild(threadEntry
);
578 threadEntry
.updateEndTime(threadEnd
);
581 for (int stackLevelQuark
: ss
.getSubAttributes(callStackQuark
, false)) {
582 if (level
> threadEntry
.getChildren().size()) {
583 CallStackEntry callStackEntry
= new CallStackEntry(threadName
, stackLevelQuark
, level
, trace
, ss
);
584 threadEntry
.addChild(callStackEntry
);
588 } catch (AttributeNotFoundException e
) {
589 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
590 } catch (StateSystemDisposedException e
) {
594 if (parentTrace
== getTrace()) {
595 synchronized (this) {
596 setStartTime(getStartTime() == SWT
.DEFAULT ? start
: Math
.min(getStartTime(), start
));
597 setEndTime(getEndTime() == SWT
.DEFAULT ? end
+ 1 : Math
.max(getEndTime(), end
+ 1));
599 synchingToTime(getTimeGraphViewer().getSelectionBegin());
602 for (ITimeGraphEntry threadEntry
: traceEntry
.getChildren()) {
603 for (ITimeGraphEntry callStackEntry
: threadEntry
.getChildren()) {
604 if (monitor
.isCanceled()) {
607 buildStatusEvents(parentTrace
, (CallStackEntry
) callStackEntry
, monitor
, start
, end
);
614 private void addUnavailableEntry(ITmfTrace trace
, ITmfTrace parentTrace
) {
615 String name
= Messages
.CallStackView_StackInfoNotAvailable
+ ' ' + '(' + trace
.getName() + ')';
616 TraceEntry unavailableEntry
= new TraceEntry(name
, 0, 0);
617 addToEntryList(parentTrace
, Collections
.singletonList(unavailableEntry
));
618 if (parentTrace
== getTrace()) {
623 private void buildStatusEvents(ITmfTrace trace
, CallStackEntry entry
, @NonNull IProgressMonitor monitor
, long start
, long end
) {
624 ITmfStateSystem ss
= entry
.getStateSystem();
625 long resolution
= Math
.max(1, (end
- ss
.getStartTime()) / getDisplayWidth());
626 List
<ITimeEvent
> eventList
= getEventList(entry
, start
, end
+ 1, resolution
, monitor
);
627 if (eventList
!= null) {
628 for (ITimeEvent event
: eventList
) {
629 entry
.addEvent(event
);
632 if (trace
== getTrace()) {
641 protected final List
<ITimeEvent
> getEventList(TimeGraphEntry tgentry
, long startTime
, long endTime
, long resolution
, IProgressMonitor monitor
) {
642 if (!(tgentry
instanceof CallStackEntry
)) {
645 CallStackEntry entry
= (CallStackEntry
) tgentry
;
646 ITmfStateSystem ss
= entry
.getStateSystem();
647 long start
= Math
.max(startTime
, ss
.getStartTime());
648 long end
= Math
.min(endTime
, ss
.getCurrentEndTime() + 1);
652 List
<ITimeEvent
> eventList
= null;
654 List
<ITmfStateInterval
> stackIntervals
= StateSystemUtils
.queryHistoryRange(ss
, entry
.getQuark(), start
, end
- 1, resolution
, monitor
);
655 eventList
= new ArrayList
<>(stackIntervals
.size());
656 long lastEndTime
= -1;
657 boolean lastIsNull
= true;
658 for (ITmfStateInterval statusInterval
: stackIntervals
) {
659 if (monitor
.isCanceled()) {
662 long time
= statusInterval
.getStartTime();
663 long duration
= statusInterval
.getEndTime() - time
+ 1;
664 if (!statusInterval
.getStateValue().isNull()) {
665 final int modulo
= CallStackPresentationProvider
.NUM_COLORS
/ 2;
666 int value
= statusInterval
.getStateValue().toString().hashCode() % modulo
+ modulo
;
667 eventList
.add(new CallStackEvent(entry
, time
, duration
, value
));
670 if (lastEndTime
== -1) {
671 // add null event if it intersects the start time
672 eventList
.add(new NullTimeEvent(entry
, time
, duration
));
674 if (lastEndTime
!= time
&& lastIsNull
) {
675 // add unknown event if between two null states
676 eventList
.add(new TimeEvent(entry
, lastEndTime
, time
- lastEndTime
));
678 if (time
+ duration
>= endTime
) {
679 // add null event if it intersects the end time
680 eventList
.add(new NullTimeEvent(entry
, time
, duration
));
685 lastEndTime
= time
+ duration
;
687 } catch (AttributeNotFoundException e
) {
688 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
689 } catch (TimeRangeException e
) {
690 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
691 } catch (StateSystemDisposedException e
) {
701 protected void synchingToTime(long time
) {
702 List
<TimeGraphEntry
> entryList
= getEntryList(getTrace());
703 if (entryList
== null) {
706 for (TimeGraphEntry traceEntry
: entryList
) {
707 for (ITimeGraphEntry threadEntry
: traceEntry
.getChildren()) {
708 ITmfStateSystem ss
= ((ThreadEntry
) threadEntry
).getStateSystem();
712 if (ss
.isCancelled()) {
715 if (time
< ss
.getStartTime() || time
> ss
.getCurrentEndTime()) {
718 for (ITimeGraphEntry child
: threadEntry
.getChildren()) {
719 CallStackEntry callStackEntry
= (CallStackEntry
) child
;
721 ITmfStateInterval stackLevelInterval
= ss
.querySingleState(time
, callStackEntry
.getQuark());
722 ITmfStateValue nameValue
= stackLevelInterval
.getStateValue();
723 String name
= ""; //$NON-NLS-1$
725 if (nameValue
.getType() == Type
.STRING
) {
726 String address
= nameValue
.unboxStr();
727 name
= getFunctionName(address
);
728 } else if (nameValue
.getType() == Type
.INTEGER
) {
729 name
= "0x" + Integer
.toHexString(nameValue
.unboxInt()); //$NON-NLS-1$
730 } else if (nameValue
.getType() == Type
.LONG
) {
731 name
= "0x" + Long
.toHexString(nameValue
.unboxLong()); //$NON-NLS-1$
733 } catch (StateValueTypeException e
) {
735 callStackEntry
.setFunctionName(name
);
736 if (name
.length() > 0) {
737 callStackEntry
.setFunctionEntryTime(stackLevelInterval
.getStartTime());
738 callStackEntry
.setFunctionExitTime(stackLevelInterval
.getEndTime() + 1);
740 } catch (AttributeNotFoundException e
) {
741 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
742 } catch (StateSystemDisposedException e
) {
748 if (Display
.getCurrent() != null) {
749 getTimeGraphCombo().refresh();
753 private void makeActions() {
754 fPreviousItemAction
= getTimeGraphViewer().getPreviousItemAction();
755 fPreviousItemAction
.setText(Messages
.TmfTimeGraphViewer_PreviousItemActionNameText
);
756 fPreviousItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousItemActionToolTipText
);
757 fNextItemAction
= getTimeGraphViewer().getNextItemAction();
758 fNextItemAction
.setText(Messages
.TmfTimeGraphViewer_NextItemActionNameText
);
759 fNextItemAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextItemActionToolTipText
);
762 private void contributeToActionBars() {
764 contributePinActionToToolBar();
765 fPinAction
.addPropertyChangeListener(new IPropertyChangeListener() {
767 public void propertyChange(PropertyChangeEvent event
) {
768 if (IAction
.CHECKED
.equals(event
.getProperty()) && !isPinned()) {
769 if (fSavedRangeSyncSignal
!= null) {
770 windowRangeUpdated(fSavedRangeSyncSignal
);
771 fSavedRangeSyncSignal
= null;
774 if (fSavedTimeSyncSignal
!= null) {
775 selectionRangeUpdated(fSavedTimeSyncSignal
);
776 fSavedTimeSyncSignal
= null;
787 protected void fillLocalToolBar(IToolBarManager manager
) {
789 manager
.add(getImportBinaryAction());
790 manager
.add(getImportMappingAction());
791 manager
.add(new Separator());
792 manager
.add(getSortByNameAction());
793 manager
.add(getSortByIdAction());
794 manager
.add(getSortByTimeAction());
795 manager
.add(new Separator());
796 manager
.add(getTimeGraphCombo().getShowFilterDialogAction());
797 manager
.add(new Separator());
798 manager
.add(getTimeGraphViewer().getResetScaleAction());
799 manager
.add(getPreviousEventAction());
800 manager
.add(getNextEventAction());
801 manager
.add(new Separator());
802 manager
.add(getTimeGraphViewer().getToggleBookmarkAction());
803 manager
.add(getTimeGraphViewer().getPreviousMarkerAction());
804 manager
.add(getTimeGraphViewer().getNextMarkerAction());
805 manager
.add(new Separator());
806 manager
.add(fPreviousItemAction
);
807 manager
.add(fNextItemAction
);
808 manager
.add(getTimeGraphViewer().getZoomInAction());
809 manager
.add(getTimeGraphViewer().getZoomOutAction());
812 private void createContextMenu() {
813 final MenuManager contextMenu
= new MenuManager();
814 contextMenu
.add(new GroupMarker(IWorkbenchActionConstants
.GROUP_REORGANIZE
));
815 contextMenu
.add(getSortByNameAction());
816 contextMenu
.add(getSortByIdAction());
817 contextMenu
.add(getSortByTimeAction());
818 contextMenu
.add(new GroupMarker(IWorkbenchActionConstants
.MB_ADDITIONS
));
820 TreeViewer treeViewer
= getTimeGraphCombo().getTreeViewer();
821 Tree tree
= treeViewer
.getTree();
822 Menu menu
= contextMenu
.createContextMenu(tree
);
824 getSite().registerContextMenu(contextMenu
, treeViewer
);
828 * Get the the next event action.
830 * @return The action object
832 private Action
getNextEventAction() {
833 if (fNextEventAction
== null) {
834 fNextEventAction
= new Action() {
837 TimeGraphViewer viewer
= getTimeGraphViewer();
838 ITimeGraphEntry entry
= viewer
.getSelection();
839 if (entry
instanceof CallStackEntry
) {
841 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
842 ITmfStateSystem ss
= callStackEntry
.getStateSystem();
843 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectionBegin()));
844 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
845 int quark
= ss
.getParentAttributeQuark(callStackEntry
.getQuark());
846 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
847 long newTime
= stackInterval
.getEndTime() + 1;
848 viewer
.setSelectedTimeNotify(newTime
, true);
849 stackInterval
= ss
.querySingleState(Math
.min(ss
.getCurrentEndTime(), newTime
), quark
);
850 int stackLevel
= stackInterval
.getStateValue().unboxInt();
851 ITimeGraphEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
852 getTimeGraphCombo().setSelection(selectedEntry
);
853 viewer
.getTimeGraphControl().fireSelectionChanged();
854 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
856 } catch (AttributeNotFoundException
| TimeRangeException
| StateSystemDisposedException
| StateValueTypeException e
) {
857 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
863 fNextEventAction
.setText(Messages
.TmfTimeGraphViewer_NextEventActionNameText
);
864 fNextEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_NextEventActionToolTipText
);
865 fNextEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_NEXT_EVENT
));
868 return fNextEventAction
;
872 * Get the previous event action.
874 * @return The Action object
876 private Action
getPreviousEventAction() {
877 if (fPrevEventAction
== null) {
878 fPrevEventAction
= new Action() {
881 TimeGraphViewer viewer
= getTimeGraphCombo().getTimeGraphViewer();
882 ITimeGraphEntry entry
= viewer
.getSelection();
883 if (entry
instanceof CallStackEntry
) {
885 CallStackEntry callStackEntry
= (CallStackEntry
) entry
;
886 ITmfStateSystem ss
= callStackEntry
.getStateSystem();
887 long time
= Math
.max(ss
.getStartTime(), Math
.min(ss
.getCurrentEndTime(), viewer
.getSelectionBegin()));
888 ThreadEntry threadEntry
= (ThreadEntry
) callStackEntry
.getParent();
889 int quark
= ss
.getParentAttributeQuark(callStackEntry
.getQuark());
890 ITmfStateInterval stackInterval
= ss
.querySingleState(time
, quark
);
891 if (stackInterval
.getStartTime() == time
&& time
> ss
.getStartTime()) {
892 stackInterval
= ss
.querySingleState(time
- 1, quark
);
894 viewer
.setSelectedTimeNotify(stackInterval
.getStartTime(), true);
895 int stackLevel
= stackInterval
.getStateValue().unboxInt();
896 ITimeGraphEntry selectedEntry
= threadEntry
.getChildren().get(Math
.max(0, stackLevel
- 1));
897 getTimeGraphCombo().setSelection(selectedEntry
);
898 viewer
.getTimeGraphControl().fireSelectionChanged();
899 startZoomThread(viewer
.getTime0(), viewer
.getTime1());
901 } catch (AttributeNotFoundException
| TimeRangeException
| StateSystemDisposedException
| StateValueTypeException e
) {
902 Activator
.getDefault().logError("Error querying state system", e
); //$NON-NLS-1$
908 fPrevEventAction
.setText(Messages
.TmfTimeGraphViewer_PreviousEventActionNameText
);
909 fPrevEventAction
.setToolTipText(Messages
.TmfTimeGraphViewer_PreviousEventActionToolTipText
);
910 fPrevEventAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_PREV_EVENT
));
913 return fPrevEventAction
;
916 private static @Nullable AbstractCallStackAnalysis
getCallStackModule(@NonNull ITmfTrace trace
) {
918 * Since we cannot know the exact analysis ID (in separate plugins), we
919 * will search using the analysis type.
921 Iterable
<AbstractCallStackAnalysis
> modules
=
922 TmfTraceUtils
.getAnalysisModulesOfClass(trace
, AbstractCallStackAnalysis
.class);
923 Iterator
<AbstractCallStackAnalysis
> it
= modules
.iterator();
925 /* This trace does not provide a call-stack analysis */
930 * We only look at the first module we find.
932 * TODO Handle the advanced case where one trace provides more than one
933 * call-stack analysis.
935 AbstractCallStackAnalysis module
= it
.next();
936 /* This analysis is not automatic, we need to schedule it on-demand */
938 module
.waitForInitialization();
942 // ------------------------------------------------------------------------
943 // Methods related to function name mapping
944 // ------------------------------------------------------------------------
947 * Common code for all import file mapping actions
949 private abstract class AbstractImportFileMappingAction
extends Action
{
950 private final String fDialogTitle
;
952 private AbstractImportFileMappingAction(String dialogTitle
) {
953 fDialogTitle
= dialogTitle
;
958 FileDialog dialog
= new FileDialog(getViewSite().getShell());
959 dialog
.setText(fDialogTitle
);
960 final String filePath
= dialog
.open();
961 if (filePath
== null) {
962 /* No file was selected, don't change anything */
967 * Start the mapping import in a separate thread (we do not want to
968 * UI thread to do this).
970 Job job
= new Job(Messages
.CallStackView_ImportMappingJobName
) {
972 public IStatus
run(IProgressMonitor monitor
) {
973 fNameMapping
= doMapping(new File(filePath
));
975 /* Refresh call stack entries and event labels */
976 Display
.getDefault().asyncExec(new Runnable() {
979 synchingToTime(getTimeGraphViewer().getSelectionBegin());
982 return Status
.OK_STATUS
;
988 abstract Map
<String
, String
> doMapping(File file
);
992 * Toolbar icon to import the function address-to-name mapping file.
994 private Action
getImportMappingAction() {
995 if (fImportMappingAction
!= null) {
996 return fImportMappingAction
;
998 fImportMappingAction
= new AbstractImportFileMappingAction(Messages
.CallStackView_ImportMappingDialogTitle
) {
1000 Map
<String
, String
> doMapping(File file
) {
1001 return FunctionNameMapper
.mapFromNmTextFile(file
);
1005 fImportMappingAction
.setText(Messages
.CallStackView_ImportMappingButtonText
);
1006 fImportMappingAction
.setToolTipText(Messages
.CallStackView_ImportMappingButtonTooltip
);
1007 fImportMappingAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH
));
1009 return fImportMappingAction
;
1012 private Action
getSortByNameAction() {
1013 if (fSortByNameAction
== null) {
1014 fSortByNameAction
= new Action(Messages
.CallStackView_SortByThreadName
, IAction
.AS_CHECK_BOX
) {
1017 if (fSortOption
== SortOption
.BY_NAME
) {
1018 saveSortOption(SortOption
.BY_NAME_REV
);
1020 saveSortOption(SortOption
.BY_NAME
);
1024 fSortByNameAction
.setToolTipText(Messages
.CallStackView_SortByThreadName
);
1025 fSortByNameAction
.setImageDescriptor(SORT_BY_NAME_ICON
);
1027 return fSortByNameAction
;
1030 private Action
getSortByIdAction() {
1031 if (fSortByIdAction
== null) {
1032 fSortByIdAction
= new Action(Messages
.CallStackView_SortByThreadId
, IAction
.AS_CHECK_BOX
) {
1035 if (fSortOption
== SortOption
.BY_ID
) {
1036 saveSortOption(SortOption
.BY_ID_REV
);
1038 saveSortOption(SortOption
.BY_ID
);
1042 fSortByIdAction
.setToolTipText(Messages
.CallStackView_SortByThreadId
);
1043 fSortByIdAction
.setImageDescriptor(SORT_BY_ID_ICON
);
1045 return fSortByIdAction
;
1048 private Action
getSortByTimeAction() {
1049 if (fSortByTimeAction
== null) {
1050 fSortByTimeAction
= new Action(Messages
.CallStackView_SortByThreadTime
, IAction
.AS_CHECK_BOX
) {
1053 if (fSortOption
== SortOption
.BY_TIME
) {
1054 saveSortOption(SortOption
.BY_TIME_REV
);
1056 saveSortOption(SortOption
.BY_TIME
);
1060 fSortByTimeAction
.setToolTipText(Messages
.CallStackView_SortByThreadTime
);
1061 fSortByTimeAction
.setImageDescriptor(SORT_BY_TIME_ICON
);
1063 return fSortByTimeAction
;
1066 private void loadSortOption() {
1067 IDialogSettings settings
= Activator
.getDefault().getDialogSettings();
1068 IDialogSettings section
= settings
.getSection(getClass().getName());
1069 if (section
== null) {
1072 String sortOption
= section
.get(SORT_OPTION_KEY
);
1073 if (sortOption
== null) {
1078 getSortByNameAction().setChecked(false);
1079 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_ICON
);
1080 getSortByIdAction().setChecked(false);
1081 getSortByIdAction().setImageDescriptor(SORT_BY_ID_ICON
);
1082 getSortByTimeAction().setChecked(false);
1083 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_ICON
);
1085 if (sortOption
.equals(SortOption
.BY_NAME
.name())) {
1086 fSortOption
= SortOption
.BY_NAME
;
1087 fThreadComparator
= new ThreadNameComparator(false);
1088 getSortByNameAction().setChecked(true);
1089 } else if (sortOption
.equals(SortOption
.BY_NAME_REV
.name())) {
1090 fSortOption
= SortOption
.BY_NAME_REV
;
1091 fThreadComparator
= new ThreadNameComparator(true);
1092 getSortByNameAction().setChecked(true);
1093 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_REV_ICON
);
1094 } else if (sortOption
.equals(SortOption
.BY_ID
.name())) {
1095 fSortOption
= SortOption
.BY_ID
;
1096 fThreadComparator
= new ThreadIdComparator(false);
1097 getSortByIdAction().setChecked(true);
1098 } else if (sortOption
.equals(SortOption
.BY_ID_REV
.name())) {
1099 fSortOption
= SortOption
.BY_ID_REV
;
1100 fThreadComparator
= new ThreadIdComparator(true);
1101 getSortByIdAction().setChecked(true);
1102 getSortByIdAction().setImageDescriptor(SORT_BY_ID_REV_ICON
);
1103 } else if (sortOption
.equals(SortOption
.BY_TIME
.name())) {
1104 fSortOption
= SortOption
.BY_TIME
;
1105 fThreadComparator
= new ThreadTimeComparator(false);
1106 getSortByTimeAction().setChecked(true);
1107 } else if (sortOption
.equals(SortOption
.BY_TIME_REV
.name())) {
1108 fSortOption
= SortOption
.BY_TIME_REV
;
1109 fThreadComparator
= new ThreadTimeComparator(true);
1110 getSortByTimeAction().setChecked(true);
1111 getSortByTimeAction().setImageDescriptor(SORT_BY_TIME_REV_ICON
);
1115 private void saveSortOption(SortOption sortOption
) {
1116 IDialogSettings settings
= Activator
.getDefault().getDialogSettings();
1117 IDialogSettings section
= settings
.getSection(getClass().getName());
1118 if (section
== null) {
1119 section
= settings
.addNewSection(getClass().getName());
1121 section
.put(SORT_OPTION_KEY
, sortOption
.name());
1123 List
<TimeGraphEntry
> entryList
= getEntryList(getTrace());
1124 if (entryList
== null) {
1127 for (TimeGraphEntry traceEntry
: entryList
) {
1128 traceEntry
.sortChildren(fThreadComparator
);
1134 * Toolbar icon to import the function address-to-name mapping binary file.
1136 private Action
getImportBinaryAction() {
1137 if (fImportBinaryFileMappingAction
!= null) {
1138 return fImportBinaryFileMappingAction
;
1141 fImportBinaryFileMappingAction
= new AbstractImportFileMappingAction(Messages
.CallStackView_ImportBinaryFileDialogTitle
) {
1143 Map
<String
, String
> doMapping(File file
) {
1144 return FunctionNameMapper
.mapFromBinaryFile(file
);
1148 fImportBinaryFileMappingAction
.setText(Messages
.CallStackView_ImportBinaryFileButtonText
);
1149 fImportBinaryFileMappingAction
.setToolTipText(Messages
.CallStackView_ImportBinaryFileButtonTooltip
);
1150 fImportBinaryFileMappingAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH
));
1152 return fImportBinaryFileMappingAction
;
1155 String
getFunctionName(String address
) {
1156 if (fNameMapping
== null) {
1157 /* No mapping available, just print the addresses */
1160 String ret
= fNameMapping
.get(address
);
1163 * We didn't find this address in the mapping file, just use the