From dd0a83ed9844d43e2cdea36edf10b75b3949921a Mon Sep 17 00:00:00 2001
From: bdr7fv <bdr7fv@git.zephyr-software.com>
Date: Wed, 12 Jun 2013 07:02:28 +0000
Subject: [PATCH] Second, and last partial commit which now fully updates the
 toolchain for the manual testing infrastructure.

Former-commit-id: 85081dd4402ea35a7431aa5ce1f384956a8533a2
---
 .gitattributes                         |   2 +
 tools/cover/Makefile                   |   7 +-
 tools/cover/cover.cpp                  |  99 ++++++++------
 tools/cover/coverage.cpp               | 170 +++++++++++++++++++++++++
 tools/cover/coverage.h                 |  27 ++++
 tools/transforms/PNMain.cpp            |  31 ++---
 tools/transforms/PNTransformDriver.cpp |  35 ++++-
 tools/transforms/PNTransformDriver.hpp |   6 +-
 8 files changed, 311 insertions(+), 66 deletions(-)
 create mode 100644 tools/cover/coverage.cpp
 create mode 100644 tools/cover/coverage.h

diff --git a/.gitattributes b/.gitattributes
index 3ac2c7d14..4e57ab464 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -354,6 +354,8 @@ third_party/sqlite-autoconf-3071300.tar.gz -text
 tools/Makefile -text
 tools/cover/Makefile -text
 tools/cover/cover.cpp -text
+tools/cover/coverage.cpp -text
+tools/cover/coverage.h -text
 tools/meds2pdb/Makefile -text
 tools/meds2pdb/meds2pdb.cpp -text
 tools/memcover/General_Utility.cpp -text
diff --git a/tools/cover/Makefile b/tools/cover/Makefile
index e534d11a9..a0b6e5e52 100644
--- a/tools/cover/Makefile
+++ b/tools/cover/Makefile
@@ -17,8 +17,9 @@
 
 CC=g++
 CFLAGS= -g
-INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include
-LIBS=-L../../lib -L../../xform -lxform -lELFIO -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d
+INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include -I../../libIRDB/include/
+LIBS=-L../../lib -L../../xform -lxform -lELFIO  -L../../libIRDB/lib/ -lIRDB-core -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -lpqxx 
+OBJS=coverage.o
 
 .SUFFIXES: .o .c .cpp
 
@@ -33,5 +34,5 @@ clean:
 	rm -f *.o core cover
 
 cover: $(OBJS) cover.cpp
-	$(CC) -o cover $(INCLUDE) cover.cpp $(OBJS) $(LIBS)
+	$(CC) $(CFLAGS) -o cover $(INCLUDE) cover.cpp $(OBJS) $(LIBS)
 
diff --git a/tools/cover/cover.cpp b/tools/cover/cover.cpp
index efc9a300d..d0a1f18c0 100644
--- a/tools/cover/cover.cpp
+++ b/tools/cover/cover.cpp
@@ -1,49 +1,70 @@
 #include <iostream>
-#include <map>
-#include "rewriter.h"
+#include "coverage.h"
+#include <cstdlib>
+#include <fstream>
 
 using namespace std;
