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

Ira*_*ter 13 stack-overflow assembly exception cpu-registers threadcontext

我已经实现了PARLANSE,这是MS Windows下的一种语言,它使用cactus栈来实现并行程序.堆栈块被分配在每个功能的基础上,并处理局部变量的大小合适,表达温度推/持久性有机污染物,并调用库(包括存储库程序工作在堆栈空间).在实践中,这样的堆栈帧可以小到32个字节,并且通常是这样.

这一切都很有效,除非代码做了一些愚蠢的事情并导致硬件陷阱......此时Windows似乎坚持在堆栈上推送整个x86机器上下文.如果包含FP/MMX /等,则大约500多个字节.寄存器,它做的.当然,32字节堆栈上的500字节推送会破坏它不应该的东西.(硬件在陷阱上推了几个字,但不是整个上下文).

[编辑2012年11月27日:请参阅测量的细节上堆叠的荒谬量Windows实际上推动 ]

我可以让Windows在其他地方存储异常上下文块(例如,到特定于线程的位置)吗?然后软件可以对线程进行异常命中并处理它而不会溢出我的小堆栈帧.

我不认为这是可能的,但我想我会问更多的观众.是否有OS标准调用/接口可能导致这种情况发生?

如果我可以让MS让我的进程可选地定义一个上下文存储位置"contextp",那么在操作系统中这样做是微不足道的,这个位置被初始化以默认启用当前的遗留行为.然后替换中断/陷阱向量代码:

  hardwareint:   push  context
                mov   contextp, esp
Run Code Online (Sandbox Code Playgroud)

...... ......

  hardwareint:  mov <somereg> contextp
                test <somereg>
                jnz  $2
                push  context
                mov   contextp, esp
                jmp $1 
         $2:    store context @ somereg
         $1:    equ   *
Run Code Online (Sandbox Code Playgroud)

保存somereg等所需的明显变化

[我现在做的是:检查每个函数的生成代码.如果它有可能生成陷阱(例如,除以零),或者我们正在调试(可能是坏指针deref等),请为FP上下文添加足够的空间到堆栈帧.堆栈帧现在最终大小约为500-1000字节,程序无法递归到目前为止,这对我们正在编写的应用程序来说有时是一个真正的问题.所以我们有一个可行的解决方案,但它使调试变得复杂]

编辑8月25日:我已经成功地将这个故事告诉了一位微软的内部工程师,他有权明确地找出MS中谁可能真正关心的人.解决方案可能有微弱的希望.

编辑9月14日:MS Kernal Group Architect听过这个故事并且很有同情心.他说MS将考虑一个解决方案(如提议的解决方案),但不太可能在服务包中.可能必须等待下一版本的Windows.(叹气......我可能会变老......)

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

编辑:2012年2月25日:( 1.5年过去了......)微软没有反应.我猜他们只是不关心我的并行性.我认为这对社区不利; MS在正常情况下使用的"大堆栈模型"限制了通过食用大量VM可以在任何一个瞬间生存的并行计算量.PARLANSE模型将允许一个应用程序在运行/等待的各种状态下具有一百万个活"谷粒"; 这在我们的一些应用程序中确实发生,其中"并行"处理了1亿个节点图.PARLANSE方案可以使用大约1Gb的RAM来实现这一点,这是非常易于管理的.如果您尝试使用MS 1Mb"大堆栈",那么您只需要10 ^ 12个字节的VM用于堆栈空间,我非常确定Windows不会让您管理一百万个线程.

编辑:2014年4月29日:( 4年过去了). 我想MS只是不读SO. 我已经在PARLANSE上完成了足够的工程设计,因此我们只需要在调试期间支付大型堆栈帧的价格,或者当FP操作正在进行时,所以我们设法找到非常实用的方法来实现这一点.MS继续令人失望; 各种版本的Windows推送到堆栈上的东西量似乎变化很大,而且非常严重地超出了对硬件环境的需求.有一些暗示,这种可变性是由于非MS产品坚持(例如防病毒)在异常处理链中嗤之以鼻; 为什么他们不能从我的地址空间之外做到这一点?任何,我们通过简单地为FP /调试陷阱添加一个大的slop因子,并等待超过该数量的字段中不可避免的MS系统来处理所有这些.

Mar*_*ort 0

Windows 异常处理称为 SEH。IIRC 您可以禁用它,但您正在使用的语言的运行时可能不喜欢它。