apicompatanamdw/compatanalysercmd/libraryanalyser/src/la_getters.cpp
changeset 0 638b9c697799
child 3 ebe3f8f03b59
equal deleted inserted replaced
-1:000000000000 0:638b9c697799
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Utility functions for getting data via 3rd party tools
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "la.hpp"
       
    20 
       
    21 // ----------------------------------------------------------------------------------------------------------
       
    22 // TIP: Use The Regex Coach (http://weitz.de/regex-coach/) to check that the regular expressions are working correctly
       
    23 // Note that in C/C++ code \ has been replaced with \\ and " with \".
       
    24 // ----------------------------------------------------------------------------------------------------------
       
    25 
       
    26 void GetSymbolTableWithNM(const string& nm_location, const string& lib_name, vector<string>& symbol_table)
       
    27 {
       
    28     symbol_table.clear();
       
    29     vector<string> tempVector;
       
    30     vector<ordinal> ordinals;
       
    31     
       
    32     // execute nm
       
    33     string cmd = nm_location + " --demangle \"" + lib_name + "\"";
       
    34     ExecuteCommand(cmd, tempVector);
       
    35 
       
    36    
       
    37     // parse the results of the command
       
    38     for (unsigned int j=0; j<tempVector.size(); j++)
       
    39     {
       
    40         // first check if we have found the beginning of a block
       
    41  
       
    42         boost::cmatch matches1;
       
    43         boost::cmatch matches2;
       
    44         boost::cmatch matches3;
       
    45     
       
    46         bool match1 = false;
       
    47         bool match2 = false;
       
    48         bool match3 = false;
       
    49     
       
    50         // Symbian OS 6.1 LIB file, example: ds00001.o:
       
    51         boost::regex re1("^ds(\\d+)\\.o\\:");
       
    52         match1 = boost::regex_match(tempVector.at(j).c_str(), matches1, re1);
       
    53     
       
    54         if (!match1)
       
    55         {
       
    56             // Symbian OS 7.x-8.x LIB file, example: C:/DOCUME~1/mattlait/LOCALS~1/Temp/1/d1000s_00001.o:
       
    57             boost::regex re2("^\\S*s_(\\d+)\\.o\\:");
       
    58             match2 = boost::regex_match(tempVector.at(j).c_str(), matches2, re2);
       
    59             
       
    60             if (!match2)
       
    61             {
       
    62                 // Symbian OS 9.x LIB file, example: AGENTDIALOG{000a0000}-14.o:
       
    63                 boost::regex re3("^\\S*\\{000a0000\\}-(\\d+)\\.o\\:");
       
    64                 match3 = boost::regex_match(tempVector.at(j).c_str(), matches3, re3);
       
    65             }
       
    66         }
       
    67     
       
    68         if (match1 || match2 || match3)
       
    69         {
       
    70             // now get the ordinal number
       
    71             string ordNum;
       
    72             
       
    73             if (match1)
       
    74                 {
       
    75                 string ms(matches1[1].first, matches1[1].second);
       
    76                 ordNum = ms;
       
    77                 }
       
    78             else if (match2)
       
    79                 {
       
    80                 string ms(matches2[1].first, matches2[1].second);
       
    81                 ordNum = ms;
       
    82                 }
       
    83             else if (match3)
       
    84                 {
       
    85                 string ms(matches3[1].first, matches3[1].second);
       
    86                 ordNum = ms;
       
    87                 }
       
    88     
       
    89             // now start looking for the line with the export name
       
    90             // eg: 00000000 T CUserActivityManager::RunL(void)
       
    91             while (j<tempVector.size()-1)
       
    92             {
       
    93                 j++;
       
    94     
       
    95                 boost::regex re4("^\\d+\\sT\\s(.*)$");
       
    96                 boost::cmatch matches4;
       
    97     
       
    98                 if (boost::regex_match(tempVector.at(j).c_str(), matches4, re4))
       
    99                 {
       
   100                     // now we have a full entry
       
   101                     string ms(matches4[1].first, matches4[1].second);
       
   102 
       
   103                     // append to the ordinal list
       
   104                     ordinals.push_back(ordinal(Str2Int(ordNum), ms));
       
   105    
       
   106                     break;
       
   107                 }
       
   108             }
       
   109         } // (match1 || match2)
       
   110     } // for (int j=0; j<tempVector.size(); j++)
       
   111     
       
   112     // convert the ordinal list into a symbol table
       
   113     ConvertOrdinalListIntoSymbolTable(ordinals, symbol_table, lib_name); 
       
   114 
       
   115 
       
   116     //for (int k=0; k<symbol_table.size(); k++)
       
   117     //{
       
   118     //    cerr << symbol_table.at(k) << endl;
       
   119     //}
       
   120 
       
   121     //if (symbol_table.size() == 0)
       
   122     //{
       
   123     //    cerr << "Warning: No ordinals in " << lib_directory << lib_name << endl;
       
   124     //}
       
   125   
       
   126 
       
   127 }
       
   128 
       
   129 // ----------------------------------------------------------------------------------------------------------
       
   130 
       
   131 void GetSymbolTableWithReadelf(const string& readelf_location, const string& cfilt_location, const string& lib_name, vector<string>& symbol_table)
       
   132 {
       
   133     symbol_table.clear();
       
   134     vector<string> tempVector;
       
   135     vector<ordinal> ordinals;
       
   136     
       
   137     // execute readelf
       
   138     // note: 2>NUL is used here to redirect standard error output to NULL since readelf seems to output lots of unwanted warning messages
       
   139     string cmd = readelf_location + " -s -W \"" + lib_name + "\" " + CERR_TO_NULL;
       
   140     ExecuteCommand(cmd, tempVector);
       
   141 
       
   142    
       
   143     // parse the results of the command
       
   144     for (unsigned int j=0; j<tempVector.size(); j++)
       
   145     {
       
   146         boost::cmatch matches1;
       
   147     
       
   148         // example:
       
   149         //     1: 00000000     4 NOTYPE  GLOBAL DEFAULT    1 _ZN13CSpdiaControl10DrawShadowER9CWindowGcRK5TSize@@SpdCtrl{000a0000}[10005986].dll
       
   150         boost::regex re1("^\\s*(\\d+)\\:.+GLOBAL.+\\d+\\s+(.*)\\@\\@.*");
       
   151         
       
   152         if (boost::regex_match(tempVector.at(j).c_str(), matches1, re1))
       
   153         {
       
   154             // match found
       
   155             string ms1(matches1[1].first, matches1[1].second);
       
   156             string ms2(matches1[2].first, matches1[2].second);
       
   157 
       
   158             // append to the ordinal list
       
   159             ordinals.push_back(ordinal(Str2Int(ms1), ms2));
       
   160         }
       
   161 
       
   162     } // for (int j=0; j<tempVector.size(); j++)
       
   163     
       
   164     // convert the ordinal list into a symbol table
       
   165     ConvertOrdinalListIntoSymbolTable(ordinals, symbol_table, lib_name); 
       
   166 
       
   167     // finally demangle all function names since it's not done in this case automatically
       
   168     DemangleOrdinalsInSymbolTable(cfilt_location, symbol_table);
       
   169 
       
   170     //for (int k=0; k<symbol_table.size(); k++)
       
   171     //{
       
   172     //    cerr << symbol_table.at(k) << endl;
       
   173     //}
       
   174 
       
   175     //if (symbol_table.size() == 0)
       
   176     //{
       
   177     //    cerr << "Warning: No ordinals in " << lib_directory << lib_name << endl;
       
   178     //}
       
   179 
       
   180 }
       
   181 
       
   182 // ----------------------------------------------------------------------------------------------------------
       
   183 
       
   184 void GetSymbolTableWithArmar(const string& armar_location, const string& cfilt_location, const string& lib_name, vector<string>& symbol_table)
       
   185 {
       
   186     symbol_table.clear();
       
   187     vector<string> tempVector;
       
   188     vector<ordinal> ordinals;
       
   189     
       
   190     // execute armar
       
   191     string cmd = armar_location + " --zs \"" + lib_name + "\"";
       
   192     ExecuteCommand(cmd, tempVector);
       
   193 
       
   194    
       
   195     // parse the results of the command
       
   196     for (unsigned int j=0; j<tempVector.size(); j++)
       
   197     {
       
   198         // find the entries, example:
       
   199         // _ZN13TAgnWeeklyRptC1Ev from AGNMODEL{000a0000}-187.o at offset 158366
       
   200         boost::regex re1("(\\S*)\\s+from\\s.*-(\\d+)\\.o.*");
       
   201         boost::cmatch matches1;
       
   202         
       
   203         if (boost::regex_match(tempVector.at(j).c_str(), matches1, re1))
       
   204         {
       
   205             // match found
       
   206             string ms1(matches1[2].first, matches1[2].second);
       
   207             string ms2(matches1[1].first, matches1[1].second);
       
   208 
       
   209             // append to the ordinal list
       
   210             ordinals.push_back(ordinal(Str2Int(ms1), ms2));            
       
   211         }
       
   212 
       
   213     } // for (int j=0; j<tempVector.size(); j++)
       
   214     
       
   215     // convert the ordinal list into a symbol table
       
   216     ConvertOrdinalListIntoSymbolTable(ordinals, symbol_table, lib_name); 
       
   217 
       
   218     // finally demangle all function names since it's not done in this case automatically
       
   219     DemangleOrdinalsInSymbolTable(cfilt_location, symbol_table);
       
   220 
       
   221 
       
   222     //for (int k=0; k<symbol_table.size(); k++)
       
   223     //{
       
   224     //    cerr << symbol_table.at(k) << endl;
       
   225     //}
       
   226 
       
   227     //if (symbol_table.size() == 0)
       
   228     //{
       
   229     //    cerr << "Warning: No ordinals in " << lib_directory << lib_name << endl;
       
   230     //}
       
   231 
       
   232 }
       
   233 
       
   234 // ----------------------------------------------------------------------------------------------------------
       
   235 
       
   236 void GetSymbolTableWithFromelf(const string& fromelf_location, const string& cfilt_location, const string& lib_name, vector<string>& symbol_table)
       
   237 {
       
   238     symbol_table.clear();
       
   239     vector<string> tempVector;
       
   240     vector<ordinal> ordinals;
       
   241     
       
   242     // execute fromelf
       
   243     string cmd = fromelf_location + " -s \"" + lib_name + "\"";
       
   244     ExecuteCommand(cmd, tempVector);
       
   245    
       
   246     // parse the results of the command
       
   247     for (unsigned int j=0; j<tempVector.size(); j++)
       
   248     {
       
   249         // first find the start of the symbol table
       
   250         // ** Section #5 '.version' (SHT_GNU_versym)
       
   251         boost::regex re1("^.*(SHT_GNU_versym).*");
       
   252         boost::cmatch matches1;
       
   253         
       
   254         if (boost::regex_match(tempVector.at(j).c_str(), matches1, re1))
       
   255         {
       
   256             //int previous_ordinal = 0;
       
   257 
       
   258             while (j<tempVector.size()-1)
       
   259             {
       
   260                 j++;
       
   261 
       
   262                 //cout << tempVector.at(j) << endl;
       
   263 
       
   264                 // now find the entries, examples:
       
   265                 //         7   _ZNK17CPbkContactEngine9FsSessionEv           2 PbkEng{000a0000}[101f4cce].dll
       
   266                 //         8   _ZN17CPbkContactEngine19CreateEmptyContactLEv
       
   267                 //                                                           2 PbkEng{000a0000}[101f4cce].dll
       
   268                 // notice that line can be spread to two lines so make sure we don't accidentally get a wrong line
       
   269 
       
   270                 // first parse out any unwanted lines
       
   271                 boost::regex re2("^\\s*\\d+\\s+\\S+\\.\\w+$");
       
   272                 boost::cmatch matches2;
       
   273                 if (boost::regex_match(tempVector.at(j).c_str(), matches2, re2))
       
   274                 {
       
   275                     //cout << "skipping" << endl;    
       
   276                     continue;                
       
   277                 }
       
   278 
       
   279                 // now it should be the wanted line
       
   280                 boost::regex re3("^\\s*(\\d+)\\s*(\\S*).*");
       
   281                 boost::cmatch matches3;
       
   282 
       
   283                 if (boost::regex_match(tempVector.at(j).c_str(), matches3, re3))
       
   284                 {    
       
   285                     // cout << tempVector.at(j) << endl;
       
   286 
       
   287                     // match found
       
   288                     string ms1(matches3[1].first, matches3[1].second);
       
   289                     string ms2(matches3[2].first, matches3[2].second);
       
   290         
       
   291                     // append to the ordinal list
       
   292                     ordinals.push_back(ordinal(Str2Int(ms1), ms2));
       
   293 
       
   294                     //cout << "match " << ms1 << " " << ms2 << endl;    
       
   295                     
       
   296                     // with fromelf, all entries are in order
       
   297                     // check that we don't miss any ordinals
       
   298                     //if (previous_ordinal + 1 != Str2Int(ms1))
       
   299                     //{
       
   300                     //    cerr << endl << "Aborting because of Fromelf ordinal order check error in " << lib_directory << lib_name << " in line:" << endl << tempVector.at(j) << endl;
       
   301                     //    exit(11);    
       
   302                     //}
       
   303                     //previous_ordinal = Str2Int(ms1);
       
   304                 }
       
   305 
       
   306             } //while (j<tempVector.size())
       
   307 
       
   308       
       
   309         } //if (boost::regex_match(tempVector.at(j).c_str(), matches1, re1))
       
   310 
       
   311     } // for (int j=0; j<tempVector.size(); j++)
       
   312 
       
   313     // convert the ordinal list into a symbol table
       
   314     ConvertOrdinalListIntoSymbolTable(ordinals, symbol_table, lib_name); 
       
   315 
       
   316     // finally demangle all function names since it's not done in this case automatically
       
   317     DemangleOrdinalsInSymbolTable(cfilt_location, symbol_table);
       
   318 
       
   319     //for (int k=0; k<symbol_table.size(); k++)
       
   320     //{
       
   321     //    cerr << symbol_table.at(k) << endl;
       
   322     //}
       
   323 
       
   324     //if (symbol_table.size() == 0)
       
   325     //{
       
   326     //    cerr << "Warning: No ordinals in " << lib_directory << lib_name << endl;
       
   327     //}
       
   328 
       
   329 }
       
   330 
       
   331 // ----------------------------------------------------------------------------------------------------------
       
   332 
       
   333 void ConvertOrdinalListIntoSymbolTable(const vector<ordinal>& ordinals, vector<string>& symbol_table, const string& lib_path)
       
   334 {
       
   335     // remove any invalid ordinals from the list    
       
   336     vector<ordinal> ordinalVectorCopy;
       
   337     ordinalVectorCopy.reserve(ordinals.size());
       
   338 
       
   339     for (unsigned int i=0; i<ordinals.size(); i++)
       
   340     {
       
   341         if (ordinals.at(i).funcpos <= 0 && ordinals.at(i).funcpos > 32000)
       
   342         {
       
   343             cerr << "Error: Invalid ordinal " << ordinals.at(i).funcname << " @ " << Int2Str(ordinals.at(i).funcpos) << endl;
       
   344         }
       
   345         else
       
   346         {
       
   347             ordinalVectorCopy.push_back(ordinals.at(i));
       
   348         }
       
   349     }
       
   350 
       
   351     // sort the ordinal list
       
   352     sort(ordinalVectorCopy.begin(), ordinalVectorCopy.end(), OrdinalCompare);
       
   353 
       
   354     // now check that there are no missing ordinals in the list
       
   355     unsigned int previous_ordnumber = 0;
       
   356     unsigned int current_ordnumber = 1;
       
   357     for (unsigned int i=0; i<ordinalVectorCopy.size(); i++)
       
   358     {      
       
   359         // get the current ordinal number
       
   360         current_ordnumber = ordinalVectorCopy.at(i).funcpos;
       
   361         //cout << "CurOrdNum: " << Int2Str(current_ordnumber) << endl;
       
   362         
       
   363         // the current ordinal number obviously should be one bigger than the previous one
       
   364         if ( current_ordnumber != previous_ordnumber+1 )
       
   365         {
       
   366             // append a dummy ordinal to the list
       
   367             ordinalVectorCopy.insert(ordinalVectorCopy.begin()+i, ordinal(i+1, "UnknownOrdinal-"+Int2Str(i+1)));
       
   368             current_ordnumber = i+1;
       
   369             //cout << "Appended a dummy ordinal at pos " << Int2Str(i+1) << endl;
       
   370         }
       
   371 
       
   372         // remember the previous ordinal number
       
   373         previous_ordnumber = current_ordnumber;
       
   374         
       
   375         // if the ordinal list is corrupted, it may lead to an infinite loop
       
   376         if (i>25000)
       
   377         {
       
   378             cerr << endl << "Something went horribly wrong when trying to parse " << lib_path << ". Aborting." << endl;           
       
   379             exit(10);
       
   380         }
       
   381     }    
       
   382    
       
   383     // finally copy data from the ordinal list to the symbol table
       
   384     if (symbol_table.size() < ordinalVectorCopy.size())
       
   385     {
       
   386         symbol_table.reserve(ordinalVectorCopy.size());
       
   387     }
       
   388     for (unsigned int i=0; i<ordinalVectorCopy.size(); i++)
       
   389     {      
       
   390         symbol_table.push_back( ordinalVectorCopy.at(i).funcname );
       
   391     }
       
   392 }
       
   393 
       
   394 // ----------------------------------------------------------------------------------------------------------
       
   395 
       
   396 void DemangleOrdinalsInSymbolTable(const string& cfilt_location, vector<string>& symbol_table)
       
   397 {
       
   398     ofstream f(_tempfile_location.c_str(), ios::trunc);
       
   399     if (f.is_open())
       
   400     {
       
   401         // create a temp file which contain all the function names
       
   402         for (unsigned int k=0; k<symbol_table.size(); k++)
       
   403         {   
       
   404             f << symbol_table.at(k) << endl;
       
   405         }
       
   406         f.close();
       
   407 
       
   408         // execute cfilt
       
   409         vector<string> cfilt_result_set;
       
   410         string tempfile_loc = _tempfile_location;
       
   411         InsertQuotesToFilePath(tempfile_loc);
       
   412         string cmd = cfilt_location + " < " + tempfile_loc;
       
   413         ExecuteCommand(cmd, cfilt_result_set);
       
   414 
       
   415         // check that all functions exist and then replace the symbol table with demangled functions        
       
   416         if (cfilt_result_set.size() == symbol_table.size())
       
   417         {
       
   418             symbol_table = cfilt_result_set;
       
   419         }
       
   420     }
       
   421     else
       
   422     {
       
   423         f.close();
       
   424     }    
       
   425 }
       
   426 
       
   427 // ----------------------------------------------------------------------------------------------------------
       
   428 
       
   429 bool OrdinalCompare(const ordinal& left, const ordinal& right)
       
   430 {
       
   431     return left.funcpos < right.funcpos;
       
   432 }
       
   433 
       
   434 // ----------------------------------------------------------------------------------------------------------
       
   435 
       
   436