LOAD_DLL_DEBUG_EVENT调试事件

 
LOAD_DLL_DEBUG_EVENT结构如下
typedef struct _LOAD_DLL_DEBUG_INFO {
  HANDLE hFile;
  LPVOID lpBaseOfDll;
  DWORD  dwDebugInfoFileOffset;
  DWORD  nDebugInfoSize;
  LPVOID lpImageName;
  WORD   fUnicode;
} LOAD_DLL_DEBUG_INFO, *LPLOAD_DLL_DEBUG_INFO;
 
其中hFile表示导入DLL的句柄,我们可以通过这个句柄得到DLL的名称;lpBaseOfDll表示导入DLL的基地址;dwDebugInfoFileOffset表示通过hFile得到调试信息的偏移量;nDebugInfoSize表示通过hFile得到调试信息的大小,以字节为单位;IpImageName表示通过hFile得到的文件名。如何通过hFile得到调试信息,我还没找到方法,不过这种方法有时是得不到调试信息的,所以暂时先不考虑。fUnicode表示由lpImageName得到文件名是Unicode或者是ANSI。
当调试器收到LOAD_DLL_DEBUG_EVENT事件时,如何得到导入DLL的名称呢?我先想到的是利用IpImageName得到导入DLL的名称,使用的代码如下:
    strDebugText = new char [100];
      strDebugText = (char *)DbgEvt.u.LoadDll.lpImageName;
      strText = strDebugText;
      strText += "\r\n";
      strPromptText = strText + strPromptText;
      ::SetDlgItemText(AfxGetMainWnd()->m_hWnd, IDC_DISPLAYINFO, strPromptText);
      delete [] strDebugText;
但结果是得不到任何调试信息。接下来的几天辗转反侧,始终没有什么办法,知道在MSDN发现这样一段代码
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <psapi.h>
#include <strsafe.h>
#define BUFSIZE 512
BOOL GetFileNameFromHandle(HANDLE hFile) 
{
  BOOL bSuccess = FALSE;
  TCHAR pszFilename[MAX_PATH+1];
  HANDLE hFileMap;
  // Get the file size.
  DWORD dwFileSizeHi = 0;
  DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi); 
  if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
  {
     _tprintf(TEXT("Cannot map a file with a length of zero.\n"));
     return FALSE;
  }
  // Create a file mapping object.
  hFileMap = CreateFileMapping(hFile, 
                    NULL, 
                    PAGE_READONLY,
                    0, 
                    1,
                    NULL);
  if (hFileMap) 
  {
    // Create a file mapping to get the file name.
    void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
    if (pMem) 
    {
      if (GetMappedFileName (GetCurrentProcess(), 
                             pMem, 
                             pszFilename,
                             MAX_PATH)) 
      {
        // Translate path with device name to drive letters.
        TCHAR szTemp[BUFSIZE];
        szTemp[0] = '\0';
        if (GetLogicalDriveStrings(BUFSIZE-1, szTemp)) 
        {
          TCHAR szName[MAX_PATH];
          TCHAR szDrive[3] = TEXT(" :");
          BOOL bFound = FALSE;
          TCHAR* p = szTemp;
          do 
          {
            // Copy the drive letter to the template string
            *szDrive = *p;
            // Look up each device name
            if (QueryDosDevice(szDrive, szName, MAX_PATH))
            {
              size_t uNameLen = _tcslen(szName);
              if (uNameLen < MAX_PATH) 
              {
                bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0;
                if (bFound && *(pszFilename + uNameLen) == _T('\\')) 
                {
                  // Reconstruct pszFilename using szTempFile
                  // Replace device path with DOS path
                  TCHAR szTempFile[MAX_PATH];
                  StringCchPrintf(szTempFile,
                            MAX_PATH,
                            TEXT("%s%s"),
                            szDrive,
                            pszFilename+uNameLen);
                  StringCchCopyN(pszFilename, MAX_PATH+1, szTempFile, _tcslen(szTempFile));
                }
              }
            }
            // Go to the next NULL character.
            while (*p++);
          } while (!bFound && *p); // end of string
        }
      }
      bSuccess = TRUE;
      UnmapViewOfFile(pMem);
    } 
    CloseHandle(hFileMap);
  }
  _tprintf(TEXT("File name is %s\n"), pszFilename);
  return(bSuccess);
}
int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hFile;
    if( argc != 2 )
    {
        _tprintf(TEXT("This sample takes a file name as a parameter.\n"));
        return 0;
    }
    hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
        OPEN_EXISTING, 0, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        _tprintf(TEXT("CreateFile failed with %d\n"), GetLastError());
        return 0;
    }
    GetFileNameFromHandle( hFile );
}
通过GetFileNameFromHandle可以通过句柄得到文件名,这个函数需要使用psapi.DLL,在windows 7下可以直接使用,在windows xp下需要下载psapi.DLL。
回到我的调试器如图所示,虽然仍是简陋,但已经能够输出DLL信息和breakpoint信息了。已经添加了简单的命令行,当初始化断点中断到调试器时,可是在命令行中输入G来继续了。除此以外,也可以手动设置断点,但由于没有引入符号文件或源码,只能在指定地址上设置断点。还有那个“send Message” 是为接下来工作做得,暂时不说了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值