[lldb-dev] LLDB blocks progress of program that handles SIGSEGV
Eugene Birukov
eugenebi at hotmail.com
Tue May 19 09:22:11 PDT 2015
Pavel,
Thanks for reply. You are right, it is reported as exception, here is the portion of MonitorSignal routine on Linux:
case SIGSEGV:
case SIGILL:
case SIGFPE:
case SIGBUS:
if (thread_sp)
std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetCrashedWithException (*info);
break;
default:
// This is just a pre-signal-delivery notification of the incoming signal.
if (thread_sp)
std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedBySignal (signo);
I have no knowledge about LLGS (yet :)) but I'd vote for the second way: current LLDB behavior makes total sense for a "normal" application which is not in the business of managing its address space. The same applies to illegal instruction - the program could be self-modifying (say, JIT compiling). Exceptions are signals on Unix from the day one and we'd better not meddle with this long-established abstraction.
I think we also need to give the choice to the developer during interactive debugging: i.e. "continue" command better have a flag that tells if to pass signal to the application or not.
Thanks,
Eugene
> From: labath at google.com
> Date: Tue, 19 May 2015 11:35:32 +0100
> Subject: Re: [lldb-dev] LLDB blocks progress of program that handles SIGSEGV
> To: eugenebi at hotmail.com
> CC: lldb-dev at cs.uiuc.edu
>
> Hello Eugene,
>
> thanks for the report. What you are describing sounds like a genuine
> LLDB problem. I have created a bug
> <https://llvm.org/bugs/show_bug.cgi?id=23571> so we don't forget about
> this. It looks like LLGS (server component of lldb) is reporting this
> segfault to LLDB as an "exception" rather than a signal
> (reason:expection in the stop-reply packet). This causes LLDB to not
> reinject the signal when continuing the inferior. Now there are two
> places we can fix this:
> - have LLGS report this event as a signal. Then LLDB should be able to
> reinject the signal correctly.
> - teach LLDB to reinject the signal even in when the stop was reported
> as an exception.
>
> I'm inclined to do the first thing but I am not sure. Could somebody
> with more LLDB knowledge shed some light on this? What is the intended
> usage/behavior in case LLGS reports reason:exception?
>
> cheers,
> pl
>
>
>
> On 18 May 2015 at 18:27, Eugene Birukov <eugenebi at hotmail.com> wrote:
> > Hello,
> >
> > I am running Linux Ubuntu 14.04 and I tried both LLDB-3.6 (installed
> > binaries using apt-get) and LLDB-3.7 (built from sources sync'ed to trunk),
> > the result is the same.
> >
> > I have a simple program (the source code is at the bottom of the message)
> > that maps a page of memory as not accessible, installs a SIGSEGV handler
> > that remaps this page as read-write, and then tries to read from it. So, the
> > expected result is that program initially receives SIGSEGV but happily
> > continues after the handler fixes the problem.
> >
> > The program runs as expected, both standalone and under GDB:
> >
> >
> > $ ./mm
> > signal 11 received
> > success 777
> >
> >
> > $ gdb --quiet ./mm
> > Reading symbols from ./mm...done.
> > (gdb) r
> > Starting program: /home/eugene/tmp/mm
> > Program received signal SIGSEGV, Segmentation fault.
> > 0x0000000000400acc in main () at mm.cpp:27
> > 27 int x = *(int*)address;
> > (gdb) c
> > Continuing.
> > signal 11 received
> > success 777
> > [Inferior 1 (process 14155) exited normally]
> > (gdb) q
> >
> > But under LLDB it spins forever on failing instruction without invoking the
> > signal handler. Also, setting "process handle" does not have any effect at
> > all:
> >
> >
> > $ ~/llvm/bin/lldb ./mm
> > (lldb) target create "./mm"
> > Current executable set to './mm' (x86_64).
> > (lldb) br se -b main
> > Breakpoint 1: where = mm`main + 30 at mm.cpp:24, address =
> > 0x0000000000400a7e
> > (lldb) pr lau
> > Process 14194 launched: './mm' (x86_64)
> > Process 14194 stopped
> > * thread #1: tid = 14194, 0x0000000000400a7e mm`main + 30 at mm.cpp:24, name
> > = 'mm', stop reason = breakpoint 1.1
> > frame #0: 0x0000000000400a7e mm`main + 30 at mm.cpp:24
> > 21
> > 22 int main()
> > 23 {
> > -> 24 sigset(SIGSEGV, handler);
> > 25
> > 26 address = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS |
> > MAP_PRIVATE, -1, 0);
> > 27 int x = *(int*)address;
> > (lldb) pr ha SIGSEGV -s false -p true -n false
> > NAME PASS STOP NOTIFY
> > ========== ===== ===== ======
> > SIGSEGV true false false
> > (lldb) c
> > Process 14194 resuming
> > Process 14194 stopped
> > * thread #1: tid = 14194, 0x0000000000400acc mm`main + 108 at mm.cpp:27,
> > name = 'mm', stop reason = address access protected (fault address:
> > 0x7ffff7ff7000)
> > frame #0: 0x0000000000400acc mm`main + 108 at mm.cpp:27
> > 24 sigset(SIGSEGV, handler);
> > 25
> > 26 address = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS |
> > MAP_PRIVATE, -1, 0);
> > -> 27 int x = *(int*)address;
> > 28 std::cout << (signaled ? "success " : "failure ") << x << "\n";
> > 29 }
> > (lldb) c
> > Process 14194 resuming
> > Process 14194 stopped
> > * thread #1: tid = 14194, 0x0000000000400acc mm`main + 108 at mm.cpp:27,
> > name = 'mm', stop reason = address access protected (fault address:
> > 0x7ffff7ff7000)
> > frame #0: 0x0000000000400acc mm`main + 108 at mm.cpp:27
> > 24 sigset(SIGSEGV, handler);
> > 25
> > 26 address = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS |
> > MAP_PRIVATE, -1, 0);
> > -> 27 int x = *(int*)address;
> > 28 std::cout << (signaled ? "success " : "failure ") << x << "\n";
> > 29 }
> > (lldb) c
> > Process 14194 resuming
> > Process 14194 stopped
> > * thread #1: tid = 14194, 0x0000000000400acc mm`main + 108 at mm.cpp:27,
> > name = 'mm', stop reason = address access protected (fault address:
> > 0x7ffff7ff7000)
> > frame #0: 0x0000000000400acc mm`main + 108 at mm.cpp:27
> > 24 sigset(SIGSEGV, handler);
> > 25
> > 26 address = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS |
> > MAP_PRIVATE, -1, 0);
> > -> 27 int x = *(int*)address;
> > 28 std::cout << (signaled ? "success " : "failure ") << x << "\n";
> > 29 }
> > (lldb)
> >
> > So, do I miss some LLDB setting?
> > Here is the program code:
> >
> >
> > $ cat mm.cpp
> > #include <iostream>
> > #include <sys/mman.h>
> > #include <signal.h>
> > #include <assert.h>
> > #include <sys/types.h>
> > #include <unistd.h>
> >
> > void* address;
> > size_t size = 0x1000;
> > bool signaled = false;
> >
> > void handler(int sig)
> > {
> > std::cout << "signal " << sig << " received\n";
> > signaled = true;
> > munmap(address, size);
> > void* newaddr = mmap(address, size, PROT_READ | PROT_WRITE,
> > MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0);
> > assert(newaddr == address);
> > *(int*)newaddr = 777;
> > }
> >
> > int main()
> > {
> > sigset(SIGSEGV, handler);
> > address = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1,
> > 0);
> > int x = *(int*)address;
> > std::cout << (signaled ? "success " : "failure ") << x << "\n";
> > }
> > $
> >
> > Thanks,
> > Eugene
> >
> >
> >
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> >
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150519/668f4b46/attachment.html>
More information about the lldb-dev
mailing list