LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
genwindef.cc
Go to the documentation of this file.
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; }
88  errMMF GetErrorType(){ return 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 }
errMMF
Definition: genwindef.cc:76
std::string GetLastError() const
Definition: genwindef.cc:282
STL namespace.
BOOL IsFiltedSymbol(std::string &pszSymbolName)
Definition: genwindef.cc:246
std::string m_strResultsString
Definition: genwindef.cc:67
PVOID GetBase(void)
Definition: genwindef.cc:85
BOOL DumpSymbols(LPTSTR lpszLibPathName, std::ostream &pFile)
Definition: genwindef.cc:130
DWORD ConvertBigEndian(DWORD bigEndian)
Definition: genwindef.cc:270
#define MakePtr(cast, ptr, addValue)
Definition: genwindef.cc:105
DebugStuff debug
Definition: DebugStruct.cxx:4
PVOID m_pMemoryMappedFileBase
Definition: genwindef.cc:94
BOOL IsValid(void)
Definition: genwindef.cc:87
int main(int argc, char **argv)
Definition: genwindef.cc:358
BOOL IsRegularLibSymbol(PSTR pszSymbolName)
Definition: genwindef.cc:230
void usage()
Definition: genwindef.cc:350
MEMORY_MAPPED_FILE * PMEMORY_MAPPED_FILE
Definition: genwindef.cc:99
MEMORY_MAPPED_FILE(PSTR pszFileName)
Definition: genwindef.cc:288
HANDLE m_hFileMapping
Definition: genwindef.cc:93
DWORD GetFileSize(void)
Definition: genwindef.cc:86
~MEMORY_MAPPED_FILE(void)
Definition: genwindef.cc:334
BOOL Dump(LPTSTR lpszLibPathName, std::ostream &pFile)
Definition: genwindef.cc:154
std::string m_strErrorMsg
Definition: genwindef.cc:68
virtual ~CLibSymbolInfo()
Definition: genwindef.cc:114
errMMF GetErrorType()
Definition: genwindef.cc:88