The Gaudi Framework  master (37c0b60a)
LibSymbolInfo.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 //==========================================
12 // Matt Pietrek
13 // Microsoft Systems Journal, April 1998
14 // Program: LibDump
15 // FILE: LibSymbolInfo.CPP
16 //==========================================
17 
18 // LibSymbolInfo.cpp: implementation of the CLibSymbolInfo class.
19 //
21 
22 #include "LibSymbolInfo.h"
23 
24 using namespace std;
25 
26 #define MakePtr( cast, ptr, addValue ) ( cast )( (DWORD)( ptr ) + (DWORD)( addValue ) )
27 
29 // CLibSymbolInfo
30 
32 
34 
35 //=============================================================================
36 // Function: DumpSymbols
37 //
38 // Parameters:
39 // LPTSTR lpszLibPathName - The library file path name
40 // CStdioFile* pFile - Address of the file in which to dump the symbols
41 //
42 // Description:
43 //
44 // Given a library file path name, the function dumps the symbol info into the file
45 // pointed to by pFile.
46 //=============================================================================
47 BOOL CLibSymbolInfo::DumpSymbols( LPTSTR lpszLibPathName, ostream& pFile ) {
48  if ( lpszLibPathName == NULL || pFile.bad() ) {
49  assert( lpszLibPathName != NULL );
50  assert( pFile.good() );
51  m_strErrorMsg.assign( "NULL <lpszLibPathName> or Invalid file handle." );
52  return FALSE;
53  }
54 
55  if ( !Dump( lpszLibPathName, pFile ) ) return FALSE;
56  return TRUE;
57 }
58 
59 //=============================================================================
60 // Function: Dump
61 //
62 // Parameters:
63 // As mentioned above.
64 //
65 // Description:
66 //
67 // Depending on the value specified in <m_bDump>/<m_bGrep> the routine dumps/greps
68 // the symbo info.
69 //=============================================================================
70 BOOL CLibSymbolInfo::Dump( LPTSTR lpszLibPathName, ostream& pFile ) {
71  string sBuff;
72  MEMORY_MAPPED_FILE libFile( lpszLibPathName );
73 
74  // Ensure that the file mapping worked
75  if ( FALSE == libFile.IsValid() ) {
76  m_strErrorMsg = "Unable to access file ";
77  m_strErrorMsg += lpszLibPathName;
78  return FALSE;
79  }
80  // All COFF libraries start with the string "!<arch>\n". Verify that this
81  // string is at the beginning of the mapped file
82 
83  PSTR pArchiveStartString = (PSTR)libFile.GetBase();
84 
85  if ( 0 != strncmp( pArchiveStartString, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE ) ) {
86  m_strErrorMsg.assign( "Not a valid COFF LIB file." );
87  return FALSE;
88  }
89 
90  // Point to the first archive member. This entry contains the LIB symbols,
91  // and immediately follows the archive start string ("!<arch>\n")
92  PIMAGE_ARCHIVE_MEMBER_HEADER pMbrHdr;
93  pMbrHdr = MakePtr( PIMAGE_ARCHIVE_MEMBER_HEADER, pArchiveStartString, IMAGE_ARCHIVE_START_SIZE );
94 
95  // First DWORD after this member header is a symbol count
96  PDWORD pcbSymbols = (PDWORD)( pMbrHdr + 1 ); // Pointer math!
97 
98  // The symbol count is stored in big endian format, so adjust as
99  // appropriate for the target architecture
100  DWORD cSymbols = ConvertBigEndian( *pcbSymbols );
101 
102  // Following the symbol count is an array of offsets to archive members
103  // (essentially, embedded .OBJ files)
104  PDWORD pMemberOffsets = pcbSymbols + 1; // Pointer math!
105 
106  // Following the array of member offsets is an array of offsets to symbol
107  // names.
108  PSTR pszSymbolName = MakePtr( PSTR, pMemberOffsets, 4 * cSymbols );
109 
110  //
111  // Loop through every symbol in the first archive member
112  //
113  for ( unsigned i = 0; i < cSymbols; i++ ) {
114  DWORD offset;
115 
116  // The offsets to the archive member that contains the symbol is stored
117  // in big endian format, so convert it appropriately.
118  offset = ConvertBigEndian( *pMemberOffsets );
119 
120  // Call DisplayLibInfoForSymbol, which figures out what kind of symbol
121  // it is. The "IsRegularLibSymbol" filters out symbols that are
122  // internal to the linking process
123  if ( IsRegularLibSymbol( pszSymbolName ) ) {
124  string symbol( pszSymbolName );
125  if ( IsFiltedSymbol( symbol ) ) { pFile << symbol << endl; }
126  }
127  // Advanced to the next symbol offset and name. The MemberOffsets
128  // array has fixed length entries, while the symbol names are
129  // sequential null-terminated strings
130  pMemberOffsets++;
131  pszSymbolName += strlen( pszSymbolName ) + 1;
132  }
133  return TRUE;
134 }
135 
136 //=============================================================================
137 // Filters out symbols that are internal to the linking process, and which
138 // the programmer never explicitly sees.
139 //=============================================================================
140 BOOL CLibSymbolInfo::IsRegularLibSymbol( PSTR pszSymbolName ) {
141  if ( 0 == strncmp( pszSymbolName, "__IMPORT_DESCRIPTOR_", 20 ) ) return FALSE;
142 
143  if ( 0 == strncmp( pszSymbolName, "__NULL_IMPORT_DESCRIPTOR", 24 ) ) return FALSE;
144 
145  if ( strstr( pszSymbolName, "_NULL_THUNK_DATA" ) ) return FALSE;
146 
147  return TRUE;
148 }
149 //=============================================================================
150 // Filters out symbols that are not needed....
151 //=============================================================================
152 BOOL CLibSymbolInfo::IsFiltedSymbol( string& symbolName ) {
153  if ( symbolName.compare( 0, 2, "__" ) == 0 ) return FALSE;
154  if ( symbolName.compare( 0, 3, "??_" ) == 0 && symbolName[3] != '0' ) // Keep 'operator/=' [??_0]
155  return FALSE;
156  if ( symbolName[0] == '_' ) {
157  symbolName.erase( 0, 1 ); // C functions ...
158  }
159  // Filter the internal Boost symbols
160  if ( symbolName.find( "detail@boost" ) != string::npos ) return FALSE;
161  if ( symbolName.find( "details@boost" ) != string::npos ) return FALSE;
162  return TRUE;
163 }
164 
165 //=============================================================================
166 // Converts from big endian to little endian numbers.
167 //=============================================================================
168 DWORD CLibSymbolInfo::ConvertBigEndian( DWORD bigEndian ) {
169  DWORD temp = 0;
170 
171  temp |= bigEndian >> 24;
172  temp |= ( ( bigEndian & 0x00FF0000 ) >> 8 );
173  temp |= ( ( bigEndian & 0x0000FF00 ) << 8 );
174  temp |= ( ( bigEndian & 0x000000FF ) << 24 );
175 
176  return temp;
177 }
178 
179 string CLibSymbolInfo::GetLastError() const { return m_strErrorMsg; }
180 
182 
183  //
184  // Given a filename, the constructor opens a file handle, creates a file
185  // mapping, and maps the entire file into memory.
186  //
187  m_hFile = INVALID_HANDLE_VALUE;
188  m_hFileMapping = 0;
189  m_pMemoryMappedFileBase = 0;
190  m_cbFile = 0;
191  m_errCode = errMMF_FileOpen; // Initial error code: not found
192  // First get a file handle
193  m_hFile =
194  CreateFile( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)0 );
195 
196  if ( m_hFile == INVALID_HANDLE_VALUE ) {
197  m_errCode = errMMF_FileOpen;
198  return;
199  }
200  m_cbFile = ::GetFileSize( m_hFile, 0 );
201  // Now, create a file mapping
202  m_hFileMapping = CreateFileMapping( m_hFile, NULL, PAGE_READONLY, 0, 0, NULL );
203  if ( m_hFileMapping == 0 ) {
204  // Oops. Something went wrong. Clean up.
205  CloseHandle( m_hFile );
206  m_hFile = INVALID_HANDLE_VALUE;
207  m_errCode = errMMF_FileMapping;
208  return;
209  }
210  m_pMemoryMappedFileBase = (PCHAR)MapViewOfFile( m_hFileMapping, FILE_MAP_READ, 0, 0, 0 );
211  if ( m_pMemoryMappedFileBase == 0 ) {
212  // Oops. Something went wrong. Clean up.
213  CloseHandle( m_hFileMapping );
214  m_hFileMapping = 0;
215  CloseHandle( m_hFile );
216  m_hFile = INVALID_HANDLE_VALUE;
217  m_errCode = errMMF_MapView;
218  return;
219  }
220  m_errCode = errMMF_NoError;
221 }
222 
224  // Clean up everything that was created by the constructor
225  if ( m_pMemoryMappedFileBase ) UnmapViewOfFile( m_pMemoryMappedFileBase );
226 
227  if ( m_hFileMapping ) CloseHandle( m_hFileMapping );
228 
229  if ( m_hFile != INVALID_HANDLE_VALUE ) CloseHandle( m_hFile );
230 
231  m_errCode = errMMF_FileOpen;
232 }
MEMORY_MAPPED_FILE::GetBase
PVOID GetBase(void)
Definition: LibSymbolInfo.h:49
std::strlen
T strlen(T... args)
CLibSymbolInfo::DumpSymbols
BOOL DumpSymbols(LPTSTR lpszLibPathName, std::ostream &pFile)
Definition: LibSymbolInfo.cpp:47
std::string::find
T find(T... args)
DataOnDemand.Dump
Dump
Definition: DataOnDemand.py:35
errMMF_NoError
@ errMMF_NoError
Definition: LibSymbolInfo.h:42
CLibSymbolInfo::CLibSymbolInfo
CLibSymbolInfo()
Definition: LibSymbolInfo.cpp:31
MEMORY_MAPPED_FILE::MEMORY_MAPPED_FILE
MEMORY_MAPPED_FILE(PSTR pszFileName)
Definition: LibSymbolInfo.cpp:181
MEMORY_MAPPED_FILE::~MEMORY_MAPPED_FILE
~MEMORY_MAPPED_FILE(void)
Definition: LibSymbolInfo.cpp:223
errMMF_FileMapping
@ errMMF_FileMapping
Definition: LibSymbolInfo.h:42
CLibSymbolInfo::~CLibSymbolInfo
virtual ~CLibSymbolInfo()
Definition: LibSymbolInfo.cpp:33
CLibSymbolInfo::IsFiltedSymbol
BOOL IsFiltedSymbol(std::string &pszSymbolName)
Definition: LibSymbolInfo.cpp:152
MEMORY_MAPPED_FILE
Definition: LibSymbolInfo.h:44
std::ostream
STL class.
std::ostream::bad
T bad(T... args)
std::string::compare
T compare(T... args)
std::string::erase
T erase(T... args)
CLibSymbolInfo::IsRegularLibSymbol
BOOL IsRegularLibSymbol(PSTR pszSymbolName)
Definition: LibSymbolInfo.cpp:140
CLibSymbolInfo::ConvertBigEndian
DWORD ConvertBigEndian(DWORD bigEndian)
Definition: LibSymbolInfo.cpp:168
std::ostream::good
T good(T... args)
std::strstr
T strstr(T... args)
std::strncmp
T strncmp(T... args)
MEMORY_MAPPED_FILE::IsValid
BOOL IsValid(void)
Definition: LibSymbolInfo.h:51
std::endl
T endl(T... args)
std
STL namespace.
errMMF_FileOpen
@ errMMF_FileOpen
Definition: LibSymbolInfo.h:42
LibSymbolInfo.h
CLibSymbolInfo::Dump
BOOL Dump(LPTSTR lpszLibPathName, std::ostream &pFile)
Definition: LibSymbolInfo.cpp:70
MakePtr
#define MakePtr(cast, ptr, addValue)
Definition: LibSymbolInfo.cpp:26
GaudiKernel.Constants.TRUE
TRUE
Definition: Constants.py:37
errMMF_MapView
@ errMMF_MapView
Definition: LibSymbolInfo.h:42
GaudiKernel.Constants.FALSE
FALSE
Definition: Constants.py:38
CLibSymbolInfo::GetLastError
std::string GetLastError() const
Definition: LibSymbolInfo.cpp:179