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

4.104.11
Last change on this file since 100f517 was 100f517, checked in by Chris Johns <chrisj@…>, on May 9, 2014 at 11:50:37 AM

covoar: Merger the covoar source from rtems-testing.git.

Use waf to build covoar.

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