Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 如何使lldb忽略EXC\u BAD\u访问异常?_Macos_Signals_Lldb - Fatal编程技术网

Macos 如何使lldb忽略EXC\u BAD\u访问异常?

Macos 如何使lldb忽略EXC\u BAD\u访问异常?,macos,signals,lldb,Macos,Signals,Lldb,我正在MacOSX上根据sigaction/sa_处理器机制编写一个程序。从用户处运行代码片段,随时准备捕获信号/异常。该程序运行良好,但问题是我无法用lldb调试它。lldb似乎无法忽略任何异常,即使我设置了 proc hand -p true -s false SIGSEGV proc hand -p true -s false SIGBUS 控制流在触发异常的指令处停止,即使我尝试了命令c,也不会跳转到我之前安装的sa_处理程序。结果是: Process 764 stopped * t

我正在MacOSX上根据sigaction/sa_处理器机制编写一个程序。从用户处运行代码片段,随时准备捕获信号/异常。该程序运行良好,但问题是我无法用lldb调试它。lldb似乎无法忽略任何异常,即使我设置了

proc hand -p true -s false SIGSEGV 
proc hand -p true -s false SIGBUS
控制流在触发异常的指令处停止,即使我尝试了命令
c
,也不会跳转到我之前安装的sa_处理程序。结果是:

Process 764 stopped
* thread #2: tid = 0xf140, 0x00000001000b8000, stop reason = EXC_BAD_ACCESS (code=2, address=0x1000b8000)
如何使lldb忽略异常/信号,并让程序的sa_处理程序执行其工作

编辑:示例代码

#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;
}
#包括
#包括
#包括
#包括
#包括
静态void处理程序(int-signo、siginfo\u t*sigaction、void*context)
{
printf(“在处理程序中。\n”);
信号(signo、SIG_DFL);
}
静态无效gen_异常()
{
printf(“gen_异常在。\n”);
*(int*)0=0;
printf(“gen_异常输出。\n”);
}
void*gen\u异常螺纹(void*parg)
{
gen_异常();
返回0;
}
int main()
{
struct-sigaction-sa;
sa.sa_sigaction=handler;
sigemptyset(和sa.sa_面具);
sa.sa_flags=sa_SIGINFO;
if(sigaction(/*SIGBUS*/SIGSEGV,&sa,NULL)=-1){
printf(“sigaction失败。\n”);
返回0;
}
pthread_t id;
pthread_create(&id,NULL,gen_exception_thread,NULL);
pthread_join(id,NULL);
返回0;
}

一点示例代码可以让这样的问题更容易回答。。。我以前从未使用过
sigaction
API,但我把它放在了一起-

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

void segv_handler (int in)
{
    puts ("in segv_handler()");
}

void sigbus_handler (int in)
{
    puts ("in sigbus_handler()");
}

int main ()
{
    struct sigaction action;
    action.sa_mask = 0;
    action.sa_flags = 0;


    action.sa_handler = segv_handler;
    sigaction (SIGSEGV, &action, NULL);
    action.sa_handler = sigbus_handler;
    sigaction (SIGBUS, &action, NULL);

    puts ("about to send SIGSEGV signal from main()");
    kill (getpid(), SIGSEGV);

    puts ("about to send SIGBUS signal from main()");
    kill (getpid(), SIGBUS);

    puts ("exiting main()");

}


