From: Cillian O'Donnell <cpodonne...@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.miesow...@gmail.com> Co-author: Vijay Kumar Banerjee <vijaykumar9...@gmail.com> Cp-author: Chris Johns <chr...@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 (chr...@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 (chr...@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 <j...@gaisler.com> +Date: Wed, 3 Jun 2009 14:57:48 -0500 +To: Joel Sherrill <joel.sherr...@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 (chr...@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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel