~ubuntu-branches/ubuntu/trusty/eclipse-linuxtools/trusty

« back to all changes in this revision

Viewing changes to valgrind/org.eclipse.linuxtools.valgrind.launch/src/org/eclipse/linuxtools/internal/valgrind/launch/ValgrindLaunchConfigurationDelegate.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2012-06-29 12:07:30 UTC
  • Revision ID: package-import@ubuntu.com-20120629120730-bfri1xys1i71dpn6
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2008, 2011 Red Hat, Inc. and others.
 
3
 * All rights reserved. This program and the accompanying materials
 
4
 * are made available under the terms of the Eclipse Public License v1.0
 
5
 * which accompanies this distribution, and is available at
 
6
 * http://www.eclipse.org/legal/epl-v10.html
 
7
 *
 
8
 * Contributors:
 
9
 *    Elliott Baron <ebaron@redhat.com> - initial API and implementation
 
10
 * Martin Oberhuber (Wind River) - [360085] Fix valgrind problem marker lifecycle
 
11
 *******************************************************************************/ 
 
12
package org.eclipse.linuxtools.internal.valgrind.launch;
 
13
 
 
14
import java.io.File;
 
15
import java.io.FileFilter;
 
16
import java.io.IOException;
 
17
import java.net.URI;
 
18
import java.util.ArrayList;
 
19
import java.util.Arrays;
 
20
import java.util.List;
 
21
import java.util.Stack;
 
22
 
 
23
import org.eclipse.cdt.debug.core.CDebugUtils;
 
24
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
 
25
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
 
26
import org.eclipse.core.filesystem.URIUtil;
 
27
import org.eclipse.core.resources.IFile;
 
28
import org.eclipse.core.resources.IMarker;
 
29
import org.eclipse.core.resources.IProject;
 
30
import org.eclipse.core.resources.IResource;
 
31
import org.eclipse.core.resources.IWorkspaceRoot;
 
32
import org.eclipse.core.resources.ResourcesPlugin;
 
33
import org.eclipse.core.runtime.CoreException;
 
34
import org.eclipse.core.runtime.IPath;
 
35
import org.eclipse.core.runtime.IProgressMonitor;
 
36
import org.eclipse.core.runtime.NullProgressMonitor;
 
37
import org.eclipse.core.runtime.Path;
 
38
import org.eclipse.core.runtime.SubMonitor;
 
39
import org.eclipse.debug.core.DebugPlugin;
 
40
import org.eclipse.debug.core.ILaunch;
 
41
import org.eclipse.debug.core.ILaunchConfiguration;
 
42
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
 
43
import org.eclipse.debug.core.model.IProcess;
 
44
import org.eclipse.debug.core.model.ISourceLocator;
 
45
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
 
46
import org.eclipse.debug.ui.DebugUITools;
 
47
import org.eclipse.debug.ui.sourcelookup.ISourceLookupResult;
 
48
import org.eclipse.linuxtools.internal.valgrind.core.CommandLineConstants;
 
49
import org.eclipse.linuxtools.internal.valgrind.core.LaunchConfigurationConstants;
 
50
import org.eclipse.linuxtools.internal.valgrind.core.ValgrindCommand;
 
51
import org.eclipse.linuxtools.internal.valgrind.core.ValgrindCoreParser;
 
52
import org.eclipse.linuxtools.internal.valgrind.core.ValgrindError;
 
53
import org.eclipse.linuxtools.internal.valgrind.core.ValgrindInfo;
 
54
import org.eclipse.linuxtools.internal.valgrind.core.ValgrindStackFrame;
 
55
import org.eclipse.linuxtools.internal.valgrind.ui.ValgrindUIPlugin;
 
56
import org.eclipse.linuxtools.internal.valgrind.ui.ValgrindViewPart;
 
57
import org.eclipse.linuxtools.valgrind.core.IValgrindMessage;
 
58
import org.eclipse.linuxtools.valgrind.launch.IValgrindLaunchDelegate;
 
59
import org.eclipse.linuxtools.valgrind.launch.IValgrindOutputDirectoryProvider;
 
60
import org.eclipse.osgi.util.NLS;
 
61
import org.osgi.framework.Version;
 
