1 /*******************************************************************************
2 * Copyright (c) 2011, 2013 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
;
25 import org
.eclipse
.cdt
.dsf
.concurrent
.DataRequestMonitor
;
26 import org
.eclipse
.cdt
.dsf
.concurrent
.DsfExecutor
;
27 import org
.eclipse
.cdt
.dsf
.concurrent
.IDsfStatusConstants
;
28 import org
.eclipse
.cdt
.dsf
.concurrent
.Query
;
29 import org
.eclipse
.cdt
.dsf
.datamodel
.DMContexts
;
30 import org
.eclipse
.cdt
.dsf
.datamodel
.IDMContext
;
31 import org
.eclipse
.cdt
.dsf
.debug
.service
.IBreakpoints
;
32 import org
.eclipse
.cdt
.dsf
.debug
.service
.IBreakpoints
.IBreakpointsTargetDMContext
;
33 import org
.eclipse
.cdt
.dsf
.debug
.service
.IRunControl
.IContainerDMContext
;
34 import org
.eclipse
.cdt
.dsf
.debug
.service
.command
.ICommandControlService
;
35 import org
.eclipse
.cdt
.dsf
.debug
.service
.command
.ICommandControlService
.ICommandControlDMContext
;
36 import org
.eclipse
.cdt
.dsf
.gdb
.internal
.GdbPlugin
;
37 import org
.eclipse
.cdt
.dsf
.gdb
.launching
.GdbLaunch
;
38 import org
.eclipse
.cdt
.dsf
.gdb
.service
.GDBTraceControl_7_2
.TraceRecordSelectedChangedEvent
;
39 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
;
40 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordDMContext
;
41 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordDMData
;
42 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceRecordSelectedChangedDMEvent
;
43 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceStatusDMData
;
44 import org
.eclipse
.cdt
.dsf
.gdb
.service
.IGDBTraceControl
.ITraceTargetDMContext
;
45 import org
.eclipse
.cdt
.dsf
.mi
.service
.IMICommandControl
;
46 import org
.eclipse
.cdt
.dsf
.mi
.service
.IMIProcesses
;
47 import org
.eclipse
.cdt
.dsf
.mi
.service
.MIBreakpointDMData
;
48 import org
.eclipse
.cdt
.dsf
.mi
.service
.MIBreakpoints
;
49 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.CommandFactory
;
50 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.output
.MIBreakListInfo
;
51 import org
.eclipse
.cdt
.dsf
.mi
.service
.command
.output
.MIBreakpoint
;
52 import org
.eclipse
.cdt
.dsf
.service
.DsfServiceEventHandler
;
53 import org
.eclipse
.cdt
.dsf
.service
.DsfServicesTracker
;
54 import org
.eclipse
.cdt
.dsf
.service
.DsfSession
;
55 import org
.eclipse
.core
.resources
.IFile
;
56 import org
.eclipse
.core
.resources
.IMarker
;
57 import org
.eclipse
.core
.runtime
.CoreException
;
58 import org
.eclipse
.core
.runtime
.IAdaptable
;
59 import org
.eclipse
.core
.runtime
.IPath
;
60 import org
.eclipse
.core
.runtime
.IStatus
;
61 import org
.eclipse
.core
.runtime
.Status
;
62 import org
.eclipse
.debug
.core
.DebugException
;
63 import org
.eclipse
.debug
.core
.DebugPlugin
;
64 import org
.eclipse
.debug
.core
.ILaunch
;
65 import org
.eclipse
.debug
.core
.ILaunchConfigurationType
;
66 import org
.eclipse
.debug
.core
.ILaunchConfigurationWorkingCopy
;
67 import org
.eclipse
.debug
.core
.ILaunchesListener2
;
68 import org
.eclipse
.debug
.internal
.ui
.viewers
.model
.provisional
.ITreeModelViewer
;
69 import org
.eclipse
.debug
.ui
.AbstractDebugView
;
70 import org
.eclipse
.debug
.ui
.DebugUITools
;
71 import org
.eclipse
.debug
.ui
.IDebugUIConstants
;
72 import org
.eclipse
.debug
.ui
.contexts
.DebugContextEvent
;
73 import org
.eclipse
.debug
.ui
.contexts
.IDebugContextListener
;
74 import org
.eclipse
.jface
.viewers
.ISelection
;
75 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
76 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
77 import org
.eclipse
.jface
.viewers
.Viewer
;
78 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.GdbTraceCorePlugin
;
79 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.event
.GdbTraceEvent
;
80 import org
.eclipse
.linuxtools
.internal
.gdbtrace
.core
.event
.GdbTraceEventContent
;
81 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEventType
;
82 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEventField
;
83 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEventType
;
84 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
85 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
86 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
87 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.ITmfTraceEditor
;
88 import org
.eclipse
.swt
.widgets
.Display
;
89 import org
.eclipse
.ui
.IEditorInput
;
90 import org
.eclipse
.ui
.IEditorPart
;
91 import org
.eclipse
.ui
.IEditorReference
;
92 import org
.eclipse
.ui
.IFileEditorInput
;
93 import org
.eclipse
.ui
.IViewPart
;
94 import org
.eclipse
.ui
.IWorkbench
;
95 import org
.eclipse
.ui
.IWorkbenchPage
;
96 import org
.eclipse
.ui
.IWorkbenchWindow
;
97 import org
.eclipse
.ui
.PlatformUI
;
98 import org
.eclipse
.ui
.ide
.IDE
;
101 * Adaptor to access GDB Tracepoint frames, previously collected and saved in a
102 * file by GDB. One instance of this maps to a single DSF-GDB session.
104 * This class offers the functions of starting a post-mortem GDB session with a
105 * tracepoint data file, navigate the data frames and return the data contained
106 * in a given tracepoint frame.
108 * Note: GDB 7.2 or later is required to handle tracepoints
110 * @author Marc Dumais
111 * @author Francois Chouinard
113 @SuppressWarnings("restriction")
114 public class DsfGdbAdaptor
{
116 private GdbTrace fGdbTrace
;
118 private int fNumberOfFrames
= 0;
120 private ILaunch fLaunch
;
121 private boolean isTerminating
;
122 private DsfSession fDsfSession
= null;
123 private String fSessionId
;
125 private String tracedExecutable
= ""; //$NON-NLS-1$
127 private String gdb72Executable
= ""; //$NON-NLS-1$
128 private String fTraceFilePath
= ""; //$NON-NLS-1$
129 private String fTraceFile
= ""; //$NON-NLS-1$
130 private String sourceLocator
= ""; //$NON-NLS-1$
132 // To save tracepoints detailed info. The key is the rank of the
133 // breakpoint (tracepoint is a kind of breakpoint)
134 private Map
<Integer
, MIBreakpointDMData
> fTpInfo
= new HashMap
<>();
136 private TmfEventType tmfEventType
= new TmfEventType(ITmfEventType
.DEFAULT_CONTEXT_ID
, "GDB Tracepoint", TmfEventField
.makeRoot(new String
[] { "Content" })); //$NON-NLS-1$ //$NON-NLS-2$
138 @SuppressWarnings("unused")
139 private static DsfGdbPlatformEventListener fPlatformEventListener
= new DsfGdbPlatformEventListener();
142 * <b><u>DsfGdbPlatformEventListener</u></b>
144 * Listens to platform and DSF-GDB events that announce important events
145 * about the launchers or a change in debug context that we might need to
148 * @author Francois Chouinard
150 private static class DsfGdbPlatformEventListener
implements
151 ILaunchesListener2
, IDebugContextListener
{
156 public DsfGdbPlatformEventListener() {
157 Display
.getDefault().syncExec(new Runnable() {
160 DebugPlugin
.getDefault().getLaunchManager().addLaunchListener(DsfGdbPlatformEventListener
.this);
161 IWorkbench wb
= PlatformUI
.getWorkbench();
162 IWorkbenchWindow win
= wb
.getActiveWorkbenchWindow();
163 DebugUITools
.getDebugContextManager().getContextService(win
).addDebugContextListener(DsfGdbPlatformEventListener
.this);
169 public synchronized void launchesRemoved(ILaunch
[] launches
) {
173 public synchronized void launchesAdded(ILaunch
[] launches
) {
177 public synchronized void launchesChanged(ILaunch
[] launches
) {
181 public synchronized void launchesTerminated(ILaunch
[] launches
) {
182 for (ILaunch launch
: launches
) {
183 String sessionId
= ((GdbLaunch
) launch
).getSession().getId();
184 closeGdbTraceEditor(sessionId
);
188 private String fCurrentSessionId
= ""; //$NON-NLS-1$
190 public void debugContextChanged(DebugContextEvent event
) {
191 ISelection selection
= event
.getContext();
192 if (selection
instanceof IStructuredSelection
) {
193 List
<?
> eventContextList
= ((IStructuredSelection
) selection
).toList();
194 for (Object eventContext
: eventContextList
) {
195 if (eventContext
instanceof IAdaptable
) {
196 IDMContext context
= (IDMContext
) ((IAdaptable
) eventContext
).getAdapter(IDMContext
.class);
197 if (context
!= null) {
199 synchronized(fCurrentSessionId
) {
200 sessionId
= context
.getSessionId();
201 if (sessionId
.equals(fCurrentSessionId
)) {
205 fCurrentSessionId
= sessionId
;
206 // Get the current trace record
207 final DsfExecutor executor
= DsfSession
.getSession(sessionId
).getExecutor();
208 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), sessionId
);
209 Query
<ITraceRecordDMContext
> getCurrentRecordQuery
= new Query
<ITraceRecordDMContext
>() {
211 public void execute(final DataRequestMonitor
<ITraceRecordDMContext
> queryRm
) {
212 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
213 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
214 if (traceControl
!= null && commandControl
!= null) {
215 ITraceTargetDMContext traceContext
= (ITraceTargetDMContext
) commandControl
.getContext();
216 traceControl
.getCurrentTraceRecordContext(traceContext
, queryRm
);
223 executor
.execute(getCurrentRecordQuery
);
224 ITraceRecordDMContext record
= getCurrentRecordQuery
.get();
225 // If we get a trace record, it means that this can be used
226 if (record
!= null && record
.getRecordId() != null) {
227 int recordId
= Integer
.parseInt(record
.getRecordId());
228 selectGdbTraceEditor(sessionId
, recordId
);
231 } catch (InterruptedException e
) {
232 } catch (java
.util
.concurrent
.ExecutionException e
) {
233 } catch (RejectedExecutionException e
) {
237 // else not DSF-GDB or GDB < 7.2
244 } // class DsfGdbPlatformEventListener
247 * Constructor for DsfGdbAdaptor. This is used when we want to launch a
248 * DSF-GDB session and use it as source in our tracing perspective.
249 * i.e. when launching from the Project Explorer
251 * @param trace the GDB trace
252 * @param gdbExec GDB executable. Must be version 7.2 or later.
253 * @param traceFile previously generated GDB tracepoint file
254 * @param tracedExecutable executable that was used to generate the tracefile
255 * workspace, where the traced executable was taken from.
257 public DsfGdbAdaptor(GdbTrace trace
, String gdbExec
, String traceFile
, String tracedExecutable
) {
258 this.fGdbTrace
= trace
;
259 this.gdb72Executable
= gdbExec
;
260 this.fTraceFilePath
= traceFile
;
261 this.fTraceFile
= traceFile
.substring(traceFile
.lastIndexOf(IPath
.SEPARATOR
) + 1);
262 this.tracedExecutable
= tracedExecutable
;
265 launchDGBPostMortemTrace();
266 } catch (CoreException e
) {
272 * Builds a launcher and launches a Post-mortem GDB session, based on a
273 * previously-gathered GDB Tracepoint file. The information used to
274 * create the launcher is provided to the constructor of this class,
275 * at instantiation time.
277 * Note: Requires GDB 7.2 or later
279 private void launchDGBPostMortemTrace() throws CoreException
{
281 ILaunchConfigurationType configType
= DebugPlugin
284 .getLaunchConfigurationType("org.eclipse.cdt.launch.postmortemLaunchType"); //$NON-NLS-1$
285 ILaunchConfigurationWorkingCopy wc
= configType
.newInstance(null, fTraceFile
);
287 wc
.setAttribute("org.eclipse.cdt.dsf.gdb.DEBUG_NAME", gdb72Executable
); //$NON-NLS-1$
288 wc
.setAttribute("org.eclipse.cdt.dsf.gdb.POST_MORTEM_TYPE", "TRACE_FILE"); //$NON-NLS-1$ //$NON-NLS-2$
289 wc
.setAttribute("org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR", 0); //$NON-NLS-1$
290 wc
.setAttribute("org.eclipse.cdt.launch.COREFILE_PATH", fTraceFilePath
); //$NON-NLS-1$
291 wc
.setAttribute("org.eclipse.cdt.launch.DEBUGGER_START_MODE", "core"); //$NON-NLS-1$ //$NON-NLS-2$
292 wc
.setAttribute("org.eclipse.cdt.launch.PROGRAM_NAME", tracedExecutable
); //$NON-NLS-1$
293 // So that the GDB launch is synchronous
294 wc
.setAttribute("org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND", false); //$NON-NLS-1$
296 if (!sourceLocator
.isEmpty()) {
297 wc
.setAttribute("org.eclipse.debug.core.source_locator_memento", sourceLocator
); //$NON-NLS-1$
300 // Launch GDB session
301 fLaunch
= wc
.doSave().launch("debug", null); //$NON-NLS-1$
302 isTerminating
= false;
304 if (fLaunch
instanceof GdbLaunch
) {
305 fSessionId
= ((GdbLaunch
) fLaunch
).getSession().getId();
308 fDsfSession
= ((GdbLaunch
) fLaunch
).getSession();
309 fDsfSession
.addServiceEventListener(this, null);
311 // Find the number of frames contained in the tracepoint file
312 fNumberOfFrames
= findNumFrames();
316 * This method terminates the current DSF-GDB session
318 public void dispose() {
319 if (fLaunch
!= null && fLaunch
.canTerminate() && !isTerminating
) {
320 isTerminating
= true;
323 } catch (DebugException e
) {
331 * This method will try (once per call) to get the number of GDB tracepoint
332 * frames for the current session, from DSF-GDB, until it succeeds at
333 * getting an amount different than zero.
335 * @return The number of frames in current session or zero if unsuccessful
337 public int getNumberOfFrames() {
338 if (fNumberOfFrames
== 0) {
339 fNumberOfFrames
= findNumFrames();
341 return fNumberOfFrames
;
346 * Wrapper around the selecting of a frame and the reading of its
347 * information. this is a work-around for the potential problem of
348 * concurrent access to these functions by more than one thread,
349 * where two clients might interfere with each other.
351 * Note: We also try to get the tracepoint info here, if it's not
354 * @param rank a long corresponding to the number of the frame to be
356 * @return A GdbTraceEvent object, or null in case of failure.
358 public synchronized GdbTraceEvent
selectAndReadFrame(final long rank
) {
359 // lazy init of tracepoints info
360 if(fTpInfo
.isEmpty()) {
363 if (selectDataFrame(rank
, false)) {
364 GdbTraceEvent event
= getTraceFrameData(rank
);
365 long ts
= event
.getTimestamp().getValue();
375 * This class implements a best-effort look-up of the detailed tracepoint
376 * information (source code filename, line number, etc...).
378 private void getTracepointInfo() {
380 // Get the latest executor/service tracker
381 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
).getExecutor();
382 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
384 Query
<Object
> selectRecordQuery
= new Query
<Object
>() {
386 public void execute(final DataRequestMonitor
<Object
> drm
) {
388 // A breakpoint is no longer GDB-global but tied to a specific process
389 // So we need to find our process and the ask for its breakpoints
390 IMIProcesses procService
= tracker
.getService(IMIProcesses
.class);
391 final ICommandControlService cmdControl
= tracker
.getService(ICommandControlService
.class);
392 if (procService
== null || cmdControl
== null) {
393 drm
.setStatus(new Status(IStatus
.ERROR
, GdbPlugin
.PLUGIN_ID
, IDsfStatusConstants
.INTERNAL_ERROR
, "Could not find necessary services", null)); //$NON-NLS-1$
398 ITraceTargetDMContext context
= (ITraceTargetDMContext
) cmdControl
.getContext();
399 ICommandControlDMContext cmdControlDMC
= DMContexts
.getAncestorOfType(context
, ICommandControlDMContext
.class);
401 procService
.getProcessesBeingDebugged(
403 new DataRequestMonitor
<IDMContext
[]>(executor
, drm
) {
405 protected void handleSuccess() {
406 assert getData() != null;
407 assert getData().length
== 1;
408 if (getData() == null || getData().length
< 1) {
413 // Choose the first process for now, until gdb can tell
414 // us which process the trace record is associated with.
415 IContainerDMContext containerDMC
= (IContainerDMContext
)(getData()[0]);
416 IBreakpointsTargetDMContext bpTargetDMC
= DMContexts
.getAncestorOfType(containerDMC
, IBreakpointsTargetDMContext
.class);
418 CommandFactory cmdFactory
= tracker
.getService(IMICommandControl
.class).getCommandFactory();
419 IBreakpoints bpService
= tracker
.getService(MIBreakpoints
.class);
420 if (cmdFactory
== null || bpService
== null) {
421 drm
.setStatus(new Status(IStatus
.ERROR
, GdbPlugin
.PLUGIN_ID
, IDsfStatusConstants
.INTERNAL_ERROR
, "Could not find necessary services", null)); //$NON-NLS-1$
426 // Execute the command
427 cmdControl
.queueCommand(cmdFactory
.createMIBreakList(bpTargetDMC
),
428 new DataRequestMonitor
<MIBreakListInfo
>(executor
, drm
) {
430 protected void handleSuccess() {
431 MIBreakpoint
[] breakpoints
= getData().getMIBreakpoints();
432 for (int i
= 0; i
< breakpoints
.length
; i
++) {
433 MIBreakpointDMData breakpoint
= new MIBreakpointDMData(breakpoints
[i
]);
434 String type
= breakpoint
.getBreakpointType();
435 // Only save info if the current breakpoint is of type tracepoint
436 if(type
.compareTo(MIBreakpoints
.TRACEPOINT
) == 0 ) {
437 fTpInfo
.put(new Integer(breakpoint
.getReference()), breakpoint
);
448 executor
.execute(selectRecordQuery
);
449 selectRecordQuery
.get(); // blocks
450 } catch (RejectedExecutionException e
) {
452 } catch (InterruptedException e
) {
453 // TODO Auto-generated catch block
455 } catch (ExecutionException e
) {
456 // TODO Auto-generated catch block
464 * Returns the number of frames contained in currently loaded tracepoint GDB
467 * Note: A postmortem GDB session must be started before calling
470 * @return the number of frames contained in currently loaded tracepoint GDB
471 * session or zero in case of error
473 private synchronized int findNumFrames() {
476 if (DsfSession
.getSession(fSessionId
) == null) {
480 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
)
482 final DsfServicesTracker tracker
= new DsfServicesTracker(
483 GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
485 Query
<ITraceStatusDMData
> selectRecordQuery
= new Query
<ITraceStatusDMData
>() {
488 final DataRequestMonitor
<ITraceStatusDMData
> queryRm
) {
489 final IGDBTraceControl traceControl
= tracker
490 .getService(IGDBTraceControl
.class);
492 final ICommandControlService commandControl
= tracker
493 .getService(ICommandControlService
.class);
494 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
497 if (traceControl
!= null) {
498 traceControl
.getTraceStatus(dmc
, queryRm
);
505 executor
.execute(selectRecordQuery
);
506 ITraceStatusDMData data
= selectRecordQuery
.get(); // blocks
507 frameNum
= data
.getNumberOfCollectedFrame();
508 } catch (InterruptedException e
) {
510 } catch (java
.util
.concurrent
.ExecutionException e
) {
512 } catch (RejectedExecutionException e
) {
521 * This method uses the DSF-GDB interface to select a given frame number
522 * in the current GDB tracepoint session.
524 * @param rank the rank of the tracepoint frame to select.
525 * @param update true if visualization should be updated
526 * @return boolean true if select worked.
528 public boolean selectDataFrame(final long rank
, final boolean update
) {
529 boolean status
= true;
531 final DsfSession dsfSession
= DsfSession
.getSession(fSessionId
);
532 if (dsfSession
== null) {
538 * Clear the selection to ensure that the new selection is not
539 * prevented from overriding the current selection by the DSF
540 * selection policy. This could be removed when DSF provides
541 * an API to force the trace record selection in the Debug view.
543 Display
.getDefault().syncExec(new Runnable() {
546 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
547 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
548 IViewPart vp
= wbPage
.findView(IDebugUIConstants
.ID_DEBUG_VIEW
);
549 if (vp
instanceof AbstractDebugView
) {
550 Viewer viewer
= ((AbstractDebugView
) vp
).getViewer();
551 if (viewer
instanceof ITreeModelViewer
) {
552 ((ITreeModelViewer
) viewer
).setSelection(StructuredSelection
.EMPTY
, false, true);
561 final DsfExecutor executor
= dsfSession
.getExecutor();
562 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
564 Query
<Object
> selectRecordQuery
= new Query
<Object
>() {
566 public void execute(final DataRequestMonitor
<Object
> queryRm
) {
567 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
569 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
570 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
.getContext();
572 if (traceControl
!= null) {
573 ITraceRecordDMContext newCtx
= traceControl
.createTraceRecordContext(dmc
, Integer
.toString((int) rank
));
575 dsfSession
.dispatchEvent(new TraceRecordSelectedChangedEvent(newCtx
), new Hashtable
<String
, String
>());
577 traceControl
.selectTraceRecord(newCtx
, queryRm
);
584 executor
.execute(selectRecordQuery
);
585 selectRecordQuery
.get(); // blocks
586 } catch (InterruptedException e
) {
588 } catch (java
.util
.concurrent
.ExecutionException e
) {
590 } catch (RejectedExecutionException e
) {
599 * This method uses DSF-GDB to read the currently selected GDB tracepoint
600 * data frame. An object of type GdbTraceEvent is build based on the
601 * information contained in the data frame and returned to the caller.
603 * NOTE : A frame must be selected before calling this method!
605 * @param rank for internal purposes - does <b>not</b> control which
606 * frame will be read!
607 * @return parsed tp frame, in the form of a GdbTraceEvent
609 private GdbTraceEvent
getTraceFrameData(final long rank
) {
611 if (DsfSession
.getSession(fSessionId
) == null) {
615 final DsfExecutor executor
= DsfSession
.getSession(fSessionId
).getExecutor();
616 final DsfServicesTracker tracker
= new DsfServicesTracker(GdbTraceCorePlugin
.getBundleContext(), fSessionId
);
618 Query
<ITraceRecordDMData
> getFrameDataQuery
= new Query
<ITraceRecordDMData
>() {
620 public void execute(final DataRequestMonitor
<ITraceRecordDMData
> rm
) {
621 final IGDBTraceControl traceControl
= tracker
.getService(IGDBTraceControl
.class);
623 final ICommandControlService commandControl
= tracker
.getService(ICommandControlService
.class);
624 final ITraceTargetDMContext dmc
= (ITraceTargetDMContext
) commandControl
.getContext();
626 if (traceControl
!= null) {
627 traceControl
.getCurrentTraceRecordContext(dmc
,
628 new DataRequestMonitor
<ITraceRecordDMContext
>(executor
, rm
) {
630 protected void handleSuccess() {
631 traceControl
.getTraceRecordData(getData(), rm
);
640 // Execute the above query
641 executor
.execute(getFrameDataQuery
);
642 ITraceRecordDMData data
= getFrameDataQuery
.get(); // blocking call
648 String ts
= data
.getTimestamp();
650 ts
= "0"; //$NON-NLS-1$
653 // get corresponding TP data
655 MIBreakpointDMData bp
= fTpInfo
.get(Integer
.valueOf(data
.getTracepointNumber()));
657 tmfEventRef
= bp
.getFileName() + ":" + bp
.getLineNumber() + " :: " + bp
.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
660 tmfEventRef
= tracedExecutable
;
663 GdbTraceEventContent evContent
= new GdbTraceEventContent(
665 Integer
.parseInt(data
.getTracepointNumber()),
666 Integer
.parseInt(data
.getRecordId()));
668 GdbTraceEvent ev
= new GdbTraceEvent(fGdbTrace
,
669 new TmfTimestamp(Integer
.parseInt(data
.getRecordId())),
670 "Tracepoint: " + data
.getTracepointNumber() + ", Frame: " + data
.getRecordId(), //$NON-NLS-1$ //$NON-NLS-2$
677 } catch (InterruptedException e
) {
678 return createExceptionEvent(rank
, "Interruption exception"); //$NON-NLS-1$
679 } catch (java
.util
.concurrent
.ExecutionException e
) {
680 return createExceptionEvent(rank
, "GDB exception"); //$NON-NLS-1$
681 } catch (RejectedExecutionException e
) {
682 return createExceptionEvent(rank
, "Request rejected exception"); //$NON-NLS-1$
683 } catch (Exception e
) {
684 return createExceptionEvent(rank
, "General exception"); //$NON-NLS-1$
693 * This is a helper method for getTraceFrameData, to create for it a
694 * "best effort" GdbTraceEvent when a problem occurs during the reading.
696 * @param rank long containing the number of the frame where the problem occurred
697 * @param message String containing a brief explanation of problem.
698 * @return a GdbTraceEvent object, filled as best as possible
700 private GdbTraceEvent
createExceptionEvent(final long rank
, final String message
) {
701 // get corresponding TP data
704 MIBreakpointDMData bp
= fTpInfo
.get(rank
);
706 tmfEventRef
= bp
.getFileName() + ":" + bp
.getLineNumber() + " :: " + bp
.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
707 tmfEventSrc
= bp
.getFileName() + " :: " + bp
.getFunctionName() + ", line: " + bp
.getLineNumber(); //$NON-NLS-1$ //$NON-NLS-2$
710 tmfEventRef
= tracedExecutable
;
711 tmfEventSrc
= "Tracepoint: n/a"; //$NON-NLS-1$
714 GdbTraceEventContent evContent
= new GdbTraceEventContent("ERROR: " + message
, 0, 0); //$NON-NLS-1$
716 GdbTraceEvent ev
= new GdbTraceEvent(fGdbTrace
,
717 new TmfTimestamp(rank
),
727 * @return DSF-GDB session id of the current session.
729 public String
getSessionId() {
734 * Handler method that catches the DSF "record selected changed" event.
735 * It in turn creates a TMF "time sync" signal.
736 * @param event TraceRecordSelectedChangedEvent: The DSF event.
738 @DsfServiceEventHandler
739 public void handleDSFRecordSelectedEvents(final ITraceRecordSelectedChangedDMEvent event
) {
740 if (event
instanceof TraceRecordSelectedChangedEvent
) {
741 TraceRecordSelectedChangedEvent traceEvent
= (TraceRecordSelectedChangedEvent
) event
;
742 ITraceRecordDMContext context
= traceEvent
.getDMContext();
743 final String reference
= context
.getRecordId();
744 if (reference
!= null) {
745 int recordId
= Integer
.parseInt(reference
);
746 selectGdbTraceEditor(context
.getSessionId(), recordId
);
751 private static void closeGdbTraceEditor(final String sessionId
) {
752 Display
.getDefault().asyncExec(new Runnable() {
755 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
756 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
757 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
758 IEditorPart editor
= editorReference
.getEditor(false);
759 if (editor
instanceof ITmfTraceEditor
) {
760 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
761 if (trace
instanceof GdbTrace
) {
762 if (((GdbTrace
) trace
).getDsfSessionId().equals(sessionId
)) {
763 wbPage
.closeEditor(editor
, false);
774 private static void selectGdbTraceEditor(final String sessionId
, final int recordId
) {
775 Display
.getDefault().asyncExec(new Runnable() {
778 for (IWorkbenchWindow wbWindow
: PlatformUI
.getWorkbench().getWorkbenchWindows()) {
779 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
780 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
781 IEditorPart editor
= editorReference
.getEditor(false);
782 if (editor
instanceof ITmfTraceEditor
) {
783 ITmfTrace trace
= ((ITmfTraceEditor
) editor
).getTrace();
784 if (trace
instanceof GdbTrace
) {
785 if (((GdbTrace
) trace
).getDsfSessionId().equals(sessionId
)) {
786 wbPage
.bringToTop(editor
);
787 if (recordId
!= -1) {
788 gotoRank(editor
, recordId
);
792 } else if (trace
instanceof TmfExperiment
) {
793 TmfExperiment experiment
= (TmfExperiment
) trace
;
794 int nbTraces
= experiment
.getTraces().length
;
795 for (int i
= 0; i
< nbTraces
; i
++) {
796 GdbTrace gdbTrace
= (GdbTrace
) experiment
.getTraces()[i
];
797 if (gdbTrace
.getDsfSessionId().equals(sessionId
)) {
798 wbPage
.bringToTop(editor
);
799 if (recordId
!= -1) {
800 int rank
= recordId
* nbTraces
+ i
;
801 gotoRank(editor
, rank
);
815 private static void gotoRank(IEditorPart editor
, int rank
) {
816 IEditorInput editorInput
= editor
.getEditorInput();
817 if (editorInput
instanceof IFileEditorInput
) {
818 IFile file
= ((IFileEditorInput
) editorInput
).getFile();
820 final IMarker marker
= file
.createMarker(IMarker
.MARKER
);
821 marker
.setAttribute(IMarker
.LOCATION
, (Integer
) rank
);
822 IDE
.gotoMarker(editor
, marker
);
824 } catch (CoreException e
) {