summaryrefslogtreecommitdiff
path: root/covoar/covmerge.cc
diff options
context:
space:
mode:
Diffstat (limited to 'covoar/covmerge.cc')
-rw-r--r--covoar/covmerge.cc541
1 files changed, 0 insertions, 541 deletions
diff --git a/covoar/covmerge.cc b/covoar/covmerge.cc
deleted file mode 100644
index e283774..0000000
--- a/covoar/covmerge.cc
+++ /dev/null
@@ -1,541 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "app_common.h"
-#include "CoverageFactory.h"
-#include "CoverageMap.h"
-#include "CoverageRanges.h"
-#include "Explanations.h"
-#include "ObjdumpProcessor.h"
-#include "Reports.h"
-
-/*
- * Variables to control global behavior
- */
-int verbose = 0;
-Coverage::CoverageFormats_t coverageFormat;
-char *mergedCoverageFile = NULL;
-char *branchReportFile = NULL;
-char *coverageReportFile = NULL;
-char *sizeReportFile = NULL;
-uint32_t lowAddress = 0xffffffff;
-uint32_t highAddress = 0xffffffff;
-
-char *target = NULL;
-char *executable = NULL;
-char *explanations = NULL;
-char *noExplanations = NULL;
-char *progname;
-
-/*
- * Global variables for the program
- */
-Coverage::CoverageMapBase *CoverageMap = NULL;
-Coverage::CoverageReaderBase *CoverageReader = NULL;
-Coverage::CoverageWriterBase *CoverageWriter = NULL;
-Coverage::ObjdumpProcessor *ObjdumpProcessor = NULL;
-Coverage::CoverageRanges *Ranges = NULL;
-Coverage::Explanations *Explanations = NULL;
-
-int BranchesAlwaysTaken = 0;
-bool BranchesFound = false;
-int BranchesNeverTaken = 0;
-int UncoveredRanges = 0;
-
-/*
- * Set of addresses we need source line number for
- */
-std::list<uint32_t> AddressesNeedingSourceLine;
-
-/*
- * Convert string to int with status out
- */
-
-bool stringToUint32(
- const char *s,
- int base,
- uint32_t *n
-)
-{
- long long result;
-
- if ( !n )
- return false;
-
- errno = 0;
- *n = 0;
-
- result = strtoll( s, NULL, base );
-
- if ( (result == 0) && errno )
- return false;
-
- if ( (result == LLONG_MAX) && (errno == ERANGE))
- return false;
-
- if ( (result == LLONG_MIN) && (errno == ERANGE))
- return false;
-
- *n = (uint32_t)result;
- return true;
-}
-
-/*
- * Print program usage message
- */
-void usage()
-{
- fprintf(
- stderr,
- "Usage: %s [-v] [-t] [-m file] -T TARGET [-e EXECUTABLE]-l ADDRESS -h ADDRESS coverage1... coverageN\n"
- "\n"
- " -l low address - low address of range to merge\n"
- " -l high address - high address of range to merge\n"
- " -f format - coverage files are in <format> "
- "(RTEMS, TSIM or Skyeye)\n"
- " -m FILE - optional merged coverage file to write\n"
- " -r REPORT - optional coverage report to write\n"
- " -s REPORT - optional size report to write\n"
- " -T TARGET - target name\n"
- " -e EXECUTABLE - name of executable to get symbols from\n"
- " -E EXPLANATIONS - name of file with explanations\n"
- " -v - verbose at initialization\n"
- "\n",
- progname
- );
-}
-
-/*
- * Look over the coverage map and compute uncovered ranges and branches
- */
-void ComputeUncovered(void)
-{
- uint32_t a, la, ha;
- std::list<Coverage::CoverageRange>::iterator it;
-
- a = lowAddress;
- while (a < highAddress) {
-
- /*
- * Find all the unexecuted addresses and add them to the range.
- */
- if (!CoverageMap->wasExecuted( a )) {
- la = a;
- for (ha=a+1; ha<=highAddress && !CoverageMap->wasExecuted(ha); ha++)
- ;
- ha--;
-
- UncoveredRanges++;
- Ranges->add( la, ha );
- AddressesNeedingSourceLine.push_back( la );
- AddressesNeedingSourceLine.push_back( ha );
- a = ha + 1;
- }
-
- else if (CoverageMap->isBranch( a )) {
- BranchesFound = true;
- la = a;
- for (ha=a+1;
- ha<=highAddress && !CoverageMap->isStartOfInstruction(ha);
- ha++)
- ;
- ha--;
-
- if (CoverageMap->wasAlwaysTaken( la )) {
- BranchesAlwaysTaken++;
- AddressesNeedingSourceLine.push_back( la );
- }
- else if (CoverageMap->wasNeverTaken( la )) {
- BranchesNeverTaken++;
- AddressesNeedingSourceLine.push_back( la );
- }
- a = ha + 1;
- }
- else
- a++;
- }
-}
-
-/*
- * Find source lines for addresses
- */
-void FindSourceForAddresses(void)
-{
- FILE *tmpfile;
- std::list<uint32_t>::iterator it;
-
- /*
- * Write a temporary file with ranges
- */
- if ( verbose )
- fprintf( stderr, "Writing ranges.tmp input to addr2line\n" );
-
- tmpfile = fopen( "ranges.tmp", "w" );
- if ( !tmpfile ) {
- fprintf( stderr, "Unable to open %s\n\n", "ranges.tmp" );
- exit(-1);
- }
-
- for (it = AddressesNeedingSourceLine.begin() ;
- it != AddressesNeedingSourceLine.end() ;
- it++ ) {
- fprintf(tmpfile, "0x%08x\n", *it);
- }
-
- fclose( tmpfile );
-
- /*
- * Generate a file with the addr2line mapping
- */
- if ( verbose )
- fprintf( stderr, "Running addr2line\n" );
-
- {
- char command[512];
- sprintf(
- command,
- "%s -e %s <%s | dos2unix >%s",
- Tools->getAddr2line(),
- executable,
- "ranges.tmp",
- "ranges01.tmp"
- );
- if ( system( command ) ) {
- fprintf( stderr, "addr2line command (%s) failed\n", command );
- exit( -1 );
- }
- }
-
- /*
- * Go back over the ranges, read the addr2line output, and correlate it.
- */
- if ( verbose )
- fprintf( stderr, "Merging addr2line output into range\n" );
-
- tmpfile = fopen( "ranges01.tmp", "r" );
- if ( !tmpfile ) {
- fprintf( stderr, "Unable to open %s\n\n", "ranges01.tmp" );
- exit(-1);
- }
-
- for (it = AddressesNeedingSourceLine.begin() ;
- it != AddressesNeedingSourceLine.end() ;
- it++ ) {
- char buffer[512];
- char *cStatus;
-
- cStatus = fgets( buffer, 512, tmpfile );
- if ( cStatus == NULL ) {
- fprintf( stderr, "Out of sync in addr2line output\n" );
- exit( -1 );
- }
- buffer[ strlen(buffer) - 1] = '\0';
-
- CoverageMap->setSourceLine( *it, std::string( buffer ) );
- }
- fclose( tmpfile );
-}
-
-#define PrintableString(_s) \
- ((!(_s)) ? "NOT SET" : (_s))
-
-int main(
- int argc,
- char **argv
-)
-{
- int opt;
- int i;
- char *format = NULL;
-
- progname = argv[0];
-
- while ((opt = getopt(argc, argv, "b:e:E:f:h:l:m:r:s:T:v")) != -1) {
- switch (opt) {
- case 'b': branchReportFile = optarg; break;
- case 'e': executable = optarg; break;
- case 'E': explanations = optarg; break;
- case 'm': mergedCoverageFile = optarg; break;
- case 'r': coverageReportFile = optarg; break;
- case 's': sizeReportFile = optarg; break;
- case 'T': target = optarg; break;
- case 'v': verbose = 1; break;
- case 'f':
- coverageFormat = Coverage::CoverageFormatToEnum(optarg);
- format = optarg;
- break;
- case 'l':
- if ( ! stringToUint32( optarg, 16, &lowAddress ) ) {
- fprintf( stderr, "Low address is not a hexadecimal number\n" );
- usage();
- exit(-1);
- }
- break;
- case 'h':
- if ( ! stringToUint32( optarg, 16, &highAddress ) ) {
- fprintf( stderr, "High address is not a hexadecimal number\n" );
- usage();
- exit(-1);
- }
- break;
- default: /* '?' */
- usage();
- exit( -1 );
- }
- }
- if ( verbose ) {
- fprintf( stderr, "verbose : %d\n", verbose );
- fprintf( stderr, "Coverage Format : %s\n", format );
- fprintf( stderr, "low address : 0x%08x\n", lowAddress );
- fprintf( stderr, "high address : 0x%08x\n", highAddress );
- fprintf( stderr, "Target : %s\n", PrintableString(target) );
- fprintf( stderr, "executable : %s\n", PrintableString(executable) );
- fprintf( stderr, "merged coverage : %s\n",
- PrintableString(mergedCoverageFile) );
- fprintf( stderr, "\n" );
- }
-
- /*
- * Target name must be set
- */
- if ( !target ) {
- fprintf( stderr, "target must be given.\n\n" );
- usage();
- exit(-1);
- }
-
- /*
- * Validate format
- */
- if ( !format ) {
- fprintf( stderr, "coverage format report must be given.\n\n" );
- usage();
- exit(-1);
- }
-
- /*
- * Validate address range
- */
- if ( lowAddress == 0xffffffff ) {
- fprintf( stderr, "Low address not specified.\n\n" );
- usage();
- exit(-1);
- }
-
- if ( highAddress == 0xffffffff ) {
- fprintf( stderr, "High address not specified.\n\n" );
- usage();
- exit(-1);
- }
-
- if ( lowAddress >= highAddress ) {
- fprintf( stderr, "Low address >= high address.\n\n" );
- usage();
- exit(-1);
- }
-
- /*
- * Create toolnames based on target
- */
- TargetInfo = Target::TargetFactory( target );
-
- /*
- * Create a ranges set
- */
- Ranges = new Coverage::CoverageRanges();
- Explanations = new Coverage::Explanations();
-
- Explanations->load( explanations );
-
- /*
- * Create coverage map
- */
- CoverageMap = new Coverage::CoverageMap( lowAddress, highAddress );
- if ( !CoverageMap ) {
- fprintf( stderr, "Unable to create coverage map.\n\n" );
- exit(-1);
- }
-
- /*
- * Create input
- */
- CoverageReader = Coverage::CreateCoverageReader(coverageFormat);
- if ( !CoverageReader ) {
- fprintf( stderr, "Unable to create coverage file reader.\n\n" );
- exit(-1);
- }
-
- /*
- * Create the objdump processor
- */
- ObjdumpProcessor = new Coverage::ObjdumpProcessor();
-
- /*
- * Create writer
- *
- * NOTE: We ALWAYS write the merged coverage in RTEMS format.
- */
- CoverageWriter = Coverage::CreateCoverageWriter(
- Coverage::COVERAGE_FORMAT_RTEMS
- );
- if ( !CoverageWriter ) {
- fprintf( stderr, "Unable to create coverage file writer.\n\n" );
- exit(-1);
- }
-
- /*
- * Add in the objdump before reading the coverage information. We may
- * want to take advantage of the information line where instructions
- * begin.
- */
- if ( executable ) {
- if ( verbose )
- fprintf( stderr, "Reading objdump of %s\n", executable );
- ObjdumpProcessor->initialize( executable, CoverageMap );
- }
-
- /*
- * Now get to some real work
- */
- if ( verbose )
- fprintf( stderr, "Processing coverage files\n" );
- for ( i=optind ; i < argc ; i++ ) {
- //fprintf( stderr, "Processing %s\n", argv[i] );
- CoverageReader->ProcessFile( argv[i], CoverageMap );
- }
-
- /*
- * Now to write some output
- */
- if ( mergedCoverageFile ) {
- if ( verbose )
- fprintf(
- stderr,
- "Writing merged coverage file (%s)\n",
- mergedCoverageFile
- );
- CoverageWriter->writeFile(
- mergedCoverageFile,
- CoverageMap,
- lowAddress,
- highAddress
- );
- }
-
- /*
- * Marks nops as executed when they are surrounded by executed instructions.
- */
- ObjdumpProcessor->markNopsAsExecuted( CoverageMap );
-
- /*
- * Iterate over the coverage map and determine the uncovered
- * ranges and branches.
- */
- ComputeUncovered();
-
- /*
- * Look up the source file and line number for the addresses
- * of interest.
- */
- FindSourceForAddresses();
-
- /*
- * Generate report of ranges not executed
- */
- if ( coverageReportFile ) {
- if ( verbose )
- fprintf( stderr, "Writing coverage report (%s)\n", coverageReportFile );
- WriteCoverageReport( coverageReportFile );
-
- /*
- * Let the user know how many cases there were
- */
- printf( "%d uncovered ranges found\n", UncoveredRanges );
- }
-
- /*
- * Generate report of branches taken/not taken
- */
- if ( branchReportFile ) {
- if ( verbose )
- fprintf( stderr, "Writing branch report (%s)\n", branchReportFile );
- WriteBranchReport( branchReportFile, lowAddress, highAddress );
-
- /*
- * Let the user know how many branch cases were found
- */
- if (!BranchesFound)
- printf( "No branch information found\n" );
- else {
- printf(
- "%d uncovered branches found\n",
- BranchesAlwaysTaken + BranchesNeverTaken
- );
- printf(
- " %d branches always taken\n", BranchesAlwaysTaken
- );
- printf(
- " %d branches never taken\n", BranchesNeverTaken
- );
- }
- }
-
- /*
- * Simple formatted report of size of ranges
- */
- if ( sizeReportFile ) {
- if ( verbose )
- fprintf( stderr, "Writing size report (%s)\n", sizeReportFile );
- WriteSizeReport( sizeReportFile );
- }
-
- /*
- * Generate annotated assembly file
- */
- if ( verbose )
- fprintf( stderr, "Writing annotated report (%s)\n", "annotated.txt" );
- WriteAnnotatedReport( "annotated.txt", lowAddress, highAddress );
-
- /*
- * write explanations that were not found
- */
- std::string str = explanations;
- str = str + ".NotFound";
- if ( verbose )
- fprintf( stderr, "Writing Not Found Report (%s)\n", str.c_str() );
- Explanations->writeNotFound(str.c_str());
-
- /*
- * Calculate coverage percentage
- */
- {
- uint32_t a;
- uint32_t notExecuted = 0;
- double percentage;
-
- for ( a=lowAddress ; a < highAddress ; a++ ) {
- if ( !CoverageMap->wasExecuted( a ) )
- notExecuted++;
- }
-
- percentage = (double) notExecuted;
- percentage /= (double) (highAddress - lowAddress);
- percentage *= 100.0;
- printf( "Bytes Analyzed : %d\n", highAddress - lowAddress );
- printf( "Bytes Not Executed : %d\n", notExecuted );
- printf( "Percentage Executed : %5.4g\n", 100.0 - percentage );
- printf( "Percentage Not Executed : %5.4g\n", percentage );
- }
-
- return 0;
-}