62
 
 
63
public class ValgrindLaunchConfigurationDelegate extends AbstractCLaunchDelegate {
 
64
 
 
65
        protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
 
66
        protected static final String NO = "no"; //$NON-NLS-1$
 
67
        protected static final String YES = "yes"; //$NON-NLS-1$
 
68
        protected static final String EQUALS = "="; //$NON-NLS-1$
 
69
 
 
70
        protected static final String LOG_FILE = CommandLineConstants.LOG_PREFIX + "%p.txt"; //$NON-NLS-1$
 
71
        protected static final FileFilter LOG_FILTER = new FileFilter() {
 
72
                public boolean accept(File pathname) {
 
73
                        return pathname.getName().startsWith(CommandLineConstants.LOG_PREFIX);
 
74
                }               
 
75
        };
 
76
 
 
77
        protected String toolID;
 
78
        protected ValgrindCommand command;
 
79
        protected IPath outputPath;
 
80
        protected IValgrindLaunchDelegate dynamicDelegate;
 
81
        protected ILaunchConfiguration config;
 
82
        protected ILaunch launch;
 
83
        protected IProcess process;
 
84
        protected String launchStr;
 
85
        protected Version valgrindVersion; // null if not used
 
86
 
 
87
        @Override
 
88
        public void launch(ILaunchConfiguration config, String mode,
 
89
                        ILaunch launch, IProgressMonitor m) throws CoreException {
 
90
                if (m == null) {
 
91
                        m = new NullProgressMonitor();
 
92
                }
 
93
 
 
94
                SubMonitor monitor = SubMonitor.convert(m, Messages.getString("ValgrindLaunchConfigurationDelegate.Profiling_Local_CCPP_Application"), 10); //$NON-NLS-1$
 
95
                // check for cancellation
 
96
                if (monitor.isCanceled()) {
 
97
                        return;
 
98
                }
 
99
 
 
100
                this.config = config;
 
101
                this.launch     = launch;
 
102
                try {
 
103
                        IProject project = CDebugUtils.verifyCProject(config).getProject();
 
104
                        command = getValgrindCommand();
 
105
 
 
106
                        // remove any output from previous run
 
107
                        ValgrindUIPlugin.getDefault().resetView();
 
108
                        // reset stored launch data
 
109
                        getPlugin().setCurrentLaunchConfiguration(null);
 
110
                        getPlugin().setCurrentLaunch(null);
 
111
 
 
112
                        String valgrindCommand= getValgrindCommand().getValgrindCommand();
 
113
                        // also ensure Valgrind version is usable
 
114
                        valgrindVersion = getPlugin().getValgrindVersion(project);
 
115
 
 
116
                        monitor.worked(1);
 
117
                        IPath exePath = CDebugUtils.verifyProgramPath(config);
 
118
                        String[] arguments = getProgramArgumentsArray(config);
 
119
                        File workDir = getWorkingDirectory(config);
 
120
                        if (workDir == null) {
 
121
                                workDir = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$
 
122
                        }
 
123
 
 
124
                        // set output directory in config
 
125
                        IValgrindOutputDirectoryProvider provider = getPlugin().getOutputDirectoryProvider();
 
126
                        setOutputPath(config, provider.getOutputPath());
 
127
                        outputPath = verifyOutputPath(config);
 
128
                        // create/empty output directory
 
129
                        createDirectory(outputPath);
 
130
 
 
131
                        // tool that was launched
 
132
                        toolID = getTool(config);
 
133
                        // ask tool extension for arguments
 
134
                        dynamicDelegate = getDynamicDelegate(toolID);
 
135
                        String[] opts = getValgrindArgumentsArray(config);
 
136
 
 
137
                        // set the default source locator if required
 
138
                        setDefaultSourceLocator(launch, config);
 
139
 
 
140
                        ArrayList<String> cmdLine = new ArrayList<String>(1 + arguments.length);
 
141
                        cmdLine.add(valgrindCommand);
 
142
                        cmdLine.addAll(Arrays.asList(opts));
 
143
                        cmdLine.add(exePath.toOSString());
 
144
                        cmdLine.addAll(Arrays.asList(arguments));
 
145
                        String[] commandArray = cmdLine.toArray(new String[cmdLine.size()]);
 
146
                        boolean usePty = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT);
 
147
                        monitor.worked(1);
 
148
                        
 
149
                        // check for cancellation
 
150
                        if (monitor.isCanceled()) {
 
151
                                return;
 
152
                        }
 
153
                        // call Valgrind
 
154
 
 
155
                        command.execute(commandArray, getEnvironment(config), workDir, valgrindCommand, usePty, project);
 
156
                        monitor.worked(3);
 
157
                        process = createNewProcess(launch, command.getProcess(), commandArray[0]);
 
158
                        // set the command line used
 
159
                        process.setAttribute(IProcess.ATTR_CMDLINE, command.getCommandLine());
 
160
                        while (!process.isTerminated()) {
 
161
                                Thread.sleep(100);
 
162
                        }
 
163
                        
 
164
                        // store these for use by other classes
 
165
                        getPlugin().setCurrentLaunchConfiguration(config);
 
166
                        getPlugin().setCurrentLaunch(launch);
 
167
 
 
168
                        // parse Valgrind logs
 
169
                        IValgrindMessage[] messages = parseLogs(outputPath);
 
170
 
 
171
                        // create launch summary string to distinguish this launch
 
172
                        launchStr = createLaunchStr();
 
173
 
 
174
                        // create view
 
175
                        ValgrindUIPlugin.getDefault().createView(launchStr, toolID);
 
176
                        // set log messages
 
177
                        ValgrindViewPart view = ValgrindUIPlugin.getDefault().getView();
 
178
                        view.setMessages(messages);
 
179
                        monitor.worked(1);
 
180
 
 
181
                        // pass off control to extender
 
182
                        dynamicDelegate.handleLaunch(config, launch, outputPath, monitor.newChild(2));
 
183
                        
 
184
                        // initialize tool-specific part of view
 
185
                        dynamicDelegate.initializeView(view.getDynamicView(), launchStr, monitor.newChild(1));
 
186
 
 
187
                        // refresh view
 
188
                        ValgrindUIPlugin.getDefault().refreshView();
 
189
 
 
190
                        // show view
 
191
                        ValgrindUIPlugin.getDefault().showView();
 
192
                        monitor.worked(1);                              
 
193
                } catch (IOException e) {
 
194
                        abort(Messages.getString("ValgrindLaunchConfigurationDelegate.Error_starting_process"), e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); //$NON-NLS-1$
 
195
                        e.printStackTrace();
 
196
                } catch (InterruptedException e) {
 
197
                        e.printStackTrace();
 
198
                } finally {
 
199
                        m.done();
 
200
                }
 
201
        }
 
