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

« back to all changes in this revision

Viewing changes to gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/CovManager.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) 2009 STMicroelectronics.
 
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
 *    Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation
 
10
 *******************************************************************************/
 
11
package org.eclipse.linuxtools.internal.gcov.parser;
 
12
 
 
13
import java.io.BufferedInputStream;
 
14
import java.io.DataInput;
 
15
import java.io.DataInputStream;
 
16
import java.io.File;
 
17
import java.io.FileInputStream;
 
18
import java.io.FileNotFoundException;
 
19
import java.io.IOException;
 
20
import java.io.InputStream;
 
21
import java.io.InputStreamReader;
 
22
import java.io.LineNumberReader;
 
23
import java.io.PrintStream;
 
24
import java.io.Serializable;
 
25
import java.util.ArrayList;
 
26
import java.util.HashMap;
 
27
import java.util.LinkedList;
 
28
import java.util.List;
 
29
import java.util.Map;
 
30
 
 
31
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
 
32
import org.eclipse.core.resources.IProject;
 
33
import org.eclipse.core.runtime.CoreException;
 
34
import org.eclipse.core.runtime.IPath;
 
35
import org.eclipse.core.runtime.IStatus;
 
36
import org.eclipse.core.runtime.Path;
 
37
import org.eclipse.core.runtime.Status;
 
38
import org.eclipse.linuxtools.binutils.utils.STSymbolManager;
 
39
import org.eclipse.linuxtools.gcov.Activator;
 
40
import org.eclipse.linuxtools.internal.gcov.model.CovFileTreeElement;
 
41
import org.eclipse.linuxtools.internal.gcov.model.CovFolderTreeElement;
 
42
import org.eclipse.linuxtools.internal.gcov.model.CovFunctionTreeElement;
 
43
import org.eclipse.linuxtools.internal.gcov.model.CovRootTreeElement;
 
44
import org.eclipse.swt.SWT;
 
45
import org.eclipse.swt.widgets.FileDialog;
 
46
import org.eclipse.swt.widgets.Shell;
 
47
import org.eclipse.ui.PlatformUI;
 
48
 
 
49
/**
 
50
 * @author Xavier Raynaud <xavier.raynaud@st.com>
 
51
 *
 
52
 */
 
