在64位OS X应用程序中处理mach异常

Bra*_*d S 15 macos darwin osx-snow-leopard

我已经能够注册我自己的机器端口以捕获我的应用程序中的机器异常,并且当我以32位为目标时它可以很好地工作.但是,当我以64位为目标时,我的异常处理程序catch_exception_raise()被调用,但传递给处理程序的异常代码数组是32位宽.预计这是32位版本,但不是64位版本.

在我捕获EXC_BAD_ACCESS第一个代码的情况下是错误号,第二个代码应该是错误的地址.由于第二个代码是32位宽,因此64位错误地址的高32位被截断.

我发现了一个标志<mach/exception_types.h>,我可以在通task_set_exception_ports()称为MACH_EXCEPTION_CODES从看达尔文源似乎控制传递给处理程序代码的大小.它似乎意味着要传递给传入的行为task_set_exception_ports().

但是,当我执行此操作并触发异常时,我的机器端口会收到通知,我调用exc_server()但我的处理程序永远不会被调用,并且当回复消息被发送回内核时,我得到默认的异常行为.

我的目标是10.6 SDK.

我真的希望苹果能更好地记录这些东西.有人有主意吗?

Bra*_*d S 16

好吧,我明白了.

要处理mach异常,你必须为你感兴趣的异常注册一个mach端口.然后等待消息到达另一个线程的端口.当消息到达时,您调用exc_server()System.library提供的实现.exec_server()获取到达的消息并调用您必须提供的三个处理程序之一.catch_exception_raise(),, catch_exception_raise_state()catch_exception_raise_state_identity()取决于您传递给的参数task_set_exception_ports().这就是32位应用程序的完成方式.

对于64位应用程序,32位方法仍然有效,但处理程序中传递给您的数据可能会被截断为32位.要将64位数据传递给您的处理程序,需要一些额外的工作,这不是很直接,据我所知,没有很好的记录.我通过查看GDB的来源偶然发现了解决方案.

而不是exc_server()在消息到达端口时调用,mach_exc_server()而是必须调用.该处理器还必须有不同的名称,以及catch_mach_exception_raise(),catch_mach_exception_raise_state()catch_mach_exception_raise_state_identity().处理程序的参数与32位对应的参数相同.问题是mach_exc_server()没有为您提供方式exc_server().要获得实现,mach_exc_server()需要使用MIG(Mach Interface Generator)实用程序.MIG接受一个接口定义文件,并生成一组源文件,其中包含一个服务器函数,用于将mach消息分派给您提供的处理程序.10.5和10.6 SDK包含用于异常消息的MIG定义文件<mach_exc.defs>,并将生成该mach_exc_server()函数.然后,将生成的源文件包含在项目中,然后就可以了.

好消息是,如果您的目标是10.6+(可能是10.5),则可以对32位和64位使用相同的异常处理.在MACH_EXCEPTION_CODES设置异常端口时,只是OR异常行为.异常代码将以64位值的形式出现,但您可以在32位构建中将它们截断为32位.

我拿起mach_exc.defs文件并将其复制到我的源目录,打开终端并使用该命令mig -v mach_exc.defs.这产生的mach_exc.h,mach_excServer.cmach_excUser.c.然后我将这些文件包含在我的项目中,在源文件中添加了服务器函数的正确声明并实现了我的处理程序.然后,我构建了我的应用程序,很高兴.

嗯,这不是最好的描述,但希望它可以帮助其他人.