#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:
              fprintf(stderr, "ERROR:  ReportsHtml::PutAnnotatedLine Unknown state\n");
              exit( -1 );
              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, 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 ); } }