加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

异常 – Windows:避免在堆栈上推送完整的x86上下文

发布时间:2020-12-13 20:11:46 所属栏目:Windows 来源:网络整理
导读:我实现了 PARLANSE,一种使用仙人掌堆栈实现并行程序的MS Windows下的语言.堆栈块按功能分配 基础和正确的大小来处理局部变量, 表达式temp推/弹出,并调用库(包括 堆栈空间用于库程序工作).这样的堆栈 帧实际上可以小到32字节,通常是. 这一切都很好,除非代码做
我实现了 PARLANSE,一种使用仙人掌堆栈实现并行程序的MS Windows下的语言.堆栈块按功能分配
基础和正确的大小来处理局部变量,
表达式temp推/弹出,并调用库(包括
堆栈空间用于库程序工作).这样的堆栈
帧实际上可以小到32字节,通常是.

这一切都很好,除非代码做愚蠢的事情
导致硬件陷阱… Windows出现在哪个位置
坚持将整个x86机器上下文“堆叠”.
如果您包含FP / MMX /等等,这是大约500字节.寄存器,
它是做什么的.自然地,一个500字节的推送在一个32字节堆栈
粉碎不应该的东西. (硬件推几句话
在陷阱上,但不是整个上下文).

[EDIT 11/27/2012:见this for measured details on the rediculous
amount of stack Windows actually pushes]

我可以让Windows存储异常上下文块
别的地方(例如,到线程特有的位置)?
那么软件可能会出现异常
打到线程并处理它,而不会溢出我的
小堆栈框架.

我不认为这是可能的,但我以为我会问一个更大的
听众.是否有操作系统标准的通话/接口
那可能会导致这种情况发生?

在操作系统中做这件事情是微不足道的,如果我可以让MS让我的
过程可选地定义上下文存储位置“contextp”,其中
被初始化为默认启用当前的旧版行为.
然后替换中断/陷阱向量代码:

hardwareint:   push  context
                mov   contextp,esp

…与…

hardwareint:  mov <somereg> contextp
                test <somereg>
                jnz  $2
                push  context
                mov   contextp,esp
                jmp $1 
         $2:    store context @ somereg
         $1:    equ   *

保存somereg等所需的明显变化等

[我现在做的是:检查每个功能的生成代码.
如果它有机会产生陷阱(例如除以零),
或者我们正在调试(可能的坏指针deref等),添加
足够的空间到FP框架的堆栈框架.堆叠帧
现在最终是~~ 500-1000字节的大小,程序不能
到目前为止,这有时是一个真正的问题
我们正在写的应用程序.所以我们有一个可行的解决方案,
但它使调试变得复杂]

编辑8月25日:我设法将这个故事告诉了微软的内部工程师
谁具有权威性,以确定谁可能实际上是谁
关心.解决方案可能会有微弱的希望.

编辑9月14日:MS Kernal集团建筑师听到这个故事,并且是同情的.他表示,MS会考虑一个解决方案(如所提出的解决方案),但不太可能在服务包中.可能要等待下一个版本的Windows. (叹…我可能长大了…)

编辑:2010年9月13日(1年后).没有微软的行动.我最新的噩梦:在Windows X64上执行32位进程的陷阱,在中断处理程序伪造32位上下文之前,将整个X64上下文推送到堆栈上?那会更大(两倍于整数寄存器的两倍,是SSE寄存器的两倍)?

编辑:2012年2月25日(1.5年过去了)…对微软没有反应.我猜他们只是不在乎我的并行性.我认为这是对社会的一种伤害; MS在正常情况下使用的“大堆栈模型”通过吃大量虚拟机限制了任何时刻可以存在的并行计算量. PARLANSE模式将让人们在各种运行/等待状态下拥有一百万个活的“谷物”应用程序;这真的发生在我们的一些应用程序中,并行处理了1亿个节点图. PARLANSE方案可以实现大约1Gb的RAM,这是非常易于管理的.如果您尝试使用MS 1Mb“大堆栈”,则需要10 ^ 12个字节的虚拟机只适用于堆栈空间,我非常确定Windows不会让您管理一百万个线程.

编辑:2014年4月29日(4年过去了).我猜MS只是不读SO.我已经在PARLANSE上做了足够的工程,所以我们只需要在调试过程中支付大堆栈帧的价格,或者在进行FP操作时,我们设法找到了非常实用的方法. MS持续令人失望;各种版本的Windows推送在堆栈上的东西的数量似乎差异很大,非常高于和超出了对硬件上下文的需求.有一些提示,一些这种变异性是由非MS产品(例如防病毒)在异常处理链中粘住鼻子引起的;为什么他们不能从我的地址空间外面呢?不管怎样,我们通过简单地为FP /调试陷阱添加一个大的斜率因子来处理所有这些,并等待超出该数量的字段中不可避免的MS系统.

基本上,您需要重新实现许多中断处理程序,即将自己挂接到中断描述符表(IDT)中.
问题是,您还需要重新实现一个内核模式 – > usermode回调(对于SEH这个回调驻留在ntdll.dll中,被命名为KiuserExceptionDispatcher,这将触发所有的SEH逻辑).关键是,系统的其余部分依赖于SEH的工作方式,现在,您的解决方案会破坏事情,因为你正在做系统的.也许你可以在中断时检查你在哪个进程.
但是,整体概念容易出错,非常严重影响系统的稳定性.
这些实际上是rootkit的技术.

编辑:一些更多的细节:你需要重新实现中断处理程序的原因是,例外(例如除以零)本质上是软件中断,并且总是通过IDT.当抛出异常时,内核收集上下文并将异常发送回usermode(通过上述的ntdll中的KiUserExceptionDispatcher).您需要在此处进行干预,因此您还需要提供一种恢复用户模式的机制. (在ntdll中有一个函数用作内核模式的入口点 – 我不记得名字,但它的名字与KiUserACP …..)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读