202
 
 
203
        protected IValgrindMessage[] parseLogs(IPath outputPath) throws IOException, CoreException {
 
204
                List<IValgrindMessage> messages = new ArrayList<IValgrindMessage>();
 
205
                
 
206
                for (File log : outputPath.toFile().listFiles(LOG_FILTER)) {
 
207
                        ValgrindCoreParser parser = new ValgrindCoreParser(log, launch);
 
208
                        IValgrindMessage[] results = parser.getMessages();
 
209
                        
 
210
                        if (results.length == 0){
 
211
                                results = new IValgrindMessage[1];
 
212
                                results[0] = new ValgrindInfo(null, Messages.getString("ValgrindOutputView.No_output"), launch);
 
213
                        }
 
214
                        messages.addAll(Arrays.asList(results));
 
215
                        createMarkers(results);
 
216
                }
 
217
                
 
218
                return messages.toArray(new IValgrindMessage[messages.size()]);
 
219
        }
 
220
        
 
221
        protected void createMarkers(IValgrindMessage[] messages) throws CoreException {
 
222
                // find the topmost stack frame within the workspace to annotate with marker
 
223
                // traverse nested errors as well
 
224
                Stack<IValgrindMessage> messageStack = new Stack<IValgrindMessage>();
 
225
                messageStack.addAll(Arrays.asList(messages));
 
226
                while (!messageStack.isEmpty()) {
 
227
                        IValgrindMessage message = messageStack.pop();
 
228
                        IMarker marker = null;
 
229
                        IValgrindMessage[] children = message.getChildren();
 
230
                        for (int i = 0; i < children.length; i++) {
 
231
                                // if we've found our marker we don't care about any further frames in this stack
 
232
                                if (children[i] instanceof ValgrindStackFrame && marker == null) {
 
233
                                        ValgrindStackFrame frame = (ValgrindStackFrame) children[i];
 
234
                                        if (frame.getLine() > 0) {
 
235
                                                ISourceLocator locator = frame.getLaunch().getSourceLocator();                                  
 
236
                                                ISourceLookupResult result = DebugUITools.lookupSource(frame.getFile(), locator);
 
237
                                                Object sourceElement = result.getSourceElement();
 
238
                                                
 
239
                                                if (sourceElement != null) {
 
240
                                                        // Resolve IResource in case we get a LocalFileStorage object
 
241
                                                        if (sourceElement instanceof LocalFileStorage) {
 
242
                                                                IPath filePath = ((LocalFileStorage) sourceElement).getFullPath();
 
243
                                                                URI fileURI = URIUtil.toURI(filePath);
 
244
                                                                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
 
245
                                                                IFile[] files = root.findFilesForLocationURI(fileURI);
 
246
                                                                if (files.length > 0) {
 
247
                                                                        // Take the first match
 
248
                                                                        sourceElement = files[0];
 
249
                                                                }
 
250
                                                        }
 
251
 
 
252
                                                        if (sourceElement instanceof IResource) {
 
253
                                                                IResource resource = (IResource) sourceElement;
 
254
                                                                marker = resource.createMarker(ValgrindLaunchPlugin.MARKER_TYPE);
 
255
                                                                marker.setAttribute(IMarker.MESSAGE, message.getText());
 
256
                                                                marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
 
257
                                                                marker.setAttribute(IMarker.LINE_NUMBER, frame.getLine());
 
258
                                                        }
 
259
                                                }
 
260
                                        }
 
261
                                }
 
262
                                else if (children[i] instanceof ValgrindError) {
 
263
                                        // nested error
 
264
                                        messageStack.push(children[i]);
 
265
                                }
 
266
                        }
 
267
                }
 
268
        }
 
