【问题标题】:How does OS X generate a crash report?OS X 如何生成崩溃报告?
【发布时间】:2012-03-04 12:05:56
【问题描述】:

可从网络、邮件列表、Mac OS X Internals 等书籍甚至源代码中获得的材料非常有限。

现在我知道 xnu 内核引发了一个 EXC_CRASH,它通知启动以启动“Problem Reporter.app”(之前是 Crash Reporter.app)。这个应用程序是使用一些调试接口来生成崩溃报告,还是内核已经生成了报告并只是通知应用程序打开已经生成的报告?

【问题讨论】:

    标签: macos kernel crash-reports xnu


    【解决方案1】:

    每个 Mach 线程和/或任务(实现 BSD 层进程的底层内核对象)都有异常端口。三个端口级别可用:线程、任务和主机。当发生异常时,会发送一条 Mach 消息 - 首先发送到线程端口,然后 - 如果没有捕获到它 - 任务的 S,最后是主机。如果您获得了端口,您可以捕获异常、调试它(就像 OS X 上的 gdb 一样)或生成故障转储(就像 Crash Reporter 一样)。具体来说,launchd - 所有 OS X 系统任务的父级 - 注册它们的异常端口,因此它获取消息,然后触发 CrashReporter(从 launchd 的 ReportCrash plist 中可以看到:

     <key>MachServices</key>
            <dict>
                    <key>com.apple.ReportCrash.DirectoryService</key>
                    <dict>
                            <key>DrainMessagesOnCrash</key>
                            <string>All</string>
                            <key>ExceptionServer</key>
                            <dict/>
                    </dict>
            </dict>
    

    XNU 内核代码负责在 EXC_CRASH 上发送消息。具体来说,proc_prepareexit 会这样做:

      /* If a core should be generated, notify crash reporter */
            if (hassigprop(WTERMSIG(rv), SA_CORE) || ((p->p_csflags & CS_KILLED) != 0)) {
                    /* 
                     * Workaround for processes checking up on PT_DENY_ATTACH:
                     * should be backed out post-Leopard (details in 5431025).
                     */
                    if ((SIGSEGV == WTERMSIG(rv)) && 
                                    (p->p_pptr->p_lflag & P_LNOATTACH)) {
                            goto skipcheck;
                    }
    
                    /*
                     * Crash Reporter looks for the signal value, original exception
                     * type, and low 20 bits of the original code in code[0] 
                     * (8, 4, and 20 bits respectively). code[1] is unmodified. 
                     */
                    code = ((WTERMSIG(rv) & 0xff) << 24) |
                            ((ut->uu_exception & 0x0f) << 20) | 
                            ((int)ut->uu_code & 0xfffff);
                    subcode = ut->uu_subcode;
                    (void) task_exception_notify(EXC_CRASH, code, subcode); // <-- Sends the msg
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多