Windbg 更改本地堆栈变量值
使用Windbg/SOS,是否可以更改堆栈上局部变量的值?如果是这样的话,怎么办?简单的回答是:视情况而定 默认情况下,本地值类型存储在堆栈上,但由于优化,它们通常只在需要时存储在寄存器中。引用类型存储在堆上,并引用堆栈(或寄存器)上的实例 我假设您希望更改本地值类型。让我们看一个简单的例子Windbg 更改本地堆栈变量值,windbg,sos,Windbg,Sos,使用Windbg/SOS,是否可以更改堆栈上局部变量的值?如果是这样的话,怎么办?简单的回答是:视情况而定 默认情况下,本地值类型存储在堆栈上,但由于优化,它们通常只在需要时存储在寄存器中。引用类型存储在堆上,并引用堆栈(或寄存器)上的实例 我假设您希望更改本地值类型。让我们看一个简单的例子 [MethodImpl(MethodImplOptions.NoInlining)] // avoid inlining of short method public static void Method(
[MethodImpl(MethodImplOptions.NoInlining)] // avoid inlining of short method
public static void Method(int x) {
Console.WriteLine("The answer is {0}", x + x);
}
假设我们在方法
上设置了一个断点,并一直运行到达到断点,堆栈如下所示:
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]
查看代码,我们看到唯一的add
指令使用esi
寄存器,因此我们的值在计算之前存储在这里。不幸的是,esi
此时没有保持正确的值,但回顾一下,我们发现movesi,ecx
。即,该值最初存储在ecx
中
要更改ecx
的值,请使用r
命令。例如,要将值设置为0x15,请执行以下操作:
0:000> r ecx=15
该方法的输出现在为:
答案是42
请记住,上面的示例只是许多可能场景中的一个。根据调试/发布版本以及32/64位,局部变量的处理方式有所不同。此外,对于复杂的方法,跟踪值的准确位置可能会有点困难
要更改实例的状态,必须在堆栈上找到引用(例如,使用
!clrstack
或!dso
)。定位后,您可以使用偏移量查找保存数据的内存,并根据需要使用e*
命令更改值。如果你还想举个例子,请告诉我 简单的答案是:视情况而定
默认情况下,本地值类型存储在堆栈上,但由于优化,它们通常只在需要时存储在寄存器中。引用类型存储在堆上,并引用堆栈(或寄存器)上的实例
我假设您希望更改本地值类型。让我们看一个简单的例子
[MethodImpl(MethodImplOptions.NoInlining)] // avoid inlining of short method
public static void Method(int x) {
Console.WriteLine("The answer is {0}", x + x);
}
假设我们在方法
上设置了一个断点,并一直运行到达到断点,堆栈如下所示:
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]
查看代码,我们看到唯一的add
指令使用esi
寄存器,因此我们的值在计算之前存储在这里。不幸的是,esi
此时没有保持正确的值,但回顾一下,我们发现movesi,ecx
。即,该值最初存储在ecx
中
要更改ecx
的值,请使用r
命令。例如,要将值设置为0x15,请执行以下操作:
0:000> r ecx=15
该方法的输出现在为:
答案是42
请记住,上面的示例只是许多可能场景中的一个。根据调试/发布版本以及32/64位,局部变量的处理方式有所不同。此外,对于复杂的方法,跟踪值的准确位置可能会有点困难
要更改实例的状态,必须在堆栈上找到引用(例如,使用
!clrstack
或!dso
)。定位后,您可以使用偏移量查找保存数据的内存,并根据需要使用e*
命令更改值。如果你还想举个例子,请告诉我 您是在寻找在托管代码内还是在非托管代码内执行此操作的方法?@Seva:因为问题被标记为SOS,所以很可能是托管代码。@Seva:@Brain是正确的,其托管代码您是在托管代码内还是在非托管代码内寻找执行此操作的方法?@Seva:因为问题被标记为SOS,所以它很可能是托管代码。@Seva:@Brain是正确的,它是托管代码