#include <stdio.h>
#include <string.h>
#include "ReportsText.h"
#include "app_common.h"
#include "CoverageRanges.h"
#include "DesiredSymbols.h"
#include "Explanations.h"
#include "ObjdumpProcessor.h"
namespace Coverage {
ReportsText::ReportsText( time_t timestamp, std::string symbolSetName ):
ReportsBase( timestamp, symbolSetName )
{
reportExtension_m = ".txt";
}
ReportsText::~ReportsText()
{
}
void ReportsText::AnnotatedStart(
FILE* aFile
)
{
fprintf(
aFile,
"========================================"
"=======================================\n"
);
}
void ReportsText::AnnotatedEnd(
FILE* aFile
)
{
}
void ReportsText::PutAnnotatedLine(
FILE* aFile,
AnnotatedLineState_t state,
std::string line,
uint32_t id
)
{
fprintf( aFile, "%s\n", line.c_str());
}
bool ReportsText::PutNoBranchInfo(
FILE* report
)
{
if ( BranchInfoAvailable &&
SymbolsToAnalyze->getNumberBranchesFound(symbolSetName_m) != 0 )
fprintf( report, "All branch paths taken.\n" );
else
fprintf( report, "No branch information found.\n" );
return true;
}
bool ReportsText::PutBranchEntry(
FILE* report,
unsigned int number,
const std::string& symbolName,
const SymbolInformation& symbolInfo,
const CoverageRanges::coverageRange_t& range
)
{
const Coverage::Explanation* explanation;
// Add an entry to the report
fprintf(
report,
"============================================\n"
"Symbol : %s (0x%x)\n"
"Line : %s (0x%x)\n"
"Size in Bytes : %d\n",
symbolName.c_str(),
symbolInfo.baseAddress,
range.lowSourceLine.c_str(),
range.lowAddress,
range.highAddress - range.lowAddress + 1
);
if (range.reason ==
Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_ALWAYS_TAKEN)
fprintf(
report, "Reason : %s\n\n", "ALWAYS TAKEN"
);
else if (range.reason ==
Coverage::CoverageRanges::UNCOVERED_REASON_BRANCH_NEVER_TAKEN)
fprintf( report, "Reason : %s\n\n", "NEVER TAKEN" );
// See if an explanation is available
explanation = AllExplanations->lookupExplanation( range.lowSourceLine );
if ( !explanation ) {
fprintf(
report,
"Classification: NONE\n"
"\n"
"Explanation:\n"
"No Explanation\n"
);
} else {
fprintf(
report,
"Classification: %s\n"
"\n"
"Explanation:\n",
explanation->classification.c_str()
);
for ( unsigned int i=0 ;
i < explanation->explanation.size();
i++) {
fprintf(
report,
"%s\n",
explanation->explanation[i].c_str()
);
}
}
fprintf(
report, "============================================\n"
);
return true;
}
void ReportsText::putCoverageNoRange(
FILE* report,
FILE* noRangeFile,
unsigned int number,
std::string symbol
)
{
fprintf(
report,
"============================================\n"
"Symbol : %s\n\n"
" *** NEVER REFERENCED ***\n\n"
"This symbol was never referenced by an analyzed executable.\n"
"Therefore there is no size or disassembly for this symbol.\n"
"This could be due to symbol misspelling or lack of a test for\n"
"this symbol.\n"
"============================================\n",
symbol.c_str()
);
fprintf( noRangeFile, "%s\n", symbol.c_str() );
}
bool ReportsText::PutCoverageLine(
FILE* report,
unsigned int number,
const std::string& symbolName,
const SymbolInformation& symbolInfo,
const CoverageRanges::coverageRange_t& range
)
{
const Coverage::Explanation* explanation;
fprintf(
report,
"============================================\n"
"Index : %d\n"
"Symbol : %s (0x%x)\n"
"Starting Line : %s (0x%x)\n"
"Ending Line : %s (0x%x)\n"
"Size in Bytes : %d\n"
"Size in Instructions : %d\n\n",
range.id,
symbolName.c_str(),
symbolInfo.baseAddress,
range.lowSourceLine.c_str(),
range.lowAddress,
range.highSourceLine.c_str(),
range.highAddress,
range.highAddress - range.lowAddress + 1,
range.instructionCount
);
explanation = AllExplanations->lookupExplanation( range.lowSourceLine );
if ( !explanation ) {
fprintf(
report,
"Classification: NONE\n"
"\n"
"Explanation:\n"
"No Explanation\n"
);
} else {
fprintf(
report,
"Classification: %s\n"
"\n"
"Explanation:\n",
explanation->classification.c_str()
);
for ( unsigned int i=0; i < explanation->explanation.size(); i++) {
fprintf( report,"%s\n", explanation->explanation[i].c_str() );
}
}
fprintf(report, "============================================\n");
return true;
}
bool ReportsText::PutSizeLine(
FILE* report,
unsigned int number,
const std::string& symbolName,
const CoverageRanges::coverageRange_t& range
)
{
fprintf(
report,
"%d\t%s\t%s\n",
range.highAddress - range.lowAddress + 1,
symbolName.c_str(),
range.lowSourceLine.c_str()
);
return true;
}
bool ReportsText::PutSymbolSummaryLine(
FILE* report,
unsigned int number,
const std::string& symbolName,
const SymbolInformation& symbolInfo
)
{
float uncoveredBytes;
float uncoveredInstructions;
if (symbolInfo.stats.sizeInBytes == 0) {
fprintf(
report,
"============================================\n"
"Symbol : %s\n"
" *** NEVER REFERENCED ***\n\n"
"This symbol was never referenced by an analyzed executable.\n"
"Therefore there is no size or disassembly for this symbol.\n"
"This could be due to symbol misspelling or lack of a test for\n"
"this symbol.\n",
symbolName.c_str()
);
} else {
if ( symbolInfo.stats.sizeInInstructions == 0 )
uncoveredInstructions = 0;
else
uncoveredInstructions = (symbolInfo.stats.uncoveredInstructions*100.0)/
symbolInfo.stats.sizeInInstructions;
if ( symbolInfo.stats.sizeInBytes == 0 )
uncoveredBytes = 0;
else
uncoveredBytes = (symbolInfo.stats.uncoveredBytes*100.0)/
symbolInfo.stats.sizeInBytes;
fprintf(
report,
"============================================\n"
"Symbol : %s\n"
"Total Size in Bytes : %d\n"
"Total Size in Instructions : %d\n"
"Total number Branches : %d\n"
"Total Always Taken : %d\n"
"Total Never Taken : %d\n"
"Percentage Uncovered Instructions : %.2f\n"
"Percentage Uncovered Bytes : %.2f\n",
symbolName.c_str(),
symbolInfo.stats.sizeInBytes,
symbolInfo.stats.sizeInInstructions,
symbolInfo.stats.branchesNotExecuted + symbolInfo.stats.branchesExecuted,
symbolInfo.stats.branchesAlwaysTaken,
symbolInfo.stats.branchesNeverTaken,
uncoveredInstructions,
uncoveredBytes
);
}
fprintf(report, "============================================\n");
return true;
}
}