#include #include #include #include #include "ReportsHtml.h" #include "app_common.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 ): ReportsBase( timestamp ) { reportExtension_m = ".html"; } ReportsHtml::~ReportsHtml() { } void ReportsHtml::WriteIndex( const char* const fileName ) { #define PRINT_ITEM( _t, _n ) \ fprintf( \ aFile, \ "
  • %s (html or "\ "text)
  • \n", \ _t, _n, _n ); #define PRINT_TEXT_ITEM( _t, _n ) \ fprintf( \ aFile, \ "
  • %s (text)
  • \n", \ _t, _n ); FILE* aFile; // Open the file aFile = OpenFile( fileName ); fprintf( aFile, "Index\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Coverage Analysis Reports
    \n" "
    %s
    \n", asctime( localtime(×tamp_m) ) ); fprintf( aFile, "
      \n" ); 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( "Size Report", "sizes" ); PRINT_TEXT_ITEM( "Explanations Not Found", "ExplanationsNotFound.txt" ); fprintf( aFile, "
    \n" "\n" "\n" ); CloseFile( aFile ); #undef PRINT_ITEM #undef PRINT_TEXT_ITEM } FILE* ReportsHtml::OpenFile( const char* const fileName ) { FILE* aFile; // Open the file aFile = ReportsBase::OpenFile( fileName ); // Put Header information on the file fprintf( aFile, "\n" "\n" "\n" "\n" "\n" ); return aFile; } FILE* ReportsHtml::OpenAnnotatedFile( const char* const fileName ) { FILE *aFile; // Open the file aFile = OpenFile(fileName); fprintf( aFile, "Annotated Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Annotated Report
    \n" "
    %s
    \n" "\n" "
    \n",
          asctime( localtime(×tamp_m) )
        );
    
        return aFile;
      }
    
      FILE* ReportsHtml::OpenBranchFile(
        const char* const fileName,
        bool              hasBranches
      )
      {
        FILE *aFile;
    
        // Open the file
        aFile = OpenFile(fileName);
    
        if ( hasBranches ) {
          // Put header information into the file
          fprintf(
            aFile,
            "Branch Report</title\n"
            "<div class=\"heading-title\">"
          );
    
          if (projectName)
            fprintf(
              aFile,
              "%s<br>",
              projectName
            );
    
          fprintf(
            aFile,
            "Branch Report</div>\n"
            "<div class =\"datetime\">%s</div>\n"
            "<body>\n"
            "<table class=\"covoar table-autosort:0 table-autofilter table-stripeclass:covoar-tr-odd"
               TABLE_HEADER_CLASS "\">\n"
            "<thead>\n"
            "<tr>\n"
            "<th class=\"table-sortable:default\" align=\"left\">Symbol</th>\n"
            "<th class=\"table-sortable:default\" align=\"left\">Line</th>\n"
            "<th class=\"table-filterable table-sortable:default\" align=\"left\">File</th>\n"
            "<th class=\"table-sortable:numeric\" align=\"left\">Size <br>Bytes</th>\n"
            "<th class=\"table-sortable:default\" align=\"left\">Reason</th>\n"
            "<th class=\"table-filterable table-sortable:default\" align=\"left\">Taken</th>\n"
    	"<th class=\"table-filterable table-sortable:default\" align=\"left\">Not Taken</th>\n"
            "<th class=\"table-filterable table-sortable:default\" align=\"left\">Classification</th>\n"
            "<th class=\"table-sortable:default\" align=\"left\">Explanation</th>\n"
            "</tr>\n"
            "</thead>\n"
            "<tbody>\n",
            asctime( localtime(×tamp_m) )
          );
        }
    
        return aFile;
      }
    
      FILE*  ReportsHtml::OpenCoverageFile(
        const char* const fileName
      )
      {
        FILE *aFile;
    
        // Open the file
        aFile = OpenFile(fileName);
    
        // Put header information into the file
        fprintf(
          aFile,
            "<title>Coverage Report\n"
            "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Coverage Report
    \n" "
    %s
    \n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n", asctime( localtime(×tamp_m) ) ); return aFile; } FILE* ReportsHtml::OpenNoRangeFile( const char* const fileName ) { FILE *aFile; // Open the file aFile = OpenFile(fileName); // Put header information into the file fprintf( aFile, " Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "No Range Report
    \n" "
    %s
    \n" "\n" "
    SymbolRangeFileSize
    Bytes
    Size
    Instructions
    ClassificationExplanation
    \n" "\n" "\n" "\n" "\n" "\n" "\n", asctime( localtime(×tamp_m) ) ); return aFile; } FILE* ReportsHtml::OpenSizeFile( const char* const fileName ) { FILE *aFile; // Open the file aFile = OpenFile(fileName); // Put header information into the file fprintf( aFile, "Size Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Size Report
    \n" "
    %s
    \n" "\n" "
    Symbol
    \n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n", asctime( localtime(×tamp_m) ) ); return aFile; } FILE* ReportsHtml::OpenSymbolSummaryFile( const char* const fileName ) { FILE *aFile; // Open the file aFile = OpenFile(fileName); // Put header information into the file fprintf( aFile, "Symbol Summary Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Symbol Summary Report
    \n" "
    %s
    \n" "\n" "
    SizeSymbolLineFile
    \n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n", asctime( localtime(×tamp_m) ) ); return aFile; } void ReportsHtml::AnnotatedStart( FILE* aFile ) { fprintf( aFile, "
    \n" ); } void ReportsHtml::AnnotatedEnd( FILE* aFile ) { } void ReportsHtml::PutAnnotatedLine( FILE* aFile, AnnotatedLineState_t state, std::string line, uint32_t id ) { std::string stateText; char number[10]; sprintf(number,"%d", 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 ) {
          fprintf( aFile, "%s", stateText.c_str() );
          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
          fprintf( report, "
    \n"); // symbol fprintf( report, "\n", symbolPtr->first.c_str() ); // line fprintf( report, "\n", rangePtr->id, rangePtr->lowSourceLine.c_str() ); // File i = rangePtr->lowSourceLine.find(":"); temp = rangePtr->lowSourceLine.substr (0, i); fprintf( report, "\n", temp.c_str() ); // Size in bytes fprintf( report, "\n", rangePtr->highAddress - rangePtr->lowAddress + 1 ); // Reason Branch was uncovered if (rangePtr->reason == Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_ALWAYS_TAKEN) fprintf( report, "\n" ); else if (rangePtr->reason == Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_NEVER_TAKEN) fprintf( report, "\n" ); // Taken / Not taken counts lowAddress = rangePtr->lowAddress; bAddress = symbolPtr->second.baseAddress; theCoverageMap = symbolPtr->second.unifiedCoverageMap; fprintf( report, "\n", theCoverageMap->getWasTaken( lowAddress - bAddress ) ); fprintf( report, "\n", theCoverageMap->getWasNotTaken( lowAddress - bAddress ) ); // See if an explanation is available and write the Classification and // the Explination Columns. explanation = AllExplanations->lookupExplanation( rangePtr->lowSourceLine ); if ( !explanation ) { // Write Classificationditr->second.baseAddress fprintf( report, "\n" "\n" ); } else { char explanationFile[48]; sprintf( explanationFile, "explanation%d.html", rangePtr->id ); fprintf( report, "\n" "\n", explanation->classification.c_str(), explanationFile ); WriteExplationFile( explanationFile, explanation ); } fprintf( report, "\n"); return true; } bool ReportsHtml::WriteExplationFile( const char* fileName, const Coverage::Explanation* explanation ) { FILE* report; report = OpenFile( fileName ); for ( unsigned int i=0 ; i < explanation->explanation.size(); i++) { fprintf( report, "%s\n", explanation->explanation[i].c_str() ); } CloseFile( report ); return true; } void ReportsHtml::putCoverageNoRange( FILE* report, FILE* noRangeFile, unsigned int count, 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 ){ fprintf( report, "\n"); fprintf( noRangeFile, "\n"); } else { fprintf( report, "\n"); fprintf( noRangeFile, "\n"); } // symbol fprintf( report, "\n", symbol.c_str() ); fprintf( noRangeFile, "\n", symbol.c_str() ); // starting line fprintf( report, "\n" ); // file fprintf( report, "\n" ); // Size in bytes fprintf( report, "\n" ); // Size in instructions fprintf( report, "\n" ); // See if an explanation is available fprintf( report, "\n" "\n" ); WriteExplationFile( "NotReferenced.html", &explanation ); fprintf( report, "\n"); fprintf( noRangeFile, "\n"); } bool ReportsHtml::PutCoverageLine( FILE* report, unsigned int count, Coverage::DesiredSymbols::symbolSet_t::iterator symbolPtr, Coverage::CoverageRanges::ranges_t::iterator rangePtr ) { const Coverage::Explanation* explanation; std::string temp; int i; // Mark the background color different for odd and even lines. if ( ( count%2 ) != 0 ) fprintf( report, "\n"); else fprintf( report, "\n"); // symbol fprintf( report, "\n", symbolPtr->first.c_str() ); // Range fprintf( report, "\n", rangePtr->id, rangePtr->lowSourceLine.c_str(), rangePtr->highSourceLine.c_str() ); // File i = rangePtr->lowSourceLine.find(":"); temp = rangePtr->lowSourceLine.substr (0, i); fprintf( report, "\n", temp.c_str() ); // Size in bytes fprintf( report, "\n", rangePtr->highAddress - rangePtr->lowAddress + 1 ); // Size in instructions fprintf( report, "\n", rangePtr->instructionCount ); // See if an explanation is available explanation = AllExplanations->lookupExplanation( rangePtr->lowSourceLine ); if ( !explanation ) { fprintf( report, "\n" ); fprintf( report, "\n" ); } else { char explanationFile[48]; sprintf( explanationFile, "explanation%d.html", rangePtr->id ); fprintf( report, "\n" "\n", explanation->classification.c_str(), explanationFile ); WriteExplationFile( explanationFile, explanation ); } fprintf( report, "\n"); return true; } bool ReportsHtml::PutSizeLine( FILE* report, unsigned int count, Coverage::DesiredSymbols::symbolSet_t::iterator symbol, Coverage::CoverageRanges::ranges_t::iterator range ) { std::string temp; int i; // Mark the background color different for odd and even lines. if ( ( count%2 ) != 0 ) fprintf( report, "\n"); else fprintf( report, "\n"); // size fprintf( report, "\n", range->highAddress - range->lowAddress + 1 ); // symbol fprintf( report, "\n", symbol->first.c_str() ); // line fprintf( report, "\n", range->id, range->lowSourceLine.c_str() ); // File i = range->lowSourceLine.find(":"); temp = range->lowSourceLine.substr (0, i); fprintf( report, "\n", temp.c_str() ); fprintf( report, "\n"); return true; } bool ReportsHtml::PutSymbolSummaryLine( FILE* report, unsigned int count, Coverage::DesiredSymbols::symbolSet_t::iterator symbol ) { // Mark the background color different for odd and even lines. if ( ( count%2 ) != 0 ) fprintf( report, "\n"); else fprintf( report, "\n"); // symbol fprintf( report, "\n", symbol->first.c_str() ); // Total Size in Bytes fprintf( report, "\n", symbol->second.stats.sizeInBytes ); // Total Size in Instructions fprintf( report, "\n", symbol->second.stats.sizeInInstructions ); // Total Uncovered Ranges fprintf( report, "\n", symbol->second.stats.uncoveredRanges ); // Uncovered Size in Bytes fprintf( report, "\n", symbol->second.stats.uncoveredBytes ); // Uncovered Size in Instructions fprintf( report, "\n", symbol->second.stats.uncoveredInstructions ); // Total number of branches fprintf( report, "\n", symbol->second.stats.branchesNotExecuted + symbol->second.stats.branchesExecuted ); // Total Always Taken fprintf( report, "\n", symbol->second.stats.branchesAlwaysTaken ); // Total Never Taken fprintf( report, "\n", symbol->second.stats.branchesNeverTaken ); // % Uncovered Instructions if ( symbol->second.stats.sizeInInstructions == 0 ) fprintf( report, "\n" ); else fprintf( report, "\n", (symbol->second.stats.uncoveredInstructions*100.0)/ symbol->second.stats.sizeInInstructions ); // % Uncovered Bytes if ( symbol->second.stats.sizeInBytes == 0 ) fprintf( report, "\n" ); else fprintf( report, "\n", (symbol->second.stats.uncoveredBytes*100.0)/ symbol->second.stats.sizeInBytes ); fprintf( report, "\n"); return true; } void ReportsHtml::CloseAnnotatedFile( FILE* aFile ) { fprintf( aFile, "\n" "\n" "" ); CloseFile(aFile); } void ReportsHtml::CloseBranchFile( FILE* aFile, bool hasBranches ) { if ( hasBranches ) { fprintf( aFile, TABLE_FOOTER "\n" "
    SymbolTotal
    Size
    Bytes
    Total
    Size
    Instr
    #
    Ranges
    Uncovered
    Size
    Bytes
    Uncovered
    Size
    Instr
    #
    Branches
    #
    Always
    Taken
    #
    Never
    Taken
    Percent
    Uncovered
    Instructions
    Percent
    Uncovered
    Bytes
    %s%s%s%dAlways TakenNever Taken%d%dNONENo Explanation%s" "Explanation
    %s%sunknownunknownunknownunknownUnknown" "No data
    %s%s
    %s
    %s%d%dNONENo Explanation%s" "Explanation
    %d%s%s%s
    %s%d%d%d%d%d%d%d%d100.00%.2f100.00%.2f
    \n" ); } fprintf( aFile, "
    \n" "\n" "" ); CloseFile(aFile); } void ReportsHtml::CloseCoverageFile( FILE* aFile ) { fprintf( aFile, TABLE_FOOTER "\n" "\n" "\n" "\n" "" ); CloseFile(aFile); } void ReportsHtml::CloseNoRangeFile( FILE* aFile ) { fprintf( aFile, TABLE_FOOTER "\n" "\n" "\n" "\n" "" ); CloseFile(aFile); } void ReportsHtml::CloseSizeFile( FILE* aFile ) { fprintf( aFile, TABLE_FOOTER "\n" "\n" "\n" "\n" "" ); CloseFile( aFile ); } void ReportsHtml::CloseSymbolSummaryFile( FILE* aFile ) { fprintf( aFile, TABLE_FOOTER "\n" "\n" "\n" "\n" "" ); CloseFile( aFile ); } }