符号信息按地址

时间:2017-03-17 08:43:27

标签: c#

我正在尝试从地址获取符号信息,但我收到错误87(0x57)ERROR_INVALID_PARAMETER,我在这里也发现了同样的问题https://social.msdn.microsoft.com/Forums/en-US/bd3e1c89-83c7-41c3-9d5d-a41069da2555/retrieving-symbol-information-by-address-in-c?forum=netfxtoolsdev但是答案对我来说不起作用,或者至少它不清楚。在SO中有一些相关问题:SymFromAddr using C#但似乎没有解决这个问题的线索。

注意:DbgHelpNative类是C#的DbgHelp.dll的包装。

这是我的代码:

static IntPtr GetThreadStartAddress(int threadId)
{

   var hThread =    OpenThread(ThreadAccess.QueryInformation, false, threadId);

   if (hThread == IntPtr.Zero) {
      throw new Win32Exception();
   }

   var buf = Marshal.AllocHGlobal(IntPtr.Size);

   try {
      var result =  NtQueryInformationThread(hThread,ThreadInfoClass.ThreadQuerySetWin32StartAddress,buf, IntPtr.Size, IntPtr.Zero);

      if (result != 0) {
        throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
      }

      IntPtr threadAddress = Marshal.ReadIntPtr(buf);

      if (DbgHelpNative.SymInitialize(IntPtr.Zero, null,     false)) {

         int bufferSize = Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) + ((2000 - 2) * 2);

         var buffer = Marshal.AllocHGlobal(bufferSize);

         DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();

         ulong displacement = 0;

         Marshal.PtrToStructure(buffer, typeof(DbgHelpNative.SYMBOL_INFO));

         symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO));

         symbolInfo.MaxNameLen = 2000;


         if (DbgHelpNative.SymFromAddr(hThread, (ulong)threadAddress, out displacement, ref symbolInfo)) {
            MessageBox.Show("Success");
         } else {
            var error = Marshal.GetLastWin32Error();
            MessageBox.Show(error.ToString());
         }
      }
      return threadAddress;
   }
   finally {
      CloseHandle(hThread);
      Marshal.FreeHGlobal(buf);
   }
}

1 个答案:

答案 0 :(得分:1)

正确的代码是:

static IntPtr GetThreadStartAddress(IntPtr hProc, int threadId)
{
    IntPtr hThread = IntPtr.Zero;
    GCHandle handle = default(GCHandle);

    try
    {
        hThread = OpenThread(ThreadAccess.QueryInformation, false, threadId);

        if (hThread == IntPtr.Zero)
        {
            throw new Win32Exception("OpenThread failed");
        }

        var threadAddress = new IntPtr[1];

        handle = GCHandle.Alloc(threadAddress, GCHandleType.Pinned);
        var result = NtQueryInformationThread(hThread, ThreadInfoClass.ThreadQuerySetWin32StartAddress, handle.AddrOfPinnedObject(), IntPtr.Size, IntPtr.Zero);

        if (result != 0)
        {
            throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
        }

        DbgHelpNative.SymSetOptions(DbgHelpNative.Options.SYMOPT_UNDNAME | DbgHelpNative.Options.SYMOPT_DEFERRED_LOADS);

        if (!DbgHelpNative.SymInitialize(hProc, null, true))
        {
            throw new Win32Exception("SymInitialize failed");
        }

        DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();

        // Look at your DbgHelpNative.SYMBOL_INFO.Name definition, there should be a SizeConst.
        // Change the 1024 to the SizeConst
        // If using Unicode, change 1024 to 1024 * 2
        // In the end SizeOfStruct should be 88, both at 32 and 64 bits, both Ansi and Unicode
        symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) - 1024;
        // Change the 1024 to the SizeConst (both for Ansi and Unicode)
        symbolInfo.MaxNameLen = 1024;

        ulong displacement;

        if (!DbgHelpNative.SymFromAddr(hProc, (ulong)threadAddress[0], out displacement, ref symbolInfo))
        {
            throw new Win32Exception("SymFromAddr failed");
        }

        Console.WriteLine("Success");

        return threadAddress[0];
    }
    finally
    {
        if (hThread != IntPtr.Zero)
        {
            CloseHandle(hThread);
        }

        if (handle.IsAllocated)
        {
            handle.Free();
        }
    }
}

**您必须在symbolInfo.SizeOfStructsymbolInfo.MaxNameLen行进行小幅修正!

请注意,您需要hProc(流程的句柄)和threadId

对于当前流程,您可以使用:

var proc = Process.GetCurrentProcess();
int id = proc.Threads[0].Id;
IntPtr addr = GetThreadStartAddress(proc.Handle, id);

请注意,如果您对DbgHelpNative使用this,我认为任何使用Ansi而不是Unicode的PInvoke都有缺陷。另一个(小的,非)问题是该库中的SizeConst设置为1024,但在MSDN示例中他们使用MAX_SYM_NAME,即2000 ...我没有'曾见过一个2000字符符号,但是......)