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