covoar: Add symbol set reader and ELF data parser to covoar.

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@gmail.com>
Co-author: Vijay Kumar Banerjee <vijaykumar9597@gmail.com>
Co-author: Chris Johns <chrisj@rtems.org>
This commit is contained in:
Cillian O'Donnell 2018-04-25 21:33:58 +01:00 committed by Chris Johns
parent e0a52a4fe4
commit 3e187baeb9
17 changed files with 734 additions and 183 deletions

View File

@ -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;
rld::files::cache cache;
bool r = true;
// Ensure that symbols file name is given.
if ( !symbolsFile ) {
fprintf(
stderr,
"ERROR: DesiredSymbols::load - no symbols file specified\n"
);
exit(-1);
}
//
// 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();
// Open symbols file.
sFile = fopen( symbolsFile, "r" );
if ( !sFile ) {
fprintf(
stderr,
"ERROR: DesiredSymbols::load - unable to open symbols file %s\n",
symbolsFile
);
exit(-1);
}
rld::config::config config;
// Process symbols file.
while ( !done ) {
if (verbose)
std::cerr << "Loading symbol sets: " << symbolsSet << std::endl;
symInfo = new SymbolInformation;
config.load (symbolsSet);
// Skip blank lines between symbols
do {
inputBuffer[0] = '\0';
inputBuffer2[0] = '\0';
cStatus = fscanf( sFile, "%s %s", inputBuffer, inputBuffer2 );
if ( cStatus == EOF ) {
done = true;
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
);
delete symInfo;
}
// Add this to the set of symbols.
else
set[ inputBuffer ] = *symInfo;
}
rld::symbols::table symbols;
cache.load_symbols (symbols, true);
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 )

View File

@ -293,9 +293,17 @@ namespace Coverage {
/*!
* This method creates the set of symbols to analyze from the symbols
* listed in the specified file.
*
* @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.
*/
void load(
const char* const symbolsFile
bool load(
const std::string& symbolsSet,
const std::string& buildTarget,
const std::string& buildBSP,
bool verbose
);
/*!

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -0,0 +1,39 @@
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010-2018 Chris Johns (chrisj@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

View File

@ -0,0 +1,38 @@
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010-2014 Chris Johns (chrisj@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

View File

@ -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

View File

@ -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.
+++

View File

@ -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@gaisler.com>
Date: Wed, 3 Jun 2009 14:57:48 -0500
To: Joel Sherrill <Joel.Sherrill@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.
> >
> >

View File

@ -0,0 +1,35 @@
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2018 Chris Johns (chrisj@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

View File

@ -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");
}

View File

@ -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
#
# Coverage, some builds of qemu support coverage.
#
%ifn %{defined bsp_qemu_cov_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

View File

@ -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'