[PATCH] covoar: Add symbol set reader and ELF data parser to covoar.
Cillian O'Donnell
cpodonnell8 at gmail.com
Sun Apr 29 10:50:28 UTC 2018
On 28 April 2018 at 08:08, Chris Johns <chrisj at rtems.org> wrote:
> 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);
>
Problem here. It tries to find the find the library but doesn't have the
top build directory.
(gdb) run -S
/home/cpod/development/rtems/test/rtems-tools/tester/rtems/testing/coverage/score-symbols.ini
-v -O /home/cpod/coverage_test/test/score
-E/home/cpod/development/rtems/test/rtems-tools/tester/rtems/testing/coverage/Explanations.txt
-pRTEMS-5
/home/cpod/development/rtems/leon3/sparc-rtems5/c/leon3/testsuites/samples/hello/hello.exe
Starting program:
/home/cpod/development/rtems/test/rtems-tools/build/tester/covoar/covoar -S
/home/cpod/development/rtems/test/rtems-tools/tester/rtems/testing/coverage/score-symbols.ini
-v -O /home/cpod/coverage_test/test/score
-E/home/cpod/development/rtems/test/rtems-tools/tester/rtems/testing/coverage/Explanations.txt
-pRTEMS-5
/home/cpod/development/rtems/leon3/sparc-rtems5/c/leon3/testsuites/samples/hello/hello.exe
warning: Unable to read coverage file: /home/cpod/coverage_test/test/sccov
Processing multiple executable/coverage file pairs
Coverage Format : html
Target : sparc-rtems5
Coverage file
/home/cpod/development/rtems/leon3/sparc-rtems5/c/leon3/testsuites/samples/hello/hello.cov
for executable:
/home/cpod/development/rtems/leon3/sparc-rtems5/c/leon3/testsuites/samples/hello/hello.exe
Loading symbol sets:
/home/cpod/development/rtems/test/rtems-tools/tester/rtems/testing/coverage/score-symbols.ini
Symbol set: score
Loading library: sparc-rtems5/c/leon3/cpukit/score/libscore.a
error: open:sparc-rtems5/c/leon3/cpukit/score/libscore.a: No such file or
directory
[Inferior 1 (process 24426) exited with code 01]
> + 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) {
>
Missing semicolon between v and d option.
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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20180429/8359103a/attachment-0002.html>
More information about the devel
mailing list