前段写过一篇文章“CLR探索系列:深入追踪托管exe加载执行过程”,在那篇文章中,主要是侧重静态代码的分析,追踪源代码的流程一步一步看是如何实现的。
这次,写一篇文章,结合Windbg,从一个托管应用程序执行的调用堆栈开始,追踪其调用堆栈中的线索,以及这些托管应用程序执行中调用的功能实现,来展示托管代码的加载和执行的流程和实现。
首先还是找一个小白鼠:
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();
}
}
}
这里找的是一个WinForm应用程序来作为小白鼠。
咱就不采用在调用的关键的mscorwks和MscoeEE的方法上面下断点来跟踪,然后解释每个断点调用堆栈和环境的解释方法了,直接把main thread的call stack给打出来一行一行的去挖掘好了。
打开Windbg,附加到进程,加载好相关的symbol和2.0的SOS,切换到第0个Thread然后输出其调用堆栈:
0:000> k
ChildEBP RetAddr
0012f4a0 7c92e9ab ntdll!KiFastSystemCallRet
0012f 3c 4 7b08432d USER32!NtUserWaitMessage+0xc
0012f 434 7b08416b System_Windows_Forms_ni+0xb432d
0012f 464 7b 0c 69fe System_Windows_Forms_ni+0xb416b
0012f 490 79e88ee4 System_Windows_Forms_ni+0xf69fe
0012f 510 79e88e31 mscorwks!CallDescrWorkerWithHandler+0xa3