amccarth updated this revision to Diff 44179.
amccarth added a comment.
Herald added subscribers: srhines, danalbert, tberghammer.

I've rolled bits of TestBuiltinTrap.py into the new test and deleted the old 
one.

This still works on Windows.  I'm not set up to test it on Linux.


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
  packages/Python/lldbsuite/test/linux/builtin_trap/Makefile
  packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py
  packages/Python/lldbsuite/test/linux/builtin_trap/main.cpp
  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/linux/builtin_trap/main.cpp
===================================================================
--- packages/Python/lldbsuite/test/linux/builtin_trap/main.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//===-- main.cpp ------------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-void bar(int const *foo) {
-  __builtin_trap(); // Set break point at this line.
-}
-
-int main() {
-  int foo = 5;
-  bar(&foo);
-}
Index: packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py
===================================================================
--- packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py
+++ /dev/null
@@ -1,51 +0,0 @@
-"""
-Test lldb ability to unwind a stack with a function containing a call to the
-'__builtin_trap' intrinsic, which GCC (4.6) encodes to an illegal opcode.
-"""
-
-from __future__ import print_function
-
-
-
-import os
-import lldb
-from lldbsuite.test.lldbtest import *
-import lldbsuite.test.lldbutil as lldbutil
-
-class BuiltinTrapTestCase(TestBase):
-
-    mydir = TestBase.compute_mydir(__file__)
-
-    def setUp(self):
-        # Call super's setUp().
-        TestBase.setUp(self)
-        # Find the line number to break at.
-        self.line = line_number('main.cpp', '// Set break point at this line.')
-
-    @expectedFailureAll("llvm.org/pr15936", compiler="gcc", compiler_version=["<=","4.6"])
-    @expectedFailureAll(archs="arm", compiler="gcc", triple=".*-android") # gcc generates incorrect linetable
-    @skipIfWindows
-    def test_with_run_command(self):
-        """Test that LLDB handles a function with __builtin_trap correctly."""
-        self.build()
-        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
-
-        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line,
-                                                 num_expected_locations=1,
-                                                 loc_exact=True)
-
-        self.runCmd("run", RUN_SUCCEEDED)
-
-        # The stop reason of the thread should be breakpoint.
-        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
-            substrs = ['stopped',
-                       'stop reason = breakpoint'])
-
-        # print backtrace, expect both 'bar' and 'main' functions to be listed
-        self.expect('bt', substrs = ['bar', 'main'])
-
-        # go up one frame
-        self.runCmd("up", RUN_SUCCEEDED)
-
-        # evaluate a local
-        self.expect('p foo', substrs = ['= 5'])
Index: packages/Python/lldbsuite/test/linux/builtin_trap/Makefile
===================================================================
--- packages/Python/lldbsuite/test/linux/builtin_trap/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-LEVEL = ../../make
-
-CXX_SOURCES := main.cpp
-
-include $(LEVEL)/Makefile.rules
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    __builtin_trap
+#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 `__builtin_trap();` 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