SEH(结构化异常处理)机制究竟如何在ARM上运行?

时间:2014-07-04 16:15:23

标签: c++ exception arm windows-ce

我了解一般概述:http://msdn.microsoft.com/en-us/library/dn743843.aspx;关于win32中的异常机制和win64中的一些异常机制有很多可用的信息,但ARM并不是那么清楚。

我想知道:当生成机器异常(内存保护违规)时,完全控制权转移到哪里(所以我可以设置断点)?它是否转移到内核模式?据推测,它从向量表中查找处理程序的地址并在那里进行传输。 内核代码是执行SEH展开,还是在用户模式下完成展开?如果在用户模式下,确切地说 - .exe,coredll或其他地方的一部分?

背景

我们有一个大型应用程序,它将__try / __except处理程序放在每个线程的顶层,以便以信息方式记录崩溃。多年来,这在MIPS上运行良好。我们现在将它移植到ARM上的WinCE 7,在VS2008下构建。我们发现在发布版本中有时无法正确处理异常。这似乎取决于代码中生成异常的确切位置(我有一个测试函数,故意访问NULL指针以引发SEH异常,我从代码中的不同位置调用它)。

我们正在使用/ EHsc选项启用SEH。发布版本使用/ O2 / Os;删除/ O2使其工作但速度明显变慢。这让我相信优化器正在删除SEH工作所需的东西 - 但具体到底是什么?并非所有功能都具有" mov r12,sp ..."序幕,但有些人仍然无法正常工作。这是PDATA中的一些错误吗? PDATA条目的数量是否有上限? " dumpbin / pdata"的输出是否正常?每行都没有函数名吗?

通过使用调试器(尽管发布版本),我可以在我的异常过滤函数的开头放置一个断点(从__except调用),并观察它在故障情况下永远不会输入。该计划刚刚退出。

4 个答案:

答案 0 :(得分:1)

  

我们正在使用/ EHsc选项启用SEH

您应该将/EHa与SEH一起使用。 /EHsc允许编译器优化掉所有异常处理逻辑,如果它可以证明在块内不会到达C ++ throw语句。

结构化异常处理__try__except甚至可以与/EHsc一起使用,但是C ++堆栈展开不会发生在结构化异常中。因此,异常后全局状态可能不一致,这可能导致处理程序失败。

答案 1 :(得分:1)

我不熟悉低级内核细节,但是指向CRT异常处理程序的指针存储在函数之前的dwords中:

0001106C     DCD _C_specific_handler  ; handler function
00011070     DCD _scope_table         ; scope table (__try/__except map)
00011074 start
00011074     MOV             R12, SP

也许把你的断点放在_C_specific_handler上,看看它是否被调用。实际功能是COREDLL。如果它被调用但没有将异常传递给您的代码,可能由于某种原因,范围表信息是错误的。

编辑:以上内容适用于WinCE 6及更早版本。既然你提到VS2008,我很确定WinCE 7仍然使用相同的异常处理模型。您提到的链接(基于代码的展开)适用于新的仅ARMv7 WinRT内核(我认为Windows Embedded Compact 2013也使用它)。

答案 2 :(得分:1)

这可能不是您问题的确切答案,但如果您的目标是捕获关键硬件异常并记录其调用堆栈,那么自Windowce CE 6.0起,您可以使用AddVectoredExceptionHandler。在应用程序我工作(vs2005,仅ARM)我能够在这个函数的帮助下获得调用堆栈,你也不需要添加SEH catch / throw,异常处理程序将始终被调用。

答案 3 :(得分:0)

这很容易。键入" ARM ARM"进入你最喜欢的搜索引擎。

较窄的搜索" ARM预取异常"。

实质上,当处理器尝试从未定义的内存区域获取数据时,会生成数据提取异常。处理器将执行转移到称为异常向量的预定义地址。其余的行为取决于程序员或操作系统。例如,在嵌入式系统上,可以调用系统故障功能。在桌面平台上,操作系统会生成信号或异常并终止程序。

其他平台可能具有可以具有围栏的高级内存管理单元(MMU)处理器。当程序访问隔离区域外时,会生成一个例外或中断。该区域将被编程到MMU中。这使得OS能够保护用户程序不应访问的存储器区域,即使存在存储器。

访问程序无权访问的未定义内存或内存区域定义为"未定义的行为"。此行为可能因编译器或平台而异,并且没有标准行为。某些平台可能会生成"信号",其他平台可能会生成"异常&#34 ;,有些平台会传递消息,有些平台会崩溃。如果您想要便携式内存异常处理,则需要编写特定于平台的代码。