+using namespace libIRDB;
+
+void usage(string prog_name)
+{
+	cerr << "usage: "<<prog_name<<" <variant_id> <coverage_file> <output_file>" << endl;
+}
 
 
 int main(int argc, char **argv)
 {
-  if (argc < 5)
-  {
-    cerr << "usage: " << argv[0] << " <elfFile> <annotationFile> <coverageFile> <outputFile>" << endl;
-    return 1;
-  }
-
-  cout << "elf file:" << argv[1] << endl;
-  cout << "MEDS annotation file:" << argv[2] << endl;
-  cout << "coverage file:" << argv[3] << endl;
-  cout << "output file:" << argv[4] << endl;
-
-  Rewriter *rewriter = new Rewriter(argv[1], argv[2]);
-
-  map<wahoo::Function*, double> coverage = rewriter->getFunctionCoverage(argv[3]);
-  if (coverage.empty())
-  {
-    cerr << "Warning: no functions found in: " << argv[0];
-    return 1;
-  }
-
-  FILE *fp = fopen(argv[4],"w+"); // output file
-  if (!fp) 
-  {
-    cerr << "Error opening output file: " << argv[4] << endl;
-    return 1;
-  }
-
-  for (map<wahoo::Function*,double>::iterator it = coverage.begin(); it != coverage.end(); ++it)
-  {
-    int count, total;
-    wahoo::Function *f = it->first;
-    if (!f) continue;
-    double coverage = f->getInstructionCoverage(&count, &total);
-    fprintf(fp, "%s %f %d %d\n", f->getName().c_str(), coverage, count, total);
-  }
-
-  fclose(fp);
 
+	if(argc != 4)
+	{
+		usage(string(argv[0]));
+		return -1;
+	}
+
+	int variant_id = atoi(argv[1]);
+	string coverage_file_name = string(argv[2]);
+	string output_file_name = string(argv[3]);
+
+	coverage prog_coverage;
+
+	ifstream coverage_file;
+	coverage_file.open(coverage_file_name.c_str());
+
+	if(!coverage_file.is_open())
+	{
+		cerr<<"Coverage Error: Could not open coverage file: "<<coverage_file_name<<endl;
+		return -1;
+	}
+
+	prog_coverage.parse_coverage_file(coverage_file);
+	coverage_file.close();
+
+	ofstream output_file;
+	output_file.open(output_file_name.c_str(),ofstream::out);
+
+	if(!output_file.is_open())
+	{
+		cerr<<"Coverage Error: Could not open output file: "<<output_file_name<<endl;
+		return -1;
+	}
+
+	pqxxDB_t pqxx_interface;
+	BaseObj_t::SetInterface(&pqxx_interface);
+	
+	VariantID_t *vidp;
+	try
+	{
+		vidp = new VariantID_t(variant_id);
+		assert(vidp->IsRegistered());
+	}
+	catch (DatabaseError_t pnide)
+	{
+		cout<<"Unexpected database error: "<<pnide<<endl;
+		return -1;	
+	}
+	
+	prog_coverage.print_function_coverage_file(vidp,output_file);
+
+	output_file.close();
 }
 