53
public class CovManager implements Serializable {
 
54
 
 
55
        /**
 
56
         * 
 
57
         */
 
58
        private static final long serialVersionUID = 5582066617970911413L;
 
59
        // input
 
60
        private final String binaryPath;
 
61
        // results
 
62
        private final ArrayList<Folder> allFolders = new ArrayList<Folder>();
 
63
        private final ArrayList<SourceFile> allSrcs = new ArrayList<SourceFile>();
 
64
        private final ArrayList<GcnoFunction> allFnctns = new ArrayList<GcnoFunction>();
 
65
        private final HashMap<String, SourceFile> sourceMap = new HashMap<String, SourceFile>();
 
66
        private long nbrPgmRuns = 0;
 
67
        // for view
 
68
        private CovRootTreeElement rootNode;
 
69
        private IProject project;
 
70
 
 
71
        /**
 
72
         * Constructor
 
73
         * @param binaryPath
 
74
         * @param project the project that will be used to get the path to run commands
 
75
         */
 
76
        public CovManager(String binaryPath, IProject project) {
 
77
                this.binaryPath = binaryPath;
 
78
                this.project = project;
 
79
        }
 
80
 
 
81
        /**
 
82
         * Constructor
 
83
         * @param binaryPath
 
84
         */
 
85
        public CovManager(String binaryPath) {
 
86
                this(binaryPath, null);
 
87
        }
 
88
 
 
89
        /**
 
90
         * parse coverage files, execute resolve graph algorithm, process counts for functions, 
 
91
         * lines and folders.    
 
92
         * @param List of coverage files paths
 
93
         * @throws CoreException, IOException, InterruptedException
 
94
         */
 
95
 
 
96
        public void processCovFiles(List<String> covFilesPaths, String initialGcda) throws CoreException, IOException, InterruptedException {
 
97
                GcdaRecordsParser daRcrd = null;
 
98
                DataInput traceFile;
 
99
                
 
100
                Map<File, File> sourcePath = new HashMap<File, File>();
 
101
                
 
102
                if (initialGcda != null) {
 
103
                        File initialGcdaFile = new File(initialGcda).getAbsoluteFile();
 
104
                        for (String s : covFilesPaths) {
 
105
                                File gcda = new File(s).getAbsoluteFile();
 
106
                                if (gcda.getName().equals(initialGcdaFile.getName()) && !gcda.equals(initialGcdaFile)) {
 
107
                                        if (!sourcePath.isEmpty()) {
 
108
                                                // hum... another file has the same name...
 
109
                                                // sorry, we have to clean sourcePath
 
110
                                                sourcePath.clear();
 
111
                                                break;
 
112
                                        } else {
 
113
                                                addSourceLookup(sourcePath, initialGcdaFile, gcda);
 
114
                                        }
 
115
                                }
 
116
                        }
 
117
                }
 
118
                
 
119
                
 
120
                
 
121
                for (String gcdaPath: covFilesPaths) {
 
122
                        String gcnoPath = gcdaPath.replace(".gcda", ".gcno");
 
123
                        // parse GCNO file
 
124
                        traceFile = OpenTraceFileStream(gcnoPath, ".gcno", sourcePath);
 
125
                        if (traceFile == null) return;
 
126
                        GcnoRecordsParser noRcrd = new GcnoRecordsParser(sourceMap, allSrcs);
 
127
                        noRcrd.parseData(traceFile);
 
128
 
 
129
                        // add new functions parsed to AllSrcs array
 
130
                        for (GcnoFunction f: noRcrd.getFnctns()) {
 
131
                                allFnctns.add(f);
 
132
                        }
 
133
 
 
134
                        //close the input stream
 
135
                        if(traceFile.getClass() == DataInputStream.class)
 
136
                                ((DataInputStream)traceFile).close();
 
137
 
 
138
                        // parse GCDA file
 
139
                        traceFile = OpenTraceFileStream(gcdaPath, ".gcda", sourcePath);
 
140
                        if (traceFile == null) return;
 
141
                        if (noRcrd.getFnctns().isEmpty()){
 
142
                                String message = gcnoPath + " doesn't contain any function:\n";
 
143
                                Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
 
144
                                throw new CoreException(status);
 
145
                        }
 
146
                        daRcrd = new GcdaRecordsParser(noRcrd.getFnctns());
 
147
                        daRcrd.parseGcdaRecord(traceFile);
 
148
 
 
149
                        //close the input stream
 
150
                        if(traceFile.getClass() == DataInputStream.class)
 
151
                                ((DataInputStream)traceFile).close();
 
152
                }
 
153
 
 
154
                // to fill the view title
 
155
                if (daRcrd != null)
 
156
                        nbrPgmRuns = daRcrd.getObjSmryNbrPgmRuns();
 
157
                /* process counts from data parsed */
 
158
 
 
159
                // solve graph for each function
 
160
                for (GcnoFunction gf : allFnctns) {
 
161
                        gf.solveGraphFnctn();
 
162
                }
 
163
 
 
164
                // allocate lines
 
165
                for (SourceFile sourceFile: allSrcs) {
 
166
                        sourceFile.createLines();
 
167
                }
 
168
 
 
169
                // add line counts
 
170
                for (GcnoFunction gf : allFnctns) {
 
171
                        gf.addLineCounts(allSrcs);
 
172
                }
 
173
 
 
174
                // accumulate lines
 
175
                for (SourceFile sf: allSrcs) {
 
176
                        sf.accumulateLineCounts();
 
177
                }
 
178
 
 
179
                /* compute counts by folder*/
 
180
 
 
181
                // make the folders list
 
182
                for (SourceFile sf : allSrcs) {
 
183
                        File srcFile = new File (sf.getName());
 
184
                        String folderName = srcFile.getParent();
 
185
                        if (folderName == null) folderName = "?";
 
186
                        Folder folder = null;
 
187
                        for (Folder f: allFolders) {
 
188
                                if (f.getPath().equals(folderName))
 
189
                                        folder = f;
 
190
                        }
 
191
                        if (folder == null){
 
192
                                folder = new Folder(folderName);
 
193
                                allFolders.add(folder);
 
194
                        }
 
195
                        folder.addSrcFiles(sf);
 
196
                }
 
197
 
 
198
                // assign sourcesList for each folder
 
199
                for (Folder f : allFolders) {
 
200
                        f.accumulateSourcesCounts();
 
201
                }       
 
202
        }
 
203
 
 
204
 
 
205
        /**
 
206
         * fill the model by count results
 
207
         * @throws CoreException, IOException, InterruptedException
 
208
         */
 
209
 
 
210
        public void fillGcovView() {
 
211
                // process counts for summary level
 
212
                int summaryTotal = 0, summaryInstrumented = 0, summaryExecuted = 0;
 
213
                for (Folder f : allFolders) {
 
214
                        summaryTotal+=f.getNumLines();
 
215
                        summaryInstrumented+=f.getLinesInstrumented();
 
216
                        summaryExecuted+=f.getLinesExecuted();
 
217
                }               
 
218
 
 
219
                // fill rootNode model: the entry of the contentProvider
 
220
                rootNode = new CovRootTreeElement("Summary", summaryTotal,summaryExecuted,
 
221
                                summaryInstrumented);
 
222
                IBinaryObject binaryObject = STSymbolManager.sharedInstance.getBinaryObject(new Path(binaryPath));
 
223
                
 
224
                for (Folder fldr : allFolders) {
 
225
                        String folderLocation = fldr.getPath();
 
226
                        CovFolderTreeElement fldrTreeElem = new CovFolderTreeElement(
 
227
                                        rootNode, folderLocation, fldr.getNumLines(), fldr.getLinesExecuted(), 
 
228
                                        fldr.getLinesInstrumented());
 
229
                        rootNode.addChild(fldrTreeElem);
 
230
 
 
231
                        for (SourceFile src : fldr.getSrcFiles()) {
 
232
                                CovFileTreeElement srcTreeElem = new CovFileTreeElement(
 
233
                                                fldrTreeElem, src.getName(), src.getNumLines(), src
 
234
                                                .getLinesExecuted(), src.getLinesInstrumented());
 
235
                                fldrTreeElem.addChild(srcTreeElem);
 
236
 
 
237
                                for (GcnoFunction fnctn : src.getFnctns()) {
 
238
                                        String name = fnctn.getName();
 
239
                                        name = STSymbolManager.sharedInstance.demangle(binaryObject, name, project);;
 
240
                                        srcTreeElem.addChild(new CovFunctionTreeElement(
 
241
                                                        srcTreeElem, name, fnctn.getSrcFile(), fnctn
 
242
                                                        .getFirstLineNmbr(), fnctn.getCvrge()
 
243
                                                        .getLinesExecuted(), fnctn.getCvrge()
 
244
                                                        .getLinesInstrumented()));
 
245
                                }
 
246
                        }
 
247
                }
 
248
        }
 
249
 
 
250
        // transform String path to stream
 
251
        private DataInput OpenTraceFileStream(String filePath, String extension, Map<File, File> sourcePath) throws FileNotFoundException{
 
252
                File f = new File(filePath).getAbsoluteFile();
 
253
                String filename = f.getName();
 
254
                if (f.isFile() && f.canRead()) {
 
255
                        FileInputStream fis = new FileInputStream(f);
 
256
                        InputStream inputStream = new BufferedInputStream(fis);
 
257
                        return new DataInputStream(inputStream);
 
258
                } else {
 
259
                        String postfix = "";
 
260
                        File dir = null;
 
261
                        do {
 
262
                                if ("".equals(postfix)) postfix = f.getName();
 
263
                                else postfix = f.getName() + File.separator + postfix;
 
264
                                f = f.getParentFile();
 
265
                                if (f != null) {
 
266
                                        dir = sourcePath.get(f);
 
267
                                } else break;
 
268
                        } while (dir == null);
 
269
                        
 
270
                        if (dir != null) {
 
271
                                f = new File(dir, postfix);
 
272
                                if (f.isFile() && f.canRead()) {
 
273
                                        return OpenTraceFileStream(f.getAbsolutePath(), extension, sourcePath);
 
274
                                }
 
275
                        }
 
276
                        
 
277
 
 
278
                        Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
 
279
                        FileDialog fg = new FileDialog(shell, SWT.OPEN);
 
280
                        fg.setFilterExtensions(new String[] {"*" + extension, "*.*", "*"});
 
281
                        fg.setFileName(filename);
 
282
                        fg.setText(filePath + " not found. Please enter location of " + filename);
 
283
                        String s = fg.open();
 
284
                        if (s == null) return null;
 
285
                        else {
 
286
                                f = new File(s).getAbsoluteFile();
 
287
                                addSourceLookup(sourcePath, f, new File(filePath).getAbsoluteFile());
 
288
                                if (f.isFile() && f.canRead()) {
 
289
                                        FileInputStream fis = new FileInputStream(f);
 
290
                                        InputStream inputStream = new BufferedInputStream(fis);
 
291
                                        return new DataInputStream(inputStream);
 
292
                                }
 
293
                        }
 
294
                }
 
295
                return null;
 
296
        }
 
297
 
 
298
 
 
299
        public ArrayList<SourceFile> getAllSrcs() {
 
300
                return allSrcs;
 
301
        }
 
302
 
 
303
        public ArrayList<GcnoFunction> getAllFnctns() {
 
304
                return allFnctns;
 
305
        }
 
306
 
 
307
        public CovRootTreeElement getRootNode() {
 
308
                return rootNode;
 
309
        }
 
310
 
 
311
        public String getBinaryPath() {
 
312
                return binaryPath;
 
313
        }
 
314
 
 
315
        public SourceFile getSourceFile(String sourcePath){
 
316
                return sourceMap.get(sourcePath);
 
317
        }
 
318
 
 
319
        public long getNbrPgmRuns() {
 
320
                return nbrPgmRuns;
 
321
        }
 
322
 
 
323
        /**
 
324
         * Retrieve a list containing gcda paths from a binary file  
 
325
         * @return
 
326
         * @throws CoreException
 
327
         * @throws IOException
 
328
         * @throws InterruptedException
 
329
         */
 
330
        public List<String> getGCDALocations() throws CoreException, IOException, InterruptedException
 
331
        {       
 
332
                IBinaryObject binaryObject = STSymbolManager.sharedInstance.getBinaryObject(new Path(binaryPath));
 
333
                String binaryPath = binaryObject.getPath().toOSString();
 
334
                List<String> l = new LinkedList<String>();
 
335
                String cpu = binaryObject.getCPU();
 
336
                Process p;
 
337
                if ("sh".equals(cpu)) {
 
338
                        String stringsTool = "sh4strings"; 
 
339
                        p = getStringsProcess(stringsTool, binaryPath);
 
340
                        if ( p == null) p = getStringsProcess("sh4-linux-strings", binaryPath);
 
341
                } else if ("stxp70".equals(cpu)) {
 
342
                        String stringsTool = "stxp70v3-strings"; 
 
343
                        p = getStringsProcess(stringsTool, binaryPath);
 
344
                } else if ("st200".equals(cpu)){
 
345
                        String stringsTool = cpu + "strings";
 
346
                        p = getStringsProcess(stringsTool, binaryPath);
 
347
                } else  {
 
348
                        String stringsTool = "strings";
 
349
                        p = getStringsProcess(stringsTool, binaryPath);
 
350
                }
 
351
                if (p == null) {
 
352
                        Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR,
 
353
                                        "An error occured during analysis: unable to retrieve gcov data", new IOException());
 
354
                        Activator.getDefault().getLog().log(status);
 
355
                        return l;
 
356
                }
 
357
                ThreadConsumer t = new ThreadConsumer(p, l);
 
358
                t.start();
 
359
                p.waitFor();
 
360
                t.join();
 
361
                return l;
 
362
        }
 
