DbgHelp.dll: вызов SymGetModuleInfo64 из C#

У меня довольно странное поведение при вызове SymGetModuleInfo64 из кода C#. Я всегда получаю ERROR_INVALID_PARAMETER (87) с Marshal.GetLastWin32Error(). Я уже прочитал много сообщений о проблемах с частыми обновлениями структуры IMAGEHLP_MODULE64 и только что скачал последние инструменты отладки для Windows (x86), загрузил dbghelp.dll из этого места, и я был совершенно уверен, что он будет работать. Тем не менее, я получаю ту же ошибку. Может кто-нибудь указать мне, что здесь не так?

Структура IMAGEHLP_MODULE64 определена в моем коде следующим образом:

[StructLayout(LayoutKind.Sequential)]
  public struct IMAGEHELP_MODULE64
  {
   //************************************************
   public int SizeOfStruct;
   public long BaseOfImage;
   public int ImageSize;
   public int TimeDateStamp;
   public int CheckSum;
   public int NumSyms;
   public SymType SymType;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
   public string ModuleName;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string ImageName;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string LoadedImageName;
   //************************************************
   //new elements v2
   //*************************************************
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string LoadedPdbName;
   public int CVSig;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 780)]
   public string CVData;
   public int PdbSig;
   public GUID PdbSig70;
   public int PdbAge;
   public bool PdbUnmatched;
   public bool DbgUnmatched;
   public bool LineNumbers;
   public bool GlobalSymbols;
   public bool TypeInfo;
   //************************************************
   //new elements v3
   //************************************************
   public bool SourceIndexed;
   public bool Publics;
   //************************************************
   //new elements v4
   //************************************************
   public int MachineType;
   public int Reserved;
   //************************************************
  }

фрагмент кода, который фактически вызывает SymGetModuleInfo64, выглядит следующим образом:

public void GetSymbolInfo(IntPtr hProcess,long modBase64,out bool success)
  {
   success = false;
   DbgHelp.IMAGEHELP_MODULE64 moduleInfo = new DbgHelp.IMAGEHELP_MODULE64();
   moduleInfo.SizeOfStruct = Marshal.SizeOf(moduleInfo);

   try
   {
    success = DbgHelp.SymGetModuleInfo64(hProcess, modBase64, out moduleInfo);

    if (success)
    {
     //Do the stuff here
    }
   }
   catch (Exception exc)
   {
   }
  }

Я застрял здесь... всегда с ошибкой 87. Пожалуйста, кто-то указывает мне в правильном направлении.

Кстати, modBase64 - это значение, ранее заполненное:

modBase64 = DbgHelp.SymLoadModule64(_handle, IntPtr.Zero, fileName, null, baseAddress, size);

где _handle - дескриптор процесса отлаживаемого процесса, fileName - путь текущего загруженного модуля, baseAddress - адресная база текущего загруженного модуля, а размер - конечно же размер текущего загруженного модуля. Я вызываю этот код, когда получаю LOAD_DLL_DEBUG_EVENT. Редактировать:

Извините, я забыл упомянуть, что подпись SymGetModuleInfo64 выглядит следующим образом:

[DllImport("dbghelp.dll", SetLastError = true)]
    public static extern bool SymGetModuleInfo64(IntPtr hProcess, long ModuleBase64, out IMAGEHELP_MODULE64 imgHelpModule);

Прежде всего, спасибо за ваш ответ.

1. Проверено SymType и его базовый тип действительно int. 2. Изменена структура GUID в System.Guid. 3. Добавлено определение CharSet=CharSet.Auto в определении структуры IMAGEHELP_MODULE64. 4.Скомментировал два последних поля. 5.Проверил размер структуры, он составляет 3264 байта (Unicode) и 1672 байта (Ansi), используя Marshal.SizeOf(instance_of_the_struct).

Файл dbghelp.dll загружен из папки%windir%\system 32, я использую Windows Server 2008 Enterprise и все еще безуспешно. По-прежнему появляется та же ошибка - 87.

Во второй попытке я раскомментировал последние два поля и использовал dbghelp.dll из каталога Debugging Tool For Windows (x86), так как я скачал последнюю версию пару дней назад, а в SDK\inc есть файл dbghelp.h, в котором говорится, что структура использует последние два поля (v4) как в этом фрагменте кода:

//
// module data structure
//

typedef struct _IMAGEHLP_MODULE64 {
    DWORD    SizeOfStruct;           // set to sizeof(IMAGEHLP_MODULE64)
    DWORD64  BaseOfImage;            // base load address of module
    DWORD    ImageSize;              // virtual size of the loaded module
    DWORD    TimeDateStamp;          // date/time stamp from pe header
    DWORD    CheckSum;               // checksum from the pe header
    DWORD    NumSyms;                // number of symbols in the symbol table
    SYM_TYPE SymType;                // type of symbols loaded
    CHAR     ModuleName[32];         // module name
    CHAR     ImageName[256];         // image name
    CHAR     LoadedImageName[256];   // symbol file name
    // new elements: 07-Jun-2002
    CHAR     LoadedPdbName[256];     // pdb file name
    DWORD    CVSig;                  // Signature of the CV record in the debug directories
    CHAR     CVData[MAX_PATH * 3];   // Contents of the CV record
    DWORD    PdbSig;                 // Signature of PDB
    GUID     PdbSig70;               // Signature of PDB (VC 7 and up)
    DWORD    PdbAge;                 // DBI age of pdb
    BOOL     PdbUnmatched;           // loaded an unmatched pdb
    BOOL     DbgUnmatched;           // loaded an unmatched dbg
    BOOL     LineNumbers;            // we have line number information
    BOOL     GlobalSymbols;          // we have internal symbol information
    BOOL     TypeInfo;               // we have type information
    // new elements: 17-Dec-2003
    BOOL     SourceIndexed;          // pdb supports source server
    BOOL     Publics;                // contains public symbols
    // new element: 15-Jul-2009
    DWORD    MachineType;            // IMAGE_FILE_MACHINE_XXX from ntimage.h and winnt.h
    DWORD    Reserved;               // Padding - don't remove.
} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;

Я не имел никакого успеха, используя обе эти версии struct, и у меня больше нет идей. Что касается адреса, который я передаю, я почти уверен, что все в порядке, поскольку я получаю его из функции SymLoadModule64, как я уже говорил ранее.

Надеюсь, кто-нибудь поймет, что здесь происходит.

1 ответ

Решение

Попробуйте изменить последний параметр (imgHelpModule) с out на ref. Для параметра out CLR не будет маршалировать какие-либо данные в функцию, поэтому API не увидит значение, которое вы поместили в SizeOfStruct.

Другие вопросы по тегам