diff --git a/tools/cover/coverage.cpp b/tools/cover/coverage.cpp
new file mode 100644
index 000000000..6b898e5d6
--- /dev/null
+++ b/tools/cover/coverage.cpp
@@ -0,0 +1,170 @@
+#include "coverage.h"
+#include <cassert>
+#include <cerrno>
+#include <cstdlib>
+#include <limits.h>
+#include <string>
+#include <fstream>
+
+using namespace std;
+using namespace libIRDB;
+
+void trim(string& str)
+{
+  string::size_type pos = str.find_last_not_of(' ');
+  if(pos != string::npos) {
+    str.erase(pos + 1);
+    pos = str.find_first_not_of(' ');
+    if(pos != string::npos) str.erase(0, pos);
+  }
+  else str.erase(str.begin(), str.end());
+}
+
+enum STR2NUM_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };
+
+//TODO: what if the string represents a negative number? Currently
+//the number will be translated into an unsigned int. I could make this
+//and incovertible situation. 
+STR2NUM_ERROR str2uint (unsigned int &i, char const *s, int base=0)
+{
+	char *end;
+	unsigned long  l;
+	errno = 0;
+	l = strtoul(s, &end, base);
+	if ((errno == ERANGE && l == ULONG_MAX) || l > UINT_MAX) {
+		return OVERFLOW;
+	}
+	if (*s == '\0' || *end != '\0') {
+		return INCONVERTIBLE;
+	}
+	i = l;
+
+	return SUCCESS;
+}
+
+
+void coverage::parse_coverage_file(ifstream &coverage_file)
+{
+	string line;
+	while(coverage_file.is_open() && std::getline(coverage_file,line))
+	{
+		trim(line);
+
+		if(line.empty())
+				continue;
+
+		string file,addr;
+
+		istringstream iss(line);
+
+		getline(iss,file,'+');
+		assert(!file.empty());
+		getline(iss,addr,'+');
+
+		//if addr is empty, assume the entry for file
+		//is the addr
+		trim(addr);
+		if(addr.empty())
+		{
+			addr = file;
+			file = "a.ncexe";
+		}
+
+
+		if(coverage_map.find(file) == coverage_map.end())
+		{
+			file_coverage fc;
+			fc.file = file;
+			coverage_map[file]=fc;
+		}			
+
+		
+		unsigned int uint_addr;
+		assert(str2uint(uint_addr,addr.c_str())==SUCCESS);
+
+		coverage_map[file].coverage[uint_addr]=uint_addr;
+	}
+}
+
+file_coverage* coverage::find_file_coverage(string url)
+{
+	for(map<string, file_coverage >::iterator it=coverage_map.begin();
+		it!=coverage_map.end(); ++it)
+	{
+		string key = it->first;
+
+		if(key.empty())
+			continue;
+
+		if(url.find(key)!=string::npos)
+		{
+			return &(it->second);
+		}
+	}
+
+	return NULL;
+}
+
+void coverage::print_coverage_for_file(file_coverage *fc, FileIR_t *fileirp, ofstream &out_file)
+{
+	for(
+		set<Function_t*>::const_iterator func_it=fileirp->GetFunctions().begin();
+		func_it!=fileirp->GetFunctions().end();
+		++func_it
+		)
+	{
+		Function_t *func = *func_it;
+		if(func==NULL)
+			continue;
+
+		unsigned int total_ins = 0;
+		unsigned int covered_ins = 0;
+
+		for(
+			set<Instruction_t*>::const_iterator it=func->GetInstructions().begin();
+			it!=func->GetInstructions().end();
+			++it
+			)
+		{
+			Instruction_t* instr = *it;
+
+			if(instr==NULL || instr->GetAddress()==NULL)
+				continue;
+
+			total_ins++;
+
+			unsigned int addr = (unsigned int) instr->GetAddress()->GetVirtualOffset();
+			if(fc->coverage.find(addr)!=fc->coverage.end())
+				covered_ins++;
+		}
+
+		out_file<<fc->file<<"+"<<func->GetName()<<" "<<((double)covered_ins)/((double)total_ins)<<" "<<covered_ins<<" "<<total_ins<<endl;
+
+	}
+}
+
+void coverage::print_function_coverage_file(libIRDB::VariantID_t *vidp,std::ofstream &out_file)
+{
+	assert(vidp);
+	for(set<File_t*>::iterator it=vidp->GetFiles().begin();
+		it!=vidp->GetFiles().end();
+		++it
+		)
+	{
+		File_t* this_file=*it;
+		assert(this_file);
+
+		// read the db  
+		FileIR_t *fileirp=new FileIR_t(*vidp,this_file);
+		assert(fileirp);
+
+		file_coverage* fc = find_file_coverage(fileirp->GetFile()->GetURL());
+
+		assert(fc != NULL);
+
+		print_coverage_for_file(fc, fileirp, out_file);
+
+		delete fileirp;
+	}
+
+}
diff --git a/tools/cover/coverage.h b/tools/cover/coverage.h
new file mode 100644
index 000000000..f44165068
--- /dev/null
+++ b/tools/cover/coverage.h
@@ -0,0 +1,27 @@
+#ifndef __PEASOUP_COVERAGE
+#define __PEASOUP_COVERAGE
+
+#include <map>
+#include <libIRDB-core.hpp>
+#include <iostream>
+#include <string>
+
+struct file_coverage
+{
+	std::string file;
+	std::map<unsigned int,unsigned int> coverage;
+};
+
+class coverage
+{
+private:
+	std::map<std::string,file_coverage> coverage_map;
+
+	file_coverage* find_file_coverage(std::string url);
+	void print_coverage_for_file(file_coverage *fc, libIRDB::FileIR_t *fileirp, std::ofstream &out_file);
+public:
+	void parse_coverage_file(std::ifstream &coverage_file);
+	void print_function_coverage_file(libIRDB::VariantID_t *vidp,std::ofstream &out_file);
+};
+
+#endif
diff --git a/tools/transforms/PNMain.cpp b/tools/transforms/PNMain.cpp
index 85c40bb51..e0eada9c4 100644
--- a/tools/transforms/PNMain.cpp
+++ b/tools/transforms/PNMain.cpp
@@ -20,6 +20,7 @@
 #include <string>
 #include <set>
 #include <cstdlib>
