#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, std::string symbolSetName ): ReportsBase( timestamp, symbolSetName ) { 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( "Uncovered Range 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, symbolSetName_m.c_str() ); // 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);
    
        // Put header information into the file
        fprintf(
          aFile,
          "Branch Report\n"
          "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Branch Report
    \n" "
    %s
    \n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\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, "Coverage Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Coverage Report
    \n" "
    %s
    \n" "\n" "
    SymbolLineFileSize
    Bytes
    ReasonTakenNot TakenClassificationExplanation
    \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, "Uncovered Range Size Report\n" "
    " ); if (projectName) fprintf( aFile, "%s
    ", projectName ); fprintf( aFile, "Uncovered Range 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; igetNumberBranchesFound(symbolSetName_m) != 0)
          fprintf( report, "All branch paths taken.\n" );
        else
          fprintf( report, "No branch information found.\n" );
        return true;
      }
    
      bool ReportsHtml::PutBranchEntry(
        FILE*                                            report,
        unsigned int                                     count,
        const std::string&                               symbolName,
        const SymbolInformation&                         symbolInfo,
        Coverage::CoverageRanges::ranges_t::iterator     rangePtr
      )
      {
        const Coverage::Explanation* explanation;
        std::string                  temp;
        int                          i;
        uint32_t                     bAddress = 0;
        uint32_t                     lowAddress = 0;
        Coverage::CoverageMapBase*   theCoverageMap = NULL;
    
        // 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", symbolName.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 = symbolInfo.baseAddress; theCoverageMap = symbolInfo.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, const std::string& symbolName, const SymbolInformation& symbolInfo, 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", symbolName.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, const std::string& symbolName, 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", symbolName.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, const std::string& symbolName, const SymbolInformation& symbolInfo ) { // 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", symbolName.c_str() ); if (symbolInfo.stats.sizeInBytes == 0) { // The symbol has never been seen. Write "unknown" for all columns. fprintf( report, "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" ); } else { // Total Size in Bytes fprintf( report, "\n", symbolInfo.stats.sizeInBytes ); // Total Size in Instructions fprintf( report, "\n", symbolInfo.stats.sizeInInstructions ); // Total Uncovered Ranges fprintf( report, "\n", symbolInfo.stats.uncoveredRanges ); // Uncovered Size in Bytes fprintf( report, "\n", symbolInfo.stats.uncoveredBytes ); // Uncovered Size in Instructions fprintf( report, "\n", symbolInfo.stats.uncoveredInstructions ); // Total number of branches fprintf( report, "\n", symbolInfo.stats.branchesNotExecuted + symbolInfo.stats.branchesExecuted ); // Total Always Taken fprintf( report, "\n", symbolInfo.stats.branchesAlwaysTaken ); // Total Never Taken fprintf( report, "\n", symbolInfo.stats.branchesNeverTaken ); // % Uncovered Instructions if ( symbolInfo.stats.sizeInInstructions == 0 ) fprintf( report, "\n" ); else fprintf( report, "\n", (symbolInfo.stats.uncoveredInstructions*100.0)/ symbolInfo.stats.sizeInInstructions ); // % Uncovered Bytes if ( symbolInfo.stats.sizeInBytes == 0 ) fprintf( report, "\n" ); else fprintf( report, "\n", (symbolInfo.stats.uncoveredBytes*100.0)/ symbolInfo.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 ) { 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
    %sunknownunknownunknownunknownunknownunknownunknownunknownunknownunknown%d%d%d%d%d%d%d%d100.00%.2f100.00%.2f
    \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 ); } }