更改本地堆栈变量值

| 使用Windbg / SOS,可以更改堆栈上的局部变量的值吗?如果可以,怎么办?     
已邀请:
简短的答案是:这取决于。 默认情况下,局部值类型存储在堆栈中,但由于优化,它们通常仅根据需要存储在寄存器中。引用类型存储在堆上,并引用堆栈上(或寄存器中)的实例。 我将假设您要更改本地值类型。让我们看一个简单的例子。
[MethodImpl(MethodImplOptions.NoInlining)] // avoid inlining of short method
public static void Method(int x) {
    Console.WriteLine(\"The answer is {0}\", x + x);
}
假设我们在
Method
上设置一个断点并运行直到命中断点,堆栈看起来像这样:
0:000> !clrstack -a
OS Thread Id: 0x1abc (0)
Child SP IP       Call Site
0035f290 003600e0 TestBench2010.Program.Method(Int32)*** WARNING: Unable to verify checksum for C:\\workspaces\\TestBench2010\\TestBench2010\\bin\\Release\\TestBench2010.exe
 [C:\\workspaces\\TestBench2010\\TestBench2010\\Program.cs @ 17]
    PARAMETERS:
        x (<CLR reg>) = 0x00000002

0035f294 003600a2 TestBench2010.Program.Main(System.String[])    [C:\\workspaces\\TestBench2010\\TestBench2010\\Program.cs @ 24]
    PARAMETERS:
        args = <no data>

0035f4c0 636221bb [GCFrame: 0035f4c0] 
注意,本地
x
被列为,但是它没有告诉我们哪个寄存器。我们可以查看寄存器并找到值为2的寄存器,但可能不止一个。相反,让我们看一下该方法的JIT编译代码。
0:000> !u 001c37f0     
Normal JIT generated code
TestBench2010.Program.Method(Int32)
Begin 003600e0, size 32

C:\\workspaces\\TestBench2010\\TestBench2010\\Program.cs @ 17:
003600e0 55              push    ebp
003600e1 8bec            mov     ebp,esp
003600e3 56              push    esi
003600e4 8bf1            mov     esi,ecx
*** WARNING: Unable to verify checksum for    C:\\windows\\assembly\\NativeImages_v4.0.30319_32\\mscorlib\\658bbc023e2f4f4e802be9483e988373\\mscorlib.ni.dll
003600e6 b9302be004      mov     ecx,offset mscorlib_ni+0x322b30 (04e02b30) (MT: System.Int32)
003600eb e8301fe5ff      call    001b2020 (JitHelp: CORINFO_HELP_NEWSFAST)
003600f0 8bd0            mov     edx,eax
003600f2 03f6            add     esi,esi    <==== This is x + x
003600f4 897204          mov     dword ptr [edx+4],esi
003600f7 8bf2            mov     esi,edx
003600f9 e882709d04      call    mscorlib_ni+0x257180 (04d37180)(System.Console.get_Out(), mdToken: 060008cd)
003600fe 56              push    esi
003600ff 8bc8            mov     ecx,eax
00360101 8b1534204c03    mov     edx,dword ptr ds:[34C2034h] (\"The answer is {0}\")
00360107 8b01            mov     eax,dword ptr [ecx]
00360109 8b403c          mov     eax,dword ptr [eax+3Ch]
0036010c ff5018          call    dword ptr [eax+18h]

C:\\workspaces\\TestBench2010\\TestBench2010\\Program.cs @ 18:
0036010f 5e              pop     esi
00360110 5d              pop     ebp
00360111 c3              ret
查看代码,我们看到唯一的
add
指令使用了
esi
寄存器,因此我们的值存储在此处,然后进行计算。不幸的是,
esi
此时未保持正确的值,但向后看,我们发现
mov esi,ecx
。即该值最初存储在“ 9”中。 要更改
ecx
的值,请使用
r
命令。例如。将该值设置为0x15,请执行以下操作:
0:000> r ecx=15
该方法的输出现在是:   答案是42 请记住,上面的示例只是许多可能的情况之一。根据调试/发布版本以及32/64位,对本地的处理方式有所不同。同样,对于复杂的方法,跟踪值的确切位置可能会有些困难。 要更改实例的状态,您必须在堆栈上定位引用(例如,使用
!clrstack
!dso
)。一旦找到,就可以使用偏移量来查找存储数据的存储器,并使用
e*
命令根据需要更改值。让我知道您是否也想要一个示例。     

要回复问题请先登录注册