+#include <sstream>
 
 using namespace std;
 using namespace libIRDB;
@@ -97,9 +98,9 @@ set<string> getFunctionList(char *p_filename)
 
 //TODO: the coverage map should not use the function name since
 //it is possible this will repeat when analyzing shared objects. 
-map<string,double> getCoverageMap(char *filename)
+map<string, map<string,double> > getCoverageMap(char *filename)
 {
-	map<string,double> coverage_map;
+	map<string, map<string,double> > coverage_map;
 
 	if(filename == NULL)
 		return coverage_map;
@@ -115,23 +116,23 @@ map<string,double> getCoverageMap(char *filename)
 
 			string line;
 			getline(coverage_file, line);
-			stringstream ss;
-			ss.str(line);
-			string func_name,tmp;
-			double coverage;
 
-			ss >>func_name;
+			stringstream ss_line;
+			ss_line.str(line);
 
-			if(func_name.compare("") == 0)
-				continue;
+			string func_id,file,func_name;
+			ss_line>>func_id;
+			istringstream iss_fid(func_id);
+			getline(iss_fid,file,'+');
+			getline(iss_fid,func_name,'+');
 
-			ss >>tmp;
+			string scoverage;
+			ss_line>>scoverage;
 
-			coverage = strtod(tmp.c_str(),NULL);
+			double coverage = strtod(scoverage.c_str(),NULL);
+			coverage_map[file][func_name]=coverage;
 
-			cout<<"func: "<<func_name<<" coverage: "<<coverage<<endl;
-
-			coverage_map[func_name] = coverage;
+			cout<<"file: "<<file<<" func: "<<func_name<<" coverage: "<<coverage<<endl;
 		}
 	
 		coverage_file.close();
@@ -284,7 +285,7 @@ int main(int argc, char **argv)
 	blackListOfFunctions = getFunctionList(blacklist_file);
 	set<std::string> onlyValidateFunctions;
 	onlyValidateFunctions = getFunctionList(only_validate);
-	map<string,double> coverage_map = getCoverageMap(coverage_file);
+	map<string, map<string,double> > coverage_map = getCoverageMap(coverage_file);
 
 	cout<<"P1threshold parsed = "<<p1threshold<<endl;
 
diff --git a/tools/transforms/PNTransformDriver.cpp b/tools/transforms/PNTransformDriver.cpp
index b39d01f03..acdb8bc67 100644
--- a/tools/transforms/PNTransformDriver.cpp
+++ b/tools/transforms/PNTransformDriver.cpp
@@ -121,7 +121,7 @@ void PNTransformDriver::AddOnlyValidateList(std::set<std::string> &only_validate
 	}
 }
 
-void PNTransformDriver::SetCoverageMap(std::map<std::string,double> coverage_map)
+void PNTransformDriver::SetCoverageMap(std::map<std::string,map<string,double> > coverage_map)
 {
 	this->coverage_map = coverage_map;
 }
@@ -438,6 +438,8 @@ void PNTransformDriver::GenerateTransformsInit()
 }
 
 
