[PATCH] covoar: Add symbol set reader and ELF data parser to covoar.
Chris Johns
chrisj at rtems.org
Sat Apr 28 07:08:18 UTC 2018
From: Cillian O'Donnell <cpodonnell8 at gmail.com>
Add ability to organize symbol sets of libraries in INI file
and then read them with covoar and load the symbols directly from the
libraries.
rtems-tools/../testing: Add configuration files for coverage analysis.
A number of covoar options are not required and are defaulted.
Co-author: Krzysztof Miesowicz <krzysztof.miesowicz at gmail.com>
Co-author: Vijay Kumar Banerjee <vijaykumar9597 at gmail.com>
Cp-author: Chris Johns <chrisj at rtems.org>
---
tester/covoar/DesiredSymbols.cc | 144 +++++-----
tester/covoar/DesiredSymbols.h | 14 +-
tester/covoar/ExecutableInfo.cc | 4 +-
tester/covoar/ExecutableInfo.h | 6 +-
tester/covoar/ObjdumpProcessor.cc | 6 +-
tester/covoar/app_common.h | 9 +-
tester/covoar/covoar.cc | 300 +++++++++++++--------
tester/covoar/wscript | 2 +
tester/rtems/testing/bsps/leon3-qemu-cov.ini | 39 +++
tester/rtems/testing/bsps/leon3-qemu.ini | 38 +++
tester/rtems/testing/coverage/Categories.txt | 19 ++
tester/rtems/testing/coverage/Explanations.txt | 35 +++
.../coverage/SPARC-Annul-Slot-Explanation.txt | 56 ++++
tester/rtems/testing/coverage/score-symbols.ini | 35 +++
tester/rtems/testing/coverage/style.css | 197 ++++++++++++++
tester/rtems/testing/qemu.cfg | 11 +-
tester/rtems/testing/testing.mc | 8 +
17 files changed, 737 insertions(+), 186 deletions(-)
create mode 100644 tester/rtems/testing/bsps/leon3-qemu-cov.ini
create mode 100644 tester/rtems/testing/bsps/leon3-qemu.ini
create mode 100644 tester/rtems/testing/coverage/Categories.txt
create mode 100644 tester/rtems/testing/coverage/Explanations.txt
create mode 100644 tester/rtems/testing/coverage/SPARC-Annul-Slot-Explanation.txt
create mode 100644 tester/rtems/testing/coverage/score-symbols.ini
create mode 100644 tester/rtems/testing/coverage/style.css
diff --git a/tester/covoar/DesiredSymbols.cc b/tester/covoar/DesiredSymbols.cc
index 00d1984..9957b28 100644
--- a/tester/covoar/DesiredSymbols.cc
+++ b/tester/covoar/DesiredSymbols.cc
@@ -16,6 +16,13 @@
#include <string.h>
#include <unistd.h>
+#include <iostream>
+
+#include "rld.h"
+#include <rld-config.h>
+#include "rld-symbols.h"
+#include "rld-files.h"
+
#include "DesiredSymbols.h"
#include "app_common.h"
#include "CoverageMap.h"
@@ -31,75 +38,90 @@ namespace Coverage {
{
}
- void DesiredSymbols::load(
- const char* const symbolsFile
+ bool DesiredSymbols::load(
+ const std::string& symbolsSet,
+ const std::string& buildTarget,
+ const std::string& buildBSP,
+ bool verbose
)
{
- int cStatus;
- bool done = false;
- FILE* sFile;
- SymbolInformation* symInfo;
- int line = 1;
- std::string symbol;
-
- // Ensure that symbols file name is given.
- if ( !symbolsFile ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::load - no symbols file specified\n"
- );
- exit(-1);
- }
-
- // Open symbols file.
- sFile = fopen( symbolsFile, "r" );
- if ( !sFile ) {
- fprintf(
- stderr,
- "ERROR: DesiredSymbols::load - unable to open symbols file %s\n",
- symbolsFile
- );
- exit(-1);
- }
-
- // Process symbols file.
- while ( !done ) {
-
- symInfo = new SymbolInformation;
-
- // Skip blank lines between symbols
- do {
- inputBuffer[0] = '\0';
- inputBuffer2[0] = '\0';
- cStatus = fscanf( sFile, "%s %s", inputBuffer, inputBuffer2 );
- if ( cStatus == EOF ) {
- done = true;
+ rld::files::cache cache;
+ bool r = true;
+
+ //
+ // Load the INI file looking for a top level:
+ //
+ // [symbols-sets]
+ // sets = A, B, C
+ //
+ // For each set read the libraries from the configuration file and load.
+ //
+ // [A]
+ // libraries = @BUILD-PREFIX@/c/@BSP@/A/libA.a
+ //
+ // [B]
+ // libraries = @BUILD-PREFIX@/c/@BSP@/B/libB.a
+ //
+ try {
+ cache.open();
+
+ rld::config::config config;
+
+ if (verbose)
+ std::cerr << "Loading symbol sets: " << symbolsSet << std::endl;
+
+ config.load (symbolsSet);
+
+ const rld::config::section& sym_section = config.get_section("symbol-sets");
+
+ rld::strings sets;
+ rld::config::parse_items (sym_section, "sets", sets, true);
+
+ for (const std::string set : sets) {
+ if (verbose)
+ std::cerr << " Symbol set: " << set << std::endl;
+ const rld::config::section& set_section = config.get_section(set);
+ rld::strings libs;
+ rld::config::parse_items (set_section, "libraries", libs, true);
+ for (std::string lib : libs) {
+ lib = rld::find_replace(lib, "@BUILD-TARGET@", buildTarget);
+ lib = rld::find_replace(lib, "@BSP@", buildBSP);
+ if (verbose)
+ std::cerr << " Loading library: " << lib << std::endl;
+ cache.add(lib);
}
- else {
- //inputBuffer[ strlen(inputBuffer) - 1] = '\0';
- line++;
- }
- } while ( !done && (inputBuffer[0] == '\0') );
+ }
- // Have we already seen this one?
- if ( !done ) {
- if (set.find( inputBuffer ) != set.end()) {
- fprintf(
- stderr,
- "File: %s, Line %d: Duplicate symbol: %s\n",
- symbolsFile,
- line,
- inputBuffer
- );
+ rld::symbols::table symbols;
- delete symInfo;
- }
+ cache.load_symbols (symbols, true);
- // Add this to the set of symbols.
- else
- set[ inputBuffer ] = *symInfo;
+ for (auto& kv : symbols.globals()) {
+ const rld::symbols::symbol& sym = *(kv.second);
+ set[sym.name()] = *(new SymbolInformation);
+ }
+ for (auto& kv : symbols.weaks()) {
+ const rld::symbols::symbol& sym = *(kv.second);
+ set[sym.name()] = *(new SymbolInformation);
+ }
+ for (auto& kv : symbols.locals()) {
+ const rld::symbols::symbol& sym = *(kv.second);
+ set[sym.name()] = *(new SymbolInformation);
}
+
+ } catch (rld::error re) {
+ std::cerr << "error: "
+ << re.where << ": " << re.what
+ << std::endl;
+ r = false;
+ } catch (...) {
+ cache.close();
+ throw;
}
+
+ cache.close();
+
+ return r;
}
void DesiredSymbols::preprocess( void )
diff --git a/tester/covoar/DesiredSymbols.h b/tester/covoar/DesiredSymbols.h
index 9524c64..21c5602 100644
--- a/tester/covoar/DesiredSymbols.h
+++ b/tester/covoar/DesiredSymbols.h
@@ -293,9 +293,17 @@ namespace Coverage {
/*!
* This method creates the set of symbols to analyze from the symbols
* listed in the specified file.
- */
- void load(
- const char* const symbolsFile
+ *
+ * @param[in] symbolsSet An INI format file of the symbols to be loaded.
+ * @param[in] buildTarget The build target
+ * @param[in] buildBSP The BSP
+ * @return Returns false if the load fails.
+ */
+ bool load(
+ const std::string& symbolsSet,
+ const std::string& buildTarget,
+ const std::string& buildBSP,
+ bool verbose
);
/*!
diff --git a/tester/covoar/ExecutableInfo.cc b/tester/covoar/ExecutableInfo.cc
index d71c435..c41d931 100644
--- a/tester/covoar/ExecutableInfo.cc
+++ b/tester/covoar/ExecutableInfo.cc
@@ -67,12 +67,12 @@ namespace Coverage {
return aCoverageMap;
}
- std::string ExecutableInfo::getFileName ( void ) const
+ const std::string& ExecutableInfo::getFileName ( void ) const
{
return executableName;
}
- std::string ExecutableInfo::getLibraryName( void ) const
+ const std::string& ExecutableInfo::getLibraryName( void ) const
{
return libraryName;
}
diff --git a/tester/covoar/ExecutableInfo.h b/tester/covoar/ExecutableInfo.h
index 7242715..20ea9bf 100644
--- a/tester/covoar/ExecutableInfo.h
+++ b/tester/covoar/ExecutableInfo.h
@@ -67,14 +67,14 @@ namespace Coverage {
*
* @return Returns the executable's file name
*/
- std::string getFileName( void ) const;
+ const std::string& getFileName( void ) const;
/*!
* This method returns the library name associated with the executable.
*
* @return Returns the executable's library name
*/
- std::string getLibraryName( void ) const;
+ const std::string& getLibraryName( void ) const;
/*!
* This method returns the load address of the dynamic library
@@ -111,7 +111,7 @@ namespace Coverage {
* This method indicates whether a dynamic library has been
* associated with the executable.
*
- * @return Returns TRUE if
+ * @return Returns TRUE if
*/
bool hasDynamicLibrary( void );
diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc
index b916984..d41906c 100644
--- a/tester/covoar/ObjdumpProcessor.cc
+++ b/tester/covoar/ObjdumpProcessor.cc
@@ -247,15 +247,15 @@ namespace Coverage {
try
{
status = rld::process::execute( TargetInfo->getObjdump(),
- args, objdumpFile.name(), err.name() );
+ args, objdumpFile.name(), err.name() );
if ( (status.type != rld::process::status::normal)
|| (status.code != 0) ) {
throw rld::error( "Objdump error", "generating objdump" );
}
} catch( rld::error& err )
{
- std::cout << "Error while running" << TargetInfo->getObjdump()
- << "for" << fileName << std::endl;
+ std::cout << "Error while running " << TargetInfo->getObjdump()
+ << " on " << fileName << std::endl;
std::cout << err.what << " in " << err.where << std::endl;
return;
}
diff --git a/tester/covoar/app_common.h b/tester/covoar/app_common.h
index d28bfd0..ac32bbd 100644
--- a/tester/covoar/app_common.h
+++ b/tester/covoar/app_common.h
@@ -1,6 +1,11 @@
#ifndef __APP_COMMON_h
#define __APP_COMMON_h
+/*
+ * This file needs to be removed and these globals removed from the
+ * global scope. For example SymbolsToAnalyze is never destructed.
+ */
+
#include <list>
#include "DesiredSymbols.h"
@@ -22,8 +27,8 @@ extern char inputBuffer[MAX_LINE_LENGTH];
extern char inputBuffer2[MAX_LINE_LENGTH];
-bool FileIsNewer( const char *f1, const char *f2 );
-bool FileIsReadable( const char *f1 );
+bool FileIsNewer( const char *f1, const char *f2 );
+bool FileIsReadable( const char *f1 );
bool ReadUntilFound( FILE *file, const char *line );
#endif
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;
}
@@ -194,22 +261,6 @@ int main(
throw option;
}
- /*
- * 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.
*/
@@ -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;
}
diff --git a/tester/covoar/wscript b/tester/covoar/wscript
index 9db4815..c0270d8 100644
--- a/tester/covoar/wscript
+++ b/tester/covoar/wscript
@@ -118,10 +118,12 @@ def build(bld):
'TraceWriterQEMU.cc'],
use = ['ccovoar'] + modules,
cflags = ['-O2', '-g'],
+ cxxflags = ['-std=c++11', '-O2', '-g'],
includes = ['.'] + rtl_includes)
bld.program(target = 'covoar',
source = ['covoar.cc'],
use = ['ccovoar'] + modules,
cflags = ['-O2', '-g'],
+ cxxflags = ['-std=c++11', '-O2', '-g'],
includes = ['.'] + rtl_includes)
diff --git a/tester/rtems/testing/bsps/leon3-qemu-cov.ini b/tester/rtems/testing/bsps/leon3-qemu-cov.ini
new file mode 100644
index 0000000..6b5e7e6
--- /dev/null
+++ b/tester/rtems/testing/bsps/leon3-qemu-cov.ini
@@ -0,0 +1,39 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2018 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# The Leon 3 QEMU BSP
+#
+[leon3-qemu]
+bsp = leon3-qemu
+arch = sparc
+tester = %{_rtscripts}/qemu.cfg
+bsp_qemu_opts = %{qemu_opts_base} -M leon3_generic
+bsp_qemu_cov_opts = -exec-trace %{test_executable}.cov
diff --git a/tester/rtems/testing/bsps/leon3-qemu.ini b/tester/rtems/testing/bsps/leon3-qemu.ini
new file mode 100644
index 0000000..9e8854c
--- /dev/null
+++ b/tester/rtems/testing/bsps/leon3-qemu.ini
@@ -0,0 +1,38 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2014 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# The Leon 3 QEMU BSP
+#
+[leon3-qemu]
+bsp = leon3-qemu
+arch = sparc
+tester = %{_rtscripts}/qemu.cfg
+bsp_qemu_opts = %{qemu_opts_base} -M leon3_generic
diff --git a/tester/rtems/testing/coverage/Categories.txt b/tester/rtems/testing/coverage/Categories.txt
new file mode 100644
index 0000000..e19a456
--- /dev/null
+++ b/tester/rtems/testing/coverage/Categories.txt
@@ -0,0 +1,19 @@
+This is the list of Explanation Categories used when analyzing RTEMS
+Coverage report. By using standard categories, the table filter on
+the web site works better.
+
+Simple Test Case
+
+Hard Test Tase
+
+Uncalled Routine
+
+Interrupt Critical Section
+
+Simple Error Case
+
+Hard Error Case
+
+Allocation Error
+
+Bharath Suri
diff --git a/tester/rtems/testing/coverage/Explanations.txt b/tester/rtems/testing/coverage/Explanations.txt
new file mode 100644
index 0000000..a5917f6
--- /dev/null
+++ b/tester/rtems/testing/coverage/Explanations.txt
@@ -0,0 +1,35 @@
+schedulerpriorityyield.c:47
+Simple Test Case
+Branch Never Taken
+New test where there is more than one thread at a priority with the
+executing thread being non-preemptive. Create a higher priority thread
+and then yield.
+
+ init task at priority 2, non-preemptive
+ create task at priority 2
+ create task at priority 1
+ yield
++++
+
+schedulerpriorityyield.c:51
+Simple Test Case
+Branch Always Taken
+New test where only one thread at a priority (non-preemptive), create a
+thread at higher priority, then yield.
+
+ init task at priority 2, non-preemptive
+ create task at priority 1
+ yield
++++
+
+schedulerpriorityyield.c:52
+Simple Test Case
+Not Executed
+Same test case as schedulerpriorityyield.c:51
++++
+
+coremsg.c:86
+Simple Test Case
+We need to request enough messages of a certain size that the math
+overflows to less than a single message.
++++
diff --git a/tester/rtems/testing/coverage/SPARC-Annul-Slot-Explanation.txt b/tester/rtems/testing/coverage/SPARC-Annul-Slot-Explanation.txt
new file mode 100644
index 0000000..ef740d3
--- /dev/null
+++ b/tester/rtems/testing/coverage/SPARC-Annul-Slot-Explanation.txt
@@ -0,0 +1,56 @@
+The SPARC assembly is often hard to understand because a single
+instruction will show up as not executed. The instructions before
+and after it will be marked as executed. The instruction before
+the one not executed should be a "bxx,a" instruction which means
+that the instruction following the branch instruction is executed
+ONLY if the branch is taken. Otherwise it is "annulled" or skipped.
+
+So when you see these cases, it means the branch was NOT taken.
+
+===================================================================
+Subject: <offlist> annul slot explanation
+From: Jiri Gaisler <jiri at gaisler.com>
+Date: Wed, 3 Jun 2009 14:57:48 -0500
+To: Joel Sherrill <Joel.Sherrill at OARcorp.com>
+
+
+Joel Sherrill wrote:
+> > Hi,
+> >
+> > I am trying to look at more coverage cases and
+> > wanted to make sure I am reading things correctly.
+> >
+> > The code in question is:
+> >
+> >
+> > if ( the_thread->current_priority > interested_priority )
+> > 200fd00: d8 00 e0 14 ld [ %g3 + 0x14 ], %o4
+> > 200fd04: 80 a3 00 04 cmp %o4, %g4
+> > 200fd08: 38 80 00 1c bgu,a 200fd78 <killinfo+0x224>
+> > 200fd0c: 98 10 00 04 mov %g4,
+> > %o4 <== NOT EXECUTED
+> >
+> > /*
+> > * If this thread is not interested, then go on to the next thread.
+> > */
+> >
+> > api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+> > 200fd10: d4 00 e1 6c ld [ %g3 + 0x16c ], %o2
+> >
+> > Am I correct in interpreting this as meaning 0x200fd0c
+> > is not executed because the bgu,a is never taken. And it
+> > is not executed as part of falling through.
+
+Yes, this is correct. The branch delay slot is only executed
+when the branch is taken.
+
+Jiri.
+
+> >
+> > So in this case we need a test where the "if" condition
+> > is true if I am reading things correctly.
+> >
+> > Thanks. There are a number of these 4 byte cases which
+> > are probably easy to hit if I read the code correctly.
+> >
+> >
diff --git a/tester/rtems/testing/coverage/score-symbols.ini b/tester/rtems/testing/coverage/score-symbols.ini
new file mode 100644
index 0000000..b3c8b18
--- /dev/null
+++ b/tester/rtems/testing/coverage/score-symbols.ini
@@ -0,0 +1,35 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+[symbol-sets]
+sets = score
+
+[score]
+libraries=@BUILD-TARGET@/c/@BSP@/cpukit/score/libscore.a
diff --git a/tester/rtems/testing/coverage/style.css b/tester/rtems/testing/coverage/style.css
new file mode 100644
index 0000000..c715518
--- /dev/null
+++ b/tester/rtems/testing/coverage/style.css
@@ -0,0 +1,197 @@
+body {
+ background: rgb(253,253,253);
+ color: rgb(0,0,0);
+ font-family: helvetica, sans-serif;
+ font-size: 1em;
+ line-height: 1.4;
+ margin: 5px, 5px, 5px, 5px;
+ padding: 0;
+}
+
+a:link {
+ color: rgb(180, 50, 50);
+ font-family: helvetica, sans-serif;
+ font-size: 1.0em;
+}
+
+a:visited {
+ color: purple;
+ font-family: helvetica, sans-serif;
+ font-size: 1.0em;
+}
+
+a:hover {
+ color: rgb(0, 0, 0);
+ font-family: helvetica, sans-serif;
+ font-size: 1.0em;
+}
+
+a:active {
+ color: red;
+ font-family: helvetica, sans-serif;
+ font-size: 1.0em;
+}
+
+.heading {
+ background: rgb(250,250,250);
+ background-image: url("http://www.rtems.org/logos/rtems_logo.jpg");
+ background-repeat: no-repeat;
+ color: rgb(55,55,55);
+ font-size: 1.5em;
+ height: 140px;
+ padding-top: 20px;
+ padding-left: 300px;
+}
+
+.heading-title {
+ text-align: center;
+ color: rgb(0,0,0);
+ font-size: 0.9em;
+ font-weight: bold;
+ padding-top: 5px;
+ padding-left: 0px;
+ text-align: center;
+ width: 100%;
+}
+
+.datetime {
+ color: rgb(55,55,55);
+ font-size: 0.8em;
+ padding-top: 5px;
+ padding-left: 0px;
+ text-align: center;
+ width: 100%;
+}
+
+.info {
+ color: rgb(55,55,55);
+ font-size: 0.6em;
+ padding-top: 5px;
+ padding-left: 00px;
+ text-align: center;
+ width: 100%;
+}
+
+.stats-table {
+ background: rgb(225,225,225);
+ font-size: 0.9em;
+ border: 1px solid rgb(200, 200, 200);
+ padding: 0;
+ margin-top: 3px;
+ margin-left: 10px;
+ width: 70%;
+}
+
+.stats-table-target {
+ background: rgb(243,243,243);
+ font-size: 1.2em;
+ padding-left: 10px;
+ text-align: left;
+}
+
+.stats-target-results {
+ background: rgb(243,243,243);
+ font-size: 0.9em;
+ text-align: right;
+ padding-right: 10px;
+}
+
+.stats-target-good {
+ background: rgb(30,230,30);
+ font-size: 0.9em;
+ text-align: right;
+ padding-right: 10px;
+}
+
+.stats-target-good {
+ background: rgb(50,180,50);
+ color: rgb(230,230,230);
+ font-size: 0.9em;
+ text-align: center;
+ padding-right: 10px;
+}
+
+.stats-target-bad {
+ background: rgb(180,50,50);
+ color: rgb(230,230,230);
+ font-size: 0.9em;
+ text-align: center;
+ padding-right: 10px;
+}
+
+.stats-table-top {
+ background: rgb(243,243,243);
+ color: rgb(0,0,0);
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.stats-table-row {
+ background: rgb(253,253,253);
+ font-size: 0.9em;
+ padding: 1px;
+ text-align: right;
+}
+
+.error-table {
+ font-size: 0.9em;
+ border: 1px solid rgb(200, 200, 200);
+ padding: 0;
+ margin-left: 10px;
+ width: 96%;
+}
+
+.error-table-top {
+ background: rgb(225,225,225);
+ color: rgb(0,0,0);
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.error-table-on {
+ background: rgb(225,225,225);
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.error-table-off {
+ background: rgb(253,253,253);
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.error-table-dups {
+ text-align: right;
+ padding-right: 2px;
+}
+
+.error-table-error {
+ background: rgb(255,150,150);
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.error-table-warning {
+ font-size: 0.9em;
+ padding-left: 2px;
+}
+
+.navbar {
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 10px;
+ width: 40%;
+}
+th.table-sortable {
+ background-image:url("unsorted.gif");
+ cursor: pointer;
+ background-position: center left;
+ background-repeat: no-repeat;
+ padding-left: 15px;
+}
+th.table-sorted-asc {
+ background-image:url("descending.gif");
+}
+th.table-sorted-desc {
+ background-image:url("ascending.gif");
+}
\ No newline at end of file
diff --git a/tester/rtems/testing/qemu.cfg b/tester/rtems/testing/qemu.cfg
index db5b6b2..858cac8 100644
--- a/tester/rtems/testing/qemu.cfg
+++ b/tester/rtems/testing/qemu.cfg
@@ -54,14 +54,23 @@
#%define qemu_opts_base -no-reboot -monitor none -serial stdio -nographic
%define qemu_opts_base -no-reboot -serial null -serial mon:stdio -nographic
%define qemu_opts_no_net -net none
+
+#
+# Converage, some builds of qemu support coverage.
+#
+%ifn %{defined bsp_qemu_ocv_opts}
+ %define bsp_qemu_cov_opts %{nil}
+%endif
+
#
# Qemu executable
#
%ifn %{defined bsp_qemu_opts}
%define bsp_qemu_opts %{nil}
%endif
+
%define qemu_cmd qemu-system-%{bsp_arch}
-%define qemu_opts %{bsp_qemu_opts}
+%define qemu_opts %{bsp_qemu_opts} %{bsp_qemu_cov_opts}
#
# Executable
diff --git a/tester/rtems/testing/testing.mc b/tester/rtems/testing/testing.mc
index 77f8419..662b352 100644
--- a/tester/rtems/testing/testing.mc
+++ b/tester/rtems/testing/testing.mc
@@ -55,3 +55,11 @@ timeout: none, none, '180'
# Tests detected as invalid that are valid
invalid_tests: none, none, '''minimum.exe'''
+
+# Coverage defaults
+cov_format: none, none, 'QEMU'
+cov_explanations: none, none, '%{_rtscripts}/coverage/Explanations.txt'
+cov_extension: none, none, 'cov'
+cov_gcnos_file: none, none, '%{_rtscripts}/coverage/rtems.gcnos'
+cov_exe_ext: none, none, 'exe'
+cov_report_format: none, none, 'html'
--
2.15.1
More information about the devel
mailing list