#include #include #include #include #include #include #include #include "ReportsHtml.h" #include "CoverageRanges.h" #include "DesiredSymbols.h" #include "ObjdumpProcessor.h" #if 0 #define TABLE_HEADER_CLASS \ " table-autopage:10 table-page-number:pagenum table-page-count:pages " #define TABLE_FOOTER \ "\n" \ "\n" \ "< < Previous\n" \ "Page " \ " of \n" \ "Next > >\n" \ "\n" \ "\n" #else #define TABLE_HEADER_CLASS "" #define TABLE_FOOTER "" #endif namespace Coverage { ReportsHtml::ReportsHtml( time_t timestamp, const std::string& symbolSetName, Coverage::Explanations& allExplanations, const std::string& projectName, const std::string& outputDirectory, const Coverage::DesiredSymbols& symbolsToAnalyze, bool branchInfoAvailable ): ReportsBase( timestamp, symbolSetName, allExplanations, projectName, outputDirectory, symbolsToAnalyze, branchInfoAvailable ), lastState_m( A_SOURCE ) { reportExtension_m = ".html"; } ReportsHtml::~ReportsHtml() { } void ReportsHtml::WriteIndex( const std::string& fileName ) { std::ofstream aFile; #define PRINT_ITEM( _t, _n ) \ aFile << "
  • " \ << _t << " (html or text)
  • " << std::endl; #define PRINT_TEXT_ITEM( _t, _n ) \ aFile << "
  • " \ << _t << " (text)
  • " << std::endl; // Open the file OpenFile( fileName, aFile ); aFile << "Index" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Coverage Analysis Reports
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "
      " << std::endl; PRINT_TEXT_ITEM( "Summary", "summary.txt" ); PRINT_ITEM( "Coverage Report", "uncovered" ); PRINT_ITEM( "Branch Report", "branch" ); PRINT_ITEM( "Annotated Assembly", "annotated" ); PRINT_ITEM( "Symbol Summary", "symbolSummary" ); PRINT_ITEM( "Uncovered Range Size Report", "sizes" ); PRINT_TEXT_ITEM( "Explanations Not Found", "ExplanationsNotFound.txt" ); aFile << "
    " << std::endl << "" << std::endl << "" << std::endl; CloseFile( aFile ); #undef PRINT_ITEM #undef PRINT_TEXT_ITEM } void ReportsHtml::OpenFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file ReportsBase::OpenFile( fileName, symbolSetName_m, aFile, outputDirectory_m ); // Put Header information on the file aFile << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::OpenAnnotatedFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file OpenFile( fileName, aFile ); aFile << "Annotated Report" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Annotated Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "
    " << std::endl;
      }
    
      void ReportsHtml::OpenBranchFile(
        const std::string& fileName,
        bool               hasBranches,
        std::ofstream&     aFile
      )
      {
        // Open the file
        OpenFile( fileName, aFile );
    
        // Put header information into the file
        aFile << "Branch Report" << std::endl
              << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Branch Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::OpenCoverageFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file OpenFile( fileName, aFile ); // Put header information into the file aFile << "Coverage Report" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Coverage Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "
    SymbolLineFileSize
    Bytes
    ReasonTakenNot TakenClassificationExplanation
    " << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::OpenNoRangeFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file OpenFile( fileName, aFile ); // Put header information into the file aFile << " Report" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "No Range Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "
    SymbolRangeFileSize
    Bytes
    Size
    Instructions
    ClassificationExplanation
    " << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::OpenSizeFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file OpenFile( fileName, aFile ); // Put header information into the file aFile << "Uncovered Range Size Report" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Uncovered Range Size Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "
    Symbol
    " << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::OpenSymbolSummaryFile( const std::string& fileName, std::ofstream& aFile ) { // Open the file OpenFile( fileName, aFile ); // Put header information into the file aFile << "Symbol Summary Report" << std::endl << "
    "; if ( !projectName_m.empty() ) { aFile << projectName_m << "
    "; } aFile << "Symbol Summary Report
    " << std::endl << "
    " << asctime( localtime( ×tamp_m ) ) << "
    " << std::endl << "" << std::endl << "
    SizeSymbolLineFile
    " << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } void ReportsHtml::AnnotatedStart( std::ofstream& aFile ) { aFile << "
    " << std::endl; } void ReportsHtml::AnnotatedEnd( std::ofstream& aFile ) { } void ReportsHtml::PutAnnotatedLine( std::ofstream& aFile, AnnotatedLineState_t state, const std::string& line, uint32_t id ) { std::string stateText; std::string number; number = std::to_string( id ); // Set the stateText based upon the current state. switch ( state ) { case A_SOURCE: stateText = "\n
    \n";
            break;
          case A_EXECUTED:
            stateText = "
    \n
    \n";
            break;
          case A_NEVER_EXECUTED:
            stateText = "
    \n"; stateText += "
    \n";
            break;
          case A_BRANCH_TAKEN:
            stateText = "
    \n"; stateText += "
    \n";
            break;
          case A_BRANCH_NOT_TAKEN:
            stateText = "
    \n"; stateText += "
    \n";
            break;
          default:
            throw rld::error( "Unknown state", "ReportsHtml::PutAnnotatedLine" );
            break;
        }
    
        // If the state has not changed there is no need to change the text block
        // format.  If it has changed close out the old format and open up the
        // new format.
        if ( state != lastState_m ) {
          aFile << stateText;
          lastState_m = state;
        }
    
        // For all the characters in the line replace html reserved special
        // characters and output the line. Note that for a /pre block this
        // is only a '<' symbol.
        for ( unsigned int i=0; i\n";
        } else {
          report << "
    " << std::endl; } // symbol report << "" << std::endl; // line report << "" << std::endl; // File i = range.lowSourceLine.find( ":" ); temp = range.lowSourceLine.substr( 0, i ); report << "" << std::endl; // Size in bytes report << "" << std::endl; // Reason Branch was uncovered if ( range.reason == Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_ALWAYS_TAKEN ) { report << "" << std::endl; } else if ( range.reason == Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_NEVER_TAKEN ) { report << "" << std::endl; } // Taken / Not taken counts lowAddress = range.lowAddress; bAddress = symbolInfo.baseAddress; theCoverageMap = symbolInfo.unifiedCoverageMap; report << "" << std::endl << "" << std::endl; // See if an explanation is available and write the Classification and // the Explination Columns. explanation = allExplanations_m.lookupExplanation( range.lowSourceLine ); if ( !explanation ) { // Write Classificationditr->second.baseAddress report << "" << std::endl << "" << std::endl; } else { std::stringstream explanationFile( "explanation" ); explanationFile << range.id << ".html"; report << "" << std::endl << "" << std::endl; WriteExplanationFile( explanationFile.str(), explanation ); } report << "" << std::endl; return true; } bool ReportsHtml::WriteExplanationFile( const std::string& fileName, const Coverage::Explanation* explanation ) { std::ofstream report; OpenFile( fileName, report ); for ( unsigned int i=0 ; i < explanation->explanation.size(); i++ ) { report << explanation->explanation[i] << std::endl; } CloseFile( report ); return true; } void ReportsHtml::putCoverageNoRange( std::ofstream& report, std::ofstream& noRangeFile, unsigned int count, const std::string& symbol ) { Coverage::Explanation explanation; explanation.explanation.push_back( "

    \n" "This symbol was never referenced by an analyzed executable. " "Therefore there is no size or disassembly for this symbol. " "This could be due to symbol misspelling or lack of a test for " "this symbol." "

    \n" ); // Mark the background color different for odd and even lines. if ( ( count % 2 ) != 0 ) { report << "" << std::endl; noRangeFile << "" << std::endl; } else { report << "" << std::endl; noRangeFile << "" << std::endl; } // symbol report << "" << std::endl; noRangeFile << "" << std::endl; // starting line report << "" << std::endl; // file report << "" << std::endl; // Size in bytes report << "" << std::endl; // Size in instructions report << "" << std::endl; // See if an explanation is available report << "" << std::endl << "" << std::endl; WriteExplanationFile( "NotReferenced.html", &explanation ); report << "" << std::endl; noRangeFile << "" << std::endl; } bool ReportsHtml::PutCoverageLine( std::ofstream& report, unsigned int count, const std::string& symbolName, const SymbolInformation& symbolInfo, const CoverageRanges::coverageRange_t& range ) { const Coverage::Explanation* explanation; std::string temp; int i; // Mark the background color different for odd and even lines. if ( ( count % 2) != 0 ) { report << "" << std::endl; } else { report << "" << std::endl; } // symbol report << "" << std::endl; // Range report << "" << std::endl; // File i = range.lowSourceLine.find( ":" ); temp = range.lowSourceLine.substr( 0, i ); report << "" << std::endl; // Size in bytes report << "" << std::endl; // Size in instructions report << "" << std::endl; // See if an explanation is available explanation = allExplanations_m.lookupExplanation( range.lowSourceLine ); if ( !explanation ) { report << "" << std::endl << "" << std::endl; } else { std::stringstream explanationFile( "explanation" ); explanationFile << range.id << ".html"; report << "" << std::endl << "" << std::endl; WriteExplanationFile( explanationFile.str(), explanation ); } report << "" << std::endl; return true; } bool ReportsHtml::PutSizeLine( std::ofstream& report, unsigned int count, const std::string& symbolName, const CoverageRanges::coverageRange_t& range ) { std::string temp; int i; // Mark the background color different for odd and even lines. if ( ( count % 2 ) != 0 ) { report << "" << std::endl; } else { report << "" << std::endl; } // size report << "" << std::endl; // symbol report << "" << std::endl; // line report << "" << std::endl; // File i = range.lowSourceLine.find( ":" ); temp = range.lowSourceLine.substr( 0, i ); report << "" << std::endl << "" << std::endl; return true; } bool ReportsHtml::PutSymbolSummaryLine( std::ofstream& report, unsigned int count, const std::string& symbolName, const SymbolInformation& symbolInfo ) { rtems::utils::ostream_guard old_state( report ); // Mark the background color different for odd and even lines. if ( ( count % 2 ) != 0 ) { report << "" << std::endl; } else { report << "" << std::endl; } // symbol report << "" << std::endl; if ( symbolInfo.stats.sizeInBytes == 0 ) { // The symbol has never been seen. Write "unknown" for all columns. report << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl; } else { // Total Size in Bytes report << "" << std::endl; // Total Size in Instructions report << "" << std::endl; // Total Uncovered Ranges report << "" << std::endl; // Uncovered Size in Bytes report << "" << std::endl; // Uncovered Size in Instructions report << "" << std::endl; // Total number of branches report << "" << std::endl; // Total Always Taken report << "" << std::endl; // Total Never Taken report << "" << std::endl; // % Uncovered Instructions if ( symbolInfo.stats.sizeInInstructions == 0 ) { report << "" << std::endl; } else { report << "" << std::endl; } // % Uncovered Bytes if ( symbolInfo.stats.sizeInBytes == 0 ) { report << "" << std::endl; } else { report << "" << std::endl; } } report << "" << std::endl; return true; } void ReportsHtml::CloseAnnotatedFile( std::ofstream& aFile ) { aFile << "" << std::endl << "" << std::endl << "" << std::endl; CloseFile( aFile ); } void ReportsHtml::CloseBranchFile( std::ofstream& aFile, bool hasBranches ) { aFile << TABLE_FOOTER << "" << std::endl << "
    SymbolTotal
    Size
    Bytes
    Total
    Size
    Instr
    #
    Ranges
    Uncovered
    Size
    Bytes
    Uncovered
    Size
    Instr
    #
    Branches
    #
    Always
    Taken
    #
    Never
    Taken
    Percent
    Uncovered
    Instructions
    Percent
    Uncovered
    Bytes
    " << symbolName << "" << range.lowSourceLine << "" << temp << "" << range.highAddress - range.lowAddress + 1 << "Always TakenNever Taken" << theCoverageMap->getWasTaken( lowAddress - bAddress ) << "" << theCoverageMap->getWasNotTaken( lowAddress - bAddress ) << "NONENo Explanation" << explanation->classification << "" << "Explanation
    " << symbol << "" << symbol << "unknownunknownunknownunknownUnknown" << "No data
    " << symbolName << "" << range.lowSourceLine << "
    " << range.highSourceLine << "
    " << temp << "" << range.highAddress - range.lowAddress + 1 << "" << range.instructionCount << "NONENo Explanation" << explanation->classification << "" << "Explanation
    " << range.highAddress - range.lowAddress + 1 << "" << symbolName << "" << range.lowSourceLine << "" << temp << "
    " << symbolName << "unknownunknownunknownunknownunknownunknownunknownunknownunknownunknown" << symbolInfo.stats.sizeInBytes << "" << symbolInfo.stats.sizeInInstructions << "" << symbolInfo.stats.uncoveredRanges << "" << symbolInfo.stats.uncoveredBytes << "" << symbolInfo.stats.uncoveredInstructions << "" << symbolInfo.stats.branchesNotExecuted + symbolInfo.stats.branchesExecuted << "" << symbolInfo.stats.branchesAlwaysTaken << "" << symbolInfo.stats.branchesNeverTaken << "100.00" << std::fixed << std::setprecision( 2 ) << ( symbolInfo.stats.uncoveredInstructions * 100.0 ) / symbolInfo.stats.sizeInInstructions << "100.00" << ( symbolInfo.stats.uncoveredBytes * 100.0 ) / symbolInfo.stats.sizeInBytes << "
    " << std::endl; CloseFile( aFile ); } void ReportsHtml::CloseCoverageFile( std::ofstream& aFile ) { aFile << TABLE_FOOTER << "" << std::endl << "" << std::endl << "
    " << std::endl << "" << std::endl << ""; CloseFile( aFile ); } void ReportsHtml::CloseNoRangeFile( std::ofstream& aFile ) { aFile << TABLE_FOOTER << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << ""; CloseFile( aFile ); } void ReportsHtml::CloseSizeFile( std::ofstream& aFile ) { aFile << TABLE_FOOTER << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << ""; CloseFile( aFile ); } void ReportsHtml::CloseSymbolSummaryFile( std::ofstream& aFile ) { aFile << TABLE_FOOTER << "" << std::endl << "" << std::endl << "" << std::endl << "" << std::endl << ""; CloseFile( aFile ); } }