+
+
 void PNTransformDriver::GenerateTransforms()
 {
 	if(transform_hierarchy.size() == 0)
@@ -479,7 +481,28 @@ void PNTransformDriver::GenerateTransforms()
 			orig_virp=new FileIR_t(*pidp,this_file);
 			assert(orig_virp && pidp);
 
-			GenerateTransformsHidden();
+			string url = orig_virp->GetFile()->GetURL();
+
+			map<string,double> file_coverage_map;
+
+			string key;
+			//find the appropriate coverage map for the given file
+			for(map<string, map<string, double> >::iterator it=coverage_map.begin();
+				it!=coverage_map.end(); ++it)
+			{
+				key = it->first;
+
+				if(key.empty())
+					continue;
+
+				if(url.find(key)!=string::npos)
+				{
+					file_coverage_map=it->second;
+					break;
+				}
+			}
+			
+			GenerateTransformsHidden(file_coverage_map);
 
 			if(timeExpired)
 				break;
@@ -495,7 +518,7 @@ void PNTransformDriver::GenerateTransforms()
 		orig_virp = new FileIR_t(*pidp);
 		assert(orig_virp && pidp);
 
-		GenerateTransformsHidden();
+		GenerateTransformsHidden(coverage_map["a.ncexe"]);
 		
 //		delete orig_virp;
 	}
@@ -612,7 +635,7 @@ inline bool PNTransformDriver::TargetFunctionCheck(Instruction_t* a, Instruction
 	return FunctionCheck(a->GetFunction(),b->GetFunction());
 }
 
-void PNTransformDriver::GenerateTransformsHidden()
+void PNTransformDriver::GenerateTransformsHidden(map<string,double> &file_coverage_map)
 {
 	SanitizeFunctions();
 
@@ -655,12 +678,12 @@ void PNTransformDriver::GenerateTransformsHidden()
 		double func_coverage = 0;
 
 		//see if the function is in the coverage map
-		if(coverage_map.find(func->GetName()) != coverage_map.end())
+		if(file_coverage_map.find(func->GetName()) != file_coverage_map.end())
 		{
 			//if coverage exists, if it is above or equal to the threshold
 			//do nothing, otherwise set hierachy to start at the level
 			//passed. 
-			func_coverage = coverage_map[func->GetName()];
+			func_coverage = file_coverage_map[func->GetName()];
 		}
 
 		//Function coverage must be strictly greater than the threshold
diff --git a/tools/transforms/PNTransformDriver.hpp b/tools/transforms/PNTransformDriver.hpp
index 504f0fa8d..c0443692a 100644
--- a/tools/transforms/PNTransformDriver.hpp
+++ b/tools/transforms/PNTransformDriver.hpp
@@ -33,7 +33,7 @@ protected:
     bool do_align;
 	//TODO: coverage map should not use function name as the key, since
 	//we may want to support coverage for shared objects. 
-	std::map<std::string,double> coverage_map;
+	std::map<std::string,std::map<std::string,double> > coverage_map;
 	int no_validation_level;
 	double coverage_threshold;
 	bool do_shared_object_protection;
@@ -82,7 +82,7 @@ protected:
     virtual void GenerateTransformsInit();
     virtual bool IsBlacklisted(libIRDB::Function_t *func);
     virtual unsigned int GetRandomCanary();
-	virtual void GenerateTransformsHidden();
+	virtual void GenerateTransformsHidden(std::map<std::string,double> &file_coverage_map);
 	void SanitizeFunctions();
 //    virtual bool WriteToDB();
     virtual bool WriteStackIRToDB();
@@ -104,7 +104,7 @@ public:
     virtual void AddOnlyValidateList(std::set<std::string> &only_validate_list);
     virtual void SetDoCanaries(bool do_canaries);
     virtual void SetDoAlignStack(bool align_stack);
-	virtual void SetCoverageMap(std::map<std::string,double> coverage_map);
+	virtual void SetCoverageMap(std::map<std::string,std::map<std::string,double> > coverage_map);
 	virtual void SetNoValidationLevel(unsigned int no_validation_level);
 	virtual void SetCoverageThreshold(double threshold);
 	virtual void SetProtectSharedObjects(bool do_protection);
-- 
GitLab