I am writing a program on Mac OSX depending on the sigaction/sa_handler mechanism. Run a code snippet from user and get ready to catch signals/exceptions at any time. The program works fine, but the problem is I can't debug it with lldb. lldb seems not being able to ignore any exceptions even I set
proc hand -p true -s false SIGSEGV
proc hand -p true -s false SIGBUS
The control flow stops at the instruction that triggers the exception and does not jump to the sa_handler I installed earlier even I tried command c
. The output was:
Process 764 stopped
* thread #2: tid = 0xf140, 0x00000001000b8000, stop reason = EXC_BAD_ACCESS (code=2, address=0x1000b8000)
How do I make lldb ignore the exception/signal and let the sa_handler of the program do its work?
EDIT: sample code
#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;
}
I needed this in a recent project, so I just built my own LLDB. I patched a line in tools/debugserver/source/MacOSX/MachTask.mm
from
err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
to
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);
which causes the debugserver to be unable to catch EXC_BAD_ACCESS
exceptions. Now, my custom LLDB works just fine: it still catches SIGSEGV
and SIGBUS
but no longer enters a silly infinite loop when faced with EXC_BAD_ACCESS
. Setting process handle
options on the previously-fatal signals works fine too, and I can now debug SEGV handlers with impunity.
Apple really ought to make this an option in LLDB...seems like a really easy fix for them.
This is a long-standing bug in the debugger interface in Mac OS X (gdb had the same problem...) If you have a developer account, please file a bug with http://bugreport.apple.com. So few people actually use SIGSEGV handlers that the problem never gets any attention from the kernel folks, so more bugs is good...
We can do it easily. Just add this code.
#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);
Don't forget to do this
proc hand -p true -s false SIGSEGV
proc hand -p true -s false SIGBUS
Full code:
#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;
}
Refer to (Chinese article): https://zhuanlan.zhihu.com/p/33542591
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With