amccarth updated this revision to Diff 44264.
amccarth added a comment.

Restored TestBuiltinTrap.py because that's actually for something else.

Changed TestDebugbreak.py to use asm("int3") on non-Windows x86.

I've ordered a Linux box, but I don't currently have one, so I haven't been 
able to try this on Linux yet.


http://reviews.llvm.org/D15834

Files:
  packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile
  
packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py
  packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c
  source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp

Index: source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
===================================================================
--- source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
+++ source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
@@ -550,56 +550,74 @@
     if (!stop_thread)
         return;
 
-    RegisterContextSP register_context = stop_thread->GetRegisterContext();
-
-    // The current EIP is AFTER the BP opcode, which is one byte.
-    uint64_t pc = register_context->GetPC() - 1;
-    if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT)
+    switch (active_exception->GetExceptionCode())
     {
-        BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
+        case EXCEPTION_SINGLE_STEP:
+        {
+            stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
+            stop_thread->SetStopInfo(stop_info);
+            WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u",
+                         stop_thread->GetID());
+            stop_thread->SetStopInfo(stop_info);
+            return;
+        }
 
-        if (site)
+        case EXCEPTION_BREAKPOINT:
         {
-            WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
-                         "RefreshStateAfterStop detected breakpoint in process %I64u at "
-                         "address 0x%I64x with breakpoint site %d",
-                         m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID());
+            RegisterContextSP register_context = stop_thread->GetRegisterContext();
 
-            if (site->ValidForThisThread(stop_thread.get()))
-            {
-                WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
-                             "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.",
-                             site->GetID(), stop_thread->GetID());
+            // The current EIP is AFTER the BP opcode, which is one byte.
+            uint64_t pc = register_context->GetPC() - 1;
 
-                stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
-                    *stop_thread, site->GetID());
-                register_context->SetPC(pc);
+            BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
+            if (site)
+            {
+                WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+                             "RefreshStateAfterStop detected breakpoint in process %I64u at "
+                             "address 0x%I64x with breakpoint site %d",
+                             m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID());
+
+                if (site->ValidForThisThread(stop_thread.get()))
+                {
+                    WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+                                 "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.",
+                                 site->GetID(), stop_thread->GetID());
+
+                    stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
+                        *stop_thread, site->GetID());
+                    register_context->SetPC(pc);
+                }
+                else
+                {
+                    WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+                                 "Breakpoint site %d is not valid for this thread, creating empty stop info.",
+                                 site->GetID());
+                }
+                stop_thread->SetStopInfo(stop_info);
+                return;
             }
             else
             {
+                // The thread hit a hard-coded breakpoint like an `int 3` or `__debugbreak()`.
                 WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
-                             "Breakpoint site %d is not valid for this thread, creating empty stop info.",
-                             site->GetID());
+                                "No breakpoint site matches for this thread. __debugbreak()?  "
+                                "Creating stop info with the exception.");
+                // FALLTHROUGH:  We'll treat this as a generic exception record in the default case.
             }
         }
-        stop_thread->SetStopInfo(stop_info);
-    }
-    else if (active_exception->GetExceptionCode() == EXCEPTION_SINGLE_STEP)
-    {
-        stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
-        stop_thread->SetStopInfo(stop_info);
-        WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u",
-                     stop_thread->GetID());
-    }
-    else
-    {
-        std::string desc;
-        llvm::raw_string_ostream desc_stream(desc);
-        desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8)
-                    << " encountered at address " << llvm::format_hex(pc, 8);
-        stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
-        stop_thread->SetStopInfo(stop_info);
-        WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str());
+
+        default:
+        {
+            std::string desc;
+            llvm::raw_string_ostream desc_stream(desc);
+            desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8)
+                        << " encountered at address "
+                        << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
+            stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
+            stop_thread->SetStopInfo(stop_info);
+            WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str());
+            return;
+        }
     }
 }
 
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c
@@ -0,0 +1,29 @@
+#ifdef _MSC_VER
+#include <intrin.h>
+#define BREAKPOINT_INTRINSIC    __debugbreak
+#else
+#define BREAKPOINT_INTRINSIC    __asm__ __volatile__ ("int3");
+#endif
+
+int
+bar(int const *foo)
+{
+    int count = 0;
+    for (int i = 0; i < 10; ++i)
+    {
+        count += 1;
+        BREAKPOINT_INTRINSIC();
+        count += 1;
+    }
+    return *foo;
+}
+
+int
+main(int argc, char **argv)
+{
+    int foo = 42;
+    bar(&foo);
+    return 0;
+}
+
+
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py
@@ -0,0 +1,53 @@
+"""
+Test embedded breakpoints, like `asm int 3;` in x86 or or `__debugbreak` on Windows.
+"""
+
+from __future__ import print_function
+
+import os
+import lldb
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+class DebugBreakTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIf(archs=not_in(["i386", "i686"]))
+    @expectedFailureAll("llvm.org/pr15936", compiler="gcc", compiler_version=["<=","4.6"])
+    @expectedFailureAll(archs="arm", compiler="gcc", triple=".*-android") # gcc generates incorrect linetable
+    @no_debug_info_test
+    def test_asm_int_3(self):
+        """Test that intrinsics like `__debugbreak();` and `asm {"int3"}` are treated like breakpoints."""
+        self.build()
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        # Run the program.
+        target = self.dbg.CreateTarget(exe)
+        process = target.LaunchSimple(None, None, self.get_process_working_directory())
+
+        # We've hit the first stop, so grab the frame.
+        self.assertEqual(process.GetState(), lldb.eStateStopped)
+        thread = process.GetThreadAtIndex(0)
+        frame = thread.GetFrameAtIndex(0)
+
+        # We should be in funciton 'bar'.
+        self.assertTrue(frame.IsValid())
+        function_name = frame.GetFunctionName()
+        self.assertTrue('bar' in function_name)
+
+        # We should be able to evaluate the parameter foo.
+        value = frame.EvaluateExpression('*foo')
+        self.assertEqual(value.GetValueAsSigned(), 42)
+
+        # The counter should be 1 at the first stop and increase by 2 for each
+        # subsequent stop.
+        counter = 1
+        while counter < 20:
+          value = frame.EvaluateExpression('count')
+          self.assertEqual(value.GetValueAsSigned(), counter)
+          counter += 2
+          process.Continue()
+
+        # The inferior should exit after the last iteration.
+        self.assertEqual(process.GetState(), lldb.eStateExited)
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+ifneq (,$(findstring icc,$(CC)))
+    CFLAGS += -debug inline-debug-info
+endif
+
+include $(LEVEL)/Makefile.rules
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to