如何使lldb忽略EXC_BAD_ACCESS异常?

jay*_*jay 5 macos signals lldb

我根据sigaction / sa_handler机制在Mac OSX上编写程序。运行用户的代码段,并随时准备捕获信号/异常。该程序工作正常,但问题是我无法使用lldb对其进行调试。lldb似乎无法忽略任何异常,即使我设置了

proc hand -p true -s false SIGSEGV 
proc hand -p true -s false SIGBUS
Run Code Online (Sandbox Code Playgroud)

控制流在触发异常的指令处停止,即使我尝试使用command,也不会跳转到我先前安装的sa_handler c。输出为:

Process 764 stopped
* thread #2: tid = 0xf140, 0x00000001000b8000, stop reason = EXC_BAD_ACCESS (code=2, address=0x1000b8000)
Run Code Online (Sandbox Code Playgroud)

如何使lldb忽略异常/信号,并让程序的sa_handler执行其工作?

编辑:示例代码

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

static void handler(int signo, siginfo_t *sigaction, void *context)
{
    printf("in handler.\n");
    signal(signo, SIG_DFL);
}

static void gen_exception()
{
    printf("gen_exception in.\n");
    *(int *)0 = 0;
    printf("gen_exception out.\n");
}

void *gen_exception_thread(void *parg)
{
    gen_exception();
    return 0;
}

int main()
{
    struct sigaction sa;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;

    if(sigaction(/*SIGBUS*/SIGSEGV, &sa, NULL) == -1) {
        printf("sigaction fails.\n");
        return 0;
    }

    pthread_t id;
    pthread_create(&id, NULL, gen_exception_thread, NULL);
    pthread_join(id, NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*ham 5

这是 Mac OS X 中调试器界面中的一个长期存在的错误(gdb 有同样的问题...)如果您有开发者帐户,请向http://bugreport.apple.com提交错误。很少有人真正使用 SIGSEGV 处理程序,以至于这个问题从未得到内核人员的任何关注,所以更多的错误是好的......

  • 嗨,吉姆:我注意到您对 [这个 LLDB 错误报告](https://llvm.org/bugs/show_bug.cgi?id=22868) 发表了评论,“执行此操作的直接方法要求调试器按以下方式运行根”。在 OS X 上,我完全可以以 root 身份运行调试器(我知道错误报告是关于 iOS 的,这是不可能的)。如果调试器以 root 身份运行,有什么方法可以修补 LLDB 以允许它忽略 EXC_BAD_ACCESS 吗? (2认同)

nne*_*neo 5

我在最近的一个项目中需要这个,所以我刚刚构建了自己的 LLDB。我tools/debugserver/source/MacOSX/MachTask.mm

err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
Run Code Online (Sandbox Code Playgroud)

err = ::task_set_exception_ports (task, m_exc_port_info.mask & ~EXC_MASK_BAD_ACCESS, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
Run Code Online (Sandbox Code Playgroud)

这导致调试服务器无法捕获EXC_BAD_ACCESS异常。现在,我的自定义 LLDB 工作得很好:它仍然可以捕获SIGSEGVSIGBUS但在遇到EXC_BAD_ACCESS. process handle在以前的致命信号上设置选项也很好用,我现在可以不受惩罚地调试 SEGV 处理程序。

Apple 真的应该在 LLDB 中将此作为一个选项......对他们来说似乎是一个非常简单的解决方案。

  • LLDB 是开源的,所以我[下载了源代码](http://lldb.llvm.org/source.html),在那里制作了必要的补丁,并编译了它。 (3认同)