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 - Initial API and implementation
12 * Patrick Tasse - Updated for TMF 2.0
13 * Matthew Khouzam - update validate
14 *******************************************************************************/
16 package org
.eclipse
.tracecompass
.internal
.gdbtrace
.core
.trace
;
18 import java
.io
.BufferedInputStream
;
20 import java
.io
.FileInputStream
;
21 import java
.io
.IOException
;
22 import java
.util
.Arrays
;
24 import org
.eclipse
.cdt
.dsf
.gdb
.IGDBLaunchConfigurationConstants
;
25 import org
.eclipse
.cdt
.dsf
.gdb
.IGdbDebugPreferenceConstants
;
26 import org
.eclipse
.cdt
.dsf
.gdb
.internal
.GdbPlugin
;
27 import org
.eclipse
.core
.resources
.IProject
;
28 import org
.eclipse
.core
.resources
.IResource
;
29 import org
.eclipse
.core
.runtime
.CoreException
;
30 import org
.eclipse
.core
.runtime
.IStatus
;
31 import org
.eclipse
.core
.runtime
.Platform
;
32 import org
.eclipse
.core
.runtime
.QualifiedName
;
33 import org
.eclipse
.core
.runtime
.Status
;
34 import org
.eclipse
.osgi
.util
.NLS
;
35 import org
.eclipse
.tracecompass
.internal
.gdbtrace
.core
.Activator
;
36 import org
.eclipse
.tracecompass
.internal
.gdbtrace
.core
.GdbTraceCorePlugin
;
37 import org
.eclipse
.tracecompass
.internal
.gdbtrace
.core
.event
.GdbTraceEvent
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.ITmfEventAspect
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfEventParser
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfContext
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTrace
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TraceValidationStatus
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.TmfLongLocation
;
51 * GDB Tracepoint extension of TmfTrace. This class implements the necessary
52 * methods and functionalities so that a GDB tracepoint file can be used by the
53 * TMF framework as a "tracer".
57 * @author Francois Chouinard
58 * @author Matthew Khouzam
60 @SuppressWarnings("restriction")
61 public class GdbTrace
extends TmfTrace
implements ITmfEventParser
{
63 // ------------------------------------------------------------------------
65 // ------------------------------------------------------------------------
67 private static final int CACHE_SIZE
= 20;
69 private static final byte[] HEADER
= new byte[] {0x7f, 'T', 'R', 'A', 'C', 'E'};
71 /** The qualified name for the 'executable' persistent property */
72 public static final QualifiedName EXEC_KEY
= new QualifiedName(GdbTraceCorePlugin
.PLUGIN_ID
, "executable"); //$NON-NLS-1$
74 // ------------------------------------------------------------------------
76 // ------------------------------------------------------------------------
78 // Interface to access GDB Tracepoints
79 private DsfGdbAdaptor fGdbTpRef
;
80 private long fNbFrames
= 0;
85 // ------------------------------------------------------------------------
87 // ------------------------------------------------------------------------
93 setCacheSize(CACHE_SIZE
);
97 public IStatus
validate(IProject project
, String path
) {
98 File file
= new File(path
);
100 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
,
101 NLS
.bind(Messages
.GdbTrace_FileNotFound
, path
));
103 if (!file
.isFile()) {
104 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
,
105 NLS
.bind(Messages
.GdbTrace_GdbTracesMustBeAFile
, path
));
107 try (BufferedInputStream stream
= new BufferedInputStream(new FileInputStream(file
))) {
108 byte[] buffer
= new byte[HEADER
.length
];
109 int read
= stream
.read(buffer
);
110 if (read
!= HEADER
.length
|| !Arrays
.equals(buffer
, HEADER
)) {
111 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
,
112 NLS
.bind(Messages
.GdbTrace_NotGdbTraceFile
, path
));
114 } catch (IOException e
) {
115 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
,
116 NLS
.bind(Messages
.GdbTrace_IOException
, path
), e
);
118 return new TraceValidationStatus(100, GdbTraceCorePlugin
.PLUGIN_ID
);
122 public void initTrace(IResource resource
, String path
, Class
<?
extends ITmfEvent
> type
) throws TmfTraceException
{
124 String tracedExecutable
= resource
.getPersistentProperty(EXEC_KEY
);
125 if (tracedExecutable
== null) {
126 throw new TmfTraceException(Messages
.GdbTrace_ExecutableNotSet
);
129 String defaultGdbCommand
= Platform
.getPreferencesService().getString(GdbPlugin
.PLUGIN_ID
,
130 IGdbDebugPreferenceConstants
.PREF_DEFAULT_GDB_COMMAND
,
131 IGDBLaunchConfigurationConstants
.DEBUGGER_DEBUG_NAME_DEFAULT
, null);
133 fGdbTpRef
= new DsfGdbAdaptor(this, defaultGdbCommand
, path
, tracedExecutable
);
134 fNbFrames
= getNbFrames();
135 } catch (CoreException e
) {
136 throw new TmfTraceException(Messages
.GdbTrace_FailedToInitializeTrace
, e
);
139 super.initTrace(resource
, path
, type
);
143 public synchronized void dispose() {
144 if (fGdbTpRef
!= null) {
151 * @return GDB-DSF session id
153 public String
getDsfSessionId() {
154 return fGdbTpRef
.getSessionId();
158 * @return the number of frames in current tp session
160 public synchronized long getNbFrames() {
161 fNbFrames
= fGdbTpRef
.getNumberOfFrames();
165 // ------------------------------------------------------------------------
167 // ------------------------------------------------------------------------
170 public Iterable
<ITmfEventAspect
> getEventAspects() {
171 return GdbEventAspects
.getAspects();
175 public synchronized TmfContext
seekEvent(ITmfLocation location
) {
176 fLocation
= (location
!= null) ?
((Long
) location
.getLocationInfo()) : 0;
177 return new TmfContext(new TmfLongLocation(fLocation
), fLocation
);
181 public synchronized ITmfContext
seekEvent(double ratio
) {
182 TmfContext context
= seekEvent((long) ratio
* getNbEvents());
187 public double getLocationRatio(ITmfLocation location
) {
188 if (getNbEvents() > 0 && location
instanceof TmfLongLocation
) {
189 return (double) ((TmfLongLocation
) location
).getLocationInfo() / getNbEvents();
195 public ITmfLocation
getCurrentLocation() {
196 return new TmfLongLocation(fLocation
);
200 public GdbTraceEvent
parseEvent(ITmfContext context
) {
201 if (context
.getRank() >= fNbFrames
) {
204 // work-around to ensure that the select and parse of trace frame will
206 GdbTraceEvent event
= fGdbTpRef
.selectAndReadFrame(context
.getRank());
212 public synchronized TmfContext
seekEvent(ITmfTimestamp timestamp
) {
213 long rank
= timestamp
.getValue();
214 return seekEvent(rank
);
218 public synchronized TmfContext
seekEvent(long rank
) {
220 TmfContext context
= new TmfContext(new TmfLongLocation(fLocation
), rank
);
225 * Select a frame and update the visualization
230 public synchronized void selectFrame(long rank
) {
231 fGdbTpRef
.selectDataFrame(rank
, true);