Windows操作系统的异常分发过程

image.png

Visual studio中的异常对话框(如上图所示),从上至下分别是:C,C++异常,.net异常,Native异常,Win32异常
windows操作系统会给每个异常一个独立的异常代码,
c++异常就是hardcode层的.msc的ASCII码为0xe06d7363
.net异常就是hardcode层的.com的ASCII码
下面是Windows操作系统分发异常的内核函数(KiDispatchException):
image.png

KiDispatchException是Windows系统分发异常的一个枢纽,Windows下的异常分为两个异常分发(图中为伪代码),if(FirstChance)表示第一轮的异常分发,第一轮的分发,它的分发顺序是什么呢,它里面有个判断:
if(PsGetCurrentProcess()->DebugPort==0)如果当前的调试端口为空,调试端口是支持用户态调试的,调试端口为空,表示当前进程不再被用户态调试,就是说没有用户态调试器,没有用到用户态调试器的时候这里会有一个判断,意思是说:要不要把这个异常分发给内核调试器(如下图所示)
image.png

某些时候,没有用户态调试器,但是整个系统有内核调试器,内核调试器有时候会用来调试特殊的用户态问题!这个时候就分发给内核调试器就是有价值的,
image.png

如果当前这个用户态异常,对应的这个进程,没有用户态调试器的时候,会考虑分给内核调试器的!
image.png

break的意思是说,在整个分发异常过程中,如果一个人处理了,其他人就不分发了!如果KD(内核调试器)处理了这个异常,这里一break,那就结束这个异常分发了!如果KD不分发这个异常,那就继续往下分,那就是著名的DbgkForwardException,这个是分发给用户态调试子系统,DbgkForwardException是内核里面支持用户态调试的内核函数,FirstChance表示第一轮分发!
如果第一轮调试器handle了,就return !异常分发的总的原则是一轮一轮的询问,如果有人说处理了,那么就不再分发!假设有调试器的情况下,调试器对于第一轮异常,会判断,对于int 3这样的调试异常,是专门给调试器的,调试器就会handle掉,直接return,第一轮就分发好了;
如果是应用程序的问题,调试器具有一定的灵活性,可以断下来,也可以不断下来!调试器可以设置,对于Visio Studio,对于C++异常,它可能在第一轮收到会收到通知,但是它不处理,因为应用程序它可能自己throw,自己catch,这时候就会向下执行的时候呢,简单理解:它就会把这个异常信息复制到用户态,
然后交给用户态的函数继续分发(见下图),这里是把异常的上下文和异常的记录拷贝到用户态的栈,把著名的陷阱帧里面的Eip改掉,改成用户态函数KeUserExceptionDispatcher(Ntdlll里面的),整个作用就是把陷阱帧里的程序指针(Eip)改掉,等一下异常返回的时候,CPU就会返回到KeUserExceptionDispatcher这个地址,即异常返回,CPU就飞到KeUserExceptionDispatcher这里,从内核态飞到用户态,飞到用户态的这个位置继续分发这个异常,

image.png
小结:

对于第一轮异常,先有对内核调试的支持,然后再分给调试器的第一轮,如果调试器对第一轮不处理,如果调试器对第一轮不处理,
if(DbgkForwardException(TrapFrame,DebugEvent,FirstChance)!=0)那边
接着上边:如果调试器对第一轮不处理,那么就分到用户态做第一轮的分发(6'53''),因为整个块都是第一轮if(FirstChance),第一轮:先给内核调试,再给调试器第一轮,最后再复制到用户态(7'03"),复制到用户态,(TrapFrame->Eip = KeUserExceptionDispatcher)复制到用户态这里的第一轮的目的是给大家的那些try...catch异常处理器和向量化异常处理,即应用程序的向量化处理,

image.png

如果第一轮还是没有人处理,那就会下面的第二轮分发,第二轮分发还是先给调试器,而且告诉调试器,这是最后的处理机会,然后再给异常端口(第二个if),异常端口通常是Windows子系统服务进程监视的,异常端口收到之后就会把这个进程杀掉,然后还不处理,就是很特殊的情况,直接调用ZwTerminateProcess();它就会把进程在内核态给悄悄杀掉,
image.png

所以整个用户应用程序的异常分发,先是第一轮,第一轮不处理再第二轮,每一轮都是先给调试器,第一轮的时候,调试器如果不处理,会给应用程序自己的处理代码,
image.png

下面是一个小程序抛出的一个c++异常:
image.png

这个c++异常,我们的编译器会把它翻译成vc_throw这样的一个特殊函数,
这个特殊函数内部再调用_CxxThrowException,这个函数内部就会调用kernel32!RaiseException,这个API就会继续调用系统调用,进入到内核里面去了,就进入到内核栈(内核之旅将不会被看到),进入内核态,走我们刚才讲的内核分发函数转了一圈之后,内核调试器不处理,用户态调试器对第一轮也不处理,然后call到用户态,把异常信息复制到用户态,程序指针指到ntdll!KiUserExceptionDispatcher(用户态的分发函数),开始用户态分发,用户态分发的时候,会找应用程序里的程序处理器,找到异常处理器之后,就开始Execute这些handler(就是ntdll!ExecuteHandler),这些handler通常是我们try......catch......;try......except......写的这些handler,图中正在执行c++的异常处理函数过程;
怎么找到异常处理器呢,这就是著名的结构化异常处理器Fs:[0]链条;
image.png

在Windows中的每个线程,都有这样一个特殊的链条,FS:[0]这样的一个特殊的段寄存器指向的线程信息块(TEB)(这个特殊的数据结构),偏移0的地方,指向的是这样的一个特殊的链条,这个链条的每个节点,都是异常注册结构,每个异常注册结构,指向一个handler函数,再指向自己的前项指针,可以想象,发生异常的时候,看下面一个演示:
image.png

try中的代码可能发生异常,发生异常的过程中,就会评估过滤表达式,过滤表达式的值决定要不要处理异常处理块,过滤表达式的返回值,一般为下面三个值:
image.png

`

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容