[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