--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/apicompatanamdw/compatanalysercmd/libraryanalyser/src/la_analysis.cpp Tue Jan 12 14:52:39 2010 +0530
@@ -0,0 +1,1161 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Functionality of analysis
+*
+*/
+
+
+#include "la.hpp"
+#include "la_parser.hpp"
+#include "xmlprocessor.hpp"
+#include "xmldomainmap.hpp"
+#include "xmlsaxparser.hpp"
+#include "xmlnode.hpp"
+#include "xmlsaxhandler.hpp"
+#include "xmlsaxerrorhandler.hpp"
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+typedef XMLSAXHandler<XMLDomainMap<XMLNode> > DOCHANDLER;
+typedef XMLSAXErrorHandler ERRORHANDLER;
+typedef XMLSAXParser<DOCHANDLER, ERRORHANDLER> PARSER;
+typedef XMLProcessor<PARSER> XMLEngine;
+
+
+int XmlTools::initialiseDOM()
+{
+ try
+ {
+ XMLPlatformUtils::Initialize();
+ } catch (const XMLException& e )
+ {
+ char* message = _X( e.getMessage() );
+ cout << "Error during initialization! :\n" << message << endl ;
+ _XX(message);
+ return -1;
+ }
+
+ DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation( _X("Core") );
+ iParser = ((DOMImplementationLS*)impl)->createDOMBuilder( DOMImplementationLS::MODE_SYNCHRONOUS, 0 );
+ if ( iParser->canSetFeature( XMLUni::fgDOMValidation, true ) )
+ iParser->setFeature( XMLUni::fgDOMValidation, true );
+ if ( iParser->canSetFeature( XMLUni::fgDOMNamespaces, true ) )
+ iParser->setFeature( XMLUni::fgDOMNamespaces, true );
+ if ( iParser->canSetFeature( XMLUni::fgDOMDatatypeNormalization, true ) )
+ iParser->setFeature( XMLUni::fgDOMDatatypeNormalization, true );
+
+ return 0;
+}
+
+void XmlTools::uninitialiseDOM()
+{
+ iParser->release();
+ XMLPlatformUtils::Terminate();
+}
+
+XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* XmlTools::readFile( const char* aFilename )
+{
+ XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc;
+ DOMErrorHandler* myErrorHandler;
+
+ fstream ifile;
+ bool validate = false;
+
+ string filedoctype;
+ string doctype("<!DOCTYPE");
+
+ //check if a document type definition is provided for the xml file
+ ifile.open(aFilename);
+ ifile >> filedoctype ;
+ ifile.close();
+
+ if(doctype.compare(filedoctype) == 0)
+ validate = true;
+
+ //if document type definition present,create and set error handler to parser, to report any parse errors in issues document.
+ if(validate)
+ {
+ myErrorHandler = new DOMPrintErrorHandler();
+ XmlTools::iParser->setErrorHandler(myErrorHandler);
+ }
+
+ try
+ {
+ doc = iParser->parseURI( aFilename );
+ }
+ catch ( const XMLException& e )
+ {
+ char* message = _X( e.getMessage() );
+ cout << "Failed to read " << aFilename << ". \"" << message << "\"" << endl ;
+ _XX( message );
+ return NULL;
+ }
+ catch ( const DOMException& e )
+ {
+ char* message = _X( e.getMessage() );
+ cout << "Failed to read " << aFilename << ". \"" << message << "\"" << endl ;
+ _XX( message );
+ return NULL;
+ }
+ catch (...)
+ {
+ cout << "Failed to read " << aFilename << ". Unexpected error." << endl ;
+ return NULL;
+ }
+
+ //delete the error handler, if set
+ if(validate)
+ delete myErrorHandler;
+
+ return doc;
+}
+
+bool DOMPrintErrorHandler::handleError(const DOMError &domError)
+{
+ // Display whatever error message passed from the parser
+ if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING)
+ XERCES_STD_QUALIFIER cerr << "\nWarning Message: ";
+ else if (domError.getSeverity() == DOMError::DOM_SEVERITY_ERROR)
+ XERCES_STD_QUALIFIER cerr << "\nError Message: ";
+ else
+ XERCES_STD_QUALIFIER cerr << "\nFatal Message: ";
+
+ char *msg = XMLString::transcode(domError.getMessage());
+ DOMLocator *errorLocator = domError.getLocation();
+ XERCES_STD_QUALIFIER cerr<< errorLocator->getLineNumber() << ",";
+ XERCES_STD_QUALIFIER cerr<< errorLocator->getColumnNumber() << ": ";
+ XERCES_STD_QUALIFIER cerr<< msg <<XERCES_STD_QUALIFIER endl;
+ XMLString::release(&msg);
+
+ // Instructs the parser to continue parsing if possible.
+ return true;
+}
+
+DOMElement* XmlTools::getTagNode( const DOMElement* aParentNode, const char* aTagName )
+{
+ DOMNodeList* list = aParentNode->getElementsByTagName( _X( aTagName ) );
+ if ( list == NULL || list->getLength() == 0 )
+ return NULL;
+ else
+ return (DOMElement*) list->item( 0 );
+}
+
+int XmlTools::getTagValue( const DOMElement* aParentNode, const char* aTagName, char* aTagValue, int minLen, int maxLen )
+{
+ DOMNodeList* list = aParentNode->getElementsByTagName( _X( aTagName ) );
+
+ strcpy( aTagValue, "" );
+ if ( list == NULL || list->getLength() == 0 )
+ return -1;
+ else
+ {
+ DOMNode* textNode = list->item( 0 )->getFirstChild();
+ if ( textNode == NULL )
+ return -1;
+
+ char* text = _X( textNode->getNodeValue() );
+ if ( text == NULL )
+ return -1;
+
+ int len =(int) strlen( text );
+ if ( len < minLen || len > maxLen )
+ return -1;
+
+ strcpy( aTagValue, text );
+ _XX( text );
+
+ return 0;
+ }
+}
+
+
+void ParseAndCompareDLLXmlFiles(const string& abaselineXmlFile,const string& acurrentXmlFile)
+{
+ XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* ibaseDoc = NULL;
+ int currIndx = -1;
+ int baseIndx = -1;
+ char dll_name[1024];
+
+ if ( XmlTools::initialiseDOM() == -1 )
+ return ;
+
+ // read report document
+ ibaseDoc = XmlTools::readFile( abaselineXmlFile.c_str() );
+ if ( ibaseDoc == NULL )
+ {
+ XmlTools::uninitialiseDOM();
+ return ;
+ }
+
+ // Parse file
+ cout << "Gathering dll information... " ;
+
+ //With SAX parser , parse the base xml doc
+ // Create an instance of our XMLFactory
+ XMLEngine baseParser(abaselineXmlFile);
+ // Turn off validation
+ baseParser.doValidation(false);
+ baseParser.parse();
+
+
+ //With SAX parser , parse the current xml doc
+ // Create an instance of our XMLFactory
+ XMLEngine currParser(acurrentXmlFile);
+ // Turn off validation
+ currParser.doValidation(false);
+ // Parse our XML file
+ currParser.parse();
+
+ cout << "Done" <<endl;
+
+ // Get the tree root
+ XMLNode baseRoot = baseParser.getRootElement();
+ XMLNode curRoot = currParser.getRootElement();
+
+ int totcurDlls = (int)curRoot.childCount();
+ int totbaseDlls = (int)baseRoot.childCount();
+
+ XMLNode dllNorode = curRoot.child("dll",currIndx);
+ XMLNode baseNode = baseRoot.child("dll",baseIndx);
+
+ //If baseline dll is missing, report it as informative
+ for(unsigned int outer = 0; outer < _lib_files_baseline.size(); outer++ )
+ {
+ dll_issue tempIssue;
+
+ string finallibname(_lib_files_baseline.at(outer));
+ finallibname=getFilename(finallibname);
+ unsigned int inner;
+
+ for(inner = baseIndx; inner < totbaseDlls; inner++ )
+ {
+ XMLNode base_dlllist = baseRoot.children_[inner];
+
+ string base_dllname = base_dlllist.child("dllname").value();
+ base_dllname = getFilename(base_dllname);
+ if (StringICmpFileNamesWithoutExtension(finallibname,base_dllname) == 0)
+ break;
+ }
+ if (inner == totbaseDlls)
+ {
+ intializeDllIssue(tempIssue);
+ tempIssue.l_dllname = finallibname;
+ tempIssue.i_list_typeid.push_back(DLL_BASELINE_MISSING);
+ _dll_issuelist.push_back(tempIssue);
+ }
+ }
+
+ // get dll breaks by comparing baseline and current dll data file
+ if (baseIndx >=0 && currIndx>=0)
+ {
+ for (unsigned long i = baseIndx; i < totbaseDlls; ++i )
+ {
+ dll_issue issue;
+ XMLNode base_dlllist = baseRoot.children_[i];
+ if ( base_dlllist.childCount() == 0 )
+ continue;
+ string base_dllname = base_dlllist.child("dllname").value();
+ base_dllname = getFilename(base_dllname);
+
+ int l;
+ //char baseVal[5][255];
+ char attribs[5][12] = { "uid1", "uid2", "uid3", "sid" ,"capability"};
+
+ if (base_dllname.size() > 0 )
+ {
+ intializeDllIssue(issue);
+ issue.l_dllname = base_dllname;
+ string baseShortName = getFilename(base_dllname);
+ int curIter;
+
+ for( curIter = currIndx ; curIter < totcurDlls ; curIter++ )
+ {
+ XMLNode curr_dlllist = curRoot.children_[curIter];
+
+ string cur_dllname = curr_dlllist.child("dllname").value();
+ cur_dllname = getFilename(cur_dllname);
+ vector<unsigned int> typeId_list;
+
+ if(stricmp (baseShortName.c_str(),cur_dllname.c_str()) == 0)
+ {
+
+ for ( l = 0; l < 5; ++ l )
+ {
+ string curVal = curr_dlllist.child(attribs[l]).value();
+ string baseVal = base_dlllist.child(attribs[l]).value();
+ unsigned int typeId = 0;
+
+ if(l == 4) // capability check
+ {
+ unsigned long baseCap =parseHex(baseVal.c_str());
+ unsigned long curCap = parseHex(curVal.c_str());
+ unsigned long resultCap = baseCap & curCap;
+ if( baseCap != resultCap)
+ typeId_list.push_back(DLL_CAPABILITY_CHANGED);
+ }
+ else if( curVal.compare(baseVal)!= 0)
+ {
+ fillDllIssue(attribs[l], typeId);
+ typeId_list.push_back(typeId);
+ }
+ }
+
+ if(typeId_list.size()> 0 )
+ {
+ issue.i_list_typeid = typeId_list;
+ _dll_issuelist.push_back(issue);
+ }
+ break;
+ }
+ }
+
+ if (curIter == totcurDlls ) // missing dll in current xml file
+ {
+ issue.i_list_typeid.push_back( DLL_CURRENT_MISSING);
+ _dll_issuelist.push_back(issue);
+ }
+ }
+
+ }
+ }//end of dll list
+
+ XmlTools::uninitialiseDOM();
+}
+
+void WriteReportHeader()
+{
+ _reportf.open(_cl_reportfile.c_str(), ios::trunc);
+
+ if (!_reportf.is_open())
+ {
+ cerr << "ERROR: Cannot open " << _cl_reportfile << " for writing!" << endl;
+ cerr << "Please check that the directory exists and there are no write permission problems" << endl;
+ exit(EXIT_CANNOT_WRITE_TO_REPORT_FILE);
+ }
+
+ WriteXMLLineOpeningTag(_reportf, 0, "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
+ WriteXMLLineOpeningTag(_reportf, 0, "?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?");
+ WriteXMLLineOpeningTag(_reportf, 0, "bbcresults");
+ WriteXMLLineOpeningTag(_reportf, 1, "header");
+
+ WriteXMLLineOpenClosed(_reportf, 2, "baselineversion", _cl_baselineversion);
+ WriteXMLLineOpenClosed(_reportf, 2, "currentversion", _cl_currentversion);
+
+ WriteXMLLineOpeningTag(_reportf, 2, "timestamp");
+ WriteXMLLineOpenClosed(_reportf, 3, "day", Int2Str(_timenow->tm_mday));
+ WriteXMLLineOpenClosed(_reportf, 3, "month", Int2Str(_timenow->tm_mon + 1));
+ WriteXMLLineOpenClosed(_reportf, 3, "year", Int2Str(1900 + _timenow->tm_year));
+ WriteXMLLineOpenClosed(_reportf, 3, "hour", Int2Str(_timenow->tm_hour));
+ WriteXMLLineOpenClosed(_reportf, 3, "minute", Int2Str(_timenow->tm_min));
+ WriteXMLLineOpenClosed(_reportf, 3, "second", Int2Str(_timenow->tm_sec));
+ WriteXMLLineClosingTag(_reportf, 2, "timestamp");
+
+ WriteXMLLineOpenClosed(_reportf, 2, "laversion", LA_VERSION);
+ WriteXMLLineOpenClosed(_reportf, 2, "formatversion", LA_REPORT_FORMAT_VERSION);
+
+ WriteXMLLineOpeningTag(_reportf, 2, "cmdlineparms");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "toolchain");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _toolchain_name);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselinelibdir");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselinelibdir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentlibdir");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentlibdir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselinedlldir");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselinedlldir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentdlldir");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentdlldir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ if(_cl_baselinedlldir.empty() || _cl_currentdlldir.empty())
+ {
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "warning");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue","Required parameters for checking dll properties not specified. Compatibility Breaks in dll are not checked." );
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+ }
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselineversion");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselineversion);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentversion");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentversion);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "reportfile");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_reportfile);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "tools");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_toolsdir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "temp");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_tempdir);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "cfilt");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_cfiltloc);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineOpeningTag(_reportf, 3, "parm");
+ WriteXMLLineOpenClosed(_reportf, 4, "pname", "set");
+ WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_set);
+ WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+ WriteXMLLineClosingTag(_reportf, 2, "cmdlineparms");
+
+ WriteXMLLineOpenClosed(_reportf, 2, "knownissuesversion", "");
+
+ WriteXMLLineClosingTag(_reportf, 1, "header");
+ WriteXMLLineOpeningTag(_reportf, 1, "issuelist");
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void GenerateAndWriteIssueList()
+{
+ int total_files = _lib_files_baseline.size();
+ int current_files = 0;
+ cout <<"Total baseline files "<< _lib_files_baseline.size() << endl;
+ cout <<"Total current files "<< _lib_files_current.size() << endl;
+
+ vector<string>::const_iterator itr;
+ for (unsigned int i=0; i<_lib_files_current.size(); i++)
+ {
+ bool exists = false;
+ // check if the same lib exists in baselinedir
+ for(itr = _lib_dirs_baseline.begin(); itr != _lib_dirs_baseline.end(); itr++)
+ {
+ if (FileExists(*itr + getFilename(_lib_files_current.at(i))))
+ {
+ exists = true;
+ break;
+ }
+ }
+ if(!exists)
+ {
+ total_files++;
+ }
+ }
+ cout <<"Total files to be processed "<< total_files << endl;
+ //vector<dll_issue> dll_issuelist;
+
+ dll_issue reportdll;
+ string dllname;
+
+ if(_baselinedllfile.size() > 0 && _currentdllfile.size() > 0)
+ {
+ ParseAndCompareDLLXmlFiles(_baselinedllfile,_currentdllfile );
+ }
+
+ unsigned int dllIssueCount = _dll_issuelist.size();
+
+ // first go through all libs in the baseline set
+ for (unsigned int i=0; i<_lib_files_baseline.size(); i++)
+ {
+ unsigned int k;
+ vector<string>::iterator itr = _lib_files_current.end();
+ bool exists = false;
+
+ //check if the same dll is present in exe_issue, if yes then add it to final report
+ intializeDllIssue(reportdll);
+ for(unsigned int indx = 0; indx < dllIssueCount; indx++)
+ {
+ dll_issue lIssue;
+ lIssue = _dll_issuelist.at(indx);
+ if(StringICmpFileNamesWithoutExtension(getFilename(lIssue.l_dllname),getFilename(_lib_files_baseline.at(i))) == 0)
+ {
+ reportdll = lIssue;
+ break;
+ }
+ }
+
+
+ // check if the same lib exists in currentdir
+ for(k = 0; k < _lib_dirs_current.size(); k++)
+ {
+ string file = _lib_dirs_current.at(k) + getFilename(_lib_files_baseline.at(i));
+ if (FileExists( file ))
+ {
+ for(itr=_lib_files_current.begin() ; itr != _lib_files_current.end() ; ++itr)
+ {
+ if(StringICmp(file,*itr)== 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+ if(exists)
+ break;
+ }
+ }
+
+ // check if the same lib exists in currentdir
+ if (!exists)
+ {
+ cout.precision(0);
+ cout << "\nAnalysing files (" << current_files+1 << "/" << total_files << "): " << _lib_files_baseline.at(i) << endl;
+
+ WriteXMLIssueOnlyInBaselineDir(_reportf, _lib_files_baseline.at(i),reportdll);
+ }
+ else
+ {
+ cout.precision(0);
+ cout << "\nAnalysing files (" << current_files+1 << "/" << total_files << "): " << _lib_files_baseline.at(i) << " => " << *itr << endl;
+ // both files are available, now get the symbol table and do the comparision process
+ vector<string> symbol_table_baseline;
+ vector<string> symbol_table_current;
+
+ // get the symbol tables of the libraries
+ if (_cl_use_gcc)
+ {
+ GetSymbolTableWithNM(_gcc_nm_location, _lib_files_baseline.at(i), symbol_table_baseline);
+ GetSymbolTableWithNM(_gcc_nm_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+ }
+ else if (_cl_use_gcce)
+ {
+ if (_cl_use_libs)
+ {
+ GetSymbolTableWithNM(_gcce_nm_location, _lib_files_baseline.at(i), symbol_table_baseline);
+ GetSymbolTableWithNM(_gcce_nm_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+ }
+ else
+ {
+ GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+ GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+ }
+ }
+ else if (_cl_use_rvct)
+ {
+ if (_cl_use_libs)
+ {
+ GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+ GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+ }
+ else
+ {
+ GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+ GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+ }
+ }
+
+ // create a vector to store all issues of this library
+ vector<issue> issue_list;
+ //Local variable to store severity of the issue
+ TypeOfSeverity severity = NO_BREAK;
+ // create and init vectors to store ordinal state
+ vector<bool> matched_baseline;
+ vector<bool> checked_baseline;
+ vector<bool> matched_current;
+ vector<bool> checked_current;
+ vector<TypeOfSeverity> map_severity;
+
+ for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+ matched_baseline.push_back(false);
+
+ for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+ checked_baseline.push_back(false);
+
+ for (unsigned int j=0; j<symbol_table_current.size(); j++)
+ matched_current.push_back(false);
+
+ for (unsigned int j=0; j<symbol_table_current.size(); j++)
+ checked_current.push_back(false);
+ //Initially set to NO_BREAK as the type of severity
+ for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+ map_severity.push_back(NO_BREAK);
+
+
+ // first loop through all ordinals in baseline to find matches
+ for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+ {
+ bool need_to_check_moving = false;
+
+ if (j < symbol_table_current.size())
+ {
+ // check if it's an exact match or otherwise binary compatible
+ if ( symbol_table_baseline.at(j) == symbol_table_current.at(j) ||
+ (severity = AreFunctionsCompatible(symbol_table_baseline.at(j), symbol_table_current.at(j)))
+ == NO_BREAK )
+ {
+ // match!
+ matched_baseline.at(j) = true;
+ matched_current.at(j) = true;
+
+ checked_baseline.at(j) = true;
+ checked_current.at(j) = true;
+ }
+ else
+ {
+ // possibly moved
+ need_to_check_moving = true;
+ //store the severity
+ map_severity.at(j) = severity;
+ }
+ }
+ else
+ {
+ // it's out of range, so it can be a match, but check if it has moved
+ need_to_check_moving = true;
+ }
+
+ // now do the actual checking if it has moved
+ if (need_to_check_moving)
+ {
+ for (unsigned int l=0; l<symbol_table_current.size(); l++)
+ {
+ if (symbol_table_baseline.at(j) == symbol_table_current.at(l))
+ {
+ // match found, mark as moved
+ map_severity.at(j) = CONFIRMED_BC_BREAK;
+ AppendToIssueListCaseMoved(issue_list, symbol_table_baseline.at(j), j+1, l+1,map_severity.at(j));
+
+ matched_baseline.at(j) = true;
+ matched_current.at(l) = true;
+
+ checked_baseline.at(j) = true;
+ checked_current.at(l) = true;
+
+ } // if
+ } // for
+ } // if (need_to_check_moving)
+ } // for (int j=0; j<symbol_table_baseline.size(); j++)
+
+
+ // check for removed ordinals when no corresponding ordinals in current
+ if (checked_baseline.size() > checked_current.size())
+ {
+ for (unsigned int j=checked_current.size(); j<checked_baseline.size(); j++)
+ {
+ if (checked_baseline.at(j) == false)
+ {
+ // ignore any absent exports
+ string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+
+ // mark as removed if not marked as absent
+ if( loc == string::npos )
+ {
+ // As removed results in both BC and SC break.
+ map_severity.at(j) = CONFIRMED_BC_AND_SC_BREAK;
+ AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,map_severity.at(j));
+ }
+
+ checked_baseline.at(j) = true;
+ }
+ }
+ }
+
+ // check for added ordinals when no corresponding ordinals in current
+ if (checked_baseline.size() < checked_current.size())
+ {
+ for (unsigned int j=checked_baseline.size(); j<checked_current.size(); j++)
+ {
+ if (checked_current.at(j) == false)
+ {
+ // ignore any absent exports
+ string::size_type loc = symbol_table_current.at(j).find("_._.absent_export", 0);
+
+ // mark as added if not marked as absent
+ if( loc == string::npos )
+ AppendToIssueListCaseAdded(issue_list, symbol_table_current.at(j), j+1,BC_INFORMATIVE);
+
+ checked_current.at(j) = true;
+ }
+ }
+ }
+
+ // check for removed cases when current has a match at the same ordinal
+ for (unsigned int j=0; j<checked_baseline.size(); j++)
+ {
+ if (checked_baseline.at(j) == false && matched_current.at(j) == true)
+ {
+ // ignore any absent exports
+ string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+
+ // mark as removed if not marked as absent
+ if( loc == string::npos )
+ {
+ // As removed results in both BC and SC break.
+ map_severity.at(j) = CONFIRMED_BC_AND_SC_BREAK;
+ AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,map_severity.at(j));
+ }
+
+ checked_baseline.at(j) = true;
+ }
+ }
+
+ // check for inserted cases
+ for (unsigned int j=0; j<checked_current.size(); j++)
+ {
+ if (checked_current.at(j) == false && matched_baseline.at(j) == true)
+ {
+ // ignore any absent exports
+ string::size_type loc = symbol_table_current.at(j).find("_._.absent_export", 0);
+
+ // mark as inserted if not marked as absent
+ if( loc == string::npos )
+ AppendToIssueListCaseInserted(issue_list, symbol_table_current.at(j), j+1,CONFIRMED_BC_BREAK);
+
+ checked_current.at(j) = true;
+ }
+ }
+
+ // check for modified cases
+ for (unsigned int j=0; j<checked_baseline.size(); j++)
+ {
+ if (checked_baseline.at(j) == false && checked_current.at(j) == false && matched_current.at(j) == false)
+ {
+ // ignore any absent exports
+ string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+ string::size_type loc2 = symbol_table_current.at(j).find("_._.absent_export", 0);
+
+ // mark as modfied if not marked as absent
+ if( loc == string::npos && loc2 == string::npos)
+ AppendToIssueListCaseModified(issue_list, symbol_table_baseline.at(j), symbol_table_current.at(j), j+1,map_severity.at(j));
+ // mark as added if absent export has been modified to something else
+ else if (loc != string::npos && loc2 == string::npos)
+ AppendToIssueListCaseAdded(issue_list, symbol_table_current.at(j), j+1,BC_INFORMATIVE);
+ // mark as removed if export has been modified as absent
+ else if (loc == string::npos && loc2 != string::npos)
+ AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,CONFIRMED_BC_AND_SC_BREAK);
+
+ checked_baseline.at(j) = true;
+ checked_current.at(j) = true;
+ }
+ }
+
+ // do some error checking :)
+ for (unsigned int j=0; j<checked_baseline.size(); j++)
+ {
+ if (checked_baseline.at(j) == false)
+ {
+ cout << "OC ALGORITHM ERROR: Baseline func " << symbol_table_baseline.at(j) << " not checked!" << endl;
+ }
+ }
+ for (unsigned int j=0; j<checked_current.size(); j++)
+ {
+ if (checked_current.at(j) == false)
+ {
+ cout << "OC ALGORITHM ERROR: Current rel func " << symbol_table_current.at(j) << " not checked!" << endl;
+ }
+ }
+
+ // sort the issue list
+ sort(issue_list.begin(), issue_list.end(), IssueCompare);
+
+ // finally write the issue_list to the xml file
+ WriteIssueListToXML(_reportf, _lib_files_baseline.at(i), *itr /*_lib_files_current.at(i)*/, issue_list, reportdll);
+
+ } // else of (!FileExists(_cl_currentlibdir + _lib_files_baseline.at(i)))
+ //erase analysed file from vector, so that files with duplicate names will be properly analysed.
+ if( _lib_files_current.end() != itr )
+ _lib_files_current.erase(itr);
+
+ current_files++;
+ } // for (unsigned int i=0; i<_lib_files_baseline.size(); i++)
+
+
+ // finally go through all libs in the currentdir set
+ for (unsigned int i=0; i<_lib_files_current.size(); i++)
+ {
+ bool exists = false;
+ vector<string>::const_iterator itr = _lib_dirs_baseline.begin();
+ // check if the same lib exists in baselinedir
+ for(;itr != _lib_dirs_baseline.end(); itr++)
+ {
+ if (FileExists(*itr + getFilename( _lib_files_current.at(i)) ))
+ {
+ exists = true;
+ break;
+ }
+ }
+ if(!exists)
+ {
+ current_files++;
+ cout.precision(0);
+ cout << "\nAnalysing files (" << current_files << "/" << total_files << "): " << _lib_files_current.at(i) << endl;
+
+ // only in currentdir
+ WriteXMLIssueOnlyInCurrentDir(_reportf, _lib_files_current.at(i));
+ }
+ }
+ cout << "\n---------------------------------------------";
+ cout << "\nFinished";
+ cout << "\nTotal Files analysed : " << total_files;
+ cout << "\n---------------------------------------------";
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteReportFooter()
+{
+ // generate the footer of XML file
+ WriteXMLLineClosingTag(_reportf, 1, "issuelist");
+ WriteXMLLineClosingTag(_reportf, 0, "bbcresults");
+
+ // close writing to the report file
+ _reportf.close();
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseMoved(vector<issue>& issueList, const string& funcname, int funcpos, int newfuncpos,TypeOfSeverity severity)
+{
+ issue i;
+ string bc_severity = "";
+ string sc_severity = "";
+ getSeverityString(severity,bc_severity,sc_severity);
+
+ i.i_typeid = ISSUE_MOVED;
+ i.i_funcname = funcname;
+ i.i_newfuncname = "";
+ i.i_funcpos = funcpos;
+ i.i_newfuncpos = newfuncpos;
+ i.i_BC_severity = bc_severity;
+ i.i_SC_severity = sc_severity;
+
+ issueList.push_back(i);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseRemoved(vector<issue>& issue_list, const string& funcname, int funcpos,TypeOfSeverity severity)
+{
+ issue i;
+ string bc_severity = "";
+ string sc_severity = "";
+ getSeverityString(severity,bc_severity,sc_severity);
+
+ i.i_typeid = ISSUE_REMOVED;
+ i.i_funcname = funcname;
+ i.i_newfuncname = "";
+ i.i_funcpos = funcpos;
+ i.i_newfuncpos = 0;
+ i.i_BC_severity = bc_severity;
+ i.i_SC_severity = sc_severity;
+
+ issue_list.push_back(i);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseInserted(vector<issue>& issue_list, const string& newfuncname, int newfuncpos,TypeOfSeverity severity)
+{
+ issue i;
+ string bc_severity = "";
+ string sc_severity = "";
+ getSeverityString(severity,bc_severity,sc_severity);
+
+ i.i_typeid = ISSUE_INSERTED;
+ i.i_funcname = "";
+ i.i_newfuncname = newfuncname;
+ i.i_funcpos = 0;
+ i.i_newfuncpos = newfuncpos;
+ i.i_BC_severity = bc_severity;
+ i.i_SC_severity = sc_severity;
+
+ issue_list.push_back(i);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseModified(vector<issue>& issue_list, const string& funcname, const string& newfuncname, int funcpos,TypeOfSeverity severity)
+{
+ issue i;
+ string bc_severity = "";
+ string sc_severity = "";
+ getSeverityString(severity,bc_severity,sc_severity);
+
+ i.i_typeid = ISSUE_MODIFIED;
+ i.i_funcname = funcname;
+ i.i_newfuncname = newfuncname;
+ i.i_funcpos = funcpos;
+ i.i_newfuncpos = 0;
+ i.i_BC_severity = bc_severity;
+ i.i_SC_severity = sc_severity;
+
+ issue_list.push_back(i);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseAdded(vector<issue>& issue_list, const string& newfuncname, int newfuncpos,TypeOfSeverity severity)
+{
+ issue i;
+ string bc_severity = "";
+ string sc_severity = "";
+ getSeverityString(severity,bc_severity,sc_severity);
+
+ i.i_typeid = ISSUE_ADDED;
+ i.i_funcname = "";
+ i.i_newfuncname = newfuncname;
+ i.i_funcpos = 0;
+ i.i_newfuncpos = newfuncpos;
+ i.i_BC_severity = bc_severity;
+ i.i_SC_severity = sc_severity;
+
+ issue_list.push_back(i);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+bool IssueCompare(const issue& left, const issue& right)
+{
+ if (left.i_funcpos > 0 && right.i_funcpos > 0)
+ {
+ if (left.i_funcpos == right.i_funcpos && left.i_newfuncpos > 0 && right.i_newfuncpos > 0)
+ return left.i_newfuncpos < right.i_newfuncpos;
+ else
+ return left.i_funcpos < right.i_funcpos;
+ }
+
+ else if (left.i_funcpos == 0 && right.i_funcpos > 0)
+ {
+ if (left.i_newfuncpos == right.i_funcpos)
+ return left.i_funcpos < right.i_newfuncpos;
+ else
+ return left.i_newfuncpos < right.i_funcpos;
+ }
+
+ else if (left.i_funcpos > 0 && right.i_funcpos == 0)
+ {
+ if (left.i_funcpos == right.i_newfuncpos)
+ return left.i_newfuncpos < right.i_funcpos;
+ else
+ return left.i_funcpos < right.i_newfuncpos;
+ }
+
+ else // if (left.i_funcpos == 0 && right.i_funcpos == 0)
+ {
+ return left.i_newfuncpos < right.i_newfuncpos;
+ }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineOpenClosed(ofstream& f, unsigned int tabstops, const string& element, const string& data)
+{
+ string tabs(tabstops, REPORT_TAB_CHAR);
+ string xmldata(data);
+
+ // replace & -> ä
+ string::size_type i=0;
+ while ((i=xmldata.find("&", i)) != string::npos)
+ {
+ xmldata.replace(i, 1, "&");
+ i++;
+ }
+
+ // replace < -> <
+ i=0;
+ while ((i=xmldata.find("<", i)) != string::npos)
+ xmldata.replace(i, 1, "<");
+
+ // replace > -> >
+ i=0;
+ while ((i=xmldata.find(">", i)) != string::npos)
+ xmldata.replace(i, 1, ">");
+
+
+ f << tabs << "<" << element << ">" << xmldata << "</" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineOpeningTag(ofstream& f, unsigned int tabstops, const string& element)
+{
+ string tabs(tabstops, REPORT_TAB_CHAR);
+
+ f << tabs << "<" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineClosingTag(ofstream& f, unsigned int tabstops, const string& element)
+{
+ string tabs(tabstops, REPORT_TAB_CHAR);
+
+ f << tabs << "</" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void writeXMLIssueLibraryHeader(ofstream& f, const string& libname, const string& curlibname)
+{
+
+ WriteXMLLineOpeningTag(f, 2, "library");
+ WriteXMLLineOpenClosed(f, 3, "name", libname);
+ WriteXMLLineOpenClosed(f, 3, "comparefilename", curlibname);
+
+ string finallibname(curlibname);
+ if (finallibname.empty())
+ finallibname=libname;
+ finallibname=getFilename(finallibname);
+ // remove any extensions from libname
+ string::size_type dot_loc = finallibname.find_last_of(".");
+ if (dot_loc != string::npos)
+ finallibname = finallibname.substr(0, dot_loc);
+ WriteXMLLineOpenClosed(f, 3, "shortname", finallibname);
+ WriteXMLLineOpenClosed(f, 3, "baseplatform", getPlatform(libname));
+ WriteXMLLineOpenClosed(f, 3, "currentplatform", getPlatform(curlibname));
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void writeXMLIssueLibraryFooter(ofstream& f)
+{
+ WriteXMLLineClosingTag(f, 2, "library");
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLIssueOnlyInBaselineDir(ofstream& f, const string& libname, dll_issue& dllIssue)
+{
+ writeXMLIssueLibraryHeader(f, libname, "");
+ WriteXMLLineOpeningTag(f, 3, "issue");
+ WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(ISSUE_ONLY_IN_BASELINEDIR));
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break");
+ WriteXMLLineOpenClosed(f, 4, "sc_severity", "SC Break");
+ WriteXMLLineClosingTag(f, 3, "issue");
+ for(unsigned int i =0; i< dllIssue.i_list_typeid.size(); i++ )
+ {
+ string typeinfo = "";
+ WriteXMLLineOpeningTag(f, 3, "issue");
+ WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(dllIssue.i_list_typeid.at(i)));
+ typeinfo = GetDllBreakTypeInfoString(dllIssue.i_list_typeid.at(i));
+ if(typeinfo.size() > 0)
+ WriteXMLLineOpenClosed(f, 4, "typeinfo", typeinfo);
+
+ if (dllIssue.i_list_typeid.at(i) == DLL_BASELINE_MISSING )
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");
+ else
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break");
+
+ WriteXMLLineOpenClosed(f, 4, "sc_severity", "None");
+
+ WriteXMLLineClosingTag(f, 3, "issue");
+ }
+ writeXMLIssueLibraryFooter(f);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLIssueOnlyInCurrentDir(ofstream& f, const string& libname)
+{
+ writeXMLIssueLibraryHeader(f, "", libname);
+ WriteXMLLineOpeningTag(f, 3, "issue");
+ WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(ISSUE_ONLY_IN_CURRENTDIR));
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");
+ WriteXMLLineOpenClosed(f, 4, "sc_severity", "Informative");
+ WriteXMLLineClosingTag(f, 3, "issue");
+ writeXMLIssueLibraryFooter(f);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteIssueListToXML(ofstream& f, const string& libname, const string& curlibname,vector<issue>& issue_list, dll_issue& dllIssue)
+{
+ if (issue_list.size() > 0 || dllIssue.i_list_typeid.size() > 0)
+ {
+ string finallibname(curlibname);
+ // write header
+ WriteXMLLineOpeningTag(f, 2, "library");
+ WriteXMLLineOpenClosed(f, 3, "name", libname);
+ WriteXMLLineOpenClosed(f, 3, "comparefilename", curlibname);
+ finallibname=getFilename(finallibname);
+ // remove any extensions from libname
+ string::size_type dot_loc = finallibname.find_last_of(".");
+ if (dot_loc != string::npos)
+ finallibname = finallibname.substr(0, dot_loc);
+ WriteXMLLineOpenClosed(f, 3, "shortname", finallibname);
+ WriteXMLLineOpenClosed(f, 3, "baseplatform", getPlatform(libname));
+ WriteXMLLineOpenClosed(f, 3, "currentplatform", getPlatform(curlibname));
+
+ // write all single issues
+ for (unsigned int i=0; i<issue_list.size(); i++)
+ {
+ WriteXMLLineOpeningTag(f, 3, "issue");
+
+ WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(issue_list.at(i).i_typeid));
+
+ if (issue_list.at(i).i_funcname.length() > 0)
+ WriteXMLLineOpenClosed(f, 4, "funcname", issue_list.at(i).i_funcname);
+
+ if (issue_list.at(i).i_newfuncname.length() > 0)
+ WriteXMLLineOpenClosed(f, 4, "newfuncname", issue_list.at(i).i_newfuncname);
+
+ if (issue_list.at(i).i_funcpos > 0)
+ WriteXMLLineOpenClosed(f, 4, "funcpos", Int2Str(issue_list.at(i).i_funcpos));
+
+ if (issue_list.at(i).i_newfuncpos > 0)
+ WriteXMLLineOpenClosed(f, 4, "newfuncpos", Int2Str(issue_list.at(i).i_newfuncpos));
+
+ if (issue_list.at(i).i_BC_severity.length() > 0)
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", issue_list.at(i).i_BC_severity);
+
+ if (issue_list.at(i).i_SC_severity.length() > 0)
+ WriteXMLLineOpenClosed(f, 4, "sc_severity", issue_list.at(i).i_SC_severity);
+
+ WriteXMLLineClosingTag(f, 3, "issue");
+ }
+
+
+ for (unsigned int i=0; i<dllIssue.i_list_typeid.size(); i++)
+ {
+ string typeinfo = "";
+ WriteXMLLineOpeningTag(f, 3, "issue");
+ WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(dllIssue.i_list_typeid.at(i)));
+ typeinfo = GetDllBreakTypeInfoString(dllIssue.i_list_typeid.at(i));
+ if(typeinfo.size() > 0)
+ WriteXMLLineOpenClosed(f, 4, "typeinfo", typeinfo);
+
+ if (dllIssue.i_list_typeid.at(i) == DLL_BASELINE_MISSING )
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");
+ else
+ WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break");
+
+ WriteXMLLineOpenClosed(f, 4, "sc_severity", "None");
+ WriteXMLLineClosingTag(f, 3, "issue");
+ }
+
+ // finally write footer
+ WriteXMLLineClosingTag(f, 2, "library");
+ }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+