363
        
 
364
        
 
365
        private Process getStringsProcess(String stringsTool, String binaryPath) {
 
366
                try {
 
367
                        Process p = Runtime.getRuntime().exec(new String[] {stringsTool, binaryPath });
 
368
                        return p;
 
369
                } catch (Exception _) {
 
370
                        return null;
 
371
                }
 
372
        }
 
373
        
 
374
        
 
375
 
 
376
        private static final class ThreadConsumer extends Thread
 
377
        {
 
378
                private final Process p;
 
379
                private final List<String> list;
 
380
                ThreadConsumer(Process p, List<String> files)
 
381
                {
 
382
                        super();
 
383
                        this.p = p;
 
384
                        this.list = files;
 
385
                }
 
386
 
 
387
                public void run()
 
388
                {
 
389
                        try {
 
390
                                populateGCDAFiles(p.getInputStream());
 
391
                        } catch (Exception _) {
 
392
                        }
 
393
                }
 
394
 
 
395
                private void populateGCDAFiles(InputStream s) throws IOException
 
396
                {
 
397
                        InputStreamReader isr = new InputStreamReader(s);
 
398
                        LineNumberReader lnr = new LineNumberReader(isr);
 
399
                        String line = null;
 
400
                        while ((line =lnr.readLine()) != null) {
 
401
                                if (line.endsWith(".gcda"))
 
402
                                {
 
403
                                        // absolute .gcda filepaths retrieved using the "strings" tool may
 
404
                                        // be prefixed by random printable characters so strip leading
 
405
                                        // characters until the filepath starts with "X:/", "X:\", "/"  or "\"
 
406
                                        // FIXME: need a more robust mechanism to locate .gcda files [Bugzilla 329710]
 
407
                                        while ((line.length() > 6) && !line.matches("^([A-Za-z]:)?[/\\\\].*")) {
 
408
                                                line = line.substring(1);
 
409
                                        }
 
410
                                        IPath p = new Path(line);
 
411
                                        String filename = p.toString();
 
412
                                        
 
413
                                        
 
414
                                        if (!list.contains(filename)) list.add(filename);
 
415
                                }
 
416
                        }
 
417
                }
 
418
        }
 
