Add ability to organize symbol sets of libraries in symbol_set.cfg and then read them with covoar (Krzysztof Miesowicz)) Also the symbols are now loaded in from ELF data rather than relying on nm.(Cillian O'Donnell)
Co-author:"Krzysztof Miesowicz <krzysztof.miesow...@gmail.com>" --- tester/covoar/SymbolSet.cpp | 153 ++++++++++++++++++++++++++++++++++++++ tester/covoar/SymbolSet.h | 79 ++++++++++++++++++++ tester/covoar/SymbolSetReader.cpp | 82 ++++++++++++++++++++ tester/covoar/SymbolSetReader.h | 34 +++++++++ tester/covoar/covoar.cc | 57 +++++++++++--- tester/covoar/wscript | 4 +- 6 files changed, 398 insertions(+), 11 deletions(-) create mode 100644 tester/covoar/SymbolSet.cpp create mode 100644 tester/covoar/SymbolSet.h create mode 100644 tester/covoar/SymbolSetReader.cpp create mode 100644 tester/covoar/SymbolSetReader.h diff --git a/tester/covoar/SymbolSet.cpp b/tester/covoar/SymbolSet.cpp new file mode 100644 index 0000000..dfa0fa1 --- /dev/null +++ b/tester/covoar/SymbolSet.cpp @@ -0,0 +1,153 @@ +/* + * Copyright 2014 Krzysztof Miesowicz (krzysztof.miesow...@gmail.com) + * All rights reserved. + * + * 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. + */ + +#include <iostream> +#include <fstream> +#include <cstdio> + +#include "SymbolSet.h" + +#include "rld.h" +#include "rld-process.h" +#include "rld-symbols.h" +#include "rld-files.h" + +namespace Symbols +{ + SymbolSet::SymbolSet () + { + } + + SymbolSet::~SymbolSet () + { + } + + std::string SymbolSet::parseElfDataLine (std::string line) + { + std::string symbol = ""; + int funcStartPos = 64; + if (line.find ("STT_FUNC") != std::string::npos) + { + symbol = line.substr (funcStartPos); + symbol = symbol.substr (0, symbol.find (' ')); + } + return symbol; + } + + std::string SymbolSet::getLibname (std::string libPath) + { + std::string libname = "", base = "", temp; + size_t pos = libPath.find_last_of ('/'); + if (pos != std::string::npos) + { + temp = libPath.substr (0, pos); + libname = libPath.substr (pos + 1); + } + pos = temp.find_last_of ('/'); + if (pos != std::string::npos) + { + base = temp.substr (pos + 1); + } + return base + "/" + libname; + } + + void SymbolSet::parseElfData (rld::process::tempfile& elfData, + const std::string& lib) + { + std::string line, symbol; + elfData.open( true ); + while ( true ) + { + elfData.read_line (line); + if ( line.empty() ) break; + symbol = parseElfDataLine (line); + if (symbol.length () > 0) + { + symbols.push_back (symbol + " " + getLibname (lib)); + } + } + } + + void SymbolSet::generateSymbolFile (rld::process::tempfile& filePath, + std::string target) + { + rld::files::cache kernel; + rld::symbols::table symbolsTable; + + for (std::string lib : libraries) + { + /* + * Load the symbols from the kernel. + */ + try + { + /* + * Load the kernel ELF file symbol table. + */ + kernel.open (); + kernel.add (lib); + kernel.load_symbols (symbolsTable, true); + + /* + * Create a symbols file. + */ + std::ofstream mout; + mout.open (filePath.name().c_str()); + if (!mout.is_open ()) + throw rld::error ("map file open failed", "map"); + mout << "RTEMS Kernel Symbols Map" << std::endl + << " kernel: " << lib << std::endl + << std::endl; + rld::symbols::output (mout, symbolsTable); + mout.close (); + } + catch (...) + { + kernel.close (); + throw; + } + + kernel.close (); + + try + { + parseElfData (filePath, lib); + } + catch (std::exception& e) + { + std::cout << "ERROR while parsing symbols output: " << e.what () + << std::endl; + } + filePath.close (); + } + + std::ofstream outputFile (filePath.name ()); + for (std::string symbol : symbols) + outputFile << symbol << std::endl; + outputFile.close (); + } +} diff --git a/tester/covoar/SymbolSet.h b/tester/covoar/SymbolSet.h new file mode 100644 index 0000000..20d7327 --- /dev/null +++ b/tester/covoar/SymbolSet.h @@ -0,0 +1,79 @@ +/* + * Copyright 2014 Krzysztof Miesowicz (krzysztof.miesow...@gmail.com) + * All rights reserved. + * + * 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. + */ + +#ifndef SYMBOLSET_H_ +#define SYMBOLSET_H_ + +#include <string> +#include <vector> + +#include "rld-process.h" + +namespace Symbols +{ + class SymbolSet + { + public: + SymbolSet (); + virtual ~SymbolSet (); + + const std::string getName () const + { + return name; + } + + void setName (const std::string& name) + { + this->name = name; + } + + const std::vector<std::string> getLibraries () const + { + return libraries; + } + + void addLibrary (std::string libraryPath) + { + libraries.push_back (libraryPath); + } + + void generateSymbolFile (rld::process::tempfile& filePath, + std::string target); + + private: + std::string name; + std::vector<std::string> libraries; + std::vector<std::string> symbols; + + std::string parseElfDataLine (std::string line); + std::string getLibname (std::string libPath); + void parseElfData (rld::process::tempfile& elfData, + const std::string& lib); + }; +} + +#endif /* SYMBOLSET_H_ */ diff --git a/tester/covoar/SymbolSetReader.cpp b/tester/covoar/SymbolSetReader.cpp new file mode 100644 index 0000000..886e256 --- /dev/null +++ b/tester/covoar/SymbolSetReader.cpp @@ -0,0 +1,82 @@ +/* + * SymbolSetReader.cpp + * + * Created on: Aug 5, 2014 + * Author: Krzysztof Mi??sowicz <krzysztof.miesow...@gmail.com> + */ + +#include "SymbolSetReader.h" +#include "iostream" +#include "fstream" + +namespace Symbols { + +SymbolSetReader::SymbolSetReader() { + // TODO Auto-generated constructor stub + +} + +SymbolSetReader::~SymbolSetReader() { + // TODO Auto-generated destructor stub +} + +std::vector<SymbolSet> SymbolSetReader::readSetFile(string filepath) { + std::vector<SymbolSet> setList { }; + ifstream file(filepath); + string line; + while (getline(file, line)) { + if (line.find("symbolset:") != std::string::npos) { + setList.emplace_back(); + } else if (line.length() > 0) { + + auto pair = parseLine(line); + + if(pair.first == "name") { + if (setList.empty()) { + setList.emplace_back(); + } + setList.rbegin()->setName(pair.second); + continue; + } + if(pair.first == "lib") { + setList.rbegin()->addLibrary(pair.second); + continue; + } + + std::cout << "Invalid entry in configuration file : " << line << endl; + break; + } + } + file.close(); + return setList; +} + +std::pair<string, string> SymbolSetReader::parseLine(string line) { + size_t delimeterPosition = line.find('='); + + if (delimeterPosition != std::string::npos) { + string key = line.substr(0, delimeterPosition); + string value = line.substr(delimeterPosition + 1); + return {trim(key), trim(value)}; + } + + return {"",""}; +} + +string& SymbolSetReader::trim(string& str) { + // trim trailing spaces + size_t endpos = str.find_last_not_of(" \t\n\r"); + if (string::npos != endpos) { + str = str.substr(0, endpos + 1); + } + + // trim leading spaces + size_t startpos = str.find_first_not_of(" \t\n\r"); + if (string::npos != startpos) { + str = str.substr(startpos); + } + + return str; +} + +} /* namespace Symbols */ diff --git a/tester/covoar/SymbolSetReader.h b/tester/covoar/SymbolSetReader.h new file mode 100644 index 0000000..24e83cf --- /dev/null +++ b/tester/covoar/SymbolSetReader.h @@ -0,0 +1,34 @@ +/* + * SymbolSetReader.h + * + * Created on: Aug 5, 2014 + * Author: Krzysztof Mi??sowicz <krzysztof.miesow...@gmail.com> + */ + +#ifndef SYMBOLSETREADER_H_ +#define SYMBOLSETREADER_H_ + +#include <string> +#include <vector> +#include <utility> +#include "SymbolSet.h" + +using namespace std; + +namespace Symbols { + +class SymbolSetReader { +public: + SymbolSetReader(); + virtual ~SymbolSetReader(); + + vector<SymbolSet> readSetFile(string filepath); +protected: + pair<string, string> parseLine(string line); +private: + string& trim(string& str); +}; + +} /* namespace Symbols */ + +#endif /* SYMBOLSETREADER_H_ */ diff --git a/tester/covoar/covoar.cc b/tester/covoar/covoar.cc index c36b00a..9d00428 100644 --- a/tester/covoar/covoar.cc +++ b/tester/covoar/covoar.cc @@ -22,6 +22,8 @@ #include "ReportsBase.h" #include "TargetFactory.h" #include "GcovData.h" +#include "SymbolSetReader.h" +#include "SymbolSet.h" #include "rld-process.h" @@ -44,6 +46,7 @@ std::list<Coverage::ExecutableInfo*> executablesToAnalyze; const char* explanations = NULL; char* progname; const char* symbolsFile = NULL; +const char* symbolSetFile = NULL; const char* gcnosFileName = NULL; char gcnoFileName[FILE_NAME_LENGTH]; char gcdaFileName[FILE_NAME_LENGTH]; @@ -51,7 +54,7 @@ char gcovBashCommand[256]; const char* target = NULL; const char* format = NULL; FILE* gcnosFile = NULL; -Gcov::GcovData* gcovFile; +Gcov::GcovData* gcovFile; /* * Print program usage message @@ -70,13 +73,15 @@ void usage() "(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 symbol_sets.cfg\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 @@ -134,6 +139,7 @@ int main( const char* singleExecutable = NULL; rld::process::tempfile objdumpFile( ".dmp" ); rld::process::tempfile err( ".err" ); + rld::process::tempfile syms( ".syms" ); bool debug = false; std::string option; @@ -144,7 +150,7 @@ int main( // progname = 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:v:d")) != -1) { switch (opt) { case '1': singleExecutable = optarg; break; case 'L': dynamicLibrary = optarg; break; @@ -154,6 +160,7 @@ int main( case 'E': explanations = optarg; break; case 'f': format = optarg; break; case 's': symbolsFile = optarg; break; + case 'S': symbolSetFile = optarg; break; case 'T': target = optarg; break; case 'O': outputDirectory = optarg; break; case 'v': Verbose = true; break; @@ -187,6 +194,14 @@ int main( } /* + * Validate that we have a symbols of interest file. + */ + if ( !symbolSetFile ) { + option = "symbol set file -S"; + throw option; + } + + /* * Has path to explanations.txt been specified. */ if ( !explanations ) { @@ -354,14 +369,34 @@ int main( // 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() - ); + + if ( symbolsFile ) { + 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 ( symbolSetFile ) { + std::cout << "Reading configuration symbol set file: " << symbolSetFile + << std::endl; + Symbols::SymbolSetReader ssr; + std::vector<Symbols::SymbolSet> symbolSets = ssr.readSetFile( symbolSetFile ); + Symbols::SymbolSet& set = symbolSets[0]; + std::cout << "Generating symbol file for " + set.getName() << std::endl; + set.generateSymbolFile( syms, target ); + SymbolsToAnalyze->load( syms.name().c_str() ); + } + if ( Verbose ) + std::cout << "Analyzing " + SymbolsToAnalyze->set.size() + << "symbols" << std::endl; // Create explanations. AllExplanations = new Coverage::Explanations(); @@ -524,6 +559,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..1cda734 100644 --- a/tester/covoar/wscript +++ b/tester/covoar/wscript @@ -104,7 +104,9 @@ def build(bld): 'Target_lm32.cc', 'Target_m68k.cc', 'Target_powerpc.cc', - 'Target_sparc.cc'], + 'Target_sparc.cc', + 'SymbolSet.cpp', + 'SymbolSetReader.cpp'], cflags = ['-O2', '-g'], cxxflags = ['-std=c++11', '-O2', '-g'], includes = ['.'] + rtl_includes) -- 2.7.4
_______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel