Windbg帮助 -> 如何阅读此调用堆栈上的代码?

8

我有一个Windows服务的转储文件。问题是,我的代码无法移动文件(出于某种原因)。现在,在我的代码中,有很多地方需要在文件系统中移动文件。因此,使用Windbg,我正在尝试查看异常发生的代码。

这是我的!clrstack转储...

0:016> !clrstack -p
OS Thread Id: 0xdf8 (16)
Child-SP         RetAddr          Call Site
0000000019edea70 0000064278a15e4f System.IO.__Error.WinIOError(Int32, System.String)
PARAMETERS:
    errorCode = <no data>
    maybeFullPath = <no data>

0000000019edead0 0000064280181ce5 System.IO.File.Move(System.String, System.String)
PARAMETERS:
    sourceFileName = <no data>
    destFileName = <no data>

0000000019edeb50 0000064280196532 MyClass.Foo.DoSomeStuffInHere(System.String)
PARAMETERS:
    this = 0x0000000000c30aa8
    filePathAndName = 0x0000000000d1aad0

现在,这对于IT技术非常有帮助...

0:016> !do 0x0000000000d1aad0
Name: System.String
MethodTable: 00000642784365e8
EEClass: 000006427803e4f0
Size: 88(0x58) bytes
(C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: C:\BlahBlahFolder\FooFolder\4469.jpg
Fields:
-snipped-

我已经找到了移动失败的文件,不错。但我想要查看调用 File.Move(..) 的 MyClass.Foo.DoSomeStuffInHere(System.String) 方法中的代码。这个方法有很多File.Move .. 我可以使用 try / catch / debug / trace 信息来解决问题,但我希望通过使用 Windbg 更高效地找到这个问题。

有什么想法吗?

2个回答

3

This is a difficult problem and may require stepping outside of one's comfort zone of managed only debugging.

What you want to do is map the IL for the function MyClass.Foo.DoSomeStuffInHere to the dissassembly of that function. My example below is x86 however x64 can follow the same steps.

This is referenced way down deep in the following link. Debugging Unexpected Process Termination

Example text from the whitepaper: In the managed stack, Debugging.Unexpected.btnSTA_Click ... Look at the code in the Debugging.Unexpected.btnSTA_Click event.

private void btnSTA_Click(object sender, System.EventArgs e)
{
   DebuggingCOMLib.STAClass staobj =  new DebuggingCOMLib.STAClass();
   staobj.RaiseError(1,5);
   Label1.Text += "STA Call Completed sucessfully";
}

If the source code is not available, you can examine the assembly by supplying the instruction pointer for the call-stack frame to the !u command. The instruction pointer can be retrieved from the !clrstack: output.

0096f970  03a00e06 [DEFAULT] [hasThis] Void
Debugging.Unexpected.btnSTA_Click(Object,Class System.EventArgs)

To disassemble this function, type !u 03a00e06.

    0:010> !u 03a00e06 
    Normal JIT generated code
    [DEFAULT] [hasThis] Void Debugging.Unexpected.btnSTA_Click(Object,Class 
    System.EventArgs)
    Begin 03a00de0, size 54
   <snip>
    03a00e18 8b15a89c1702     mov     edx,[02179ca8] ("STA Call Completed 
    sucessfully")
    03a00e1e e83d3590ff       call    03304360 (System.String.Concat)
    <snip>
    03a00e2f 5e               pop     esi
    03a00e30 5f               pop     edi
    03a00e31 c20400           ret     0x4

Ok, now what?
Scan your own !u output for a line like

call    03304360 (System.IO.File.Move)

Also, you can run !ip2md 03a00e06 to get the MethodDesc and then run !dumpil to examine the IL code if that is easier.

You could count the number of calls to System.IO.File.Move in the !u output and then count down the same number in the IL. Then you can use .NET Reflector to Disassemble the method and map the C# to IL and compare the result.

Lot's of steps, but it would get you to the same result :-)

Thanks, Aaron


3

除非应用程序在调试模式下部署,否则您无法获取精确的代码行。如果是这种情况,我相信它会在!clrstack调用中显示。


谢谢伙计 :) 它处于发布模式。我不想说那个,因为我不想影响任何答案,以防那不是答案。太棒了,伙计。我会尝试在调试模式、发布等重新构建。干杯,伙计(我担心有人会说那是问题所在)。干杯! - Pure.Krome
你可以将其重构,使得对 File.Move 的多次调用在不同的方法中... - TheSoftwareJedi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接