"""
Test hardware breakpoints for multiple threads.
"""
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
from functionalities.breakpoint.hardware_breakpoints.base import *
class HardwareBreakpointMultiThreadTestCase(HardwareBreakpointTestBase):
def does_not_support_hw_breakpoints(self):
return not super().supports_hw_breakpoints()
@skipIfOutOfTreeDebugserver
@skipTestIfFn(does_not_support_hw_breakpoints)
def test_hw_break_set_delete_multi_thread_macos(self):
self.build()
self.setTearDownCleanup()
self.break_multi_thread("delete")
@skipIfOutOfTreeDebugserver
@skipTestIfFn(does_not_support_hw_breakpoints)
def test_hw_break_set_disable_multi_thread_macos(self):
self.build()
self.setTearDownCleanup()
self.break_multi_thread("disable")
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Our simple source filename.
self.source = "main.cpp"
# Find the line number to break inside main().
self.first_stop = line_number(
self.source, "Starting thread creation with hardware breakpoint set"
)
def break_multi_thread(self, removal_type):
"""Test that lldb hardware breakpoints work for multiple threads."""
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
# Stop in main before creating any threads.
lldbutil.run_break_set_by_file_and_line(
self, None, self.first_stop, num_expected_locations=1
)
# Run the program.
self.runCmd("run", RUN_SUCCEEDED)
# We should be stopped again due to the breakpoint.
# The stop reason of the thread should be breakpoint.
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT,
substrs=["stopped", "stop reason = breakpoint"],
)
# Now set a hardware breakpoint in thread function.
self.expect(
"breakpoint set -b hw_break_function --hardware",
substrs=["Breakpoint", "hw_break_function", "address = 0x"],
)
# We should stop in hw_break_function function for 4 threads.
count = 0
while count < 2:
self.runCmd("process continue")
# We should be stopped in hw_break_function
# The stop reason of the thread should be breakpoint.
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT,
substrs=[
"hw_break_function",
"stop reason = breakpoint",
],
)
# Continue the loop and test that we are stopped 4 times.
count += 1
# Check the breakpoint list.
self.expect("breakpoint list", substrs=["hw_break_function", "hardware"])
self.expect(
"breakpoint list -v",
substrs=["function = hw_break_function", "hardware = true"],
)
if removal_type == "delete":
self.runCmd("settings set auto-confirm true")
# Now 'breakpoint delete' should just work fine without confirmation
# prompt from the command interpreter.
self.expect("breakpoint delete", startstr="All breakpoints removed")
# Restore the original setting of auto-confirm.
self.runCmd("settings clear auto-confirm")
elif removal_type == "disable":
self.expect("breakpoint disable", startstr="All breakpoints disabled.")
# Continue. Program should exit without stopping anywhere.
self.runCmd("process continue")
# Process should have stopped and exited with status = 0
self.expect(
"process status",
PROCESS_STOPPED,
patterns=["Process .* exited with status = 0"],
)