srcanamdw/appdep/src/appdep_cache.cpp
changeset 0 509e4801c378
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanamdw/appdep/src/appdep_cache.cpp	Sat Jan 09 10:04:12 2010 +0530
@@ -0,0 +1,557 @@
+/*
+* Copyright (c) 2007 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:  Cache handling routines 
+*
+*/
+
+
+#include "appdep.hpp"
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+void ReadDataFromSymbolTablesCache(target& a_target)
+{
+	string line;
+	
+	ifstream symtabcachef(a_target.st_cache_path.c_str());
+    if (!symtabcachef.is_open())
+    {
+        cerr << "Warning: Regenerating corrupted cache of target " << a_target.name << endl;
+        a_target.cache_files_valid = false;
+        _some_cache_needs_update = true;
+        return;    
+    }	
+	
+	getline(symtabcachef, line);
+	if (line != CACHE_ST_HEADER)
+    {
+        cerr << "Warning: Regenerating corrupted cache of target " << a_target.name  << endl;
+        a_target.cache_files_valid = false;  
+        _some_cache_needs_update = true;
+    }
+    else
+    {     
+        // loop through all lines in the file
+        while(!symtabcachef.eof())
+        {
+            getline(symtabcachef, line);
+            
+            if (line.length() > 0 && line[0] != CACHE_COMMENT_CHAR)
+            {
+                // first entry is the directory|filename|modification_time|symbol_table_size , eg
+                // x:\epoc32\release\armv5\urel\|avkon.dll|1160666488|178
+                string::size_type delim1 = line.find(CACHE_SEP, 0);
+                string::size_type delim2 = line.find(CACHE_SEP, delim1+1);
+                string::size_type delim3 = line.find(CACHE_SEP, delim2+1);
+
+                import_library_info lib_info;
+                lib_info.directory = line.substr(0, delim1);
+                lib_info.filename = line.substr(delim1+1, delim2-delim1-1);
+                lib_info.mod_time = Str2Int( line.substr(delim2+1, delim3-delim2-1) );
+                unsigned int symbol_table_size = Str2Int( line.substr(delim3+1, line.length()-delim3-1) );
+                
+                // get symbol table
+                vector<string> symbol_table; 
+                for (unsigned int j=0; j<symbol_table_size; j++)
+                {
+                    getline(symtabcachef, line);
+                    symbol_table.push_back( line );
+                }
+                
+                lib_info.symbol_table = symbol_table;
+                
+                // append binary info to the vectory
+                a_target.import_libraries.push_back( lib_info );
+            }            
+        }
+        
+        // check that the last line of the file contains the footer of the cache
+        if (line != CACHE_FOOTER)
+        {
+            cerr << "Warning: Regenerating corrupted cache of target " << a_target.name  << endl;
+            a_target.import_libraries.clear();
+            a_target.cache_files_valid = false;  
+            _some_cache_needs_update = true;
+        }
+    }
+    
+    symtabcachef.close();  
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void ReadDataFromDependenciesCache(target& a_target)
+{
+    string line;
+        	
+    // read data from the dependencies cache file
+	ifstream depcachef(a_target.dep_cache_path.c_str());
+    if (!depcachef.is_open())
+    {
+        cerr << "Warning: Regenerating corrupted cache of target " << a_target.name << endl;
+        a_target.cache_files_valid = false;
+        _some_cache_needs_update = true;
+        return;    
+    }	
+	
+	getline(depcachef, line);
+	if (line != CACHE_DEP_HEADER)
+    {
+        cerr << "Warning: Regenerating corrupted cache of target " << a_target.name  << endl;
+        a_target.cache_files_valid = false;  
+        _some_cache_needs_update = true;
+    }
+    else
+    {     
+        // loop through all lines in the file
+        while(!depcachef.eof())
+        {
+            getline(depcachef, line);
+            
+            if (line.length() > 0 && line[0] != CACHE_COMMENT_CHAR)
+            {
+                // first entry is the directory|filename|binary_format|uid1|uid2|uid3|secureid|vendorid|capabilities|min_heap_size|max_heap_size|stack_size|modification_time|number_of_dependencies , eg
+                // x:\epoc32\release\armv5\urel\|about.exe|EPOC Exe for ARMV4 CPU|0x1000007a|0x100039ce|0x10005a22|0x10005a22|0x101fb657|782384|4096|1048576|8192|1160666488|11
+                string::size_type delim1 = line.find(CACHE_SEP, 0);
+                string::size_type delim2 = line.find(CACHE_SEP, delim1+1);
+                string::size_type delim3 = line.find(CACHE_SEP, delim2+1);
+                string::size_type delim4 = line.find(CACHE_SEP, delim3+1);
+                string::size_type delim5 = line.find(CACHE_SEP, delim4+1);
+                string::size_type delim6 = line.find(CACHE_SEP, delim5+1);
+                string::size_type delim7 = line.find(CACHE_SEP, delim6+1);
+                string::size_type delim8 = line.find(CACHE_SEP, delim7+1);
+                string::size_type delim9 = line.find(CACHE_SEP, delim8+1);
+                string::size_type delim10 = line.find(CACHE_SEP, delim9+1);
+                string::size_type delim11 = line.find(CACHE_SEP, delim10+1);
+                string::size_type delim12 = line.find(CACHE_SEP, delim11+1);
+                string::size_type delim13 = line.find(CACHE_SEP, delim12+1);
+
+                binary_info b_info;
+                b_info.directory = line.substr(0, delim1);
+                b_info.filename = line.substr(delim1+1, delim2-delim1-1);
+                b_info.binary_format = line.substr(delim2+1, delim3-delim2-1);
+                b_info.uid1 = line.substr(delim3+1, delim4-delim3-1);
+                b_info.uid2 = line.substr(delim4+1, delim5-delim4-1);
+                b_info.uid3 = line.substr(delim5+1, delim6-delim5-1);
+                b_info.secureid = line.substr(delim6+1, delim7-delim6-1);
+                b_info.vendorid = line.substr(delim7+1, delim8-delim7-1);
+                b_info.capabilities = Str2Int( line.substr(delim8+1, delim9-delim8-1) );
+                b_info.min_heap_size = Str2Int( line.substr(delim9+1, delim10-delim9-1) );
+                b_info.max_heap_size = Str2Int( line.substr(delim10+1, delim11-delim10-1) );
+                b_info.stack_size = Str2Int( line.substr(delim11+1, delim12-delim11-1) );
+                b_info.mod_time = Str2Int( line.substr(delim12+1, delim13-delim12-1) );
+                unsigned int number_of_deps = Str2Int( line.substr(delim13+1, line.length()-delim13-1) );
+                
+                vector<dependency> deps; 
+                for (unsigned int j=0; j<number_of_deps; j++)
+                {
+                    getline(depcachef, line);
+                    
+                    // second type entry is filename|number_of_imports , eg
+                    // APPARC.DLL|6
+                    string::size_type delim1 = line.find(CACHE_SEP, 0);
+                    
+                    dependency dep;
+                    dep.filename = line.substr(0, delim1);
+                    unsigned int number_of_imports = Str2Int( line.substr(delim1+1, line.length()-delim1-1) );
+                    
+                    vector<import> imps;
+                    for (unsigned int k=0; k<number_of_imports; k++)
+                    {
+                        getline(depcachef, line);
+                        
+                        // third type on entry is funcpos|funcname|is_vtable|vtable_offset, eg
+                        // 121|CApaDocument::Capability() const|0|0
+                        string::size_type delim1 = line.find(CACHE_SEP, 0);
+                        string::size_type delim2 = line.find(CACHE_SEP, delim1+1);
+                        string::size_type delim3 = line.find(CACHE_SEP, delim2+1);
+                        
+                        import imp;
+                        imp.funcpos = Str2Int( line.substr(0, delim1) );
+                        imp.funcname = line.substr(delim1+1, delim2-delim1-1);
+                        imp.is_vtable = Str2Int( line.substr(delim2+1, delim3-delim2-1) );
+                        imp.vtable_offset = Str2Int( line.substr(delim3+1, line.length()-delim3-1) );
+                        
+                        // append to the import info vector
+                        imps.push_back( imp );
+                    }                     
+                    
+                    // now we have import info too
+                    dep.imports = imps;
+                    
+                    // append to the deps info vector
+                    deps.push_back( dep );
+                                    
+                }
+                // now we have the dep info too
+                b_info.dependencies = deps;
+                
+                // apppend binary info to the vector
+                a_target.binaries.push_back( b_info );
+            }            
+        }
+
+        // check that the last line of the file contains the footer of the cache
+        if (line != CACHE_FOOTER)
+        {
+            cerr << "Warning: Regenerating corrupted cache of target " << a_target.name  << endl;
+            a_target.binaries.clear();
+            a_target.cache_files_valid = false;  
+            _some_cache_needs_update = true;
+        }
+    }
+    depcachef.close();         
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void GetDataFromImportTables(target& a_target)
+{
+    // read data from import libraries if needed
+    for (unsigned int i=0; i<a_target.lib_files.size(); i++)
+    {
+        bool is_new_file = true;
+
+        vector<string> symbol_table;
+
+        if (_cl_print_debug)
+            cerr << "Processing " << a_target.release_lib_dir << a_target.lib_files.at(i) << "...";
+
+        // if not generating a clean cache, check if this file was already in the cache 
+        if (!_cl_generate_clean_cache)
+        {
+            // first try to find existing file
+            bool update_file = false;
+            int position = 0;
+            
+            for (unsigned int j=0; j<a_target.import_libraries.size(); j++)
+            {
+                // check if names match
+                if (StringICmpFileNamesWithoutExtension(a_target.lib_files.at(i), a_target.import_libraries.at(j).filename) == 0)
+                {
+                    // the file was already found from the cache
+                    is_new_file = false;
+                    
+                    // compare modification times
+                    struct stat stat_p;
+                    stat((a_target.release_lib_dir + a_target.lib_files.at(i)).c_str(), &stat_p); // get new stats
+                    
+                    if (!TimestampsMatches(a_target.import_libraries.at(j).mod_time, stat_p.st_mtime))
+                    {
+                        // time stamps are different so needs to update the file
+                        update_file = true;
+                        position = j;                         
+                    }
+                    
+                    // there can't be anymore same names, so break the loop anyway
+                    break;
+                }
+            }
+
+            // get the new data
+            if (update_file)
+            {
+                a_target.cache_files_valid = false;  // cache files on disk must be rewritten
+                
+                import_library_info& lib_info = a_target.import_libraries.at(position);
+                lib_info.directory = a_target.release_lib_dir;
+                                 
+                if (_cl_use_gcc)
+                {
+                    GetSymbolTableWithNM(_gcc_nm_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                }
+                else if (_cl_use_gcce)
+                {
+                    if (_cl_use_libs)
+                    {
+                        GetSymbolTableWithNM(_gcce_nm_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                    }
+                    else
+                    {
+                        GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                    }
+                }
+                else if (_cl_use_rvct)
+                {
+                    if (_cl_use_libs)
+                    {
+                        GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                    }
+                    else
+                    {
+                        GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                    }
+                }
+                
+                lib_info.symbol_table = symbol_table;
+                
+                // get statistics of the file and set the modification time
+                struct stat stat_p;
+                stat((a_target.release_lib_dir + a_target.lib_files.at(i)).c_str(), &stat_p);
+                lib_info.mod_time = stat_p.st_mtime;
+                
+                // record changed import libraries
+                _changed_import_libraries.push_back( lib_info );
+            }
+        }
+        
+        // this is a new file, get info and append it to the vector
+        if (is_new_file)
+        {
+            a_target.cache_files_valid = false;  // cache files on disk must be rewritten
+
+            // get the symbol tables of the library
+            if (_cl_use_gcc)
+            {
+                GetSymbolTableWithNM(_gcc_nm_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+            }
+            else if (_cl_use_gcce)
+            {
+                if (_cl_use_libs)
+                {
+                    GetSymbolTableWithNM(_gcce_nm_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                }
+                else
+                {
+                    GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                }
+            }
+            else if (_cl_use_rvct)
+            {
+                if (_cl_use_libs)
+                {
+                    GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                }
+                else
+                {
+                    GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, a_target.release_lib_dir, a_target.lib_files.at(i), symbol_table);
+                }
+            }
+            
+            // get statistics of the file
+            struct stat stat_p;
+            stat((a_target.release_lib_dir + a_target.lib_files.at(i)).c_str(), &stat_p);
+            
+            // create a new entry to list of all import libraries
+            import_library_info lib_info;
+            lib_info.directory = a_target.release_lib_dir;
+            lib_info.filename = a_target.lib_files.at(i);
+            lib_info.mod_time = stat_p.st_mtime;
+            lib_info.symbol_table = symbol_table;
+            
+            a_target.import_libraries.push_back( lib_info );
+        }         
+        if (_cl_print_debug)
+            cerr << "OK" << endl;
+        else
+            ShowProgressInfo(_current_progress_percentage, _current_progress, _max_progress, false);
+    }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void GetDataFromBinaries(target& a_target)
+{
+    // read data from binaries
+    for (unsigned int i=0; i<a_target.bin_files.size(); i++)
+    {
+        bool is_new_file = true;
+
+        if (_cl_print_debug)
+            cerr << "Processing " << a_target.release_bin_dir << a_target.bin_files.at(i) << "...";
+
+        // if not generating a clean cache, check if this file was already in the cache 
+        if (!_cl_generate_clean_cache)
+        {
+            // first try to find existing file
+            bool update_file = false;
+            int position = 0;
+            
+            for (unsigned int j=0; j<a_target.binaries.size(); j++)
+            {
+                // check if names match
+                if (StringICmp(a_target.bin_files.at(i).c_str(), a_target.binaries.at(j).filename.c_str()) == 0)
+                {
+                    is_new_file = false;
+
+                    // compare modification times
+                    struct stat stat_p;
+                    stat((a_target.release_bin_dir + a_target.bin_files.at(i)).c_str(), &stat_p); // get new stats
+                    
+                    if (!TimestampsMatches(a_target.binaries.at(j).mod_time, stat_p.st_mtime))
+                    {
+                        // time stamps are different so needs to update the file
+                        update_file = true;
+                        position = j;   
+                        break; 
+                    }
+                    
+                    // the entry also needs to be updated if any import library which this binary has dependency on has changed
+                    for (unsigned int k=0; k<_changed_import_libraries.size(); k++)
+                    {
+                        for (unsigned int p=0; p<a_target.binaries.at(j).dependencies.size(); p++)
+                        {
+                            // check for file name match
+                            if (StringICmpFileNamesWithoutExtension(a_target.binaries.at(j).dependencies.at(p).filename, _changed_import_libraries.at(k).filename) == 0)
+                            {
+                                update_file = true;
+                                position = j;   
+                                break;
+                            }
+                        }
+
+                        // no need to loop anymore if the file needs update
+                        if (update_file)
+                            break;
+                    }
+                    
+                    // there can't be anymore same names, so break the loop anyway
+                    break;
+                }
+            }
+
+            // get the new data
+            if (update_file)
+            {
+                a_target.cache_files_valid = false;  // cache files on disk must be rewritten
+                
+                binary_info& b_info = a_target.binaries.at(position);
+                b_info.directory = a_target.release_bin_dir;
+                                 
+                GetImportTableWithPetran(_petran_location, b_info);
+                
+                // get statistics of the file and set the modification time
+                struct stat stat_p;
+                stat((a_target.release_bin_dir + a_target.bin_files.at(i)).c_str(), &stat_p);
+                b_info.mod_time = stat_p.st_mtime;
+            }
+        }
+
+        // this is a new file, get info and append it to the vector
+        if (is_new_file)
+        {            
+            a_target.cache_files_valid = false;  // cache files on disk must be rewritten
+
+            binary_info b_info;
+            b_info.directory = a_target.release_bin_dir;
+            b_info.filename = a_target.bin_files.at(i);
+                             
+            GetImportTableWithPetran(_petran_location, b_info);
+            
+            // get statistics of the file and set the modification time
+            struct stat stat_p;
+            stat((a_target.release_bin_dir + a_target.bin_files.at(i)).c_str(), &stat_p);
+            b_info.mod_time = stat_p.st_mtime;
+            
+            // create a new entry to list of all binary files
+            a_target.binaries.push_back( b_info );
+        }
+        
+        if (_cl_print_debug)
+            cerr << "OK" << endl;
+        else
+            ShowProgressInfo(_current_progress_percentage, _current_progress, _max_progress, false);
+    }
+
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteDataToSymbolTableCacheFile(const target& a_target)
+{
+    // open the cache file for writing
+    ofstream symtabcachef(a_target.st_cache_path.c_str(), ios::trunc);
+    if (!symtabcachef.is_open())
+    {
+        symtabcachef.close();
+		cerr << endl << "ERROR: Cannot open " << a_target.st_cache_path << " for writing!" << endl;
+		cerr << "Please check that the directory exists and there are no write permission problems" << endl;
+		exit(EXIT_CANNOT_WRITE_TO_CACHE_FILE);
+    }
+            
+    // write data to the cache file
+    symtabcachef << CACHE_ST_HEADER << endl;
+    
+    for (unsigned int i=0; i<a_target.import_libraries.size(); i++)
+    {
+        vector<string> symbol_table = a_target.import_libraries.at(i).symbol_table;
+
+        symtabcachef << a_target.import_libraries.at(i).directory << CACHE_SEP << a_target.import_libraries.at(i).filename << CACHE_SEP
+                     << a_target.import_libraries.at(i).mod_time << CACHE_SEP << symbol_table.size() << endl;
+        
+        for (unsigned int j=0; j<symbol_table.size(); j++)
+        {
+            symtabcachef << symbol_table.at(j) << endl;
+        }
+    }
+
+    // write footer, note that there is no eol char
+    symtabcachef << CACHE_FOOTER;
+
+    symtabcachef.close(); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteDataToDependenciesCacheFile(const target& a_target)
+{
+    // open the cache file for writing
+    ofstream depcachef(a_target.dep_cache_path.c_str(), ios::trunc);
+    if (!depcachef.is_open())
+    {
+        depcachef.close();
+		cerr << endl << "ERROR: Cannot open " << a_target.dep_cache_path << " for writing!" << endl;
+		cerr << "Please check that the directory exists and there are no write permission problems" << endl;
+		exit(EXIT_CANNOT_WRITE_TO_CACHE_FILE);
+    }
+
+    // write data to the cache file
+    depcachef << CACHE_DEP_HEADER << endl;
+    
+    for (unsigned int i=0; i<a_target.binaries.size(); i++)
+    {
+        vector<dependency> deps = a_target.binaries.at(i).dependencies;
+
+        depcachef << a_target.binaries.at(i).directory << CACHE_SEP << a_target.binaries.at(i).filename << CACHE_SEP
+                  << a_target.binaries.at(i).binary_format << CACHE_SEP << a_target.binaries.at(i).uid1 << CACHE_SEP
+                  << a_target.binaries.at(i).uid2 << CACHE_SEP << a_target.binaries.at(i).uid3 << CACHE_SEP
+                  << a_target.binaries.at(i).secureid << CACHE_SEP << a_target.binaries.at(i).vendorid << CACHE_SEP
+                  << a_target.binaries.at(i).capabilities << CACHE_SEP << a_target.binaries.at(i).min_heap_size << CACHE_SEP
+                  << a_target.binaries.at(i).max_heap_size << CACHE_SEP << a_target.binaries.at(i).stack_size << CACHE_SEP
+                  << a_target.binaries.at(i).mod_time << CACHE_SEP << deps.size() << endl;
+        
+        for (unsigned int j=0; j<deps.size(); j++)
+        {
+            vector<import> imps = deps.at(j).imports;
+
+            depcachef << deps.at(j).filename << CACHE_SEP << imps.size() << endl;
+            
+            for (unsigned int k=0; k<imps.size(); k++)
+            {
+                depcachef << imps.at(k).funcpos << CACHE_SEP << imps.at(k).funcname << CACHE_SEP << imps.at(k).is_vtable
+                          << CACHE_SEP << imps.at(k).vtable_offset << endl;   
+            }
+        }
+    }
+
+    // write footer, note that there is no eol char
+    depcachef << CACHE_FOOTER;
+
+    depcachef.close();  
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+