[Lldb-commits] [lldb] r228803 - Fix segfault notification in lldb-mi

Ilia K ki.stfu at gmail.com
Tue Feb 10 20:58:42 PST 2015


Author: ki.stfu
Date: Tue Feb 10 22:58:41 2015
New Revision: 228803

URL: http://llvm.org/viewvc/llvm-project?rev=228803&view=rev
Log:
Fix segfault notification in lldb-mi

Summary:
This patch adds system exception handling in lldb-mi + tests.

All tests pass on OS X.

Reviewers: zturner, abidh, clayborg

Reviewed By: clayborg

Subscribers: emaste, lldb-commits, zturner, clayborg, abidh

Differential Revision: http://reviews.llvm.org/D7500

Modified:
    lldb/trunk/test/tools/lldb-mi/TestMiNotification.py
    lldb/trunk/test/tools/lldb-mi/main.c
    lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
    lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h

Modified: lldb/trunk/test/tools/lldb-mi/TestMiNotification.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/TestMiNotification.py?rev=228803&r1=228802&r2=228803&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/TestMiNotification.py (original)
+++ lldb/trunk/test/tools/lldb-mi/TestMiNotification.py Tue Feb 10 22:58:41 2015
@@ -122,5 +122,89 @@ class MiNotificationTestCase(lldbmi_test
             # Clean up
             debugserver_child.terminate(force = True)
 
+    @lldbmi_test
+    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+    def test_lldbmi_stopped_when_segfault_local(self):
+        """Test that 'lldb-mi --interpreter' notifies after it was stopped when segfault occurred (local)."""
+
+        self.spawnLldbMi(args = None)
+
+        # Load executable
+        self.runCmd("-file-exec-and-symbols %s" % self.myexe)
+        self.expect("\^done")
+
+        # Run to main
+        self.runCmd("-break-insert -f main")
+        self.expect("\^done,bkpt={number=\"1\"")
+        self.runCmd("-exec-run")
+        self.expect("\^running")
+        self.expect("\*stopped,reason=\"breakpoint-hit\"")
+
+        # Set dosegfault=1 and run (to cause a segfault error)
+        self.runCmd("-data-evaluate-expression \"dosegfault=1\"")
+        self.expect("\^done,value=\"1\"")
+        self.runCmd("-exec-continue")
+        self.expect("\^running")
+
+        # Test that *stopped is printed
+        self.expect("\*stopped,reason=\"exception-received\",exception=\"EXC_BAD_ACCESS \(code=1, address=0x0\)\",thread-id=\"1\",stopped-threads=\"all\"")
+
+    @lldbmi_test
+    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    def test_lldbmi_stopped_when_segfault_remote(self):
+        """Test that 'lldb-mi --interpreter' notifies after it was stopped when segfault occurred (remote)."""
+
+        # Prepare debugserver
+        import os, sys
+        lldb_gdbserver_folder = os.path.abspath(os.path.join(os.path.dirname(os.getcwd()), "lldb-gdbserver"))
+        sys.path.append(lldb_gdbserver_folder)
+        import lldbgdbserverutils
+        debugserver_exe = lldbgdbserverutils.get_debugserver_exe()
+        if not debugserver_exe:
+            raise Exception("debugserver not found")
+        hostname = "localhost"
+        import random
+        port = 12000 + random.randint(0,3999) # the same as GdbRemoteTestCaseBase.get_next_port
+        import pexpect
+        debugserver_child = pexpect.spawn("%s %s:%d" % (debugserver_exe, hostname, port))
+
+        self.spawnLldbMi(args = None)
+
+        # Connect to debugserver
+        self.runCmd("-interpreter-exec command \"platform select remote-macosx --sysroot /\"")
+        self.expect("\^done")
+        self.runCmd("-file-exec-and-symbols %s" % self.myexe)
+        self.expect("\^done")
+        self.runCmd("-interpreter-exec command \"process connect connect://%s:%d\"" % (hostname, port))
+        self.expect("\^done")
+
+        try:
+            # Run to main
+            self.runCmd("-break-insert -f main")
+            self.expect("\^done,bkpt={number=\"1\"")
+            #FIXME -exec-run doesn't work
+            self.runCmd("-interpreter-exec command \"process launch\"") #FIXME: self.runCmd("-exec-run")
+            self.expect("\^done")                                       #FIXME: self.expect("\^running")
+            self.expect("\*stopped,reason=\"breakpoint-hit\"")
+
+            # Set dosegfault=1 and run (to cause a segfault error)
+            self.runCmd("-data-evaluate-expression \"dosegfault=1\"")
+            self.expect("\^done,value=\"1\"")
+            self.runCmd("-exec-continue")
+            self.expect("\^running")
+
+            # Test that *stopped is printed
+            self.expect("\*stopped,reason=\"exception-received\",exception=\"EXC_BAD_ACCESS \(code=1, address=0x0\)\",thread-id=\"1\",stopped-threads=\"all\"")
+
+            # Exit
+            self.runCmd("-gdb-exit")
+            self.runCmd("") #FIXME lldb-mi hangs here on Linux; extra return is needed
+            self.expect("\^exit")
+
+        finally:
+            # Clean up
+            debugserver_child.terminate(force = True)
+
 if __name__ == '__main__':
     unittest2.main()

Modified: lldb/trunk/test/tools/lldb-mi/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/main.c?rev=228803&r1=228802&r2=228803&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/main.c (original)
+++ lldb/trunk/test/tools/lldb-mi/main.c Tue Feb 10 22:58:41 2015
@@ -11,7 +11,7 @@
 extern int a_MyFunction();
 extern int b_MyFunction();
 extern int infloop();
-int doloop;
+int doloop, dosegfault;
 int g_MyVar = 3;
 static int s_MyVar = 4;
 int main (int argc, char const *argv[])
@@ -24,6 +24,8 @@ int main (int argc, char const *argv[])
     //BP_localstest -- it must be at line #24 (or fix it in main*.micmds)
     if (doloop) // BP_doloop
         infloop();
+    if (dosegfault)
+        *(volatile int *)NULL = 1;
     if (argc > 1 && *argv[1] == 'l') {
         a++;
         printf("a=%d, argv[1]=%s\n", a, argv[1]); //BP_argtest

Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp?rev=228803&r1=228802&r2=228803&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp Tue Feb 10 22:58:41 2015
@@ -796,6 +796,7 @@ CMICmnLLDBDebuggerHandleEvents::HandlePr
             break;
         case lldb::eStopReasonException:
             pEventType = "eStopReasonException";
+            bOk = HandleProcessEventStopException();
             break;
         case lldb::eStopReasonExec:
             pEventType = "eStopReasonExec";
@@ -933,6 +934,44 @@ CMICmnLLDBDebuggerHandleEvents::HandlePr
 
     return bOk;
 }
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop exception.
+// Type:    Method.
+// Args:    None.
+// Return:  MIstatus::success - Functional succeeded.
+//          MIstatus::failure - Functional failed.
+// Throws:  None.
+//--
+bool
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException(void)
+{
+    const lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
+    lldb::SBThread sbThread = sbProcess.GetSelectedThread();
+    const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0);
+    std::shared_ptr<char> spStopDescription(new char[nStopDescriptionLen]);
+    sbThread.GetStopDescription(spStopDescription.get(), nStopDescriptionLen);
+
+    // MI print "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
+    const CMICmnMIValueConst miValueConst("exception-received");
+    const CMICmnMIValueResult miValueResult("reason", miValueConst);
+    CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
+    const CMIUtilString strReason(spStopDescription.get());
+    const CMICmnMIValueConst miValueConst2(strReason);
+    const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
+    bool bOk = miOutOfBandRecord.Add(miValueResult2);
+    const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbThread.GetIndexID()));
+    const CMICmnMIValueConst miValueConst3(strThreadId);
+    const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
+    bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+    const CMICmnMIValueConst miValueConst4("all");
+    const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
+    bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+    bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
+    bOk = bOk && TextToStdout("(gdb)");
+
+    return bOk;
+}
 
 //++ ------------------------------------------------------------------------------------
 // Details: Form partial MI response in a MI value tuple object.

Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h?rev=228803&r1=228802&r2=228803&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h Tue Feb 10 22:58:41 2015
@@ -77,6 +77,7 @@ class CMICmnLLDBDebuggerHandleEvents : p
     bool HandleProcessEventStopReasonTrace(void);
     bool HandleProcessEventStopReasonBreakpoint(void);
     bool HandleProcessEventStopSignal(bool &vwrbShouldBrk);
+    bool HandleProcessEventStopException(void);
     bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent);
     bool MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple);
     bool MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord);





More information about the lldb-commits mailing list