269
 
 
270
        protected IProcess createNewProcess(ILaunch launch, Process systemProcess, String programName) {
 
271
                return DebugPlugin.newProcess(launch, systemProcess, renderProcessLabel(programName));
 
272
        }
 
273
 
 
274
        protected ValgrindCommand getValgrindCommand() {
 
275
                return getPlugin().getValgrindCommand();
 
276
        }
 
277
 
 
278
        protected ValgrindLaunchPlugin getPlugin() {
 
279
                return ValgrindLaunchPlugin.getDefault();
 
280
        }
 
281
 
 
282
        protected IValgrindLaunchDelegate getDynamicDelegate(String toolID) throws CoreException {
 
283
                return getPlugin().getToolDelegate(toolID);
 
284
        }
 
285
 
 
286
        protected IPath verifyOutputPath(ILaunchConfiguration config) throws CoreException {
 
287
                IPath result = null;
 
288
                String strPath = config.getAttribute(LaunchConfigurationConstants.ATTR_INTERNAL_OUTPUT_DIR, (String) null);
 
289
                if (strPath != null) {
 
290
                        result = Path.fromPortableString(strPath);                      
 
291
                }
 
292
                if (result == null) {
 
293
                        abort(Messages.getString("ValgrindLaunchConfigurationDelegate.Retrieving_location_failed"), null, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); //$NON-NLS-1$
 
294
                }
 
295
                return result;
 
296
        }
 
297
 
 
298
        protected void setOutputPath(ILaunchConfiguration config, IPath outputPath) throws CoreException {
 
299
                ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
 
300
                wc.setAttribute(LaunchConfigurationConstants.ATTR_INTERNAL_OUTPUT_DIR, outputPath.toPortableString());
 
301
                wc.doSave();
 
302
        }
 
303
 
 
304
        protected void createDirectory(IPath path) throws IOException {
 
305
                File outputDir = path.toFile();
 
306
 
 
307
                if (outputDir.exists()) {
 
308
                        // delete any preexisting files
 
309
                        for (File outputFile : outputDir.listFiles()) {
 
310
                                if (outputFile.isFile() && !outputFile.delete()) {
 
311
                                        throw new IOException(NLS.bind(Messages.getString("ValgrindOutputDirectory.Couldnt_delete"), outputFile.getAbsolutePath())); //$NON-NLS-1$
 
312
                                }
 
313
                        }
 
314
                }
 
315
                else if (!outputDir.mkdir()) {
 
316
                        throw new IOException(NLS.bind(Messages.getString("ValgrindOutputDirectory.Couldnt_create"), outputDir.getAbsolutePath())); //$NON-NLS-1$
 
317
                }
 
318
        }
 
319
 
 
320
        protected String createLaunchStr() {
 
321
                return config.getName() + " [" + getPlugin().getToolName(toolID) + "] " + process.getLabel(); //$NON-NLS-1$ //$NON-NLS-2$
 
322
        }
 
323
 
 
324
        protected String[] getValgrindArgumentsArray(ILaunchConfiguration config) throws CoreException {
 
325
                ArrayList<String> opts = new ArrayList<String>();
 
326
                opts.add(CommandLineConstants.OPT_TOOL + EQUALS + getPlugin().getToolName(toolID));
 
327
                opts.add(CommandLineConstants.OPT_QUIET); // suppress uninteresting output
 
328
                opts.add(CommandLineConstants.OPT_LOGFILE + EQUALS + outputPath.append(LOG_FILE).toOSString());
 
329
 
 
330
                opts.add(CommandLineConstants.OPT_TRACECHILD + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_TRACECHILD, LaunchConfigurationConstants.DEFAULT_GENERAL_TRACECHILD) ? YES : NO));
 
