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

5
Last change on this file since fb987e8 was f4773ac, checked in by Cillian O'Donnell <cpodonnell8@…>, on 09/13/17 at 15:45:30

covoar: Add function defs to fix Windows build errors.

Closes #3129

  • Property mode set to 100644
File size: 14.5 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#ifdef _WIN32
18#include <direct.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#ifdef _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      const std::size_t  LINE_LENGTH = 150;
217      char               textLine[LINE_LENGTH];
218
219      state = A_SOURCE;
220
221      if ( itr->isInstruction ) {
222        if (!theCoverageMap->wasExecuted( itr->address - bAddress )){
223          annotation = "<== NOT EXECUTED";
224          state = A_NEVER_EXECUTED;
225          id = theRanges->getId( itr->address );
226        } else if (theCoverageMap->isBranch( itr->address - bAddress )) {
227          id = theBranches->getId( itr->address );
228          if (theCoverageMap->wasAlwaysTaken( itr->address - bAddress )){
229            annotation = "<== ALWAYS TAKEN";
230            state = A_BRANCH_TAKEN;
231          } else if (theCoverageMap->wasNeverTaken( itr->address - bAddress )){
232            annotation = "<== NEVER TAKEN";
233            state = A_BRANCH_NOT_TAKEN;
234          }
235        } else {
236          state = A_EXECUTED;
237        }
238      }
239
240      snprintf( textLine, LINE_LENGTH, "%-70s", itr->line.c_str() );
241      line = textLine + annotation;
242
243      PutAnnotatedLine( aFile, state, line, id);
244    }
245
246    AnnotatedEnd( aFile );
247  }
248
249  CloseAnnotatedFile( aFile );
250}
251
252/*
253 *  Write branch report
254 */
255void ReportsBase::WriteBranchReport(
256  const char* const fileName
257) {
258  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
259  FILE*                                           report = NULL;
260  Coverage::CoverageRanges::ranges_t::iterator    ritr;
261  Coverage::CoverageRanges*                       theBranches;
262  unsigned int                                    count;
263  bool                                            hasBranches = true;
264
265  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
266      (BranchInfoAvailable == false) )
267     hasBranches = false;
268
269  // Open the branch report file
270  report = OpenBranchFile( fileName, hasBranches );
271  if (!report)
272    return;
273
274  // If no branches were found of branch coverage is not supported
275  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
276      (BranchInfoAvailable == false) ) {
277
278    PutNoBranchInfo(report);
279
280    // If branches were found, ...
281  } else {
282
283    // Process uncovered branches for each symbol.
284    count = 0;
285    for (ditr = SymbolsToAnalyze->set.begin();
286         ditr != SymbolsToAnalyze->set.end();
287         ditr++) {
288
289      theBranches = ditr->second.uncoveredBranches;
290
291      if (theBranches && !theBranches->set.empty()) {
292
293        for (ritr =  theBranches->set.begin() ;
294             ritr != theBranches->set.end() ;
295             ritr++ ) {
296          count++;
297          PutBranchEntry( report, count, ditr, ritr );
298        }
299      }
300    }
301  }
302
303  CloseBranchFile( report, hasBranches );
304}
305
306/*
307 *  Write coverage report
308 */
309void ReportsBase::WriteCoverageReport(
310  const char* const fileName
311)
312{
313  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
314  FILE*                                           report;
315  Coverage::CoverageRanges::ranges_t::iterator    ritr;
316  Coverage::CoverageRanges*                       theRanges;
317  unsigned int                                    count;
318  FILE*                                           NoRangeFile;
319  std::string                                     NoRangeName;
320
321  // Open special file that captures NoRange informaiton
322  NoRangeName = "no_range_";
323  NoRangeName +=  fileName;
324  NoRangeFile = OpenNoRangeFile ( NoRangeName.c_str() );
325  if (!NoRangeFile) {
326    return;
327  }
328
329  // Open the coverage report file.
330  report = OpenCoverageFile( fileName );
331  if ( !report ) {
332    return;
333  }
334
335  // Process uncovered ranges for each symbol.
336  count = 0;
337  for (ditr = SymbolsToAnalyze->set.begin();
338       ditr != SymbolsToAnalyze->set.end();
339       ditr++) {
340
341    theRanges = ditr->second.uncoveredRanges;
342
343    // If uncoveredRanges doesn't exist, then the symbol was never
344    // referenced by any executable.  There may be a problem with the
345    // desired symbols list or with the executables so put something
346    // in the report.
347    if (theRanges == NULL) {
348      putCoverageNoRange( report, NoRangeFile, count, ditr->first );
349      count++;
350    }  else if (!theRanges->set.empty()) {
351
352      for (ritr =  theRanges->set.begin() ;
353           ritr != theRanges->set.end() ;
354           ritr++ ) {
355        PutCoverageLine( report, count, ditr, ritr );
356        count++;
357      }
358    }
359  }
360
361  CloseNoRangeFile( NoRangeFile );
362  CloseCoverageFile( report );
363
364}
365
366/*
367 * Write size report
368 */
369void ReportsBase::WriteSizeReport(
370  const char* const fileName
371)
372{
373  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
374  FILE*                                           report;
375  Coverage::CoverageRanges::ranges_t::iterator    ritr;
376  Coverage::CoverageRanges*                       theRanges;
377  unsigned int                                    count;
378
379  // Open the report file.
380  report = OpenSizeFile( fileName );
381  if ( !report ) {
382    return;
383  }
384
385  // Process uncovered ranges for each symbol.
386  count = 0;
387  for (ditr = SymbolsToAnalyze->set.begin();
388       ditr != SymbolsToAnalyze->set.end();
389       ditr++) {
390
391    theRanges = ditr->second.uncoveredRanges;
392
393    if (theRanges && !theRanges->set.empty()) {
394
395      for (ritr =  theRanges->set.begin() ;
396           ritr != theRanges->set.end() ;
397           ritr++ ) {
398        PutSizeLine( report, count, ditr, ritr );
399        count++;
400      }
401    }
402  }
403
404  CloseSizeFile( report );
405}
406
407void ReportsBase::WriteSymbolSummaryReport(
408  const char* const fileName
409)
410{
411  Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
412  FILE*                                           report;
413  unsigned int                                    count;
414
415  // Open the report file.
416  report = OpenSymbolSummaryFile( fileName );
417  if ( !report ) {
418    return;
419  }
420
421  // Process each symbol.
422  count = 0;
423  for (ditr = SymbolsToAnalyze->set.begin();
424       ditr != SymbolsToAnalyze->set.end();
425       ditr++) {
426
427    PutSymbolSummaryLine( report, count, ditr );
428    count++;
429  }
430
431  CloseSymbolSummaryFile( report );
432}
433
434void  ReportsBase::WriteSummaryReport(
435  const char* const fileName
436)
437{
438    // Calculate coverage statistics and output results.
439  uint32_t                                        a;
440  uint32_t                                        endAddress;
441  Coverage::DesiredSymbols::symbolSet_t::iterator itr;
442  uint32_t                                        notExecuted = 0;
443  double                                          percentage;
444  Coverage::CoverageMapBase*                      theCoverageMap;
445  uint32_t                                        totalBytes = 0;
446  FILE*                                           report;
447
448  // Open the report file.
449  report = OpenFile( fileName );
450  if ( !report ) {
451    return;
452  }
453
454  // Look at each symbol.
455  for (itr = SymbolsToAnalyze->set.begin();
456       itr != SymbolsToAnalyze->set.end();
457       itr++) {
458
459    // If the symbol's unified coverage map exists, scan through it
460    // and count bytes.
461    theCoverageMap = itr->second.unifiedCoverageMap;
462    if (theCoverageMap) {
463
464      endAddress = itr->second.stats.sizeInBytes - 1;
465
466      for (a = 0; a <= endAddress; a++) {
467        totalBytes++;
468        if (!theCoverageMap->wasExecuted( a ))
469          notExecuted++;
470      }
471    }
472  }
473
474  percentage = (double) notExecuted;
475  percentage /= (double) totalBytes;
476  percentage *= 100.0;
477
478  fprintf( report, "Bytes Analyzed           : %d\n", totalBytes );
479  fprintf( report, "Bytes Not Executed       : %d\n", notExecuted );
480  fprintf( report, "Percentage Executed      : %5.4g\n", 100.0 - percentage  );
481  fprintf( report, "Percentage Not Executed  : %5.4g\n", percentage  );
482  fprintf(
483    report,
484    "Uncovered ranges found   : %d\n",
485    SymbolsToAnalyze->getNumberUncoveredRanges()
486  );
487  if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
488      (BranchInfoAvailable == false) ) {
489    fprintf( report, "No branch information available\n" );
490  } else {
491    fprintf(
492      report,
493      "Total branches found     : %d\n",
494      SymbolsToAnalyze->getNumberBranchesFound()
495    );
496    fprintf(
497      report,
498      "Uncovered branches found : %d\n",
499      SymbolsToAnalyze->getNumberBranchesAlwaysTaken() +
500       SymbolsToAnalyze->getNumberBranchesNeverTaken()
501    );
502    fprintf(
503      report,
504      "   %d branches always taken\n",
505      SymbolsToAnalyze->getNumberBranchesAlwaysTaken()
506    );
507    fprintf(
508      report,
509      "   %d branches never taken\n",
510      SymbolsToAnalyze->getNumberBranchesNeverTaken()
511    );
512  }
513}
514
515void GenerateReports()
516{
517  typedef std::list<ReportsBase *> reportList_t;
518
519  reportList_t           reportList;
520  reportList_t::iterator ritr;
521  std::string            reportName;
522  ReportsBase*           reports;
523
524  time_t timestamp;
525
526
527  timestamp = time(NULL); /* get current cal time */
528  reports = new ReportsText(timestamp);
529  reportList.push_back(reports);
530  reports = new ReportsHtml(timestamp);
531  reportList.push_back(reports);
532
533  for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
534    reports = *ritr;
535
536    reportName = "index" + reports->ReportExtension();
537    if (Verbose)
538      fprintf(
539        stderr, "Generate %s\n", reportName.c_str()
540      );
541    reports->WriteIndex( reportName.c_str() );
542
543    reportName = "annotated" + reports->ReportExtension();
544    if (Verbose)
545      fprintf(
546        stderr, "Generate %s\n", reportName.c_str()
547      );
548    reports->WriteAnnotatedReport( reportName.c_str() );
549
550    reportName = "branch" + reports->ReportExtension();
551    if (Verbose)
552      fprintf(
553        stderr, "Generate %s\n", reportName.c_str()
554      );
555    reports->WriteBranchReport(reportName.c_str() );
556
557    reportName = "uncovered" + reports->ReportExtension();
558    if (Verbose)
559      fprintf(
560        stderr, "Generate %s\n", reportName.c_str()
561      );
562    reports->WriteCoverageReport(reportName.c_str() );
563
564    reportName = "sizes" + reports->ReportExtension();
565    if (Verbose)
566      fprintf(
567        stderr, "Generate %s\n", reportName.c_str()
568      );
569    reports->WriteSizeReport(reportName.c_str() );
570
571    reportName = "symbolSummary" + reports->ReportExtension();
572    if (Verbose)
573      fprintf(
574        stderr, "Generate %s\n", reportName.c_str()
575      );
576    reports->WriteSymbolSummaryReport(reportName.c_str() );
577  }
578
579  for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
580    reports = *ritr;
581    delete reports;
582  }
583
584  ReportsBase::WriteSummaryReport( "summary.txt" );
585}
586
587}
Note: See TracBrowser for help on using the repository browser.