关于SEH局部展开的一点思考
来源:互联网 发布:聚合数据公司怎么样 编辑:程序博客网 时间:2024/05/16 08:16
最近读了Matt Pietrek的《A Crash Course on the Depths of Win32 Structured Exception Handling》,有如醍醐灌顶,尤其是编译器级的SEH,如果是SEH的初学者,推荐读一下这篇文章,不要先去看《windows核心编程》的异常处理章节,那样只会越搞越乱。如果把SEH帧链和_SCOPETABLE链这两条链搞清了基本就OK了,至于细节部分值得深究的地方还是很多的。但在这篇文章中一个没有具体提到的问题就是SEH的局部展开,也就是_local_unwind函数,由于这是一个与编译器相关的函数,所以对研究系统的SEH没有障碍。后来我在张银奎的《软件调试》补编的异常编译章节中找到了一段该函数的伪码,摘录如下:
这段伪码中最主要的是12行开始的那个while循环,第18行判断pCurScopeEntry->lpfnFilter是否为NULL,原因是在VC中try_finally块和try_except块一样,都对应一个scopetable中的_SCOPETABLE表项,区别在于try_finally对应表项的lpfnFilter值为NULL,也就是说没有过滤表达式。因此以上代码可以看出,局部展开的任务主要是搜索_SCOPETABLE链中的try_finally节点并执行finally处理代码。为了验证这个说法,我写了一小段代码
#include <windows.h>
#include <stdio.h>
void ViewScopeTable(DWORD* pSEHFrame)
{
DWORD* Scopetable = (DWORD*)*(pSEHFrame+2);
DWORD TryLevel = *(pSEHFrame+3);
DWORD* pCurTable = (DWORD*)(Scopetable + TryLevel*3);
while( TRUE )
{
printf("prevTryLevel:%x/nlpfnfilter:%x/nlpfnHandler:%x/n/n",
*pCurTable,
*(pCurTable+1),
*(pCurTable+2)
);
if( ( TryLevel = *(pCurTable) ) == 0xFFFFFFFF)
break;
pCurTable = (DWORD*)(Scopetable + TryLevel*3);
}
}
void ShowSEHFrame()
{
DWORD pSEHHead;
_asm mov eax, fs:[0]
_asm mov pSEHHead, eax
printf("fs:[0]:%x/n/n", pSEHHead);
DWORD* pHead = (DWORD*)pSEHHead;
while(TRUE)
{
printf("Frame addr:%x/nprev:%x/nhandler:%x/nscopetable:%x/ntrylevel:%x/n/n",
Head,
*pHead,
*(pHead+1),
*(pHead+2),
*(pHead+3)
);
ViewScopeTable(pHead);
if( *pHead == 0xFFFFFFFF )
break;
pHead = (DWORD*)*pHead;
}
}
void func1()
{
_try{
_try{
_try{
ShowSEHFrame();
}_except( EXCEPTION_CONTINUE_SEARCH ) //except块
{
}
}_finally //有意设置成finally块
{
}
}_except( EXCEPTION_CONTINUE_SEARCH ) //except块
{
}
}
int main()
{
func1();
}
执行结果如下:
可见try_finally块和try_except一样被插入到_SCOPETABLE链中,只是lpfnFilter为0。
在Matt Pietrek的_except_handler3的伪码中有这样一句:
if ( pRegistrationFrame->scopetable[trylevel].lpfnFilter )
.......
即判断_SCOPETABLE项的lpfnFilter,若是try_finally块则直接略过该节点,查询下一节点。而在上述的_local_unwind2伪码中,若是try_except节点则略过,查询下一节点。由此可以总结出:
try_except节点在发生异常时搜索异常处理块时被使用,而try_finally节点则用于局部展开的时候。
由于VC中的异常handler都指向_except_handler3,不是一个异常处理块对应一个异常处理帧,故没有办法在全局展开时直接用_except_handler3完成清理工作,所以有了try_finally结构,这样看来这个结构的出现也是在情理之中的。
- 关于SEH局部展开的一点思考
- X64 SEH的展开
- 关于 && 的一点思考
- 关于计算机体系结构的一点思考。
- 关于计算机体系结构的一点思考
- 关于继承的一点思考
- 关于盗版的一点思考
- 关于宏的一点思考
- 关于计算机的一点思考
- 关于编程的一点思考
- 关于软件设计的一点思考
- 关于string的一点思考
- 关于makefile的一点思考
- 关于“概念”的一点思考
- 关于重载的一点思考
- 关于XSS的一点思考
- 关于code的一点思考
- 关于前端的一点思考
- 一个it老总对于新人的一点建议
- 巧用Sc命令,解决服务窗口无法打开故障
- 从char/wchar_t到TCHAR
- ThinkPHP与RBAC:基于角色的权限管理
- 北京54转西安80坐标系
- 关于SEH局部展开的一点思考
- DEV中的lookupEdit控件的初始化
- MFC笔记3
- handle
- snort数据库详解
- 有点意思:不患寡而患不均,不患贫而患不安
- 【转载】黑莓开发学习(入门教程)03-经典的HelloWorld程序
- DNS BIND的配置