summaryrefslogtreecommitdiffstats
path: root/tester/covoar/covoar.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tester/covoar/covoar.cc')
-rw-r--r--tester/covoar/covoar.cc300
1 files changed, 189 insertions, 111 deletions
diff --git a/tester/covoar/covoar.cc b/tester/covoar/covoar.cc
index c36b00a..81c90d2 100644
--- a/tester/covoar/covoar.cc
+++ b/tester/covoar/covoar.cc
@@ -29,34 +29,92 @@
#define kill(p,s) raise(s)
#endif
+typedef std::list<std::string> CoverageNames;
+typedef std::list<Coverage::ExecutableInfo*> Executables;
+
/*
- * Variables to control general behavior
+ * Create a build path from the executable paths. Also extract the build prefix
+ * and BSP names.
*/
-const char* coverageFileExtension = NULL;
-std::list<std::string> coverageFileNames;
-int coverageExtensionLength = 0;
-Coverage::CoverageFormats_t coverageFormat;
-Coverage::CoverageReaderBase* coverageReader = NULL;
-char* executable = NULL;
-const char* executableExtension = NULL;
-int executableExtensionLength = 0;
-std::list<Coverage::ExecutableInfo*> executablesToAnalyze;
-const char* explanations = NULL;
-char* progname;
-const char* symbolsFile = NULL;
-const char* gcnosFileName = NULL;
-char gcnoFileName[FILE_NAME_LENGTH];
-char gcdaFileName[FILE_NAME_LENGTH];
-char gcovBashCommand[256];
-const char* target = NULL;
-const char* format = NULL;
-FILE* gcnosFile = NULL;
-Gcov::GcovData* gcovFile;
+static void createBuildPath(Executables& executablesToAnalyze,
+ std::string& buildPath,
+ std::string& buildPrefix,
+ std::string& buildBSP)
+{
+ for (const auto& exe : executablesToAnalyze) {
+ rld::strings eparts;
+ rld::split(eparts, rld::path::path_abs(exe->getFileName()), RLD_PATH_SEPARATOR);
+ std::string fail; // empty means all is OK else an error string
+ for (rld::path::paths::reverse_iterator pri = eparts.rbegin();
+ pri != eparts.rend();
+ ++pri) {
+ if (*pri == "testsuites") {
+ ++pri;
+ if (pri == eparts.rend()) {
+ fail = "invalid executable path, no BSP";
+ break;
+ }
+ if (buildBSP.empty()) {
+ buildBSP = *pri;
+ } else {
+ if (buildBSP != *pri) {
+ fail = "executable BSP does not match: " + buildBSP;
+ break;
+ }
+ }
+ ++pri;
+ if (pri == eparts.rend() || *pri != "c") {
+ fail = "invalid executable path, no 'c'";
+ break;
+ }
+ ++pri;
+ if (pri == eparts.rend()) {
+ fail = "invalid executable path, no arch prefix";
+ break;
+ }
+ if (buildPrefix.empty()) {
+ buildPrefix = *pri;
+ } else {
+ if (buildBSP != *pri) {
+ fail = "executable build prefix does not match: " + buildPrefix;
+ break;
+ }
+ }
+ ++pri;
+ if (pri == eparts.rend()) {
+ fail = "invalid executable path, no build top";
+ break;
+ }
+ //
+ // The remaining parts of the path is the build path. Iterator over them
+ // and collect into a new paths variable to join to make a path.
+ //
+ rld::path::paths bparts;
+ for (; pri != eparts.rend(); ++pri)
+ bparts.insert(bparts.begin(), *pri);
+ std::string thisBuildPath;
+ rld::path::path_join(thisBuildPath, bparts, thisBuildPath);
+ if (buildPath.empty()) {
+ buildPath = thisBuildPath;
+ } else {
+ if (buildBSP != *pri) {
+ fail = "executable build path does not match: " + buildPath;
+ }
+ }
+ break;
+ }
+ }
+ if (!fail.empty()) {
+ std::cerr << "ERROR: " << fail << std::endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+}
/*
* Print program usage message
*/
-void usage()
+void usage(const std::string& progname)
{
fprintf(
stderr,
@@ -69,17 +127,18 @@ void usage()
" -f FORMAT - coverage file format "
"(RTEMS, QEMU, TSIM or Skyeye)\n"
" -E EXPLANATIONS - name of file with explanations\n"
- " -s SYMBOLS_FILE - name of file with symbols of interest\n"
+ " -s SYMBOL_SET_FILE - path to the INI format symbol sets\n"
" -1 EXECUTABLE - name of executable to get symbols from\n"
" -e EXE_EXTENSION - extension of the executables to analyze\n"
" -c COVERAGEFILE_EXTENSION - extension of the coverage files to analyze\n"
" -g GCNOS_LIST - name of file with list of *.gcno files\n"
" -p PROJECT_NAME - name of the project\n"
" -C ConfigurationFileName - name of configuration file\n"
- " -O Output_Directory - name of output directory (default=."
+ " -O Output_Directory - name of output directory (default=.\n"
+ " -d debug - disable cleaning of tempfiles."
"\n",
- progname,
- progname
+ progname.c_str(),
+ progname.c_str()
);
}
@@ -125,42 +184,58 @@ int main(
char** argv
)
{
- std::list<std::string>::iterator citr;
- std::string coverageFileName;
- std::list<Coverage::ExecutableInfo*>::iterator eitr;
- Coverage::ExecutableInfo* executableInfo = NULL;
- int i;
- int opt;
- const char* singleExecutable = NULL;
- rld::process::tempfile objdumpFile( ".dmp" );
- rld::process::tempfile err( ".err" );
- bool debug = false;
- std::string option;
+ CoverageNames coverageFileNames;
+ std::string coverageFileName;
+ Executables executablesToAnalyze;
+ Coverage::ExecutableInfo* executableInfo = NULL;
+ std::string executableExtension = "exe";
+ std::string coverageExtension = "cov";
+ Coverage::CoverageFormats_t coverageFormat;
+ Coverage::CoverageReaderBase* coverageReader = NULL;
+ char* executable = NULL;
+ const char* explanations = NULL;
+ const char* gcnosFileName = NULL;
+ char gcnoFileName[FILE_NAME_LENGTH];
+ char gcdaFileName[FILE_NAME_LENGTH];
+ char gcovBashCommand[256];
+ std::string target;
+ const char* format = "html";
+ FILE* gcnosFile = NULL;
+ Gcov::GcovData* gcovFile;
+ const char* singleExecutable = NULL;
+ rld::process::tempfile objdumpFile( ".dmp" );
+ rld::process::tempfile err( ".err" );
+ rld::process::tempfile syms( ".syms" );
+ bool debug = false;
+ std::string symbolSet;
+ std::string progname;
+ std::string option;
+ int opt;
setup_signals();
//
// Process command line options.
//
- progname = argv[0];
+ progname = rld::path::basename(argv[0]);
- while ((opt = getopt(argc, argv, "1:L:e:c:g:E:f:s:T:O:p:v:d")) != -1) {
+ while ((opt = getopt(argc, argv, "1:L:e:c:g:E:f:s:S:T:O:p:vd")) != -1) {
switch (opt) {
- case '1': singleExecutable = optarg; break;
- case 'L': dynamicLibrary = optarg; break;
- case 'e': executableExtension = optarg; break;
- case 'c': coverageFileExtension = optarg; break;
- case 'g': gcnosFileName = optarg; break;
- case 'E': explanations = optarg; break;
- case 'f': format = optarg; break;
- case 's': symbolsFile = optarg; break;
- case 'T': target = optarg; break;
- case 'O': outputDirectory = optarg; break;
- case 'v': Verbose = true; break;
- case 'p': projectName = optarg; break;
- case 'd': debug = true; break;
+ case '1': singleExecutable = optarg; break;
+ case 'L': dynamicLibrary = optarg; break;
+ case 'e': executableExtension = optarg; break;
+ case 'c': coverageExtension = optarg; break;
+ case 'g': gcnosFileName = optarg; break;
+ case 'E': explanations = optarg; break;
+ case 'f': format = optarg; break;
+ case 'S': symbolSet = optarg; break;
+ case 'T': target = optarg; break;
+ case 'O': outputDirectory = optarg; break;
+ case 'v': Verbose = true; break;
+ case 'p': projectName = optarg; break;
+ case 'd': debug = true; break;
default: /* '?' */
- usage();
+ usage(progname);
exit(EXIT_FAILURE);
}
}
@@ -171,18 +246,10 @@ int main(
*/
/*
- * Target name must be set.
+ * Validate that we have a symbols of interest file.
*/
- if ( !target ) {
- option = "target -T";
- throw option;
- }
-
- /*
- * Validate simulator format.
- */
- if ( !format ) {
- option = "format -f";
+ if ( symbolSet.empty() ) {
+ option = "symbol set file -S";
throw option;
}
@@ -195,22 +262,6 @@ int main(
}
/*
- * Has coverage file extension been specified.
- */
- if ( !coverageFileExtension ) {
- option = "coverage extension -c";
- throw option;
- }
-
- /*
- * Has executable extension been specified.
- */
- if ( !executableExtension ) {
- option = "executable extension -e";
- throw option;
- }
-
- /*
* Check for project name.
*/
if ( !projectName ) {
@@ -220,8 +271,8 @@ int main(
}
catch( std::string option )
{
- std::cout << "error missing option: " + option << std::endl;
- usage();
+ std::cerr << "error missing option: " + option << std::endl;
+ usage(progname);
exit(EXIT_FAILURE);
}
@@ -238,7 +289,7 @@ int main(
);
} else {
- for (i=optind; i < argc; i++) {
+ for (int i = optind; i < argc; i++) {
// Ensure that the coverage file is readable.
if (!FileIsReadable( argv[i] )) {
fprintf(
@@ -266,11 +317,10 @@ int main(
}
}
}
-
- // If not invoked with a single executable, process the remaining
- // arguments as executables and derive the coverage file names.
else {
- for (i = optind; i < argc; i++) {
+ // If not invoked with a single executable, process the remaining
+ // arguments as executables and derive the coverage file names.
+ for (int i = optind; i < argc; i++) {
// Ensure that the executable is readable.
if (!FileIsReadable( argv[i] )) {
@@ -282,9 +332,9 @@ int main(
} else {
coverageFileName = argv[i];
coverageFileName.replace(
- coverageFileName.length() - executableExtensionLength,
- executableExtensionLength,
- coverageFileExtension
+ coverageFileName.length() - executableExtension.size(),
+ executableExtension.size(),
+ coverageExtension
);
if (!FileIsReadable( coverageFileName.c_str() )) {
@@ -310,6 +360,33 @@ int main(
exit(EXIT_FAILURE);
}
+ // The executablesToAnalyze and coverageFileNames containers need
+ // to be the name size of some of the code below breaks. Lets
+ // check and make sure.
+ if (executablesToAnalyze.size() != coverageFileNames.size()) {
+ std::cerr << "ERROR: executables and coverage name size mismatch" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ //
+ // Find the top of the BSP's build tree and if we have found the top
+ // check the executable is under the same path and BSP.
+ //
+ std::string buildPath;
+ std::string buildTarget;
+ std::string buildBSP;
+ createBuildPath(executablesToAnalyze,
+ buildPath,
+ buildTarget,
+ buildBSP);
+
+ //
+ // Use a command line target if provided.
+ //
+ if (!target.empty()) {
+ buildTarget = target;
+ }
+
if (Verbose) {
if (singleExecutable) {
fprintf(
@@ -323,12 +400,12 @@ int main(
);
}
fprintf( stderr, "Coverage Format : %s\n", format );
- fprintf( stderr, "Target : %s\n", PrintableString(target) );
+ fprintf( stderr, "Target : %s\n", buildTarget.c_str() );
fprintf( stderr, "\n" );
-#if 1
+
// Process each executable/coverage file pair.
- eitr = executablesToAnalyze.begin();
- for (citr = coverageFileNames.begin();
+ Executables::iterator eitr = executablesToAnalyze.begin();
+ for (CoverageNames::iterator citr = coverageFileNames.begin();
citr != coverageFileNames.end();
citr++) {
@@ -342,7 +419,6 @@ int main(
if (!singleExecutable)
eitr++;
}
-#endif
}
//
@@ -350,19 +426,22 @@ int main(
//
// Create data based on target.
- TargetInfo = Target::TargetFactory( target );
+ TargetInfo = Target::TargetFactory( buildTarget );
// Create the set of desired symbols.
SymbolsToAnalyze = new Coverage::DesiredSymbols();
- SymbolsToAnalyze->load( symbolsFile );
- if (Verbose) {
- fprintf(
- stderr,
- "Analyzing %u symbols\n",
- (unsigned int) SymbolsToAnalyze->set.size()
- );
+
+ //
+ // Read symbol configuration file and load needed symbols.
+ //
+ if (!SymbolsToAnalyze->load( symbolSet, buildTarget, buildBSP, Verbose )) {
+ exit(EXIT_FAILURE);
}
+ if ( Verbose )
+ std::cout << "Analyzing " << SymbolsToAnalyze->set.size()
+ << " symbols" << std::endl;
+
// Create explanations.
AllExplanations = new Coverage::Explanations();
if ( explanations )
@@ -379,7 +458,7 @@ int main(
objdumpProcessor = new Coverage::ObjdumpProcessor();
// Prepare each executable for analysis.
- for (eitr = executablesToAnalyze.begin();
+ for (Executables::iterator eitr = executablesToAnalyze.begin();
eitr != executablesToAnalyze.end();
eitr++) {
@@ -407,22 +486,19 @@ int main(
//
// Process each executable/coverage file pair.
- eitr = executablesToAnalyze.begin();
- for (citr = coverageFileNames.begin();
- citr != coverageFileNames.end();
- citr++) {
-
+ Executables::iterator eitr = executablesToAnalyze.begin();
+ for (const auto& cname : coverageFileNames) {
if (Verbose) {
fprintf(
stderr,
"Processing coverage file %s for executable %s\n",
- (*citr).c_str(),
+ cname.c_str(),
((*eitr)->getFileName()).c_str()
);
}
// Process its coverage file.
- coverageReader->processFile( (*citr).c_str(), *eitr );
+ coverageReader->processFile( cname.c_str(), *eitr );
// Merge each symbols coverage map into a unified coverage map.
(*eitr)->mergeCoverage();
@@ -524,6 +600,8 @@ int main(
objdumpFile.keep();
err.override( "objdump_exec_log" );
err.keep();
+ syms.override( "symbols_list" );
+ syms.keep();
}
return 0;
}