ctf: preserve byte order if explicitly set in a typedef
[deliverable/tracecompass.git] / gdbtrace / org.eclipse.tracecompass.gdbtrace.core / src / org / eclipse / tracecompass / internal / gdbtrace / core / trace / DsfGdbAdaptor.java
CommitLineData
6de2f761 1/*******************************************************************************
c19380ab 2 * Copyright (c) 2011, 2015 Ericsson
6de2f761
PT
3 *
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
8 *
9 * Contributors:
10 * Marc Dumais - Initial implementation
11 * Francois Chouinard - Misc improvements, DSF signal handling, dynamic experiment
12 * Patrick Tasse - Updated for TMF 2.0
ce800780 13 * Bernd Hufmann - Fixed deadlock during shutdown
6de2f761
PT
14 *******************************************************************************/
15
04c0d7d3 16package org.eclipse.tracecompass.internal.gdbtrace.core.trace;
6de2f761
PT
17
18import java.util.HashMap;
19import java.util.Hashtable;
20import java.util.List;
21import java.util.Map;
22import java.util.concurrent.ExecutionException;
23import java.util.concurrent.RejectedExecutionException;
e9a6e38e
MAL
24import java.util.concurrent.TimeUnit;
25import java.util.concurrent.TimeoutException;
6de2f761
PT
26
27import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
28import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
29import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
30import org.eclipse.cdt.dsf.concurrent.Query;
31import org.eclipse.cdt.dsf.datamodel.DMContexts;
32import org.eclipse.cdt.dsf.datamodel.IDMContext;
33import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
34import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
35import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
36import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
37import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
e9a6e38e 38import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
6de2f761 39import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
6de2f761
PT
40import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
41import org.eclipse.cdt.dsf.gdb.service.GDBTraceControl_7_2.TraceRecordSelectedChangedEvent;
42import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
43import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
44import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMData;
45import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
46import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData;
47import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
48import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
49import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
50import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
51import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
52import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
53import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
54import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
55import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
56import org.eclipse.cdt.dsf.service.DsfServicesTracker;
57import org.eclipse.cdt.dsf.service.DsfSession;
58import org.eclipse.core.resources.IFile;
59import org.eclipse.core.resources.IMarker;
60import org.eclipse.core.runtime.CoreException;
61import org.eclipse.core.runtime.IAdaptable;
62import org.eclipse.core.runtime.IPath;
63import org.eclipse.core.runtime.IStatus;
e9a6e38e 64import org.eclipse.core.runtime.Platform;
6de2f761
PT
65import org.eclipse.core.runtime.Status;
66import org.eclipse.debug.core.DebugException;
67import org.eclipse.debug.core.DebugPlugin;
68import org.eclipse.debug.core.ILaunch;
69import org.eclipse.debug.core.ILaunchConfigurationType;
70import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
71import org.eclipse.debug.core.ILaunchesListener2;
72import org.eclipse.debug.internal.ui.viewers.model.provisional.ITreeModelViewer;
73import org.eclipse.debug.ui.AbstractDebugView;
74import org.eclipse.debug.ui.DebugUITools;
75import org.eclipse.debug.ui.IDebugUIConstants;
76import org.eclipse.debug.ui.contexts.DebugContextEvent;
77import org.eclipse.debug.ui.contexts.IDebugContextListener;
78import org.eclipse.jface.viewers.ISelection;
79import org.eclipse.jface.viewers.IStructuredSelection;
80import org.eclipse.jface.viewers.StructuredSelection;
81import org.eclipse.jface.viewers.Viewer;
6de2f761 82import org.eclipse.swt.widgets.Display;
04c0d7d3
AM
83import org.eclipse.tracecompass.internal.gdbtrace.core.GdbTraceCorePlugin;
84import org.eclipse.tracecompass.internal.gdbtrace.core.event.GdbTraceEvent;
85import org.eclipse.tracecompass.internal.gdbtrace.core.event.GdbTraceEventContent;
2bdf0193
AM
86import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
87import org.eclipse.tracecompass.tmf.core.event.TmfEventType;
88import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
89import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
5c5fa260 90import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
2bdf0193 91import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
6de2f761
PT
92import org.eclipse.ui.IEditorInput;
93import org.eclipse.ui.IEditorPart;
94import org.eclipse.ui.IEditorReference;
95import org.eclipse.ui.IFileEditorInput;
96import org.eclipse.ui.IViewPart;
97import org.eclipse.ui.IWorkbench;
98import org.eclipse.ui.IWorkbenchPage;
99import org.eclipse.ui.IWorkbenchWindow;
100import org.eclipse.ui.PlatformUI;
101import org.eclipse.ui.ide.IDE;
102
103/**
104 * Adaptor to access GDB Tracepoint frames, previously collected and saved in a
105 * file by GDB. One instance of this maps to a single DSF-GDB session.
106 * <p>
107 * This class offers the functions of starting a post-mortem GDB session with a
108 * tracepoint data file, navigate the data frames and return the data contained
109 * in a given tracepoint frame.
110 * <p>
111 * Note: GDB 7.2 or later is required to handle tracepoints
112 *
113 * @author Marc Dumais
114 * @author Francois Chouinard
115 */
116@SuppressWarnings("restriction")
117public class DsfGdbAdaptor {
118
396a504f 119 private static final Object SESSION_LOCK = new Object();
d88818e2
JCK
120 private static final String INTERRUPTION_EXCEPTION = "Interruption exception"; //$NON-NLS-1$
121 private static final String GDB_EXCEPTION = "GDB exception"; //$NON-NLS-1$
122 private static final String REQUEST_REJECTED_EXCEPTION = "Request rejected exception"; //$NON-NLS-1$
123 private static final String TIMEOUT = "Timeout"; //$NON-NLS-1$
396a504f 124
6de2f761
PT
125 private GdbTrace fGdbTrace;
126
127 private int fNumberOfFrames = 0;
e9a6e38e
MAL
128 private boolean fIsTimeoutEnabled;
129 private int fTimeout;
6de2f761
PT
130
131 private ILaunch fLaunch;
132 private boolean isTerminating;
133 private DsfSession fDsfSession = null;
134 private String fSessionId;
135
136 private String tracedExecutable = ""; //$NON-NLS-1$
137
138 private String gdb72Executable = ""; //$NON-NLS-1$
139 private String fTraceFilePath = ""; //$NON-NLS-1$
140 private String fTraceFile = ""; //$NON-NLS-1$
141 private String sourceLocator = ""; //$NON-NLS-1$
142
143 // To save tracepoints detailed info. The key is the rank of the
144 // breakpoint (tracepoint is a kind of breakpoint)
76faccfa 145 private Map<Integer, MIBreakpointDMData> fTpInfo = new HashMap<>();
6de2f761 146
e600c338 147 private TmfEventType tmfEventType = new TmfEventType("GDB Tracepoint", TmfEventField.makeRoot(new String[] { "Content" })); //$NON-NLS-1$ //$NON-NLS-2$
6de2f761 148
b82a2108
AM
149 {
150 new DsfGdbPlatformEventListener();
151 }
6de2f761
PT
152
153 /**
154 * <b><u>DsfGdbPlatformEventListener</u></b>
155 * <p>
156 * Listens to platform and DSF-GDB events that announce important events
157 * about the launchers or a change in debug context that we might need to
158 * react-to.
159 * <p>
160 * @author Francois Chouinard
161 */
e9a6e38e 162 private class DsfGdbPlatformEventListener implements
6de2f761
PT
163 ILaunchesListener2, IDebugContextListener {
164
165 /**
166 *
167 */
168 public DsfGdbPlatformEventListener() {
169 Display.getDefault().syncExec(new Runnable() {
170 @Override
171 public void run() {
172 DebugPlugin.getDefault().getLaunchManager().addLaunchListener(DsfGdbPlatformEventListener.this);
173 IWorkbench wb = PlatformUI.getWorkbench();
174 IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
175 DebugUITools.getDebugContextManager().getContextService(win).addDebugContextListener(DsfGdbPlatformEventListener.this);
176 }
177 });
178 }
179
180 @Override
181 public synchronized void launchesRemoved(ILaunch[] launches) {
182 }
183
184 @Override
185 public synchronized void launchesAdded(ILaunch[] launches) {
186 }
187
188 @Override
189 public synchronized void launchesChanged(ILaunch[] launches) {
190 }
191
192 @Override
193 public synchronized void launchesTerminated(ILaunch[] launches) {
194 for (ILaunch launch : launches) {
195 String sessionId = ((GdbLaunch) launch).getSession().getId();
196 closeGdbTraceEditor(sessionId);
197 }
198 }
199
200 private String fCurrentSessionId = ""; //$NON-NLS-1$
201 @Override
202 public void debugContextChanged(DebugContextEvent event) {
203 ISelection selection = event.getContext();
204 if (selection instanceof IStructuredSelection) {
205 List<?> eventContextList = ((IStructuredSelection) selection).toList();
206 for (Object eventContext : eventContextList) {
207 if (eventContext instanceof IAdaptable) {
34de057e
MAL
208 Object contextObject = ((IAdaptable) eventContext).getAdapter(IDMContext.class);
209 IDMContext context = (IDMContext) contextObject;
6de2f761
PT
210 if (context != null) {
211 String sessionId;
396a504f 212 synchronized(SESSION_LOCK) {
6de2f761
PT
213 sessionId = context.getSessionId();
214 if (sessionId.equals(fCurrentSessionId)) {
215 return;
216 }
396a504f 217 fCurrentSessionId = sessionId;
6de2f761 218 }
6de2f761
PT
219 // Get the current trace record
220 final DsfExecutor executor = DsfSession.getSession(sessionId).getExecutor();
221 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), sessionId);
222 Query<ITraceRecordDMContext> getCurrentRecordQuery = new Query<ITraceRecordDMContext>() {
223 @Override
224 public void execute(final DataRequestMonitor<ITraceRecordDMContext> queryRm) {
225 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
226 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
227 if (traceControl != null && commandControl != null) {
228 ITraceTargetDMContext traceContext = (ITraceTargetDMContext) commandControl.getContext();
d5efe032 229 traceControl.getCurrentTraceRecordContext(traceContext, queryRm);
6de2f761
PT
230 } else {
231 queryRm.done();
232 }
233 }
234 };
235 try {
236 executor.execute(getCurrentRecordQuery);
e9a6e38e
MAL
237 ITraceRecordDMContext record;
238 if (DsfGdbAdaptor.this.fIsTimeoutEnabled) {
239 record = getCurrentRecordQuery.get(fTimeout, TimeUnit.MILLISECONDS);
240 } else {
241 record = getCurrentRecordQuery.get();
242 }
6de2f761
PT
243 // If we get a trace record, it means that this can be used
244 if (record != null && record.getRecordId() != null) {
245 int recordId = Integer.parseInt(record.getRecordId());
246 selectGdbTraceEditor(sessionId, recordId);
247 break;
248 }
249 } catch (InterruptedException e) {
d88818e2 250 GdbTraceCorePlugin.logError(INTERRUPTION_EXCEPTION, e);
e9a6e38e 251 } catch (ExecutionException e) {
d88818e2 252 GdbTraceCorePlugin.logError(GDB_EXCEPTION, e);
6de2f761 253 } catch (RejectedExecutionException e) {
d88818e2 254 GdbTraceCorePlugin.logError(REQUEST_REJECTED_EXCEPTION, e);
e9a6e38e 255 } catch (TimeoutException e) {
d88818e2 256 GdbTraceCorePlugin.logError(TIMEOUT, e);
6de2f761
PT
257 } finally {
258 tracker.dispose();
259 }
260 // else not DSF-GDB or GDB < 7.2
261 }
262 }
263 // else not DSF
264 }
265 }
266 }
267 } // class DsfGdbPlatformEventListener
268
269 /**
270 * Constructor for DsfGdbAdaptor. This is used when we want to launch a
271 * DSF-GDB session and use it as source in our tracing perspective.
272 * i.e. when launching from the Project Explorer
273 *
274 * @param trace the GDB trace
275 * @param gdbExec GDB executable. Must be version 7.2 or later.
276 * @param traceFile previously generated GDB tracepoint file
277 * @param tracedExecutable executable that was used to generate the tracefile
278 * workspace, where the traced executable was taken from.
279 */
280 public DsfGdbAdaptor(GdbTrace trace, String gdbExec, String traceFile, String tracedExecutable) {
281 this.fGdbTrace = trace;
282 this.gdb72Executable = gdbExec;
283 this.fTraceFilePath = traceFile;
284 this.fTraceFile = traceFile.substring(traceFile.lastIndexOf(IPath.SEPARATOR) + 1);
285 this.tracedExecutable = tracedExecutable;
286
287 try {
288 launchDGBPostMortemTrace();
289 } catch (CoreException e) {
290 e.printStackTrace();
291 }
292 }
293
294 /**
295 * Builds a launcher and launches a Post-mortem GDB session, based on a
296 * previously-gathered GDB Tracepoint file. The information used to
297 * create the launcher is provided to the constructor of this class,
298 * at instantiation time.
299 * <p>
300 * Note: Requires GDB 7.2 or later
301 */
302 private void launchDGBPostMortemTrace() throws CoreException {
e9a6e38e
MAL
303 fIsTimeoutEnabled = Platform.getPreferencesService().getBoolean(GdbPlugin.PLUGIN_ID, IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, false, null);
304 if (fIsTimeoutEnabled) {
305 fTimeout = Platform.getPreferencesService().getInt(GdbPlugin.PLUGIN_ID, IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT, null);
306 }
6de2f761
PT
307
308 ILaunchConfigurationType configType = DebugPlugin
309 .getDefault()
310 .getLaunchManager()
311 .getLaunchConfigurationType("org.eclipse.cdt.launch.postmortemLaunchType"); //$NON-NLS-1$
312 ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, fTraceFile);
313
314 wc.setAttribute("org.eclipse.cdt.dsf.gdb.DEBUG_NAME", gdb72Executable); //$NON-NLS-1$
315 wc.setAttribute("org.eclipse.cdt.dsf.gdb.POST_MORTEM_TYPE", "TRACE_FILE"); //$NON-NLS-1$ //$NON-NLS-2$
316 wc.setAttribute("org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR", 0); //$NON-NLS-1$
317 wc.setAttribute("org.eclipse.cdt.launch.COREFILE_PATH", fTraceFilePath); //$NON-NLS-1$
318 wc.setAttribute("org.eclipse.cdt.launch.DEBUGGER_START_MODE", "core"); //$NON-NLS-1$ //$NON-NLS-2$
319 wc.setAttribute("org.eclipse.cdt.launch.PROGRAM_NAME", tracedExecutable); //$NON-NLS-1$
320 // So that the GDB launch is synchronous
321 wc.setAttribute("org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND", false); //$NON-NLS-1$
322
323 if (!sourceLocator.isEmpty()) {
324 wc.setAttribute("org.eclipse.debug.core.source_locator_memento", sourceLocator); //$NON-NLS-1$
325 }
326
327 // Launch GDB session
328 fLaunch = wc.doSave().launch("debug", null); //$NON-NLS-1$
329 isTerminating = false;
330
331 if (fLaunch instanceof GdbLaunch) {
332 fSessionId = ((GdbLaunch) fLaunch).getSession().getId();
333 }
334
335 fDsfSession = ((GdbLaunch) fLaunch).getSession();
336 fDsfSession.addServiceEventListener(this, null);
337
338 // Find the number of frames contained in the tracepoint file
339 fNumberOfFrames = findNumFrames();
340 }
341
342 /**
343 * This method terminates the current DSF-GDB session
344 */
345 public void dispose() {
346 if (fLaunch != null && fLaunch.canTerminate() && !isTerminating) {
347 isTerminating = true;
ce800780
BH
348 try {
349 fLaunch.terminate();
350 } catch (DebugException e) {
351 e.printStackTrace();
352 }
353 fLaunch = null;
6de2f761
PT
354 }
355 }
356
357 /**
358 * This method will try (once per call) to get the number of GDB tracepoint
359 * frames for the current session, from DSF-GDB, until it succeeds at
360 * getting an amount different than zero.
361 *
362 * @return The number of frames in current session or zero if unsuccessful
363 */
364 public int getNumberOfFrames() {
365 if (fNumberOfFrames == 0) {
366 fNumberOfFrames = findNumFrames();
367 }
368 return fNumberOfFrames;
369 }
370
371
372 /**
373 * Wrapper around the selecting of a frame and the reading of its
374 * information. this is a work-around for the potential problem of
375 * concurrent access to these functions by more than one thread,
376 * where two clients might interfere with each other.
377 * <p>
378 * Note: We also try to get the tracepoint info here, if it's not
379 * already filled-in.
380 *
381 * @param rank a long corresponding to the number of the frame to be
382 * selected and read
383 * @return A GdbTraceEvent object, or null in case of failure.
384 */
385 public synchronized GdbTraceEvent selectAndReadFrame(final long rank) {
386 // lazy init of tracepoints info
387 if(fTpInfo.isEmpty()) {
388 getTracepointInfo();
389 }
390 if (selectDataFrame(rank, false)) {
391 GdbTraceEvent event = getTraceFrameData(rank);
392 long ts = event.getTimestamp().getValue();
393 if (ts == rank) {
394 return event;
395 }
396 }
397 return null;
398 }
399
400
401 /**
402 * This class implements a best-effort look-up of the detailed tracepoint
403 * information (source code filename, line number, etc...).
404 */
405 private void getTracepointInfo() {
406
407 // Get the latest executor/service tracker
408 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
409 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
410
411 Query<Object> selectRecordQuery = new Query<Object>() {
412 @Override
413 public void execute(final DataRequestMonitor<Object> drm) {
414
415 // A breakpoint is no longer GDB-global but tied to a specific process
416 // So we need to find our process and the ask for its breakpoints
417 IMIProcesses procService = tracker.getService(IMIProcesses.class);
418 final ICommandControlService cmdControl = tracker.getService(ICommandControlService.class);
419 if (procService == null || cmdControl == null) {
420 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
421 drm.done();
422 return;
423 }
424
425 ITraceTargetDMContext context = (ITraceTargetDMContext) cmdControl.getContext();
426 ICommandControlDMContext cmdControlDMC = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
427
428 procService.getProcessesBeingDebugged(
429 cmdControlDMC,
430 new DataRequestMonitor<IDMContext[]>(executor, drm) {
431 @Override
432 protected void handleSuccess() {
433 assert getData() != null;
434 assert getData().length == 1;
435 if (getData() == null || getData().length < 1) {
436 drm.done();
437 return;
438 }
439
440 // Choose the first process for now, until gdb can tell
441 // us which process the trace record is associated with.
442 IContainerDMContext containerDMC = (IContainerDMContext)(getData()[0]);
443 IBreakpointsTargetDMContext bpTargetDMC = DMContexts.getAncestorOfType(containerDMC , IBreakpointsTargetDMContext.class);
444
445 CommandFactory cmdFactory = tracker.getService(IMICommandControl.class).getCommandFactory();
446 IBreakpoints bpService = tracker.getService(MIBreakpoints.class);
447 if (cmdFactory == null || bpService == null) {
448 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
449 drm.done();
450 return;
451 }
452
453 // Execute the command
454 cmdControl.queueCommand(cmdFactory.createMIBreakList(bpTargetDMC),
455 new DataRequestMonitor<MIBreakListInfo>(executor, drm) {
456 @Override
457 protected void handleSuccess() {
458 MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
459 for (int i = 0; i < breakpoints.length; i++) {
460 MIBreakpointDMData breakpoint = new MIBreakpointDMData(breakpoints[i]);
461 String type = breakpoint.getBreakpointType();
462 // Only save info if the current breakpoint is of type tracepoint
463 if(type.compareTo(MIBreakpoints.TRACEPOINT) == 0 ) {
ec6cb556 464 fTpInfo.put(Integer.valueOf(breakpoint.getReference()), breakpoint);
6de2f761
PT
465 }
466 }
467 drm.done();
468 }
469 });
470 }
471 });
472 }
473 };
474 try {
475 executor.execute(selectRecordQuery);
e9a6e38e
MAL
476 if (fIsTimeoutEnabled) {
477 selectRecordQuery.get(fTimeout, TimeUnit.MILLISECONDS); // blocks until time out
478 } else {
479 selectRecordQuery.get(); // blocks
480 }
6de2f761 481 } catch (InterruptedException e) {
d88818e2 482 GdbTraceCorePlugin.logError(INTERRUPTION_EXCEPTION, e);
6de2f761 483 } catch (ExecutionException e) {
d88818e2 484 GdbTraceCorePlugin.logError(GDB_EXCEPTION, e);
e9a6e38e 485 } catch (RejectedExecutionException e) {
d88818e2 486 GdbTraceCorePlugin.logError(REQUEST_REJECTED_EXCEPTION, e);
e9a6e38e 487 } catch (TimeoutException e) {
d88818e2 488 GdbTraceCorePlugin.logError(TIMEOUT, e);
6de2f761
PT
489 } finally {
490 tracker.dispose();
491 }
492 }
493
494 /**
495 * Returns the number of frames contained in currently loaded tracepoint GDB
496 * session.
497 * <p>
498 * Note: A postmortem GDB session must be started before calling
499 * this method
500 *
501 * @return the number of frames contained in currently loaded tracepoint GDB
502 * session or zero in case of error
503 */
504 private synchronized int findNumFrames() {
505 int frameNum = 0;
506
507 if (DsfSession.getSession(fSessionId) == null) {
508 return 0;
509 }
510
511 final DsfExecutor executor = DsfSession.getSession(fSessionId)
512 .getExecutor();
513 final DsfServicesTracker tracker = new DsfServicesTracker(
514 GdbTraceCorePlugin.getBundleContext(), fSessionId);
515
516 Query<ITraceStatusDMData> selectRecordQuery = new Query<ITraceStatusDMData>() {
517 @Override
518 public void execute(
519 final DataRequestMonitor<ITraceStatusDMData> queryRm) {
520 final IGDBTraceControl traceControl = tracker
521 .getService(IGDBTraceControl.class);
522
523 final ICommandControlService commandControl = tracker
524 .getService(ICommandControlService.class);
525 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl
526 .getContext();
527
528 if (traceControl != null) {
529 traceControl.getTraceStatus(dmc, queryRm);
530 } else {
531 queryRm.done();
532 }
533 }
534 };
535 try {
536 executor.execute(selectRecordQuery);
e9a6e38e
MAL
537 ITraceStatusDMData data;
538 if (fIsTimeoutEnabled) {
539 data = selectRecordQuery.get(fTimeout, TimeUnit.MILLISECONDS); // blocks until time out
540 } else {
541 data = selectRecordQuery.get(); // blocks
542 }
543
6de2f761
PT
544 frameNum = data.getNumberOfCollectedFrame();
545 } catch (InterruptedException e) {
d88818e2 546 GdbTraceCorePlugin.logError(INTERRUPTION_EXCEPTION, e);
e9a6e38e 547 } catch (ExecutionException e) {
d88818e2 548 GdbTraceCorePlugin.logError(GDB_EXCEPTION, e);
6de2f761 549 } catch (RejectedExecutionException e) {
d88818e2 550 GdbTraceCorePlugin.logError(REQUEST_REJECTED_EXCEPTION, e);
e9a6e38e 551 } catch (TimeoutException e) {
d88818e2 552 GdbTraceCorePlugin.logError(TIMEOUT, e);
6de2f761
PT
553 } finally {
554 tracker.dispose();
555 }
556 return frameNum;
557 }
558
559 /**
560 * This method uses the DSF-GDB interface to select a given frame number
561 * in the current GDB tracepoint session.
562 *
563 * @param rank the rank of the tracepoint frame to select.
564 * @param update true if visualization should be updated
565 * @return boolean true if select worked.
566 */
567 public boolean selectDataFrame(final long rank, final boolean update) {
568 boolean status = true;
569
570 final DsfSession dsfSession = DsfSession.getSession(fSessionId);
571 if (dsfSession == null) {
572 return false;
573 }
574
575 if (update) {
576 /*
577 * Clear the selection to ensure that the new selection is not
578 * prevented from overriding the current selection by the DSF
579 * selection policy. This could be removed when DSF provides
580 * an API to force the trace record selection in the Debug view.
581 */
582 Display.getDefault().syncExec(new Runnable() {
583 @Override
584 public void run() {
585 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
586 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
587 IViewPart vp = wbPage.findView(IDebugUIConstants.ID_DEBUG_VIEW);
588 if (vp instanceof AbstractDebugView) {
589 Viewer viewer = ((AbstractDebugView) vp).getViewer();
590 if (viewer instanceof ITreeModelViewer) {
591 ((ITreeModelViewer) viewer).setSelection(StructuredSelection.EMPTY, false, true);
592 }
593 }
594 }
595 }
596 }
597 });
598 }
599
600 final DsfExecutor executor = dsfSession.getExecutor();
601 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
602
603 Query<Object> selectRecordQuery = new Query<Object>() {
604 @Override
605 public void execute(final DataRequestMonitor<Object> queryRm) {
606 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
607
608 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
609 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
610
611 if (traceControl != null) {
612 ITraceRecordDMContext newCtx = traceControl.createTraceRecordContext(dmc, Integer.toString((int) rank));
613 if (update) {
614 dsfSession.dispatchEvent(new TraceRecordSelectedChangedEvent(newCtx), new Hashtable<String, String>());
615 }
616 traceControl.selectTraceRecord(newCtx, queryRm);
617 } else {
618 queryRm.done();
619 }
620 }
621 };
622 try {
623 executor.execute(selectRecordQuery);
e9a6e38e
MAL
624 if (fIsTimeoutEnabled) {
625 selectRecordQuery.get(fTimeout, TimeUnit.MILLISECONDS); // blocks until time out
626 } else {
627 selectRecordQuery.get(); // blocks
628 }
6de2f761
PT
629 } catch (InterruptedException e) {
630 status = false;
d88818e2 631 GdbTraceCorePlugin.logError(INTERRUPTION_EXCEPTION, e);
e9a6e38e 632 } catch (ExecutionException e) {
6de2f761 633 status = false;
d88818e2 634 GdbTraceCorePlugin.logError(GDB_EXCEPTION, e);
6de2f761
PT
635 } catch (RejectedExecutionException e) {
636 status = false;
d88818e2 637 GdbTraceCorePlugin.logError(REQUEST_REJECTED_EXCEPTION, e);
e9a6e38e
MAL
638 } catch (TimeoutException e) {
639 status = false;
d88818e2 640 GdbTraceCorePlugin.logError(TIMEOUT, e);
6de2f761
PT
641 } finally {
642 tracker.dispose();
643 }
644 return status;
645 }
646
647 /**
648 * This method uses DSF-GDB to read the currently selected GDB tracepoint
649 * data frame. An object of type GdbTraceEvent is build based on the
650 * information contained in the data frame and returned to the caller.
651 * <p>
652 * NOTE : A frame must be selected before calling this method!
653 *
654 * @param rank for internal purposes - does <b>not</b> control which
655 * frame will be read!
656 * @return parsed tp frame, in the form of a GdbTraceEvent
657 */
658 private GdbTraceEvent getTraceFrameData(final long rank) {
659
660 if (DsfSession.getSession(fSessionId) == null) {
661 return null;
662 }
663
664 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
665 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
666
667 Query<ITraceRecordDMData> getFrameDataQuery = new Query<ITraceRecordDMData>() {
668 @Override
669 public void execute(final DataRequestMonitor<ITraceRecordDMData> rm) {
670 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
671
672 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
673 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
674
675 if (traceControl != null) {
676 traceControl.getCurrentTraceRecordContext(dmc,
677 new DataRequestMonitor<ITraceRecordDMContext>(executor, rm) {
678 @Override
679 protected void handleSuccess() {
680 traceControl.getTraceRecordData(getData(), rm);
681 }
682 });
683 } else {
684 rm.done();
685 }
686 }
687 };
688 try {
689 // Execute the above query
690 executor.execute(getFrameDataQuery);
e9a6e38e
MAL
691 ITraceRecordDMData data;
692 if (fIsTimeoutEnabled) {
693 data = getFrameDataQuery.get(fTimeout, TimeUnit.MILLISECONDS); // blocking call until time out
694 } else {
695 data = getFrameDataQuery.get();
696 }
6de2f761
PT
697
698 if (data == null) {
699 return null;
700 }
701
702 String ts = data.getTimestamp();
703 if (ts == null) {
704 ts = "0"; //$NON-NLS-1$
705 }
706
707 // get corresponding TP data
708 String tmfEventRef;
709 MIBreakpointDMData bp = fTpInfo.get(Integer.valueOf(data.getTracepointNumber()));
710 if (bp != null) {
711 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
712 }
713 else {
714 tmfEventRef = tracedExecutable;
715 }
716
717 GdbTraceEventContent evContent = new GdbTraceEventContent(
718 data.getContent(),
719 Integer.parseInt(data.getTracepointNumber()),
720 Integer.parseInt(data.getRecordId()));
721
722 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
723 new TmfTimestamp(Integer.parseInt(data.getRecordId())),
724 "Tracepoint: " + data.getTracepointNumber() + ", Frame: " + data.getRecordId(), //$NON-NLS-1$ //$NON-NLS-2$
725 tmfEventType,
726 evContent,
727 tmfEventRef);
728
729 return ev;
730
731 } catch (InterruptedException e) {
d88818e2 732 return createExceptionEvent(rank, INTERRUPTION_EXCEPTION);
6de2f761 733 } catch (java.util.concurrent.ExecutionException e) {
d88818e2 734 return createExceptionEvent(rank, GDB_EXCEPTION);
6de2f761 735 } catch (RejectedExecutionException e) {
d88818e2 736 return createExceptionEvent(rank, REQUEST_REJECTED_EXCEPTION);
e9a6e38e 737 } catch (TimeoutException e) {
d88818e2 738 return createExceptionEvent(rank, TIMEOUT);
6de2f761
PT
739 }
740
741 finally {
742 tracker.dispose();
743 }
744 }
745
746 /**
747 * This is a helper method for getTraceFrameData, to create for it a
748 * "best effort" GdbTraceEvent when a problem occurs during the reading.
749 *
750 * @param rank long containing the number of the frame where the problem occurred
751 * @param message String containing a brief explanation of problem.
752 * @return a GdbTraceEvent object, filled as best as possible
753 */
754 private GdbTraceEvent createExceptionEvent(final long rank, final String message) {
755 // get corresponding TP data
756 String tmfEventRef;
757 String tmfEventSrc;
758 MIBreakpointDMData bp = fTpInfo.get(rank);
759 if (bp != null) {
760 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
761 tmfEventSrc = bp.getFileName() + " :: " + bp.getFunctionName() + ", line: " + bp.getLineNumber(); //$NON-NLS-1$ //$NON-NLS-2$
762 }
763 else {
764 tmfEventRef = tracedExecutable;
765 tmfEventSrc = "Tracepoint: n/a"; //$NON-NLS-1$
766 }
767
768 GdbTraceEventContent evContent = new GdbTraceEventContent("ERROR: " + message, 0, 0); //$NON-NLS-1$
769
770 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
771 new TmfTimestamp(rank),
772 tmfEventSrc,
773 tmfEventType,
774 evContent,
775 tmfEventRef);
776
777 return ev;
778 }
779
780 /**
781 * @return DSF-GDB session id of the current session.
782 */
783 public String getSessionId() {
784 return fSessionId;
785 }
786
787 /**
788 * Handler method that catches the DSF "record selected changed" event.
789 * It in turn creates a TMF "time sync" signal.
790 * @param event TraceRecordSelectedChangedEvent: The DSF event.
791 */
792 @DsfServiceEventHandler
793 public void handleDSFRecordSelectedEvents(final ITraceRecordSelectedChangedDMEvent event) {
794 if (event instanceof TraceRecordSelectedChangedEvent) {
795 TraceRecordSelectedChangedEvent traceEvent = (TraceRecordSelectedChangedEvent) event;
796 ITraceRecordDMContext context = traceEvent.getDMContext();
797 final String reference = context.getRecordId();
798 if (reference != null) {
799 int recordId = Integer.parseInt(reference);
800 selectGdbTraceEditor(context.getSessionId(), recordId);
801 }
802 }
803 }
804
805 private static void closeGdbTraceEditor(final String sessionId) {
806 Display.getDefault().asyncExec(new Runnable() {
807 @Override
808 public void run() {
809 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
810 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
811 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
812 IEditorPart editor = editorReference.getEditor(false);
813 if (editor instanceof ITmfTraceEditor) {
814 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
815 if (trace instanceof GdbTrace) {
816 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
817 wbPage.closeEditor(editor, false);
818 }
819 }
820 }
821 }
822 }
823 }
824 }
825 });
826 }
827
828 private static void selectGdbTraceEditor(final String sessionId, final int recordId) {
829 Display.getDefault().asyncExec(new Runnable() {
830 @Override
831 public void run() {
832 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
833 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
834 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
835 IEditorPart editor = editorReference.getEditor(false);
836 if (editor instanceof ITmfTraceEditor) {
837 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
838 if (trace instanceof GdbTrace) {
839 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
840 wbPage.bringToTop(editor);
841 if (recordId != -1) {
842 gotoRank(editor, recordId);
843 }
844 return;
845 }
846 } else if (trace instanceof TmfExperiment) {
847 TmfExperiment experiment = (TmfExperiment) trace;
fa62dc1d
BH
848 List<ITmfTrace> expTraces = experiment.getTraces();
849 int nbTraces = expTraces.size();
6de2f761 850 for (int i = 0; i < nbTraces; i++) {
fa62dc1d 851 GdbTrace gdbTrace = (GdbTrace) expTraces.get(i);
6de2f761
PT
852 if (gdbTrace.getDsfSessionId().equals(sessionId)) {
853 wbPage.bringToTop(editor);
854 if (recordId != -1) {
855 int rank = recordId * nbTraces + i;
856 gotoRank(editor, rank);
857 }
858 return;
859 }
860 }
861 }
862 }
863 }
864 }
865 }
866 }
867 });
868 }
869
870 private static void gotoRank(IEditorPart editor, int rank) {
871 IEditorInput editorInput = editor.getEditorInput();
872 if (editorInput instanceof IFileEditorInput) {
873 IFile file = ((IFileEditorInput) editorInput).getFile();
874 try {
875 final IMarker marker = file.createMarker(IMarker.MARKER);
876 marker.setAttribute(IMarker.LOCATION, (Integer) rank);
877 IDE.gotoMarker(editor, marker);
878 marker.delete();
879 } catch (CoreException e) {
880 e.printStackTrace();
881 }
882 }
883 }
c19380ab 884}
This page took 0.097915 seconds and 5 git commands to generate.