我调查了 .Net Framework JITter 编译结果,我想以编程方式获取异常处理程序链。可能有人可以帮助我进行这项调查吗?
为了使任务更容易,我调试以下代码:
class Program
{
static void Main(string[] args) { MethodA(); }
static void MethodA() { MethodB(); }
static void MethodB()
{
try { MethodC(); }
catch (Exception exception) { MethodC(); }
}
static void MethodC() { MethodD(); }
static void MethodD()
{
try { MethodE(); }
catch (Exception exception) { MethodE(); }
}
static void MethodE() { throw new Exception(); }
}
发现了什么?
- JITter 使用标准方式构建堆栈帧(locals,
EBP
,EIP
, params) - 第一个参数通过寄存器移动到方法(fastcall)
- try-catch-finally 在哪里?我不知道。真的。方法没有任何代码可以从链中注销最后一个处理程序。
- 静态方法仅推送到堆栈
EBP
和EIP
。这意味着,堆栈不能包含链并且链在堆栈外。
我使用的是:MS Visual Studio 2010,用于按地址解析 .Net 对象和元数据的 SOS 扩展。VMMap 来理解,给定地址是什么类型的内存页和(呵呵)MS OneNote 用不同的颜色标记内存转储以标记为已解决(这意味着,我明白我发现了什么)
我很乐意了解这条链在哪里,但我没有这样做的经验。
重要提示:CLR 不使用 SEH 处理异常(很多文章,作者在 CLR 中写了关于 SEH 的文章。CLR 只包装 SEH 以将其异常转换为 CLR 类型)