On 28 April 2018 at 08:08, Chris Johns <chr...@rtems.org> wrote: > 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); >
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 (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