Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 27 #ifdef _WIN32 28 // Disable a warning in Boost program_options headers: 29 // inconsistent linkage in program_options/variables_map.hpp 30 #pragma warning ( disable : 4273 ) 31 #define popen _popen 32 #define pclose _pclose 33 #define fileno _fileno 34 #include <stdlib.h> 35 #endif 36 37 // Include files---------------------------------------------------------------- 38 #include <vector> 39 #include <string> 40 #include <iostream> 41 #include <fstream> 42 43 // LibSymbolinfo---------------------------------------------------------------- 44 #if !defined(AFX_LIBSYMBOLINFO_H__1A7003B4_BA53_11D1_AE46_1CFB51000000__INCLUDED_) 45 #define AFX_LIBSYMBOLINFO_H__1A7003B4_BA53_11D1_AE46_1CFB51000000__INCLUDED_ 46 47 #if _MSC_VER >= 1000 48 #pragma once 49 #endif // _MSC_VER >= 1000 50 51 #include <string> 52 #include <iostream> 53 54 #include <stdio.h> 55 #include <assert.h> 56 #include <windows.h> 57 58 class CLibSymbolInfo 59 { 60 public: 61 CLibSymbolInfo(); 62 virtual ~CLibSymbolInfo(); 63 BOOL DumpSymbols(LPTSTR lpszLibPathName, std::ostream& pFile); 64 std::string GetLastError() const; 65 66 protected: 67 std::string m_strResultsString; 68 std::string m_strErrorMsg; 69 70 BOOL Dump(LPTSTR lpszLibPathName, std::ostream& pFile); 71 BOOL IsRegularLibSymbol( PSTR pszSymbolName ); 72 BOOL IsFiltedSymbol( std::string& pszSymbolName ); 73 DWORD ConvertBigEndian(DWORD bigEndian); 74 }; 75 76 enum errMMF { errMMF_NoError, errMMF_FileOpen, 77 errMMF_FileMapping, errMMF_MapView }; 78 79 class MEMORY_MAPPED_FILE 80 { 81 public: 82 MEMORY_MAPPED_FILE( PSTR pszFileName ); 83 ~MEMORY_MAPPED_FILE(void); 84 85 PVOID GetBase( void ){ return m_pMemoryMappedFileBase; } 86 DWORD GetFileSize( void ){ return m_cbFile; } 87 BOOL IsValid( void ) { return errMMF_NoError == m_errCode; } 88 errMMF GetErrorType(){ return m_errCode; } 89 90 private: 91 92 HANDLE m_hFile; 93 HANDLE m_hFileMapping; // Handle of memory mapped file 94 PVOID m_pMemoryMappedFileBase; 95 DWORD m_cbFile; 96 errMMF m_errCode; 97 }; 98 99 typedef MEMORY_MAPPED_FILE* PMEMORY_MAPPED_FILE; 100 101 #endif // !defined(AFX_LIBSYMBOLINFO_H__1A7003B4_BA53_11D1_AE46_1CFB51000000__INCLUDED_) 102 103 using namespace std; 104 105 #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue)) 106 107 ///////////////////////////////////////////////////////////////////////////// 108 // CLibSymbolInfo 109 110 CLibSymbolInfo::CLibSymbolInfo() 111 { 112 } 113 114 CLibSymbolInfo::~CLibSymbolInfo() 115 { 116 } 117 118 //============================================================================= 119 // Function: DumpSymbols 120 // 121 // Parameters: 122 // LPTSTR lpszLibPathName - The library file path name 123 // CStdioFile* pFile - Address of the file in which to dump the symbols 124 // 125 // Description: 126 // 127 // Given a library file path name, the function dumps the symbol info into the file 128 // pointed to by pFile. 129 //============================================================================= 130 BOOL CLibSymbolInfo::DumpSymbols(LPTSTR lpszLibPathName, ostream& pFile) 131 { 132 if(lpszLibPathName == NULL || pFile.bad() ) { 133 assert(lpszLibPathName != NULL); 134 assert(pFile.good()); 135 m_strErrorMsg.assign("NULL <lpszLibPathName> or Invalid file handle."); 136 return FALSE; 137 } 138 139 if(!Dump(lpszLibPathName, pFile)) return FALSE; 140 return TRUE; 141 } 142 143 //============================================================================= 144 // Function: Dump 145 // 146 // Parameters: 147 // As mentioned above. 148 // 149 // Description: 150 // 151 // Depending on the value specified in <m_bDump>/<m_bGrep> the routine dumps/greps 152 // the symbo info. 153 //============================================================================= 154 BOOL CLibSymbolInfo::Dump(LPTSTR lpszLibPathName, ostream& pFile) 155 { 156 string sBuff; 157 MEMORY_MAPPED_FILE libFile(lpszLibPathName); 158 159 // Ensure that the file mapping worked 160 if( FALSE == libFile.IsValid() ) { 161 m_strErrorMsg = "Unable to access file "; 162 m_strErrorMsg+= lpszLibPathName; 163 return FALSE; 164 } 165 // All COFF libraries start with the string "!<arch>\n". Verify that this 166 // string is at the beginning of the mapped file 167 168 PSTR pArchiveStartString = (PSTR)libFile.GetBase(); 169 170 if ( 0 != strncmp( pArchiveStartString, IMAGE_ARCHIVE_START, 171 IMAGE_ARCHIVE_START_SIZE ) ) { 172 m_strErrorMsg.assign("Not a valid COFF LIB file."); 173 return FALSE; 174 } 175 176 // Point to the first archive member. This entry contains the LIB symbols, 177 // and immediately follows the archive start string ("!<arch>\n") 178 PIMAGE_ARCHIVE_MEMBER_HEADER pMbrHdr; 179 pMbrHdr = MakePtr( PIMAGE_ARCHIVE_MEMBER_HEADER, pArchiveStartString, 180 IMAGE_ARCHIVE_START_SIZE ); 181 182 // First DWORD after this member header is a symbol count 183 PDWORD pcbSymbols = (PDWORD)(pMbrHdr + 1); // Pointer math! 184 185 // The symbol count is stored in big endian format, so adjust as 186 // appropriate for the target architecture 187 DWORD cSymbols = ConvertBigEndian( *pcbSymbols ); 188 189 // Following the symbol count is an array of offsets to archive members 190 // (essentially, embedded .OBJ files) 191 PDWORD pMemberOffsets = pcbSymbols + 1; // Pointer math! 192 193 // Following the array of member offsets is an array of offsets to symbol 194 // names. 195 PSTR pszSymbolName = MakePtr( PSTR, pMemberOffsets, 4 * cSymbols ); 196 197 // 198 // Loop through every symbol in the first archive member 199 // 200 for ( unsigned i = 0; i < cSymbols; i++ ) 201 { 202 DWORD offset; 203 204 // The offsets to the archive member that contains the symbol is stored 205 // in big endian format, so convert it appropriately. 206 offset = ConvertBigEndian( *pMemberOffsets ); 207 208 // Call DisplayLibInfoForSymbol, which figures out what kind of symbol 209 // it is. The "IsRegularLibSymbol" filters out symbols that are 210 // internal to the linking process 211 if ( IsRegularLibSymbol( pszSymbolName ) ) { 212 string symbol(pszSymbolName); 213 if (IsFiltedSymbol(symbol) ) { 214 pFile << symbol << endl; 215 } 216 } 217 // Advanced to the next symbol offset and name. The MemberOffsets 218 // array has fixed length entries, while the symbol names are 219 // sequential null-terminated strings 220 pMemberOffsets++; 221 pszSymbolName += strlen(pszSymbolName) + 1; 222 } 223 return TRUE; 224 } 225 226 //============================================================================= 227 // Filters out symbols that are internal to the linking process, and which 228 // the programmer never explicitly sees. 229 //============================================================================= 230 BOOL CLibSymbolInfo::IsRegularLibSymbol( PSTR pszSymbolName ) 231 { 232 if ( 0 == strncmp( pszSymbolName, "__IMPORT_DESCRIPTOR_", 20 ) ) 233 return FALSE; 234 235 if ( 0 == strncmp( pszSymbolName, "__NULL_IMPORT_DESCRIPTOR", 24 ) ) 236 return FALSE; 237 238 if ( strstr( pszSymbolName, "_NULL_THUNK_DATA" ) ) 239 return FALSE; 240 241 return TRUE; 242 } 243 //============================================================================= 244 // Filters out symbols that are not needed.... 245 //============================================================================= 246 BOOL CLibSymbolInfo::IsFiltedSymbol( string& symbolName ) 247 { 248 // Filter problematic symbols for Win64 249 if ( symbolName.substr(0,3) == "_CT" ) return FALSE; 250 if ( symbolName.substr(0,3) == "_TI" ) return FALSE; 251 // Filter other symbols 252 if ( symbolName.substr(0,2) == "__" ) 253 return FALSE; 254 if ( symbolName.substr(0,3) == "??_" && symbolName[3] != '0') // Keep 'operator/=' [??_0] 255 return FALSE; 256 if( symbolName[0] == '_') { 257 symbolName.erase(0, 1); // C functions ... 258 } 259 // Filter the internal Boost symbols 260 if (symbolName.find ("detail@boost") != string::npos ) 261 return FALSE; 262 if (symbolName.find ("details@boost") != string::npos ) 263 return FALSE; 264 return TRUE; 265 } 266 267 //============================================================================= 268 // Converts from big endian to little endian numbers. 269 //============================================================================= 270 DWORD CLibSymbolInfo::ConvertBigEndian(DWORD bigEndian) 271 { 272 DWORD temp = 0; 273 274 temp |= bigEndian >> 24; 275 temp |= ((bigEndian & 0x00FF0000) >> 8); 276 temp |= ((bigEndian & 0x0000FF00) << 8); 277 temp |= ((bigEndian & 0x000000FF) << 24); 278 279 return temp; 280 } 281 282 string CLibSymbolInfo::GetLastError() const 283 { 284 return m_strErrorMsg; 285 } 286 287 288 MEMORY_MAPPED_FILE::MEMORY_MAPPED_FILE( PSTR pszFileName ) { 289 290 // 291 // Given a filename, the constructor opens a file handle, creates a file 292 // mapping, and maps the entire file into memory. 293 // 294 m_hFile = INVALID_HANDLE_VALUE; 295 m_hFileMapping = 0; 296 m_pMemoryMappedFileBase = 0; 297 m_cbFile = 0; 298 m_errCode = errMMF_FileOpen; // Initial error code: not found 299 // First get a file handle 300 m_hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 301 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)0); 302 303 if ( m_hFile == INVALID_HANDLE_VALUE ) 304 { 305 m_errCode = errMMF_FileOpen; 306 return; 307 } 308 m_cbFile = ::GetFileSize( m_hFile, 0 ); 309 // Now, create a file mapping 310 m_hFileMapping = CreateFileMapping(m_hFile,NULL, PAGE_READONLY, 0, 0,NULL); 311 if ( m_hFileMapping == 0 ) 312 { 313 // Oops. Something went wrong. Clean up. 314 CloseHandle(m_hFile); 315 m_hFile = INVALID_HANDLE_VALUE; 316 m_errCode = errMMF_FileMapping; 317 return; 318 } 319 m_pMemoryMappedFileBase = (PCHAR)MapViewOfFile( m_hFileMapping, 320 FILE_MAP_READ, 0, 0, 0); 321 if ( m_pMemoryMappedFileBase == 0 ) 322 { 323 // Oops. Something went wrong. Clean up. 324 CloseHandle(m_hFileMapping); 325 m_hFileMapping = 0; 326 CloseHandle(m_hFile); 327 m_hFile = INVALID_HANDLE_VALUE; 328 m_errCode = errMMF_MapView; 329 return; 330 } 331 m_errCode = errMMF_NoError; 332 } 333 334 MEMORY_MAPPED_FILE::~MEMORY_MAPPED_FILE(void) 335 { 336 // Clean up everything that was created by the constructor 337 if ( m_pMemoryMappedFileBase ) 338 UnmapViewOfFile( m_pMemoryMappedFileBase ); 339 340 if ( m_hFileMapping ) 341 CloseHandle( m_hFileMapping ); 342 343 if ( m_hFile != INVALID_HANDLE_VALUE ) 344 CloseHandle( m_hFile ); 345 346 m_errCode = errMMF_FileOpen; 347 } 348 349 namespace windef { 350 void usage(){ 351 cerr << "Usage: genwindef [-l <dllname>] [-o <output-file> | exports.def] <obj or lib filenames>" << endl; 352 exit(1); 353 } 354 } 355 356 357 //--- Command main program----------------------------------------------------- 358 int main ( int argc, char** argv ) 359 //----------------------------------------------------------------------------- 360 { 361 string outfile("exports.def"); 362 string library("UnknownLib"); 363 string objfiles; 364 bool debug(false); 365 366 int arg; 367 if (argc < 3) windef::usage(); 368 arg = 1; 369 while (argv[arg][0] == '-') { 370 if (strcmp(argv[arg], "--") == 0) { 371 windef::usage(); 372 } 373 else if (strcmp(argv[arg], "-l") == 0) { 374 arg++; 375 if (arg == argc) windef::usage(); 376 library = argv[arg]; 377 } 378 else if (strcmp(argv[arg], "-o") == 0) { 379 arg++; 380 if (arg == argc) windef::usage(); 381 outfile = argv[arg]; 382 } 383 arg++; 384 } 385 if (arg == argc) windef::usage(); 386 for (arg; arg < argc; arg++) { 387 objfiles += argv[arg]; 388 if( arg+1 < argc) objfiles += " "; 389 } 390 391 CLibSymbolInfo libsymbols; 392 ofstream out(outfile.c_str()); 393 if(out.fail()) { 394 cerr << "windef: Error opening file " << outfile << endl; 395 return 1; 396 } 397 out << "LIBRARY " << library << endl; 398 out << "EXPORTS" << endl; 399 400 libsymbols.DumpSymbols(const_cast<char*>(objfiles.c_str()), out); 401 402 out.close(); 403 404 405 return 0; 406 } 407