ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
genwindef.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file genwindef.cc
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 
59 {
60 public:
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 
78 
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; }
89 
90  private:
91 
92  HANDLE m_hFile;
93  HANDLE m_hFileMapping; // Handle of memory mapped file
95  DWORD m_cbFile;
97 };
98 
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 
108 // CLibSymbolInfo
109 
111 {
112 }
113 
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 //=============================================================================
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 //=============================================================================
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 
283 {
284  return m_strErrorMsg;
285 }
286 
287 
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 
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 }