diff options
author | Chris Johns <chrisj@rtems.org> | 2014-05-09 21:50:37 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2014-06-18 16:48:08 +1200 |
commit | 100f517ab37265acdf067e36b6860020ec8b2184 (patch) | |
tree | 2316c8b888e11dcbcfbfc66a0c1e31991ea20656 /tester/covoar/ReportsBase.cc | |
parent | 4.11: Add ntp patch. (diff) | |
download | rtems-tools-100f517ab37265acdf067e36b6860020ec8b2184.tar.bz2 |
covoar: Merger the covoar source from rtems-testing.git.
Use waf to build covoar.
Diffstat (limited to 'tester/covoar/ReportsBase.cc')
-rw-r--r-- | tester/covoar/ReportsBase.cc | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/tester/covoar/ReportsBase.cc b/tester/covoar/ReportsBase.cc new file mode 100644 index 0000000..d401bdd --- /dev/null +++ b/tester/covoar/ReportsBase.cc @@ -0,0 +1,578 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "ReportsBase.h" +#include "app_common.h" +#include "CoverageRanges.h" +#include "DesiredSymbols.h" +#include "Explanations.h" +#include "ObjdumpProcessor.h" + +#include "ReportsText.h" +#include "ReportsHtml.h" + +namespace Coverage { + +ReportsBase::ReportsBase( time_t timestamp ): + reportExtension_m(""), + timestamp_m( timestamp ) +{ +} + +ReportsBase::~ReportsBase() +{ +} + +FILE* ReportsBase::OpenFile( + const char* const fileName +) +{ + int sc; + FILE *aFile; + std::string file; + + // Create the output directory if it does not already exist + sc = mkdir( outputDirectory,0755 ); + if ( (sc == -1) && (errno != EEXIST) ) { + fprintf(stderr, "Unable to create output directory %s\n", outputDirectory); + return NULL; + } + + file = outputDirectory; + file += "/"; + file += fileName; + + // Open the file. + aFile = fopen( file.c_str(), "w" ); + if ( !aFile ) { + fprintf( stderr, "Unable to open %s\n", file.c_str() ); + } + return aFile; +} + +void ReportsBase::WriteIndex( + const char* const fileName +) +{ +} + +FILE* ReportsBase::OpenAnnotatedFile( + const char* const fileName +) +{ + return OpenFile(fileName); +} + +FILE* ReportsBase::OpenBranchFile( + const char* const fileName, + bool hasBranches +) +{ + return OpenFile(fileName); +} + +FILE* ReportsBase::OpenCoverageFile( + const char* const fileName +) +{ + return OpenFile(fileName); +} + +FILE* ReportsBase::OpenNoRangeFile( + const char* const fileName +) +{ + return OpenFile(fileName); +} + + +FILE* ReportsBase::OpenSizeFile( + const char* const fileName +) +{ + return OpenFile(fileName); +} + +FILE* ReportsBase::OpenSymbolSummaryFile( + const char* const fileName +) +{ + return OpenFile(fileName); +} + +void ReportsBase::CloseFile( + FILE* aFile +) +{ + fclose( aFile ); +} + +void ReportsBase::CloseAnnotatedFile( + FILE* aFile +) +{ + CloseFile( aFile ); +} + +void ReportsBase::CloseBranchFile( + FILE* aFile, + bool hasBranches +) +{ + CloseFile( aFile ); +} + +void ReportsBase::CloseCoverageFile( + FILE* aFile +) +{ + CloseFile( aFile ); +} + +void ReportsBase::CloseNoRangeFile( + FILE* aFile +) +{ + CloseFile( aFile ); +} + +void ReportsBase::CloseSizeFile( + FILE* aFile +) +{ + CloseFile( aFile ); +} + +void ReportsBase::CloseSymbolSummaryFile( + FILE* aFile +) +{ + CloseFile( aFile ); +} + +/* + * Write annotated report + */ +void ReportsBase::WriteAnnotatedReport( + const char* const fileName +) { + FILE* aFile = NULL; + Coverage::DesiredSymbols::symbolSet_t::iterator ditr; + Coverage::CoverageRanges* theBranches; + Coverage::CoverageRanges* theRanges; + Coverage::CoverageMapBase* theCoverageMap = NULL; + uint32_t bAddress = 0; + AnnotatedLineState_t state; + std::list<Coverage::ObjdumpProcessor::objdumpLine_t>* theInstructions; + std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator itr; + + aFile = OpenAnnotatedFile(fileName); + if (!aFile) + return; + + // Process uncovered branches for each symbol. + for (ditr = SymbolsToAnalyze->set.begin(); + ditr != SymbolsToAnalyze->set.end(); + ditr++) { + + // If uncoveredRanges and uncoveredBranches don't exist, then the + // symbol was never referenced by any executable. Just skip it. + if ((ditr->second.uncoveredRanges == NULL) && + (ditr->second.uncoveredBranches == NULL)) + continue; + + // If uncoveredRanges and uncoveredBranches are empty, then everything + // must have been covered for this symbol. Just skip it. + if ((ditr->second.uncoveredRanges->set.empty()) && + (ditr->second.uncoveredBranches->set.empty())) + continue; + + theCoverageMap = ditr->second.unifiedCoverageMap; + bAddress = ditr->second.baseAddress; + theInstructions = &(ditr->second.instructions); + theRanges = ditr->second.uncoveredRanges; + theBranches = ditr->second.uncoveredBranches; + + // Add annotations to each line where necessary + AnnotatedStart( aFile ); + for (itr = theInstructions->begin(); + itr != theInstructions->end(); + itr++ ) { + + uint32_t id = 0; + std::string annotation = ""; + std::string line; + char textLine[150]; + + state = A_SOURCE; + + if ( itr->isInstruction ) { + if (!theCoverageMap->wasExecuted( itr->address - bAddress )){ + annotation = "<== NOT EXECUTED"; + state = A_NEVER_EXECUTED; + id = theRanges->getId( itr->address ); + } else if (theCoverageMap->isBranch( itr->address - bAddress )) { + id = theBranches->getId( itr->address ); + if (theCoverageMap->wasAlwaysTaken( itr->address - bAddress )){ + annotation = "<== ALWAYS TAKEN"; + state = A_BRANCH_TAKEN; + } else if (theCoverageMap->wasNeverTaken( itr->address - bAddress )){ + annotation = "<== NEVER TAKEN"; + state = A_BRANCH_NOT_TAKEN; + } + } else { + state = A_EXECUTED; + } + } + + sprintf( textLine, "%-70s", itr->line.c_str() ); + line = textLine + annotation; + + PutAnnotatedLine( aFile, state, line, id); + } + + AnnotatedEnd( aFile ); + } + + CloseAnnotatedFile( aFile ); +} + +/* + * Write branch report + */ +void ReportsBase::WriteBranchReport( + const char* const fileName +) { + Coverage::DesiredSymbols::symbolSet_t::iterator ditr; + FILE* report = NULL; + Coverage::CoverageRanges::ranges_t::iterator ritr; + Coverage::CoverageRanges* theBranches; + unsigned int count; + bool hasBranches = true; + + if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) || + (BranchInfoAvailable == false) ) + hasBranches = false; + + // Open the branch report file + report = OpenBranchFile( fileName, hasBranches ); + if (!report) + return; + + // If no branches were found of branch coverage is not supported + if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) || + (BranchInfoAvailable == false) ) { + + PutNoBranchInfo(report); + + // If branches were found, ... + } else { + + // Process uncovered branches for each symbol. + count = 0; + for (ditr = SymbolsToAnalyze->set.begin(); + ditr != SymbolsToAnalyze->set.end(); + ditr++) { + + theBranches = ditr->second.uncoveredBranches; + + if (theBranches && !theBranches->set.empty()) { + + for (ritr = theBranches->set.begin() ; + ritr != theBranches->set.end() ; + ritr++ ) { + count++; + PutBranchEntry( report, count, ditr, ritr ); + } + } + } + } + + CloseBranchFile( report, hasBranches ); +} + +/* + * Write coverage report + */ +void ReportsBase::WriteCoverageReport( + const char* const fileName +) +{ + Coverage::DesiredSymbols::symbolSet_t::iterator ditr; + FILE* report; + Coverage::CoverageRanges::ranges_t::iterator ritr; + Coverage::CoverageRanges* theRanges; + unsigned int count; + FILE* NoRangeFile; + std::string NoRangeName; + + // Open special file that captures NoRange informaiton + NoRangeName = "no_range_"; + NoRangeName += fileName; + NoRangeFile = OpenNoRangeFile ( NoRangeName.c_str() ); + if (!NoRangeFile) { + return; + } + + // Open the coverage report file. + report = OpenCoverageFile( fileName ); + if ( !report ) { + return; + } + + // Process uncovered ranges for each symbol. + count = 0; + for (ditr = SymbolsToAnalyze->set.begin(); + ditr != SymbolsToAnalyze->set.end(); + ditr++) { + + theRanges = ditr->second.uncoveredRanges; + + // If uncoveredRanges doesn't exist, then the symbol was never + // referenced by any executable. There may be a problem with the + // desired symbols list or with the executables so put something + // in the report. + if (theRanges == NULL) { + putCoverageNoRange( report, NoRangeFile, count, ditr->first ); + count++; + } else if (!theRanges->set.empty()) { + + for (ritr = theRanges->set.begin() ; + ritr != theRanges->set.end() ; + ritr++ ) { + PutCoverageLine( report, count, ditr, ritr ); + count++; + } + } + } + + CloseNoRangeFile( NoRangeFile ); + CloseCoverageFile( report ); + +} + +/* + * Write size report + */ +void ReportsBase::WriteSizeReport( + const char* const fileName +) +{ + Coverage::DesiredSymbols::symbolSet_t::iterator ditr; + FILE* report; + Coverage::CoverageRanges::ranges_t::iterator ritr; + Coverage::CoverageRanges* theRanges; + unsigned int count; + + // Open the report file. + report = OpenSizeFile( fileName ); + if ( !report ) { + return; + } + + // Process uncovered ranges for each symbol. + count = 0; + for (ditr = SymbolsToAnalyze->set.begin(); + ditr != SymbolsToAnalyze->set.end(); + ditr++) { + + theRanges = ditr->second.uncoveredRanges; + + if (theRanges && !theRanges->set.empty()) { + + for (ritr = theRanges->set.begin() ; + ritr != theRanges->set.end() ; + ritr++ ) { + PutSizeLine( report, count, ditr, ritr ); + count++; + } + } + } + + CloseSizeFile( report ); +} + +void ReportsBase::WriteSymbolSummaryReport( + const char* const fileName +) +{ + Coverage::DesiredSymbols::symbolSet_t::iterator ditr; + FILE* report; + unsigned int count; + + // Open the report file. + report = OpenSymbolSummaryFile( fileName ); + if ( !report ) { + return; + } + + // Process each symbol. + count = 0; + for (ditr = SymbolsToAnalyze->set.begin(); + ditr != SymbolsToAnalyze->set.end(); + ditr++) { + + PutSymbolSummaryLine( report, count, ditr ); + count++; + } + + CloseSymbolSummaryFile( report ); +} + +void ReportsBase::WriteSummaryReport( + const char* const fileName +) +{ + // Calculate coverage statistics and output results. + uint32_t a; + uint32_t endAddress; + Coverage::DesiredSymbols::symbolSet_t::iterator itr; + uint32_t notExecuted = 0; + double percentage; + Coverage::CoverageMapBase* theCoverageMap; + uint32_t totalBytes = 0; + FILE* report; + + // Open the report file. + report = OpenFile( fileName ); + if ( !report ) { + return; + } + + // Look at each symbol. + for (itr = SymbolsToAnalyze->set.begin(); + itr != SymbolsToAnalyze->set.end(); + itr++) { + + // If the symbol's unified coverage map exists, scan through it + // and count bytes. + theCoverageMap = itr->second.unifiedCoverageMap; + if (theCoverageMap) { + + endAddress = itr->second.stats.sizeInBytes - 1; + + for (a = 0; a <= endAddress; a++) { + totalBytes++; + if (!theCoverageMap->wasExecuted( a )) + notExecuted++; + } + } + } + + percentage = (double) notExecuted; + percentage /= (double) totalBytes; + percentage *= 100.0; + + fprintf( report, "Bytes Analyzed : %d\n", totalBytes ); + fprintf( report, "Bytes Not Executed : %d\n", notExecuted ); + fprintf( report, "Percentage Executed : %5.4g\n", 100.0 - percentage ); + fprintf( report, "Percentage Not Executed : %5.4g\n", percentage ); + fprintf( + report, + "Uncovered ranges found : %d\n", + SymbolsToAnalyze->getNumberUncoveredRanges() + ); + if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) || + (BranchInfoAvailable == false) ) { + fprintf( report, "No branch information available\n" ); + } else { + fprintf( + report, + "Total branches found : %d\n", + SymbolsToAnalyze->getNumberBranchesFound() + ); + fprintf( + report, + "Uncovered branches found : %d\n", + SymbolsToAnalyze->getNumberBranchesAlwaysTaken() + + SymbolsToAnalyze->getNumberBranchesNeverTaken() + ); + fprintf( + report, + " %d branches always taken\n", + SymbolsToAnalyze->getNumberBranchesAlwaysTaken() + ); + fprintf( + report, + " %d branches never taken\n", + SymbolsToAnalyze->getNumberBranchesNeverTaken() + ); + } +} + +void GenerateReports() +{ + typedef std::list<ReportsBase *> reportList_t; + + reportList_t reportList; + reportList_t::iterator ritr; + std::string reportName; + ReportsBase* reports; + + time_t timestamp; + + + timestamp = time(NULL); /* get current cal time */ + reports = new ReportsText(timestamp); + reportList.push_back(reports); + reports = new ReportsHtml(timestamp); + reportList.push_back(reports); + + for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) { + reports = *ritr; + + reportName = "index" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteIndex( reportName.c_str() ); + + reportName = "annotated" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteAnnotatedReport( reportName.c_str() ); + + reportName = "branch" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteBranchReport(reportName.c_str() ); + + reportName = "uncovered" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteCoverageReport(reportName.c_str() ); + + reportName = "sizes" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteSizeReport(reportName.c_str() ); + + reportName = "symbolSummary" + reports->ReportExtension(); + if (Verbose) + fprintf( + stderr, "Generate %s\n", reportName.c_str() + ); + reports->WriteSymbolSummaryReport(reportName.c_str() ); + } + + for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) { + reports = *ritr; + delete reports; + } + + ReportsBase::WriteSummaryReport( "summary.txt" ); +} + +} |