source: rtems-tools/tester/covoar/ReportsBase.cc @ f381f26

4.104.11
Last change on this file since f381f26 was f381f26, checked in by Chris Johns <chrisj@…>, on Jan 19, 2015 at 9:56:14 PM

Fix covoar so it builds for Windows.

  • Property mode set to 100644
File size: 14.4 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <errno.h>
4#include <sys/stat.h>
5#include <sys/types.h>
6
7#include "ReportsBase.h"
8#include "app_common.h"
9#include "CoverageRanges.h"
10#include "DesiredSymbols.h"
11#include "Explanations.h"
12#include "ObjdumpProcessor.h"
13
14#include "ReportsText.h"
15#include "ReportsHtml.h"
16
17#if WIN32
18#include <io.h>
19#endif
20
21namespace Coverage {
22
23ReportsBase::ReportsBase( time_t timestamp ):
24  reportExtension_m(""),
25  timestamp_m( timestamp )
26{
27}
28
29ReportsBase::~ReportsBase()
30{
31}
32
33FILE* ReportsBase::OpenFile(
34  const char* const fileName
35)
36{
37  int          sc;
38  FILE        *aFile;
39  std::string  file;
40
41  // Create the output directory if it does not already exist
42#if WIN32
43  sc = _mkdir( outputDirectory );
44#else
45  sc = mkdir( outputDirectory,0755 );
46#endif
47  if ( (sc == -1) && (errno != EEXIST) ) {
48    fprintf(stderr, "Unable to create output directory %s\n", outputDirectory);
49    return NULL;
50  }
51
52  file = outputDirectory;
53  file += "/";
54  file += fileName;
55
56  // Open the file.
57  aFile = fopen( file.c_str(), "w" );
58  if ( !aFile ) {
59    fprintf( stderr, "Unable to open %s\n", file.c_str() );
60  }
61  return aFile;
62}
63
64void ReportsBase::WriteIndex(
65  const char* const fileName
66)
67{
68}
69
70FILE* ReportsBase::OpenAnnotatedFile(
71  const char* const fileName
72)
73{
74  return OpenFile(fileName);
75}
76
77FILE* ReportsBase::OpenBranchFile(
78  const char* const fileName,
79  bool              hasBranches
80)
81{
82  return OpenFile(fileName);
83}
84
85FILE* ReportsBase::OpenCoverageFile(
86  const char* const fileName
87)
88{
89  return OpenFile(fileName);
90}
91
92FILE* ReportsBase::OpenNoRangeFile(
93  const char* const fileName
94)
95{
96  return OpenFile(fileName);
97}
98
99
100FILE* ReportsBase::OpenSizeFile(
101  const char* const fileName
102)
103{
104  return OpenFile(fileName);
105}
106
107FILE* ReportsBase::OpenSymbolSummaryFile(
108  const char* const fileName
109)
110{
111  return OpenFile(fileName);
112}
113
114void ReportsBase::CloseFile(
115  FILE*  aFile
116)
117{
118  fclose( aFile );
119}
120
121void ReportsBase::CloseAnnotatedFile(
122  FILE*  aFile
123)
124{
125  CloseFile( aFile );
126}
127
128void ReportsBase::CloseBranchFile(
129  FILE*  aFile,
130  bool   hasBranches
131)
132{
133  CloseFile( aFile );
134}
135
136void  ReportsBase::CloseCoverageFile(
137  FILE*  aFile
138)
139{
140  CloseFile( aFile );
141}
142
143void  ReportsBase::CloseNoRangeFile(
144  FILE*  aFile
145)
146{
147  CloseFile( aFile );
148}
149
150void  ReportsBase::CloseSizeFile(
151  FILE*  aFile
152)
153{
154  CloseFile( aFile );
155}
156
157void  ReportsBase::CloseSymbolSummaryFile(
158  FILE*  aFile
159)
160{
161  CloseFile( aFile );
162}
163
164/*
165 *  Write annotated report
166 */
167void ReportsBase::WriteAnnotatedReport(
168  const char* const fileName
169) {
170  FILE*                                                          aFile = NULL;
171  Coverage::DesiredSymbols::symbolSet_t::iterator                ditr;
172  Coverage::CoverageRanges*                                      theBranches;
173  Coverage::CoverageRanges*                                      theRanges;
174  Coverage::CoverageMapBase*                                     theCoverageMap = NULL;
175  uint32_t                                                       bAddress = 0;
176  AnnotatedLineState_t                                           state;
177  std::list<Coverage::ObjdumpProcessor::objdumpLine_t>*          theInstructions;
178  std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator itr;
179
180  aFile = OpenAnnotatedFile(fileName);
181  if (!aFile)
182    return;
183
184  // Process uncovered branches for each symbol.
185  for (ditr = SymbolsToAnalyze->set.begin();
186       ditr != SymbolsToAnalyze->set.end();
187       ditr++) {
188
189    // If uncoveredRanges and uncoveredBranches don't exist, then the
190    // symbol was never referenced by any executable.  Just skip it.
191    if ((ditr->second.uncoveredRanges == NULL) &&
192        (ditr->second.uncoveredBranches == NULL))
193      continue;
194
195    // If uncoveredRanges and uncoveredBranches are empty, then everything
196    // must have been covered for this symbol.  Just skip it.
197    if ((ditr->second.uncoveredRanges->set.empty()) &&
198        (ditr->second.uncoveredBranches->set.empty()))
199      continue;
200
201    theCoverageMap = ditr->second.unifiedCoverageMap;
202    bAddress = ditr->second.baseAddress;
203    theInstructions = &(ditr->second.instructions);
204    theRanges = ditr->second.uncoveredRanges;
205    theBranches = ditr->second.uncoveredBranches;
206
207    // Add annotations to each line where necessary
208    AnnotatedStart( aFile );
209    for (itr = theInstructions->begin();
210         itr != theInstructions->end();
211         itr++ ) {
212
213      uint32_t     id = 0;
214      std::string  annotation = "";
215      std::string  line;
216      char         textLine[150];
217
218      state = A_SOURCE;
219
220      if ( itr->isInstruction ) {
221        if (!theCoverageMap->wasExecuted( itr->address - bAddress )){
222          annotation = "<== NOT EXECUTED";
223          state = A_NEVER_EXECUTED;
224          id = theRanges->getId( itr->address );
225        } else if (theCoverageMap->isBranch( itr->address - bAddress )) {
226          id = theBranches->getId( itr->address );
227          if (theCoverageMap->wasAlwaysTaken( itr->address - bAddress )){
228            annotation = "<== ALWAYS TAKEN";
229            state = A_BRANCH_TAKEN;
230          } else if (theCoverageMap->wasNeverTaken( itr->address - bAddress )){
231            annotation = "<== NEVER TAKEN";
232            state = A_BRANCH_NOT_TAKEN;
233          }
234        } else {
235          state = A_EXECUTED;
236        }
237      }
238
239      sprintf( textLine, "%-70s", itr->line.c_str() );
240      line = textLine + annotation;
241
242      PutAnnotatedLine( aFile, state, line, id);
243    }
244
245    AnnotatedEnd( aFile );
246  }
247
248  CloseAnnotatedFile( aFile );
249}
250
251/*
252 *  Write branch report
253 */
254void ReportsBase::WriteBranchReport(
255  const char* const fileName
256) {
257  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
258  FILE*                                           report = NULL;
259  Coverage::CoverageRanges::ranges_t::iterator    ritr;
260  Coverage::CoverageRanges*                       theBranches;
261  unsigned int                                    count;
262  bool                                            hasBranches = true;
263
264  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
265      (BranchInfoAvailable == false) )
266     hasBranches = false;
267
268  // Open the branch report file
269  report = OpenBranchFile( fileName, hasBranches );
270  if (!report)
271    return;
272
273  // If no branches were found of branch coverage is not supported
274  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
275      (BranchInfoAvailable == false) ) {
276
277    PutNoBranchInfo(report);
278
279    // If branches were found, ...
280  } else {
281
282    // Process uncovered branches for each symbol.
283    count = 0;
284    for (ditr = SymbolsToAnalyze->set.begin();
285         ditr != SymbolsToAnalyze->set.end();
286         ditr++) {
287
288      theBranches = ditr->second.uncoveredBranches;
289
290      if (theBranches && !theBranches->set.empty()) {
291
292        for (ritr =  theBranches->set.begin() ;
293             ritr != theBranches->set.end() ;
294             ritr++ ) {
295          count++;
296          PutBranchEntry( report, count, ditr, ritr );
297        }
298      }
299    }
300  }
301
302  CloseBranchFile( report, hasBranches );
303}
304
305/*
306 *  Write coverage report
307 */
308void ReportsBase::WriteCoverageReport(
309  const char* const fileName
310)
311{
312  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
313  FILE*                                           report;
314  Coverage::CoverageRanges::ranges_t::iterator    ritr;
315  Coverage::CoverageRanges*                       theRanges;
316  unsigned int                                    count;
317  FILE*                                           NoRangeFile;
318  std::string                                     NoRangeName;
319
320  // Open special file that captures NoRange informaiton
321  NoRangeName = "no_range_";
322  NoRangeName +=  fileName;
323  NoRangeFile = OpenNoRangeFile ( NoRangeName.c_str() );
324  if (!NoRangeFile) {
325    return;
326  }
327
328  // Open the coverage report file.
329  report = OpenCoverageFile( fileName );
330  if ( !report ) {
331    return;
332  }
333
334  // Process uncovered ranges for each symbol.
335  count = 0;
336  for (ditr = SymbolsToAnalyze->set.begin();
337       ditr != SymbolsToAnalyze->set.end();
338       ditr++) {
339
340    theRanges = ditr->second.uncoveredRanges;
341
342    // If uncoveredRanges doesn't exist, then the symbol was never
343    // referenced by any executable.  There may be a problem with the
344    // desired symbols list or with the executables so put something
345    // in the report.
346    if (theRanges == NULL) {
347      putCoverageNoRange( report, NoRangeFile, count, ditr->first );
348      count++;
349    }  else if (!theRanges->set.empty()) {
350
351      for (ritr =  theRanges->set.begin() ;
352           ritr != theRanges->set.end() ;
353           ritr++ ) {
354        PutCoverageLine( report, count, ditr, ritr );
355        count++;
356      }
357    }
358  }
359
360  CloseNoRangeFile( NoRangeFile );
361  CloseCoverageFile( report );
362
363}
364
365/*
366 * Write size report
367 */
368void ReportsBase::WriteSizeReport(
369  const char* const fileName
370)
371{
372  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
373  FILE*                                           report;
374  Coverage::CoverageRanges::ranges_t::iterator    ritr;
375  Coverage::CoverageRanges*                       theRanges;
376  unsigned int                                    count;
377
378  // Open the report file.
379  report = OpenSizeFile( fileName );
380  if ( !report ) {
381    return;
382  }
383
384  // Process uncovered ranges for each symbol.
385  count = 0;
386  for (ditr = SymbolsToAnalyze->set.begin();
387       ditr != SymbolsToAnalyze->set.end();
388       ditr++) {
389
390    theRanges = ditr->second.uncoveredRanges;
391
392    if (theRanges && !theRanges->set.empty()) {
393
394      for (ritr =  theRanges->set.begin() ;
395           ritr != theRanges->set.end() ;
396           ritr++ ) {
397        PutSizeLine( report, count, ditr, ritr );
398        count++;
399      }
400    }
401  }
402
403  CloseSizeFile( report );
404}
405
406void ReportsBase::WriteSymbolSummaryReport(
407  const char* const fileName
408)
409{
410  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
411  FILE*                                           report;
412  unsigned int                                    count;
413
414  // Open the report file.
415  report = OpenSymbolSummaryFile( fileName );
416  if ( !report ) {
417    return;
418  }
419
420  // Process each symbol.
421  count = 0;
422  for (ditr = SymbolsToAnalyze->set.begin();
423       ditr != SymbolsToAnalyze->set.end();
424       ditr++) {
425
426    PutSymbolSummaryLine( report, count, ditr );
427    count++;
428  }
429
430  CloseSymbolSummaryFile( report );
431}
432
433void  ReportsBase::WriteSummaryReport(
434  const char* const fileName
435)
436{
437    // Calculate coverage statistics and output results.
438  uint32_t                                        a;
439  uint32_t                                        endAddress;
440  Coverage::DesiredSymbols::symbolSet_t::iterator itr;
441  uint32_t                                        notExecuted = 0;
442  double                                          percentage;
443  Coverage::CoverageMapBase*                      theCoverageMap;
444  uint32_t                                        totalBytes = 0;
445  FILE*                                           report;
446
447  // Open the report file.
448  report = OpenFile( fileName );
449  if ( !report ) {
450    return;
451  }
452
453  // Look at each symbol.
454  for (itr = SymbolsToAnalyze->set.begin();
455       itr != SymbolsToAnalyze->set.end();
456       itr++) {
457
458    // If the symbol's unified coverage map exists, scan through it
459    // and count bytes.
460    theCoverageMap = itr->second.unifiedCoverageMap;
461    if (theCoverageMap) {
462
463      endAddress = itr->second.stats.sizeInBytes - 1;
464
465      for (a = 0; a <= endAddress; a++) {
466        totalBytes++;
467        if (!theCoverageMap->wasExecuted( a ))
468          notExecuted++;
469      }
470    }
471  }
472
473  percentage = (double) notExecuted;
474  percentage /= (double) totalBytes;
475  percentage *= 100.0;
476
477  fprintf( report, "Bytes Analyzed           : %d\n", totalBytes );
478  fprintf( report, "Bytes Not Executed       : %d\n", notExecuted );
479  fprintf( report, "Percentage Executed      : %5.4g\n", 100.0 - percentage  );
480  fprintf( report, "Percentage Not Executed  : %5.4g\n", percentage  );
481  fprintf(
482    report,
483    "Uncovered ranges found   : %d\n",
484    SymbolsToAnalyze->getNumberUncoveredRanges()
485  );
486  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
487      (BranchInfoAvailable == false) ) {
488    fprintf( report, "No branch information available\n" );
489  } else {
490    fprintf(
491      report,
492      "Total branches found     : %d\n",
493      SymbolsToAnalyze->getNumberBranchesFound()
494    );
495    fprintf(
496      report,
497      "Uncovered branches found : %d\n",
498      SymbolsToAnalyze->getNumberBranchesAlwaysTaken() +
499       SymbolsToAnalyze->getNumberBranchesNeverTaken()
500    );
501    fprintf(
502      report,
503      "   %d branches always taken\n",
504      SymbolsToAnalyze->getNumberBranchesAlwaysTaken()
505    );
506    fprintf(
507      report,
508      "   %d branches never taken\n",
509      SymbolsToAnalyze->getNumberBranchesNeverTaken()
510    );
511  }
512}
513
514void GenerateReports()
515{
516  typedef std::list<ReportsBase *> reportList_t;
517
518  reportList_t           reportList;
519  reportList_t::iterator ritr;
520  std::string            reportName;
521  ReportsBase*           reports;
522
523  time_t timestamp;
524
525
526  timestamp = time(NULL); /* get current cal time */
527  reports = new ReportsText(timestamp);
528  reportList.push_back(reports);
529  reports = new ReportsHtml(timestamp);
530  reportList.push_back(reports);
531
532  for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
533    reports = *ritr;
534
535    reportName = "index" + reports->ReportExtension();
536    if (Verbose)
537      fprintf(
538        stderr, "Generate %s\n", reportName.c_str()
539      );
540    reports->WriteIndex( reportName.c_str() );
541
542    reportName = "annotated" + reports->ReportExtension();
543    if (Verbose)
544      fprintf(
545        stderr, "Generate %s\n", reportName.c_str()
546      );
547    reports->WriteAnnotatedReport( reportName.c_str() );
548
549    reportName = "branch" + reports->ReportExtension();
550    if (Verbose)
551      fprintf(
552        stderr, "Generate %s\n", reportName.c_str()
553      );
554    reports->WriteBranchReport(reportName.c_str() );
555
556    reportName = "uncovered" + reports->ReportExtension();
557    if (Verbose)
558      fprintf(
559        stderr, "Generate %s\n", reportName.c_str()
560      );
561    reports->WriteCoverageReport(reportName.c_str() );
562
563    reportName = "sizes" + reports->ReportExtension();
564    if (Verbose)
565      fprintf(
566        stderr, "Generate %s\n", reportName.c_str()
567      );
568    reports->WriteSizeReport(reportName.c_str() );
569
570    reportName = "symbolSummary" + reports->ReportExtension();
571    if (Verbose)
572      fprintf(
573        stderr, "Generate %s\n", reportName.c_str()
574      );
575    reports->WriteSymbolSummaryReport(reportName.c_str() );
576  }
577
578  for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
579    reports = *ritr;
580    delete reports;
581  }
582
583  ReportsBase::WriteSummaryReport( "summary.txt" );
584}
585
586}
Note: See TracBrowser for help on using the repository browser.