2009-10-13 96 views
1

我使用Windbg从sos.dll中使用Windbg的!U命令来反汇编托管代码(用C#编写,控制台应用程序)。我发现当使用!U来组装一个托管函数时,拆开的IL代码仅包含我所做的函数调用,以及其余部分(非函数调用C#代码),例如C#中的a=a*2foreach循环,只有本机汇编语言代码显示,是否正确的预期行为?我的问题是,我想知道!U是否能够将所有代码(除了函数调用代码)都组装到IL中,从而将托管代码二进制DLL组装成IL?反汇编托管代码问题

由于提前,乔治

回答

1

我不认为WinDbg的工作在IL水平。您可能必须使用ildasm才能获得IL反汇编。

+0

我知道ildasm或反射器可以做到这一点。但我正在调试运行时或调试崩溃转储,我需要调用堆栈地址信息以及IL代码(ildasm或反射器无法提供)。如果只显示本地汇编代码,则很难调试,这就是为什么我要用调用堆栈地址信息反汇编到IL代码的原因。任何意见或解决方案? – George2 2009-10-13 04:51:55

9

如果您想在调试时转储IL,则可以使用SOS的!dumpil命令。它需要一个MethodDesc指针作为输入,所以你必须首先获取它。

获取MethodDesc指针的一种方法是使用!name2ee命令。

因此,举例来说,如果你在类型Bar(组装ClassLibrary1)使用!name2ee这样

0:000> !name2ee ClassLibrary1!ClassLibrary1.Bar.Foo 
Module: 001630bc (ClassLibrary1.dll) 
Token: 0x06000001 
MethodDesc: 00163450 <=== HERE 
Name: ClassLibrary1.Bar.Foo() 
JITTED Code Address: 007500f0 

此之后有一个方法Foo,你可以做一个!dumpil 00163450转储IL的方法Foo这样

0:000> !dumpil 00163450 
ilAddr = 73532050 
IL_0000: ldstr "Foo" 
IL_0005: call System.Console::WriteLine 
+0

我发现!dumpil无法转储原生地址信息?例如,如果我发现我的代码在原生地址0x11111111处崩溃或中断,我想查看它正在执行哪个IL代码?可以!dumpil这样做? – George2 2009-10-13 08:30:15

+2

你必须记住,IL代码实际上并没有运行。它被编译成本地代码,然后运行。但是,如果您执行崩溃过程的转储,则您将拥有JITTED代码和原始IL作为转储的一部分。使用!U显示CLR意识到生成的代码的拆卸。使用!dumpil显示IL。 从异常堆栈跟踪和!name2ee您应该能够根据需要找到JITTED和IL代码。 – 2009-10-13 08:58:37

+0

我的问题是,使用!对于非函数调用托管代码(例如a = a + 2或foreach循环),永远不应该使用IL代码来处理非函数调用托管代码,只会显示本机汇编代码。那是预期的行为? – George2 2009-10-13 09:03:47