顯示EXE,DLL或PDB文件中指定函數的Parameter和local variables信息

  上次寫了列出EXE,DLLPDB文件中的符號信息,這次再貼一段代碼。舉例說明如何列舉一指定函數的局部信息,即函數的參數和局部變量信息。呵呵,本人即不愛說廢話,又怕打字太累。^_^,開門見山,來看下面代碼吧。Enjoy!<?XML:NAMESPACE PREFIX = O />

//============================================================================

// LFVars : A small tool used to display function symbol informaton from EXE, DLL or PDB files

//         L(ist)F(untion)Vars: list function parameters and local variabls.

// Author : zyq654321 --- Oct, 2004

// Comment: This is only a sample code to show you how to dump symbol information,

//          you can improve it and your advise is appreciated.

#include <windows.h>

#include <TCHAR.h>

#define _NO_CVCONST_H // We should define the constant in order to ...

#include <dbghelp.h>

#include <stdio.h>

 

#pragma comment( lib, "dbghelp.lib" )

 

BOOL CALLBACK LFVarsCallback( SYMBOL_INFO* pSymInfo, ULONG SymbolSize, PVOID UserContext )

{   

     if( pSymInfo != 0 )

     {

         // Increase the counter of found local variables and parameters

         if( UserContext != 0 )

              *(int*)UserContext += 1;

         // list parameters or variables

         _tprintf(_T("Name: %s /n"),pSymInfo->Name);

         _tprintf(_T("    Type: %s   "),

                         (pSymInfo->Flags & SYMFLAG_PARAMETER) ? "Function Parameter" :

                         ( (pSymInfo->Flags & SYMFLAG_LOCAL)? "Local Variable": "Unknown"));

         TCHAR tcsReg[10];

         switch(pSymInfo->Register)

         {

         case 17:

              _tcscpy(tcsReg,_T("[EAX]"));

              break;

         case 18:

              _tcscpy(tcsReg,_T("[ECX]"));

              break;

         case 19:

              _tcscpy(tcsReg,_T("[EDX]"));

              break;

         case 20:

              _tcscpy(tcsReg,_T("[EBX]"));

              break;

         case 21:

              _tcscpy(tcsReg,_T("[ESP]"));

              break;

         case 22:

              _tcscpy(tcsReg,_T("[EBP]"));

              break;

         case 23:

              _tcscpy(tcsReg,_T("[ESI]"));

              break;

         case 24:

              _tcscpy(tcsReg,_T("[EDI]"));

              break;

         default:

              _tcscpy(tcsReg,_T("Unknown"));

              break;

         }

         _tprintf( _T("Register: %s  "), tcsReg );

         UINT uMax = 0xFFFFFFFF;

         _tprintf( _T("Address(Offset): %c0x%X   "),

                    (LONG)pSymInfo->Address >= 0? &apos; &apos; : &apos;-&apos;,

                   (LONG)pSymInfo->Address >= 0? pSymInfo->Address : (uMax - pSymInfo->Address + 1));

         _tprintf( _T("Size: %d /n"), pSymInfo->Size);

 

         //ShowSymbolDetails( *pSymInfo );

     }

 

     return TRUE; // Continue enumeration

}

 

int main( int argc, const TCHAR* argv[] )