331
                opts.add(CommandLineConstants.OPT_CHILDSILENT + EQUALS + YES); // necessary for parsing
 
332
                opts.add(CommandLineConstants.OPT_FREERES + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_FREERES, LaunchConfigurationConstants.DEFAULT_GENERAL_FREERES) ? YES : NO));
 
333
 
 
334
                opts.add(CommandLineConstants.OPT_DEMANGLE + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_DEMANGLE, LaunchConfigurationConstants.DEFAULT_GENERAL_DEMANGLE) ? YES : NO));
 
335
                opts.add(CommandLineConstants.OPT_NUMCALLERS + EQUALS + config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_NUMCALLERS, LaunchConfigurationConstants.DEFAULT_GENERAL_NUMCALLERS));
 
336
                opts.add(CommandLineConstants.OPT_ERRLIMIT + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_ERRLIMIT, LaunchConfigurationConstants.DEFAULT_GENERAL_ERRLIMIT) ? YES : NO));
 
337
                opts.add(CommandLineConstants.OPT_BELOWMAIN + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_BELOWMAIN, LaunchConfigurationConstants.DEFAULT_GENERAL_BELOWMAIN) ? YES : NO));
 
338
                opts.add(CommandLineConstants.OPT_MAXFRAME + EQUALS + config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_MAXFRAME, LaunchConfigurationConstants.DEFAULT_GENERAL_MAXFRAME));
 
339
 
 
340
                // 3.4.0 specific
 
341
                if (valgrindVersion == null || valgrindVersion.compareTo(ValgrindLaunchPlugin.VER_3_4_0) >= 0) {
 
342
                        boolean useMainStack = config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_MAINSTACK_BOOL, LaunchConfigurationConstants.DEFAULT_GENERAL_MAINSTACK_BOOL);
 
343
                        if (useMainStack) {
 
344
                                opts.add(CommandLineConstants.OPT_MAINSTACK + EQUALS + config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_MAINSTACK, LaunchConfigurationConstants.DEFAULT_GENERAL_MAINSTACK));
 
345
                        }
 
346
                }
 
347
                
 
348
                // 3.6.0 specific
 
349
                if (valgrindVersion == null || valgrindVersion.compareTo(ValgrindLaunchPlugin.VER_3_6_0) >= 0) {
 
350
                        if (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_DSYMUTIL, LaunchConfigurationConstants.DEFAULT_GENERAL_DSYMUTIL) != LaunchConfigurationConstants.DEFAULT_GENERAL_DSYMUTIL)
 
351
                                opts.add(CommandLineConstants.OPT_DSYMUTIL + EQUALS + (config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_DSYMUTIL, LaunchConfigurationConstants.DEFAULT_GENERAL_DSYMUTIL) ? YES : NO));
 
352
                }
 
353
                
 
354
                List<?> suppFiles = config.getAttribute(LaunchConfigurationConstants.ATTR_GENERAL_SUPPFILES, LaunchConfigurationConstants.DEFAULT_GENERAL_SUPPFILES); 
 
355
                for (Object strpath : suppFiles) {
 
356
                        IPath suppfile = getPlugin().parseWSPath((String) strpath);
 
357
                        if (suppfile != null) {
 
358
                                opts.add(CommandLineConstants.OPT_SUPPFILE + EQUALS + suppfile.toOSString());
 
359
                        }
 
360
                }
 
361
                opts.addAll(Arrays.asList(dynamicDelegate.getCommandArray(config, valgrindVersion, outputPath)));               
 
362
 
 
363
                String[] ret = new String[opts.size()];
 
364
                return opts.toArray(ret);
 
365
        }
 
366
 
 
367
        protected String getTool(ILaunchConfiguration config) throws CoreException {
 
368
                return config.getAttribute(LaunchConfigurationConstants.ATTR_TOOL, LaunchConfigurationConstants.DEFAULT_TOOL);
 
369
        }
 
370
 
 
371
        @Override
 
372
        protected String getPluginID() {
 
373
                return ValgrindLaunchPlugin.PLUGIN_ID;
 
374
        }
 
375
 
 
376
        @Override
 
377
        public boolean finalLaunchCheck(ILaunchConfiguration configuration,
 
378
                        String mode, IProgressMonitor monitor) throws CoreException {
 
379
                //Delete our own problem markers
 
380
                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
 
381
                root.deleteMarkers(ValgrindLaunchPlugin.MARKER_TYPE, true, IResource.DEPTH_INFINITE); //$NON-NLS-1$
 
382
                return super.finalLaunchCheck(configuration, mode, monitor);
 
383
        }
 
384
 
 
385
}