1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson
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 * Marc Dumais - Initial implementation
11 * Francois Chouinard - Misc improvements, DSF signal handling, dynamic experiment
12 * Patrick Tasse - Updated for TMF 2.0
13 * Bernd Hufmann - Fixed deadlock during shutdown
14 *******************************************************************************/
16 package org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.trace
;
18 import java
.util
.HashMap
;
19 import java
.util
.Hashtable
;
20 import java
.util
.List
;
22 import java
.util
.concurrent
.ExecutionException
;
23 import java
.util
.concurrent
.RejectedExecutionException
;
24 import java
.util
.concurrent
.TimeUnit
;
25 import java
.util
.concurrent
.TimeoutException
;
27 import org
.eclipse
.cdt
.dsf
.concurrent
.DataRequestMonitor
;
28 import org
.eclipse
.cdt
.dsf
.concurrent
.DsfExecutor
;
29 import org
.eclipse
.cdt
.dsf
.concurrent
.IDsfStatusConstants
;
30 import org
.eclipse
.cdt
.dsf
.concurrent
.Query
;
31 import org
.eclipse
.cdt
.dsf
.datamodel
.DMContexts
;
32 import org
.eclipse
.cdt
.dsf
.datamodel
.IDMContext
;
33 import org
.eclipse
.cdt
.dsf
.debug
.service
.IBreakpoints
;
34 import org
.eclipse
.cdt
.dsf
.debug
.service
.IBreakpoints
.IBreakpointsTargetDMContext
;
35 import org
.eclipse
.cdt
.dsf
.debug
.service
.IRunControl
.IContainerDMContext
;
36 import org
.eclipse
.cdt
.dsf
.debug
.service
.command
.ICommandControlService
;
37 import org
.eclipse
.cdt
.dsf
.debug
.service
.command
.ICommandControlService
.ICommandControlDMContext
;
38 import org
.eclipse
.cdt
.dsf
.gdb
.IGdbDebugPreferenceConstants
;
39 import org
.eclipse
.cdt
.dsf
.gdb
.internal
.GdbPlugin
;
40 import org
.eclipse
.cdt
.dsf
.gdb
.launching
.GdbLaunch
;
41 import org
.eclipse
.cdt
.dsf
.gdb
.service
.GDBTraceControl_7_2
.TraceRecordSelectedChangedEvent
;
42 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
;
43 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordDMContext
;
44 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordDMData
;
45 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordSelectedChangedDMEvent
;
46 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceStatusDMData
;
47 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceTargetDMContext
;
48 import org
.eclipse
.cdt
.dsf
.mi
.service
.IMICommandControl
;
49 import org
.eclipse
.cdt
.dsf
.mi
.service
.IMIProcesses
;
50 import org
.eclipse
.cdt
.dsf
.mi
.service
.MIBreakpointDMData
;
51 import org
.eclipse
.cdt
.dsf
.mi
.service
.MIBreakpoints
;
52 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.CommandFactory
;
53 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.output
.MIBreakListInfo
;
54 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.output
.MIBreakpoint
;
55 import org
.eclipse
.cdt
.dsf
.service
.DsfServiceEventHandler
;
56 import org
.eclipse
.cdt
.dsf
.service
.DsfServicesTracker
;
57 import org
.eclipse
.cdt
.dsf
.service
.DsfSession
;
58 import org
.eclipse
.core
.resources
.IFile
;
59 import org
.eclipse
.core
.resources
.IMarker
;
60 import org
.eclipse
.core
.runtime
.CoreException
;
61 import org
.eclipse
.core
.runtime
.IAdaptable
;
62 import org
.eclipse
.core
.runtime
.IPath
;
63 import org
.eclipse
.core
.runtime
.IStatus
;
64 import org
.eclipse
.core
.runtime
.Platform
;
65 import org
.eclipse
.core
.runtime
.Status
;
66 import org
.eclipse
.debug
.core
.DebugException
;
67 import org
.eclipse
.debug
.core
.DebugPlugin
;
68 import org
.eclipse
.debug
.core
.ILaunch
;
69 import org
.eclipse
.debug
.core
.ILaunchConfigurationType
;
70 import org
.eclipse
.debug
.core
.ILaunchConfigurationWorkingCopy
;
71 import org
.eclipse
.debug
.core
.ILaunchesListener2
;
72 import org
.eclipse
.debug
.internal
.ui
.viewers
.model
.provisional
.ITreeModelViewer
;
73 import org
.eclipse
.debug
.ui
.AbstractDebugView
;
74 import org
.eclipse
.debug
.ui
.DebugUITools
;
75 import org
.eclipse
.debug
.ui
.IDebugUIConstants
;
76 import org
.eclipse
.debug
.ui
.contexts
.DebugContextEvent
;
77 import org
.eclipse
.debug
.ui
.contexts
.IDebugContextListener
;
78 import org
.eclipse
.jface
.viewers
.ISelection
;
79 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
80 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
81 import org
.eclipse
.jface
.viewers
.Viewer
;
82 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.Activator
;
83 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.GdbTraceCorePlugin
;
84 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.event
.GdbTraceEvent
;
85 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.event
.GdbTraceEventContent
;
86 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEventType
;
87 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEventField
;
88 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEventType
;
89 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
90 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
91 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
92 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.ITmfTraceEditor
;
93 import org
.eclipse
.swt
.widgets
.Display
;
94 import org
.eclipse
.ui
.IEditorInput
;
95 import org
.eclipse
.ui
.IEditorPart
;
96 import org
.eclipse
.ui
.IEditorReference
;
97 import org
.eclipse
.ui
.IFileEditorInput
;
98 import org
.eclipse
.ui
.IViewPart
;
99 import org
.eclipse
.ui
.IWorkbench
;
100 import org
.eclipse
.ui
.IWorkbenchPage
;
101 import org
.eclipse
.ui
.IWorkbenchWindow
;
102 import org
.eclipse
.ui
.PlatformUI
;
103 import org
.eclipse
.ui
.ide
.IDE
;
106 * Adaptor to access GDB Tracepoint frames, previously collected and saved in a
107 * file by GDB. One instance of this maps to a single DSF-GDB session.
109 * This class offers the functions of starting a post-mortem GDB session with a
110 * tracepoint data file, navigate the data frames and return the data contained
111 * in a given tracepoint frame.
113 * Note: GDB 7.2 or later is required to handle tracepoints
115 * @author Marc Dumais
116 * @author Francois Chouinard
118 @SuppressWarnings("restriction")
119 public class DsfGdbAdaptor
{
121 private GdbTrace fGdbTrace
;
123 private int fNumberOfFrames
= 0;
124 private boolean fIsTimeoutEnabled
;
125 private int fTimeout
;
127 private ILaunch fLaunch
;
128 private boolean isTerminating
;
129 private DsfSession fDsfSession
= null;
130 private String fSessionId
;
132 private String tracedExecutable
= ""; //$NON-NLS-1$
134 private String gdb72Executable
= ""; //$NON-NLS-1$
135 private String fTraceFilePath
= ""; //$NON-NLS-1$
136 private String fTraceFile
= ""; //$NON-NLS-1$
137 private String sourceLocator
= ""; //$NON-NLS-1$
139 // To save tracepoints detailed info. The key is the rank of the
140 // breakpoint (tracepoint is a kind of breakpoint)
141 private Map
<Integer
, MIBreakpointDMData
> fTpInfo
= new HashMap
<>();
143 private TmfEventType tmfEventType
= new TmfEventType(ITmfEventType
.DEFAULT_CONTEXT_ID
, "GDB Tracepoint", TmfEventField
.makeRoot(new String
[] { "Content" })); //$NON-NLS-1$ //$NON-NLS-2$
146 new DsfGdbPlatformEventListener();
150 * <b><u>DsfGdbPlatformEventListener</u></b>
152 * Listens to platform and DSF-GDB events that announce important events
153 * about the launchers or a change in debug context that we might need to
156 * @author Francois Chouinard
158 private class DsfGdbPlatformEventListener
implements
159 ILaunchesListener2
, IDebugContextListener
{
164 public DsfGdbPlatformEventListener() {
165 Display
.getDefault().syncExec(new Runnable() {
168 DebugPlugin
.getDefault().getLaunchManager().addLaunchListener(DsfGdbPlatformEventListener
.this);
169 IWorkbench wb
= PlatformUI
.getWorkbench();
170 IWorkbenchWindow win
= wb
.getActiveWorkbenchWindow();
171 DebugUITools
.getDebugContextManager().getContextService(win
).addDebugContextListener(DsfGdbPlatformEventListener
.this);
177 public synchronized void launchesRemoved(ILaunch
[] launches
) {
181 public synchronized void launchesAdded(ILaunch
[] launches
) {
185 public synchronized void launchesChanged(ILaunch
[] launches
) {
189 public synchronized void launchesTerminated(ILaunch
[] launches
) {
190 for (ILaunch launch
: launches
) {
191 String sessionId
= ((GdbLaunch
) launch
).getSession().getId();
192 closeGdbTraceEditor(sessionId
);
196 private String fCurrentSessionId
= ""; //$NON-NLS-1$
198 public void debugContextChanged(DebugContextEvent event
) {
199 ISelection selection
= event
.getContext();
200 if (selection
instanceof IStructuredSelection
) {
201 List
<?
> eventContextList
= ((IStructuredSelection
) selection
).toList();
202 for (Object eventContext
: eventContextList
) {
203 if (eventContext
instanceof IAdaptable
) {
204 IDMContext context
= (IDMContext
) ((IAdaptable
) eventContext
).getAdapter(IDMContext
.class);
205 if (context
!= null) {
207 synchronized(fCurrentSessionId
) {
208 sessionId
= context
.getSessionId();
209 if (sessionId
.equals(fCurrentSessionId
)) {
213 fCurrentSessionId
= sessionId
;
214 // Get the current trace record
215 final DsfExecutor executor
= DsfSession
.getSession(sessionId
).getExecutor();
216 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), sessionId
);
217 Query
<ITraceRecordDMContext
> getCurrentRecordQuery
= new Query
<ITraceRecordDMContext
>() {
219 public void execute(final DataRequestMonitor
<ITraceRecordDMContext
> queryRm
) {
220 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
221 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
222 if (traceControl
!= null && commandControl
!= null) {
223 ITraceTargetDMContext traceContext
= (ITraceTargetDMContext
) commandControl
.getContext();
224 traceControl
.getCurrentTraceRecordContext(traceContext
, queryRm
);
231 executor
.execute(getCurrentRecordQuery
);
232 ITraceRecordDMContext record
;
233 if (DsfGdbAdaptor
.this.fIsTimeoutEnabled
) {
234 record
= getCurrentRecordQuery
.get(fTimeout
, TimeUnit
.MILLISECONDS
);
236 record
= getCurrentRecordQuery
.get();
238 // If we get a trace record, it means that this can be used
239 if (record
!= null && record
.getRecordId() != null) {
240 int recordId
= Integer
.parseInt(record
.getRecordId());
241 selectGdbTraceEditor(sessionId
, recordId
);
244 } catch (InterruptedException e
) {
245 Activator
.logError("Interruption exception", e
); //$NON-NLS-1$
246 } catch (ExecutionException e
) {
247 Activator
.logError("GDB exception", e
); //$NON-NLS-1$
248 } catch (RejectedExecutionException e
) {
249 Activator
.logError("Request rejected exception", e
); //$NON-NLS-1$
250 } catch (TimeoutException e
) {
251 Activator
.logError("Timeout", e
); //$NON-NLS-1$
255 // else not DSF-GDB or GDB < 7.2
262 } // class DsfGdbPlatformEventListener
265 * Constructor for DsfGdbAdaptor. This is used when we want to launch a
266 * DSF-GDB session and use it as source in our tracing perspective.
267 * i.e. when launching from the Project Explorer
269 * @param trace the GDB trace
270 * @param gdbExec GDB executable. Must be version 7.2 or later.
271 * @param traceFile previously generated GDB tracepoint file
272 * @param tracedExecutable executable that was used to generate the tracefile
273 * workspace, where the traced executable was taken from.
275 public DsfGdbAdaptor(GdbTrace trace
, String gdbExec
, String traceFile
, String tracedExecutable
) {
276 this.fGdbTrace
= trace
;
277 this.gdb72Executable
= gdbExec
;
278 this.fTraceFilePath
= traceFile
;
279 this.fTraceFile
= traceFile
.substring(traceFile
.lastIndexOf(IPath
.SEPARATOR
) + 1);
280 this.tracedExecutable
= tracedExecutable
;
283 launchDGBPostMortemTrace();
284 } catch (CoreException e
) {
290 * Builds a launcher and launches a Post-mortem GDB session, based on a
291 * previously-gathered GDB Tracepoint file. The information used to
292 * create the launcher is provided to the constructor of this class,
293 * at instantiation time.
295 * Note: Requires GDB 7.2 or later
297 private void launchDGBPostMortemTrace() throws CoreException
{
298 fIsTimeoutEnabled
= Platform
.getPreferencesService().getBoolean(GdbPlugin
.PLUGIN_ID
, IGdbDebugPreferenceConstants
.PREF_COMMAND_TIMEOUT
, false, null);
299 if (fIsTimeoutEnabled
) {
300 fTimeout
= Platform
.getPreferencesService().getInt(GdbPlugin
.PLUGIN_ID
, IGdbDebugPreferenceConstants
.PREF_COMMAND_TIMEOUT_VALUE
, IGdbDebugPreferenceConstants
.COMMAND_TIMEOUT_VALUE_DEFAULT
, null);
303 ILaunchConfigurationType configType
= DebugPlugin
306 .getLaunchConfigurationType("org.eclipse.cdt.launch.postmortemLaunchType"); //$NON-NLS-1$
307 ILaunchConfigurationWorkingCopy wc
= configType
.newInstance(null, fTraceFile
);
309 wc
.setAttribute("org.eclipse.cdt.dsf.gdb.DEBUG_NAME", gdb72Executable
); //$NON-NLS-1$
310 wc
.setAttribute("org.eclipse.cdt.dsf.gdb.POST_MORTEM_TYPE", "TRACE_FILE"); //$NON-NLS-1$ //$NON-NLS-2$
311 wc
.setAttribute("org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR", 0); //$NON-NLS-1$
312 wc
.setAttribute("org.eclipse.cdt.launch.COREFILE_PATH", fTraceFilePath
); //$NON-NLS-1$
313 wc
.setAttribute("org.eclipse.cdt.launch.DEBUGGER_START_MODE", "core"); //$NON-NLS-1$ //$NON-NLS-2$
314 wc
.setAttribute("org.eclipse.cdt.launch.PROGRAM_NAME", tracedExecutable
); //$NON-NLS-1$
315 // So that the GDB launch is synchronous
316 wc
.setAttribute("org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND", false); //$NON-NLS-1$
318 if (!sourceLocator
.isEmpty()) {
319 wc
.setAttribute("org.eclipse.debug.core.source_locator_memento", sourceLocator
); //$NON-NLS-1$
322 // Launch GDB session
323 fLaunch
= wc
.doSave().launch("debug", null); //$NON-NLS-1$
324 isTerminating
= false;
326 if (fLaunch
instanceof GdbLaunch
) {
327 fSessionId
= ((GdbLaunch
) fLaunch
).getSession().getId();
330 fDsfSession
= ((GdbLaunch
) fLaunch
).getSession();
331 fDsfSession
.addServiceEventListener(this, null);
333 // Find the number of frames contained in the tracepoint file
334 fNumberOfFrames
= findNumFrames();
338 * This method terminates the current DSF-GDB session
340 public void dispose() {
341 if (fLaunch
!= null && fLaunch
.canTerminate() && !isTerminating
) {
342 isTerminating
= true;
345 } catch (DebugException e
) {
353 * This method will try (once per call) to get the number of GDB tracepoint
354 * frames for the current session, from DSF-GDB, until it succeeds at
355 * getting an amount different than zero.
357 * @return The number of frames in current session or zero if unsuccessful
359 public int getNumberOfFrames() {
360 if (fNumberOfFrames
== 0) {
361 fNumberOfFrames
= findNumFrames();
363 return fNumberOfFrames
;
368 * Wrapper around the selecting of a frame and the reading of its
369 * information. this is a work-around for the potential problem of
370 * concurrent access to these functions by more than one thread,
371 * where two clients might interfere with each other.
373 * Note: We also try to get the tracepoint info here, if it's not
376 * @param rank a long corresponding to the number of the frame to be
378 * @return A GdbTraceEvent object, or null in case of failure.
380 public synchronized GdbTraceEvent
selectAndReadFrame(final long rank
) {
381 // lazy init of tracepoints info
382 if(fTpInfo
.isEmpty()) {
385 if (selectDataFrame(rank
, false)) {
386 GdbTraceEvent event
= getTraceFrameData(rank
);
387 long ts
= event
.getTimestamp().getValue();
397 * This class implements a best-effort look-up of the detailed tracepoint
398 * information (source code filename, line number, etc...).
400 private void getTracepointInfo() {
402 // Get the latest executor/service tracker
403 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
).getExecutor();
404 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
406 Query
<Object
> selectRecordQuery
= new Query
<Object
>() {
408 public void execute(final DataRequestMonitor
<Object
> drm
) {
410 // A breakpoint is no longer GDB-global but tied to a specific process
411 // So we need to find our process and the ask for its breakpoints
412 IMIProcesses procService
= tracker
.getService(IMIProcesses
.class);
413 final ICommandControlService cmdControl
= tracker
.getService(ICommandControlService
.class);
414 if (procService
== null || cmdControl
== null) {
415 drm
.setStatus(new Status(IStatus
.ERROR
, GdbPlugin
.PLUGIN_ID
, IDsfStatusConstants
.INTERNAL_ERROR
, "Could not find necessary services", null)); //$NON-NLS-1$
420 ITraceTargetDMContext context
= (ITraceTargetDMContext
) cmdControl
.getContext();
421 ICommandControlDMContext cmdControlDMC
= DMContexts
.getAncestorOfType(context
, ICommandControlDMContext
.class);
423 procService
.getProcessesBeingDebugged(
425 new DataRequestMonitor
<IDMContext
[]>(executor
, drm
) {
427 protected void handleSuccess() {
428 assert getData() != null;
429 assert getData().length
== 1;
430 if (getData() == null || getData().length
< 1) {
435 // Choose the first process for now, until gdb can tell
436 // us which process the trace record is associated with.
437 IContainerDMContext containerDMC
= (IContainerDMContext
)(getData()[0]);
438 IBreakpointsTargetDMContext bpTargetDMC
= DMContexts
.getAncestorOfType(containerDMC
, IBreakpointsTargetDMContext
.class);
440 CommandFactory cmdFactory
= tracker
.getService(IMICommandControl
.class).getCommandFactory();
441 IBreakpoints bpService
= tracker
.getService(MIBreakpoints
.class);
442 if (cmdFactory
== null || bpService
== null) {
443 drm
.setStatus(new Status(IStatus
.ERROR
, GdbPlugin
.PLUGIN_ID
, IDsfStatusConstants
.INTERNAL_ERROR
, "Could not find necessary services", null)); //$NON-NLS-1$
448 // Execute the command
449 cmdControl
.queueCommand(cmdFactory
.createMIBreakList(bpTargetDMC
),
450 new DataRequestMonitor
<MIBreakListInfo
>(executor
, drm
) {
452 protected void handleSuccess() {
453 MIBreakpoint
[] breakpoints
= getData().getMIBreakpoints();
454 for (int i
= 0; i
< breakpoints
.length
; i
++) {
455 MIBreakpointDMData breakpoint
= new MIBreakpointDMData(breakpoints
[i
]);
456 String type
= breakpoint
.getBreakpointType();
457 // Only save info if the current breakpoint is of type tracepoint
458 if(type
.compareTo(MIBreakpoints
.TRACEPOINT
) == 0 ) {
459 fTpInfo
.put(new Integer(breakpoint
.getReference()), breakpoint
);
470 executor
.execute(selectRecordQuery
);
471 if (fIsTimeoutEnabled
) {
472 selectRecordQuery
.get(fTimeout
, TimeUnit
.MILLISECONDS
); // blocks until time out
474 selectRecordQuery
.get(); // blocks
476 } catch (InterruptedException e
) {
477 Activator
.logError("Interruption exception", e
); //$NON-NLS-1$
478 } catch (ExecutionException e
) {
479 Activator
.logError("GDB exception", e
); //$NON-NLS-1$
480 } catch (RejectedExecutionException e
) {
481 Activator
.logError("Request rejected exception", e
); //$NON-NLS-1$
482 } catch (TimeoutException e
) {
483 Activator
.logError("Timeout", e
); //$NON-NLS-1$
490 * Returns the number of frames contained in currently loaded tracepoint GDB
493 * Note: A postmortem GDB session must be started before calling
496 * @return the number of frames contained in currently loaded tracepoint GDB
497 * session or zero in case of error
499 private synchronized int findNumFrames() {
502 if (DsfSession
.getSession(fSessionId
) == null) {
506 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
)
508 final DsfServicesTracker tracker
= new DsfServicesTracker(
509 GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
511 Query
<ITraceStatusDMData
> selectRecordQuery
= new Query
<ITraceStatusDMData
>() {
514 final DataRequestMonitor
<ITraceStatusDMData
> queryRm
) {
515 final IGDBTraceControl traceControl
= tracker
516 .getService(IGDBTraceControl
.class);
518 final ICommandControlService commandControl
= tracker
519 .getService(ICommandControlService
.class);
520 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
523 if (traceControl
!= null) {
524 traceControl
.getTraceStatus(dmc
, queryRm
);
531 executor
.execute(selectRecordQuery
);
532 ITraceStatusDMData data
;
533 if (fIsTimeoutEnabled
) {
534 data
= selectRecordQuery
.get(fTimeout
, TimeUnit
.MILLISECONDS
); // blocks until time out
536 data
= selectRecordQuery
.get(); // blocks
539 frameNum
= data
.getNumberOfCollectedFrame();
540 } catch (InterruptedException e
) {
541 Activator
.logError("Interruption exception", e
); //$NON-NLS-1$
542 } catch (ExecutionException e
) {
543 Activator
.logError("GDB exception", e
); //$NON-NLS-1$
544 } catch (RejectedExecutionException e
) {
545 Activator
.logError("Request rejected exception", e
); //$NON-NLS-1$
546 } catch (TimeoutException e
) {
547 Activator
.logError("Timeout", e
); //$NON-NLS-1$
555 * This method uses the DSF-GDB interface to select a given frame number
556 * in the current GDB tracepoint session.
558 * @param rank the rank of the tracepoint frame to select.
559 * @param update true if visualization should be updated
560 * @return boolean true if select worked.
562 public boolean selectDataFrame(final long rank
, final boolean update
) {
563 boolean status
= true;
565 final DsfSession dsfSession
= DsfSession
.getSession(fSessionId
);
566 if (dsfSession
== null) {
572 * Clear the selection to ensure that the new selection is not
573 * prevented from overriding the current selection by the DSF
574 * selection policy. This could be removed when DSF provides
575 * an API to force the trace record selection in the Debug view.
577 Display
.getDefault().syncExec(new Runnable() {
580 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
581 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
582 IViewPart vp
= wbPage
.findView(IDebugUIConstants
.ID_DEBUG_VIEW
);
583 if (vp
instanceof AbstractDebugView
) {
584 Viewer viewer
= ((AbstractDebugView
) vp
).getViewer();
585 if (viewer
instanceof ITreeModelViewer
) {
586 ((ITreeModelViewer
) viewer
).setSelection(StructuredSelection
.EMPTY
, false, true);
595 final DsfExecutor executor
= dsfSession
.getExecutor();
596 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
598 Query
<Object
> selectRecordQuery
= new Query
<Object
>() {
600 public void execute(final DataRequestMonitor
<Object
> queryRm
) {
601 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
603 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
604 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
.getContext();
606 if (traceControl
!= null) {
607 ITraceRecordDMContext newCtx
= traceControl
.createTraceRecordContext(dmc
, Integer
.toString((int) rank
));
609 dsfSession
.dispatchEvent(new TraceRecordSelectedChangedEvent(newCtx
), new Hashtable
<String
, String
>());
611 traceControl
.selectTraceRecord(newCtx
, queryRm
);
618 executor
.execute(selectRecordQuery
);
619 if (fIsTimeoutEnabled
) {
620 selectRecordQuery
.get(fTimeout
, TimeUnit
.MILLISECONDS
); // blocks until time out
622 selectRecordQuery
.get(); // blocks
624 } catch (InterruptedException e
) {
626 Activator
.logError("Interruption exception", e
); //$NON-NLS-1$
627 } catch (ExecutionException e
) {
629 Activator
.logError("GDB exception", e
); //$NON-NLS-1$
630 } catch (RejectedExecutionException e
) {
632 Activator
.logError("Request rejected exception", e
); //$NON-NLS-1$
633 } catch (TimeoutException e
) {
635 Activator
.logError("Timeout", e
); //$NON-NLS-1$
643 * This method uses DSF-GDB to read the currently selected GDB tracepoint
644 * data frame. An object of type GdbTraceEvent is build based on the
645 * information contained in the data frame and returned to the caller.
647 * NOTE : A frame must be selected before calling this method!
649 * @param rank for internal purposes - does <b>not</b> control which
650 * frame will be read!
651 * @return parsed tp frame, in the form of a GdbTraceEvent
653 private GdbTraceEvent
getTraceFrameData(final long rank
) {
655 if (DsfSession
.getSession(fSessionId
) == null) {
659 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
).getExecutor();
660 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
662 Query
<ITraceRecordDMData
> getFrameDataQuery
= new Query
<ITraceRecordDMData
>() {
664 public void execute(final DataRequestMonitor
<ITraceRecordDMData
> rm
) {
665 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
667 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
668 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
.getContext();
670 if (traceControl
!= null) {
671 traceControl
.getCurrentTraceRecordContext(dmc
,
672 new DataRequestMonitor
<ITraceRecordDMContext
>(executor
, rm
) {
674 protected void handleSuccess() {
675 traceControl
.getTraceRecordData(getData(), rm
);
684 // Execute the above query
685 executor
.execute(getFrameDataQuery
);
686 ITraceRecordDMData data
;
687 if (fIsTimeoutEnabled
) {
688 data
= getFrameDataQuery
.get(fTimeout
, TimeUnit
.MILLISECONDS
); // blocking call until time out
690 data
= getFrameDataQuery
.get();
697 String ts
= data
.getTimestamp();
699 ts
= "0"; //$NON-NLS-1$
702 // get corresponding TP data
704 MIBreakpointDMData bp
= fTpInfo
.get(Integer
.valueOf(data
.getTracepointNumber()));
706 tmfEventRef
= bp
.getFileName() + ":" + bp
.getLineNumber() + " :: " + bp
.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
709 tmfEventRef
= tracedExecutable
;
712 GdbTraceEventContent evContent
= new GdbTraceEventContent(
714 Integer
.parseInt(data
.getTracepointNumber()),
715 Integer
.parseInt(data
.getRecordId()));
717 GdbTraceEvent ev
= new GdbTraceEvent(fGdbTrace
,
718 new TmfTimestamp(Integer
.parseInt(data
.getRecordId())),
719 "Tracepoint: " + data
.getTracepointNumber() + ", Frame: " + data
.getRecordId(), //$NON-NLS-1$ //$NON-NLS-2$
726 } catch (InterruptedException e
) {
727 return createExceptionEvent(rank
, "Interruption exception"); //$NON-NLS-1$
728 } catch (java
.util
.concurrent
.ExecutionException e
) {
729 return createExceptionEvent(rank
, "GDB exception"); //$NON-NLS-1$
730 } catch (RejectedExecutionException e
) {
731 return createExceptionEvent(rank
, "Request rejected exception"); //$NON-NLS-1$
732 } catch (TimeoutException e
) {
733 return createExceptionEvent(rank
, "Timeout"); //$NON-NLS-1$
742 * This is a helper method for getTraceFrameData, to create for it a
743 * "best effort" GdbTraceEvent when a problem occurs during the reading.
745 * @param rank long containing the number of the frame where the problem occurred
746 * @param message String containing a brief explanation of problem.
747 * @return a GdbTraceEvent object, filled as best as possible
749 private GdbTraceEvent
createExceptionEvent(final long rank
, final String message
) {
750 // get corresponding TP data
753 MIBreakpointDMData bp
= fTpInfo
.get(rank
);
755 tmfEventRef
= bp
.getFileName() + ":" + bp
.getLineNumber() + " :: " + bp
.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
756 tmfEventSrc
= bp
.getFileName() + " :: " + bp
.getFunctionName() + ", line: " + bp
.getLineNumber(); //$NON-NLS-1$ //$NON-NLS-2$
759 tmfEventRef
= tracedExecutable
;
760 tmfEventSrc
= "Tracepoint: n/a"; //$NON-NLS-1$
763 GdbTraceEventContent evContent
= new GdbTraceEventContent("ERROR: " + message
, 0, 0); //$NON-NLS-1$
765 GdbTraceEvent ev
= new GdbTraceEvent(fGdbTrace
,
766 new TmfTimestamp(rank
),
776 * @return DSF-GDB session id of the current session.
778 public String
getSessionId() {
783 * Handler method that catches the DSF "record selected changed" event.
784 * It in turn creates a TMF "time sync" signal.
785 * @param event TraceRecordSelectedChangedEvent: The DSF event.
787 @DsfServiceEventHandler
788 public void handleDSFRecordSelectedEvents(final ITraceRecordSelectedChangedDMEvent event
) {
789 if (event
instanceof TraceRecordSelectedChangedEvent
) {
790 TraceRecordSelectedChangedEvent traceEvent
= (TraceRecordSelectedChangedEvent
) event
;
791 ITraceRecordDMContext context
= traceEvent
.getDMContext();
792 final String reference
= context
.getRecordId();
793 if (reference
!= null) {
794 int recordId
= Integer
.parseInt(reference
);
795 selectGdbTraceEditor(context
.getSessionId(), recordId
);
800 private static void closeGdbTraceEditor(final String sessionId
) {
801 Display
.getDefault().asyncExec(new Runnable() {
804 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
805 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
806 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
807 IEditorPart editor
= editorReference
.getEditor(false);
808 if (editor
instanceof ITmfTraceEditor
) {
809 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
810 if (trace
instanceof GdbTrace
) {
811 if (((GdbTrace
) trace
).getDsfSessionId().equals(sessionId
)) {
812 wbPage
.closeEditor(editor
, false);
823 private static void selectGdbTraceEditor(final String sessionId
, final int recordId
) {
824 Display
.getDefault().asyncExec(new Runnable() {
827 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
828 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
829 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
830 IEditorPart editor
= editorReference
.getEditor(false);
831 if (editor
instanceof ITmfTraceEditor
) {
832 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
833 if (trace
instanceof GdbTrace
) {
834 if (((GdbTrace
) trace
).getDsfSessionId().equals(sessionId
)) {
835 wbPage
.bringToTop(editor
);
836 if (recordId
!= -1) {
837 gotoRank(editor
, recordId
);
841 } else if (trace
instanceof TmfExperiment
) {
842 TmfExperiment experiment
= (TmfExperiment
) trace
;
843 int nbTraces
= experiment
.getTraces().length
;
844 for (int i
= 0; i
< nbTraces
; i
++) {
845 GdbTrace gdbTrace
= (GdbTrace
) experiment
.getTraces()[i
];
846 if (gdbTrace
.getDsfSessionId().equals(sessionId
)) {
847 wbPage
.bringToTop(editor
);
848 if (recordId
!= -1) {
849 int rank
= recordId
* nbTraces
+ i
;
850 gotoRank(editor
, rank
);
864 private static void gotoRank(IEditorPart editor
, int rank
) {
865 IEditorInput editorInput
= editor
.getEditorInput();
866 if (editorInput
instanceof IFileEditorInput
) {
867 IFile file
= ((IFileEditorInput
) editorInput
).getFile();
869 final IMarker marker
= file
.createMarker(IMarker
.MARKER
);
870 marker
.setAttribute(IMarker
.LOCATION
, (Integer
) rank
);
871 IDE
.gotoMarker(editor
, marker
);
873 } catch (CoreException e
) {