[Lldb-commits] [lldb] r257186 - Treat an embedded int3/__debugbreak() as a breakpoint on Windows, includes a cross-platform test.
Adrian McCarthy via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 8 10:28:04 PST 2016
Author: amccarth
Date: Fri Jan 8 12:28:03 2016
New Revision: 257186
URL: http://llvm.org/viewvc/llvm-project?rev=257186&view=rev
Log:
Treat an embedded int3/__debugbreak() as a breakpoint on Windows, includes a cross-platform test.
Added:
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c
Modified:
lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile?rev=257186&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile Fri Jan 8 12:28:03 2016
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py?rev=257186&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py Fri Jan 8 12:28:03 2016
@@ -0,0 +1,51 @@
+"""
+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"]))
+ @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)
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c?rev=257186&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c Fri Jan 8 12:28:03 2016
@@ -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;
+}
+
+
Modified: lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp?rev=257186&r1=257185&r2=257186&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp Fri Jan 8 12:28:03 2016
@@ -550,56 +550,74 @@ ProcessWindowsLive::RefreshStateAfterSto
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;
+ }
}
}
More information about the lldb-commits
mailing list