[PATCH 1/2] covoar: Add symbol set reader and ELF data parser to covoar.
Cillian O'Donnell
cpodonnell8 at gmail.com
Wed Apr 25 20:33:58 UTC 2018
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.miesowicz at 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.miesowicz at 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.miesowicz at 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.miesowicz at 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.miesowicz at 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
More information about the devel
mailing list