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