% lldb a.out
(lldb) br s -n main
(lldb) r
(lldb) pr h -p true -s false SIGSEGV SIGBUS
(lldb) c
Process 54743 resuming
about to send SIGSEGV signal from main()
Process 54743 stopped and restarted: thread 1 received signal: SIGSEGV
in segv_handler()
about to send SIGBUS signal from main()
Process 54743 stopped and restarted: thread 1 received signal: SIGBUS
in sigbus_handler()
exiting main()
Process 54743 exited with status = 0 (0x00000000) 
(lldb) 
#包括
#包括
#包括
无效segv_处理程序(整数英寸)
{
放入(“在segv_handler()中”);
}
无效sigbus_处理程序(int-in)
{
puts(“在sigbus_handler()中”);
}
int main()
{
结构动作;
action.sa_mask=0;
action.sa_标志=0;
action.sa_handler=segv_handler;
sigaction(SIGSEGV,&action,NULL);
action.sa_handler=sigbus_handler;
sigaction(SIGBUS,&action,NULL);
puts(“即将从main()发送SIGSEGV信号”);
kill(getpid(),SIGSEGV);
puts(“即将从main()发送SIGBUS信号”);
kill(getpid(),SIGBUS);
卖出(“退出主();
}
%lldb a.out
(lldb)br s-n干管
(lldb)r
(lldb)pr h-p真-s假SIGSEGV SIGBUS
(lldb)c
进程54743恢复
即将从main()发送SIGSEGV信号
进程54743停止并重新启动:线程1收到信号:SIGSEGV
在segv_handler()中
即将从main()发送SIGBUS信号
进程54743停止并重新启动:线程1收到信号:SIGBUS
在sigbus_handler()中
退出main()
进程54743退出,状态为0(0x00000000)
(lldb)
看起来这里一切正常。如果我在
进程句柄
参数中添加了
-n false
,lldb就不会打印有关
进程的行了。。停止并重新启动


请注意,这些信号设置不会在进程执行期间保持不变。因此,如果您正在启动调试会话(
r
一旦您已经启动了一次进程),则需要重新设置这些会话。您可能需要创建一个命令别名快捷方式,并将其放入
~/.lldbinit
文件中,这样您就可以使用一个短cmd来设置处理过程的方式。

这是Mac OS X中调试器界面中的一个长期存在的错误(gdb也有同样的问题…),如果您有一个开发人员帐户,请使用它提交一个错误。很少有人真正使用SIGSEGV处理程序,所以这个问题从未引起内核人员的任何注意,所以更多的bug是好的…

我在最近的一个项目中需要它,所以我只构建了自己的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);

这会导致debugserver无法捕获
EXC\u BAD\u访问
异常。现在,我的自定义LLDB工作得很好:它仍然捕获
SIGSEGV
SIGBUS
,但在面对
EXC\u BAD\u访问时不再进入愚蠢的无限循环。在以前的致命信号上设置
processhandle
选项也很好,现在我可以调试SEGV处理程序而不受惩罚


苹果真的应该在LLDB中选择这个选项……对他们来说似乎是一个非常简单的解决方案。

我们可以很容易地做到。只需添加此代码

#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>

int ret = task_set_exception_ports(
                                   mach_task_self(),
                                   EXC_MASK_BAD_ACCESS,
                                   MACH_PORT_NULL,//m_exception_port,
                                   EXCEPTION_DEFAULT,
                                   0);

完整代码:

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

#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.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()
{
    task_set_exception_ports(
                             mach_task_self(),
                             EXC_MASK_BAD_ACCESS,
                             MACH_PORT_NULL,//m_exception_port,
                             EXCEPTION_DEFAULT,
                             0);
    
    
    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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态void处理程序(int-signo、siginfo\u t*sigaction、void*context)
{
printf(“在处理程序中。\n”);
信号(signo、SIG_DFL);
}
静态无效gen_异常()
{
printf(“gen_异常在。\n”);
*(int*)0=0;
printf(“gen_异常输出。\n”);
}
void*gen\u异常螺纹(void*parg)
{
gen_异常();
返回0;
}
int main()
{
任务\u设置\u异常\u端口(
mach_task_self(),
EXC\u屏蔽\u不良访问,
MACH\u PORT\u NULL,//m\u exception\u PORT,
默认情况下的例外情况,
0);
struct-sigaction-sa;
sa.sa_sigaction=handler;
sigemptyset(和sa.sa_面具);
sa.sa_flags=sa_SIGINFO;
if(sigaction(/*SIGBUS*/SIGSEGV,&sa,NULL)=-1){
printf(“sigaction失败。\n”);
返回0;
}
pthread_t id;
pthread_create(&id,NULL,gen_exception_thread,NULL);
pthread_join(id,NULL);
返回0;
}

请参阅(中文文章):

嗨,吉姆:我注意到你评论说“要做到这一点,最直接的方法是调试器以root用户身份运行”。在OSX上,我可以以root用户身份运行调试器(我知道错误报告是关于iOS的,这是不可能的)。如果调试器以root用户身份运行,我有没有办法修补LLDB以允许它忽略EXC_BAD_访问?*field*@jim ingham您能详细说明一下“实现这一点的直接方法要求调试器以root用户身份运行”吗?假设用户可以以root用户身份运行gdb
proc hand -p true -s false SIGSEGV 
proc hand -p true -s false SIGBUS
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.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()
{
    task_set_exception_ports(
                             mach_task_self(),
                             EXC_MASK_BAD_ACCESS,
                             MACH_PORT_NULL,//m_exception_port,
                             EXCEPTION_DEFAULT,
                             0);
    
    
    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;
}