【IT168技术文档】
从一个托管应用程序执行的调用堆栈开始,追踪其调用堆栈中的线索,以及这些托管应用程序执行中调用的功能实现,来展示托管代码的加载和执行的流程和实现。
首先还是找一个小白鼠:
这里找的是一个WinForm应用程序来作为小白鼠。public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { System.Object o = new object(); lock (o) { System.GC.Collect(); } } }
咱就不采用在调用的关键的mscorwks和MscoeEE的方法上面下断点来跟踪,然后解释每个断点调用堆栈和环境的解释方法了,直接把main thread的call stack给打出来一行一行的去挖掘好了。
打开Windbg,附加到进程,加载好相关的symbol和2.0的SOS,切换到第0个Thread然后输出其调用堆栈:
0:000> k ChildEBP RetAddr 0012f4a0 7c92e9ab ntdll!KiFastSystemCallRet 0012f3c4 7b08432d USER32!NtUserWaitMessage+0xc 0012f434 7b08416b System_Windows_Forms_ni+0xb432d 0012f464 7b0c69fe System_Windows_Forms_ni+0xb416b 0012f490 79e88ee4 System_Windows_Forms_ni+0xf69fe 0012f510 79e88e31 mscorwks!CallDescrWorkerWithHandler+0xa3 0012f650 79e88d19 mscorwks!MethodDesc::CallDescr+0x19c 0012f668 79e88cf6 mscorwks!MethodDesc::CallTargetWorker+0x20 0012f67c 79f084b0 mscorwks!MethodDescCallSite::Call+0x18 0012f7e0 79f082a9 mscorwks!ClassLoader::RunMain+0x220 0012fa48 79f0817e mscorwks!Assembly::ExecuteMainMethod+0xa6 0012ff18 79f07dc7 mscorwks!SystemDomain::ExecuteMainMethod+0x398 0012ff68 79f05f61 mscorwks!ExecuteEXE+0x59 0012ffb0 79011b5f mscorwks!_CorExeMain+0x11b 0012ffc0 7c816fd7 mscoree!_CorExeMain+0x2c 0012fff0 00000000 KERNEL32!BaseProcessStart+0x23