2017-08-08 97 views
0

我正在开发一个使用VSIX的visual studio的调试器插件。我的问题是我有一个地址数组,但我不能将IDebugMemoryBytes2设置为一个特定的地址。我使用DEBUG_PROPERTY_INFO并获取地址数组,我也可以使用IDebugMemoryContext2中的Add函数将上下文设置为数组中的特定地址。但是,我需要使用ReadAt函数从指定地址(从IDebugMemoryBytes2)中检索n个字节。使用VSIX从任意内存地址检索数据

有没有人有任何想法如何从内存中的任意地址检索数据?

我加入同一信息

我现在用的是微软的Visual Studio扩展包来建立我的调试器插件。在我尝试使用这个插件进行调试的应用程序中,有一个双指针,我需要阅读这些值以在我的插件中进一步处理它们。为此,无法在监视窗口中显示所有指针变量,因此,我无法获得指针变量所指向的所有数组块的DEBUG_PROPERTY_INFO。这是我想解决的问题。我没有办法读取这个双指针指向的内存。

现在至于调试进程中的事件,由于插件是用于调试变量的,我在我知道这个指针被填充的地方放置一个断点,然后返回插件进行进一步评估。

作为一个开始,我以某种方式能够获得每个数组的起始地址。但是,我仍然无法从每个这些起始地址读取x个字节的内存。

即,例如,如果我有INT ** PTR = //指向东西

我有存在于PTR地址[0],PTR [1],PTR [2]等。但我需要去这些地址中的每一个地址并获取它们指向的内存块。

为此,经过多次搜索,我发现这个链接:https://macropolygon.wordpress.com/2012/12/16/evaluating-debugged-process-memory-in-a-visual-studio-extension/这似乎解决我的问题。

所以要使用表达式计算器函数,我需要一个IDebugStackFrame2对象来获取ExpressionContext。为了得到这个对象,我需要注册到调试对象进程中用于断点的事件。至于在帖子中说,我所做的:

public int Event(IDebugEngine2 engine, IDebugProcess2 process, 
       IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 
       debugEvent, ref Guid riidEvent, uint attributes) 
{ 
    if (debugEvent is IDebugBreakpointEvent2) 
    { 
     this.thread = thread; 
    } 

    return VSConstants.S_OK; 
} 

我的注册是这样的:

private void GetCurrentThread() 
{ 
    uint cookie; 
    DBGMODE[] modeArray = new DBGMODE[1]; 
    // Get the Debugger service. 
    debugService = Package.GetGlobalService(typeof(SVsShellDebugger)) as 
                   IVsDebugger; 
    if (debugService != null) 
    { 
     // Register for debug events. 
     // Assumes the current class implements IDebugEventCallback2. 
     debugService.AdviseDebuggerEvents(this, out cookie); 
     debugService.AdviseDebugEventCallback(this); 
     debugService.GetMode(modeArray); 

     modeArray[0] = modeArray[0] & ~DBGMODE.DBGMODE_EncMask; 

     if (modeArray[0] == DBGMODE.DBGMODE_Break) 
     { 
       GetCurrentStackFrame(); 
     } 
    } 
} 

但是,这似乎并没有在所有调用事件功能,因此,我不知道怎么样获取IDebugThread2对象。

我也试过在同一职位建议的其他方式:

namespace Microsoft.VisualStudio.Debugger.Interop.Internal 
{ 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("1DA40549-8CCC-48CF-B99B-FC22FE3AFEDF")] 
    public interface IDebuggerInternal11 { 
     [DispId(0x6001001f)] 
     IDebugThread2 CurrentThread { [return: 
     MarshalAs(UnmanagedType.Interface)] 
     [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = 
     MethodCodeType.Runtime)] 
     get; [param: In, MarshalAs(UnmanagedType.Interface)] 
     [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = 
     MethodCodeType.Runtime)] set; } 
    } 
} 

private void GetCurrentThread() 
{ 
    debugService = Package.GetGlobalService(typeof(SVsShellDebugger)) as IVsDebugger; 
    if (debugService != null) 
    { 
     IDebuggerInternal11 debuggerServiceInternal = 
         (IDebuggerInternal11)debugService; 
     thread = debuggerServiceInternal.CurrentThread; 

     GetCurrentStackFrame(); 
    } 
} 

但在这个方法中,我想我失去了一些东西,但我不知道,因为该行的执行后

IDebuggerInternal11 debuggerServiceInternal = 
            (IDebuggerInternal11)debugService; 

当我检查debuggerServiceInternal变量的值,我看到有一个System.Security.SecurityException为CurrentThread,CurrentStackFrame(和如此明显的下一行导致系统崩溃)。为此,我搜索了该错误,发现我错过了该类的ComImport属性。所以我补充说,现在,我得到一个System.AccessViolationException:试图读取或写入受保护的内存。这通常表明其他内存已损坏。

我是C#编程的新手,因此,在短时间内掌握很多东西有点困难。我现在失去了如何继续前进。

任何帮助相同或建议尝试另一种方式来实现我的目标将不胜感激。

非常感谢,

Esash

回答

0

很多搜​​索后,因为我短的时间,我需要一个快速的解决方案,因此,就目前而言,这似乎是最快捷的方式来解决这个问题通过显示指针的所有元素来破解.natvis文件,然后使用IDebug *接口方法使用相同的旧方法来访问和检索每个指针元素的内存上下文。但是,在msdn论坛发布相同的问题后,我认为正确的答案是Greggs提到的: “为了读取内存,如果你想要一个快速的方法来做到这一点,你只需要原始内存,调试引擎的目标是正常的Visual Studio本地引擎(换句话说,你不是创建你自己的调试引擎),我会推荐引用Microsoft.VisualStudio.Debugger.Engine。然后你可以使用DkmStackFrame.ExtractFromDTEObject来获取DkmStackFrame对象,这会给你DkmProcess对象,你可以调用DkmProcess.ReadMemory来从目标中读取内存。“

现在,在尝试了解如何实现此操作之后,我发现您可以使用以下代码完成此操作: DkmProcess.GetProcesses()并对返回的进程执行ReadMemory。 现在有一个问题,如果返回多个进程会怎么样。那么,我尝试将许多进程附加到当前的调试过程,并尝试将很多进程附加到调试对象进程中,但发现DkmProcess.GetProcesses()仅获得我从其中重新获得控制权的那个,而不是其他进程我附属于。我不确定这是否可以在所有情况下都能正常工作,但对我而言,这种方式是有效的,对于任何有类似要求的人来说,这可能也会起作用。

使用.natvis文件来实现这一点意味着,为VS2013和以前的版本使用IndexListItems,并为VS2015及更高版本使用CustomListItems,并使其看起来更漂亮,使用“无派生”属性。没有办法让Synthetic标签只显示每个变量的基地址,因此,上面的属性是最好的方法,但这在VS2013和以前的版本中是不可用的(基地址可能会显示,但对于那些想要超越显示内容并且访问指针元素的内存上下文的人,Synthetic标记不是正确的)。

我希望这有助于一些像我一样使用IDebug *接口挣扎的开发人员。作为参考,我也给了我的问题被回答的msdn论坛的链接。

https://social.msdn.microsoft.com/Forums/en-US/030cef1c-ee79-46e9-8e40-bfc59f14cc34/how-can-i-send-a-custom-debug-event-to-my-idebugeventcallback2-handler?forum=vsdebug

感谢。