///////////////////////////////////////////////////////////////////////////////
//
// SymFromName.cpp
//
// Author: Oleg Starodumov
//
//
///////////////////////////////////////////////////////////////////////////////
//
// Description:
//
// This example looks up a symbol by name and displays some simple information
// about it.
//
// This example shows how to:
//
// * Define _NO_CVCONST_H to be able to use various non-default declarations
// from DbgHelp.h (e.g. SymTagEnum enumeration)
// * Initialize DbgHelp
// * Load symbols for a module or from a .PDB file
// * Check what kind of symbols is loaded
// * Look up a symbol by name (supplied by the user)
// * Display simple information about the symbol
// * Unload symbols
// * Deinitialize DbgHelp
//
// Actions:
//
// * Enable debug option
// * Initialize DbgHelp
// * If symbols should be loaded from a .PDB file, determine its size
// * Load symbols
// * Obtain and display information about loaded symbols
// * Look up a symbol by name
// * Display simple information about the symbol
// * Unload symbols
// * Deinitialize DbgHelp
//
// Command line parameters:
//
// * Path to the module you want to load symbols for,
// or to a .PDB file to load the symbols from
// * Name of the symbol to search for
//
///////////////////////////////////////////////////////////////////////////////
// Include files
//
#include
"stdafx.h"#include
<windows.h>#include
<tchar.h>// Now we have to define _NO_CVCONST_H to be able to access
// various declarations from DbgHelp.h, which are not available by default
#define
_NO_CVCONST_H#include
<dbghelp.h>#include
<stdio.h>
///////////////////////////////////////////////////////////////////////////////
// Directives
//
#pragma
comment( lib, "dbghelp.lib" )
///////////////////////////////////////////////////////////////////////////////
// Declarations
//
bool
GetFileParams( const TCHAR* pFileName, DWORD64& BaseAddr, DWORD& FileSize );bool
GetFileSize( const TCHAR* pFileName, DWORD& FileSize );void
ShowSymbolInfo( DWORD64 ModBase );void
ShowSymbolDetails( SYMBOL_INFO& SymInfo );const
TCHAR* TagStr( ULONG Tag );
///////////////////////////////////////////////////////////////////////////////
// CSymbolInfoPackage class declaration
//
// Wrapper for SYMBOL_INFO_PACKAGE structure
//
struct
CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE{
CSymbolInfoPackage(){
si.SizeOfStruct = sizeof(SYMBOL_INFO); si.MaxNameLen = sizeof(name);}
};
///////////////////////////////////////////////////////////////////////////////
// main
//
int
_tmain( int argc, const TCHAR* argv[] ){
BOOL bRet = FALSE;// Check command line parameters if( argc < 3 )
{
_tprintf( _T("Usage: %s <FilePathAndName> <SymbolName> \n"), argv[0] ); return 0;}
const TCHAR* pSymName = argv[2];// Set options DWORD Options = SymGetOptions(); // SYMOPT_DEBUG option asks DbgHelp to print additional troubleshooting // messages to debug output - use the debugger's Debug Output window // to view the messages Options |= SYMOPT_DEBUG;
::
SymSetOptions( Options );// Initialize DbgHelp and load symbols for all modules of the current process bRet = ::SymInitialize ( GetCurrentProcess(), // Process handle of the current process NULL, // No user-defined search path -> use default FALSE // Do not load symbols for modules in the current process
);
if( !bRet ){
_tprintf(_T("Error: SymInitialize() failed. Error code: %u \n"), ::GetLastError()); return 0;}
do
{
// Determine the base address and the file size const TCHAR* pFileName = argv[1]; DWORD64 BaseAddr = 0; DWORD FileSize = 0; if( !GetFileParams( pFileName, BaseAddr, FileSize ) ){
_tprintf( _T("Error: Cannot obtain file parameters (internal error).\n") ); break;}
// Load symbols for the module _tprintf( _T("Loading symbols for: %s ... \n"), pFileName ); DWORD64 ModBase = ::SymLoadModule64 ( GetCurrentProcess(), // Process handle of the current process NULL, // Handle to the module's image file (not needed) pFileName, // Path/name of the file NULL, // User-defined short name of the module (it can be NULL) BaseAddr, // Base address of the module (cannot be NULL if .PDB file is used, otherwise it can be NULL) FileSize // Size of the file (cannot be NULL if .PDB file is used, otherwise it can be NULL)
);
if( ModBase == 0 ){
_tprintf(_T("Error: SymLoadModule64() failed. Error code: %u \n"), ::GetLastError()); break;}
_tprintf( _T("Load address: %I64x \n"), ModBase );ShowSymbolInfo(ModBase); // Look up symbol by name _tprintf( _T("Looking for symbol %s ... \n"), pSymName ); CSymbolInfoPackage sip; // it contains SYMBOL_INFO structure plus additional // space for the name of the symbol bRet = ::SymFromName( GetCurrentProcess(), // Process handle of the current process pSymName, // Symbol name
&
sip.si // Address of the SYMBOL_INFO structure (inside "sip" object));
if( !bRet ){
_tprintf( _T("Error: SymFromName() failed. Error code: %u \n"), ::GetLastError() );}
else{
// Display information about the symbol _tprintf( _T("Symbol found: \n") ); ShowSymbolDetails( sip.si );}
// Unload symbols for the module bRet = ::SymUnloadModule64( GetCurrentProcess(), ModBase ); if( !bRet )
{
_tprintf( _T("Error: SymUnloadModule64() failed. Error code: %u \n"), ::GetLastError() );}
}
while( 0 );// Deinitialize DbgHelp bRet = ::SymCleanup( GetCurrentProcess() ); if( !bRet )
{
_tprintf(_T("Error: SymCleanup() failed. Error code: %u \n"), ::GetLastError()); return 0;}
// Complete return 0;
}
///////////////////////////////////////////////////////////////////////////////
// Functions
//
bool
GetFileParams( const TCHAR* pFileName, DWORD64& BaseAddr, DWORD& FileSize ){
// Check parameters if( pFileName == 0 ){
return false;}
// Determine the extension of the file TCHAR szFileExt[_MAX_EXT] = {0}; _tsplitpath( pFileName, NULL, NULL, NULL, szFileExt );
// Is it .PDB file ? if( _tcsicmp( szFileExt, _T(".PDB") ) == 0 )
{
// Yes, it is a .PDB file // Determine its size, and use a dummy base address BaseAddr = 0x10000000; // it can be any non-zero value, but if we load symbols // from more than one file, memory regions specified // for different files should not overlap // (region is "base address + file size") if( !GetFileSize( pFileName, FileSize ) ){
return false;}
}
else{
// It is not a .PDB file // Base address and file size can be 0 BaseAddr = 0; FileSize = 0;}
// Complete return true;
}
bool
GetFileSize( const TCHAR* pFileName, DWORD& FileSize ){
// Check parameters if( pFileName == 0 ){
return false;}
// Open the file HANDLE hFile = ::CreateFile( pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile == INVALID_HANDLE_VALUE )
{
_tprintf( _T("CreateFile() failed. Error: %u \n"), ::GetLastError() ); return false;}
// Obtain the size of the file FileSize = ::GetFileSize( hFile, NULL ); if( FileSize == INVALID_FILE_SIZE )
{
_tprintf( _T("GetFileSize() failed. Error: %u \n"), ::GetLastError() ); // and continue ...}
// Close the file if( !::CloseHandle( hFile ) )
{
_tprintf( _T("CloseHandle() failed. Error: %u \n"), ::GetLastError() ); // and continue ...}
// Complete return ( FileSize != INVALID_FILE_SIZE );
}
void
ShowSymbolInfo( DWORD64 ModBase ){
// Get module information IMAGEHLP_MODULE64 ModuleInfo; memset(&ModuleInfo, 0, sizeof(ModuleInfo) ); ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); BOOL bRet = ::SymGetModuleInfo64( GetCurrentProcess(), ModBase, &ModuleInfo ); if( !bRet ){
_tprintf(_T("Error: SymGetModuleInfo64() failed. Error code: %u \n"), ::GetLastError()); return;}
// Display information about symbols // Kind of symbols switch( ModuleInfo.SymType )
{
case SymNone: _tprintf( _T("No symbols available for the module.\n") ); break; case SymExport: _tprintf( _T("Loaded symbols: Exports\n") ); break; case SymCoff: _tprintf( _T("Loaded symbols: COFF\n") ); break; case SymCv: _tprintf( _T("Loaded symbols: CodeView\n") ); break; case SymSym: _tprintf( _T("Loaded symbols: SYM\n") ); break; case SymVirtual: _tprintf( _T("Loaded symbols: Virtual\n") ); break; case SymPdb: _tprintf( _T("Loaded symbols: PDB\n") ); break; case SymDia: _tprintf( _T("Loaded symbols: DIA\n") ); break; case SymDeferred: _tprintf( _T("Loaded symbols: Deferred\n") ); // not actually loaded break; default: _tprintf( _T("Loaded symbols: Unknown format.\n") ); break;}
// Image name if( _tcslen( ModuleInfo.ImageName ) > 0 ){
_tprintf( _T("Image name: %s \n"), ModuleInfo.ImageName );}
// Loaded image name if( _tcslen( ModuleInfo.LoadedImageName ) > 0 ){
_tprintf( _T("Loaded image name: %s \n"), ModuleInfo.LoadedImageName );}
// Loaded PDB name if( _tcslen( ModuleInfo.LoadedPdbName ) > 0 ){
_tprintf( _T("PDB file name: %s \n"), ModuleInfo.LoadedPdbName );}
// Is debug information unmatched ? // (It can only happen if the debug information is contained // in a separate file (.DBG or .PDB) if( ModuleInfo.PdbUnmatched || ModuleInfo.DbgUnmatched ){
_tprintf( _T("Warning: Unmatched symbols. \n") );}
// Contents // Line numbers available ? _tprintf( _T("Line numbers: %s \n"), ModuleInfo.LineNumbers ? _T("Available") : _T("Not available") ); // Global symbols available ? _tprintf( _T("Global symbols: %s \n"), ModuleInfo.GlobalSymbols ? _T("Available") : _T("Not available") ); // Type information available ? _tprintf( _T("Type information: %s \n"), ModuleInfo.TypeInfo ? _T("Available") : _T("Not available") ); // Source indexing available ? _tprintf( _T("Source indexing: %s \n"), ModuleInfo.SourceIndexed ? _T("Yes") : _T("No") ); // Public symbols available ? _tprintf( _T("Public symbols: %s \n"), ModuleInfo.Publics ? _T("Available") : _T("Not available") );
}
void
ShowSymbolDetails( SYMBOL_INFO& SymInfo ){
}const
TCHAR* TagStr( ULONG Tag ){
}
Have you tried by implementation of Stackwalker?
http://www.codeproject.com/threads/StackWalker.asp
Normaly you will get error 87 if symbols are not loaded correctly...
--
Greetings
Jochen
My blog about Win32 and .NET
http://blog.kalmbachnet.de/
I compiled your code. When I ran it, I had not trouble with the call to
SymGetModuleInfo64(). I suspect that you are running this code against
and older and unmatched version of dbghelp.dll - like say the one in
your system directory.
The pSymName parameter to SymFromName() is completely malformed. You
are passing in the name of the pdb. I would suggest you pass in a
symbol name with a module specifier. Something like "SymFromName!main".
.pat styles [microsoft]
> &sip.si // Address of the SYMBOL_INFO structure (inside "sip" object)
"Ken Chen" <che...@ubisoft.com.cn> wrote in message news:urFBvckJ...@TK2MSFTNGP05.phx.gbl...
"Ken Chen" <che...@ubisoft.com.cn> wrote in message news:urFBvckJ...@TK2MSFTNGP05.phx.gbl...
With both implicit and explicit linking, Windows first searches for "known DLLs", such as Kernel32.dll and User32.dll. Windows then searches for the DLLs in the following sequence:
The directory where the executable module for the current process is located.
The current directory.
The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
The directories listed in the PATH environment variable.
another part of msdn is saying:
http://msdn2.microsoft.com/en-us/library/ms682586.aspx
Standard Search Order
The dynamic-link library (DLL) search order used by the system depends on whether safe DLL search mode is enabled or disabled.
Windows Vista, Windows Server 2003, and Windows XP SP2: Safe DLL search mode is enabled by default. To disable this feature, create the HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode registry value and set it to 0. Calling the SetDllDirectory function effectively disables SafeDllSearchMode while the specified directory is in the search path and changes the search order as described in this topic.
Windows XP and Windows 2000 SP4: Safe DLL search mode is disabled by default. To enable this feature, create the SafeDllSearchMode registry value and set it to 1.
If SafeDllSearchMode is enabled, the search order is as follows:
If SafeDllSearchMode is disabled, the search order is as follows:
Which means system path is searched before current directory on windows xp sp2. That should be the correct answer, and that explains every matter i met.
And another old version (2005) of MSDN,(which i am using) said windows xp set SafeDllSearchMode to 0 by default and windows server 2003 set it to 1 by default, which means current directory first for windows xp. Crying........................
Ken.
"Avi Cohen Stuart" <aviXcohenXstuart@ssaglobalXcom> wrote in message news:uafdhHsJ...@TK2MSFTNGP03.phx.gbl...