{

     if(argc < 3)

     {

        goto FAILED_PARAM;

     }

 

     // Set debug options

     DWORD dwOpn = SymGetOptions();

     dwOpn |= SYMOPT_DEBUG;

     SymSetOptions(dwOpn);

 

     // Initilaize the symbol handle for the current process

     if(!SymInitialize( GetCurrentProcess(), 

                                    NULL,                

                               FALSE ))  

     {

         _tprintf(_T("Failed when SymInitialize():%d/n"), GetLastError());

         return 0;

     }

 

     if( argv[1] == NULL || argv[2] == NULL)

     {

         goto FAILED_PARAM;

     }

 

     //------------------------------------------------------------------------

     // Set initial parameters

     TCHAR pszExt[MAX_PATH];

     _tsplitpath( argv[1], NULL, NULL, NULL, pszExt );

     DWORD64 dw64Base     = 0; // if the image is a .pdb file, dw64Base cannot be zero.

                               // if the value is zero, the library obtains the load address

                               //  from the symbol file.

     DWORD   dwFileSize = 0; // if the image is a .pdb file, dwFileSize cannot be zero.

                                   // if the value is zero, the library obtains the size

                               //  from the symbol file.

 

     _tcslwr(pszExt);

     if(_tcsicmp(pszExt, _T(".pdb")) == 0)

     {

         // this is a .pdb file, and so we should set the load address and file size;

         dw64Base = 0x10000000;

         // get the file size

         HANDLE hFile = CreateFile( argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );

         if( INVALID_HANDLE_VALUE == hFile )

         {

              _tprintf(_T("Failed when open %s: %d"), argv[1], GetLastError());

              goto FAILED_PARAM;

         }

         if( INVALID_FILE_SIZE == ( dwFileSize = GetFileSize(hFile, NULL) ))

         {

              _tprintf(_T("Failed when read the size of %s: %d"), argv[1], GetLastError());

              goto FAILED_PARAM;

         }

         CloseHandle(hFile);

     }

 

     //------------------------------------------------------------------------

     // Load symbol table

     _tprintf(_T("Load %s...../n"), argv[1]);

     DWORD64 dw64ModAddress = SymLoadModule64( GetCurrentProcess(),

                                                     NULL,              

                                                     argv[1],          

                                                     NULL,              

                                                     dw64Base,         

                                                     dwFileSize);

 

     if( dw64ModAddress == 0 )

     {

         _tprintf(_T("Failed when SymLoadModule64(): %d /n"), GetLastError());

         return 0;

     }

     _tprintf(_T("Load Address: %I64x /n"), dw64ModAddress);

 

     //------------------------------------------------------------------------

     // Display the function parameters and local variables according to the

     //  specified function name.

     SYMBOL_INFO symInfo;

     symInfo.SizeOfStruct = sizeof(SYMBOL_INFO);   

     if(! SymFromName( GetCurrentProcess(),

                         argv[2],           

                         &symInfo) )

     {

         _tprintf( _T("Failed When SymFromName(): %d /n"), GetLastError() );

         goto FAILED_AFTER_LOAD;

     }

 

     // We only need functon symbol

     if( symInfo.Tag != SymTagFunction )

     {

         _tprintf( _T("Invalid Function Name or Not Found./n") );

         goto FAILED_AFTER_LOAD;

     }

 

     // List funtion&apos;s parameters and its local variables

     IMAGEHLP_STACK_FRAME stackFrm;

     stackFrm.InstructionOffset = symInfo.Address;

     if(!SymSetContext( GetCurrentProcess(),

                         &stackFrm,                

                         0 ))

     {

         _tprintf( _T("Failed when SymSetContext: %d /n"), GetLastError() );

         goto FAILED_AFTER_LOAD;

     }

 

     int nVarsCnt = 0;

     if(!SymEnumSymbols( GetCurrentProcess(),

                            0,                  

                            0,                  

                            LFVarsCallback, 

                            &nVarsCnt ) )

     {

         _tprintf( _T("Failed when SymEnumSymbols(): %d /n"), GetLastError() );

         goto FAILED_AFTER_LOAD; 

     }

 

     _tprintf( _T("%d function parmeters and local variables had been listed./n"), nVarsCnt );   

 

 

FAILED_AFTER_LOAD:

     //------------------------------------------------------------------------

     // Unload symbols table

     if(!SymUnloadModule64( GetCurrentProcess(), dw64ModAddress ))       

     {

         _tprintf( _T("Failed when SymUnloadModule64() : %d /n"), GetLastError() );

     }

 

     if(!SymCleanup(GetCurrentProcess()))

     {

         _tprintf(_T("Failed when SymCleanup(): %d /n"), GetLastError());

         return 0;

     }

 

 

     return 0;

 

FAILED_PARAM:

     _tprintf(_T("Failed Parameter!/n"));

     _tprintf(_T("Usage: LFVars -filename -function_name/n"));

     _tprintf(_T("filename: a EXE, DLL or PDB file/n"));

     return 0;

}

呵呵,舉了兩個例子代碼後。真正的有用的應該是如何建立自己的dubegging過程。空了,偶會整理一下,貼點更爽的例子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章