419
 
 
420
        public void dumpProcessCovFilesResult(PrintStream ps) throws FileNotFoundException {
 
421
                ps.println("Parse gcda and gcno files done, resolve graph algorithm executed, now display results");
 
422
                ps.println("- PRINT FUNCTIONS ARRAY : ");
 
423
                for (int i = 0; i < allFnctns.size(); i++) {
 
424
                        ps.println("-- FUNCTION " +i);
 
425
                        ps.println("     name = " + allFnctns.get(i).getName());
 
426
                        ps.println("     instrumentd lines = " + allFnctns.get(i).getCvrge().getLinesInstrumented());
 
427
                        ps.println("     executed lines = "+ allFnctns.get(i).getCvrge().getLinesExecuted());
 
428
                }               
 
429
                ps.println("- PRINT SRCS ARRAY : ");
 
430
                for (int i = 0; i < allSrcs.size(); i++) {
 
431
                        ps.println("-- FILE " + i);
 
432
                        ps.println("     name = " + allSrcs.get(i).getName());
 
433
                        ps.println("     total lines = " + allSrcs.get(i).getNumLines());
 
434
                        ps.println("     instrumentd lines = "+ allSrcs.get(i).getLinesInstrumented());
 
435
                        ps.println("     executed lines = "+ allSrcs.get(i).getLinesExecuted());
 
436
                }
 
437
        }
 
438
 
 
439
 
 
440
        /**
 
441
         * @return the sourceMap
 
442
         */
 
443
        public HashMap<String, SourceFile> getSourceMap() {
 
444
                return sourceMap;
 
445
        }
 
446
        
 
447
 
 
448
        private void addSourceLookup(Map<File, File> map, File hostPath, File compilerPath) {
 
449
                while (hostPath.getName().equals(compilerPath.getName())) {
 
450
                        hostPath = hostPath.getParentFile();
 
451
                        compilerPath = compilerPath.getParentFile();
 
452
                }
 
453
                map.put(compilerPath, hostPath);
 
454
        }
 
455
        
 
456
}