diff options
author | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
commit | 78b9749c0a4ea980a8b934645da6ae98fcc665e8 (patch) | |
tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/functionalities/watchpoint | |
parent | 60cb593f9d55fa5ca7a5372b731f2330345b4b9a (diff) | |
download | FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.zip FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.tar.gz |
Vendor import of lldb trunk r256945:
https://llvm.org/svn/llvm-project/lldb/trunk@256945
Diffstat (limited to 'packages/Python/lldbsuite/test/functionalities/watchpoint')
35 files changed, 1961 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/Makefile new file mode 100644 index 0000000..8817fff --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py new file mode 100644 index 0000000..f0a0b5a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py @@ -0,0 +1,98 @@ +""" +Test lldb watchpoint that uses '-s size' to watch a pointed location with size. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class HelloWatchLocationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # This is for verifying that watch location works. + self.violating_func = "do_bad_thing_with_location"; + # Build dictionary to have unique executable names for each test method. + self.exe_name = self.testMethodName + self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet + def test_hello_watchlocation(self): + """Test watching a location with '-s size' option.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1, loc_exact=False) + + # 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 let's set a write-type watchpoint pointed to by 'g_char_ptr'. + # The main.cpp, by design, misbehaves by not following the agreed upon + # protocol of using a mutex while accessing the global pool and by not + # incrmenting the global pool by 2. + self.expect("watchpoint set expression -w write -s 1 -- g_char_ptr", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 1', 'type = w']) + # Get a hold of the watchpoint id just created, it is used later on to + # match the watchpoint id which is expected to be fired. + match = re.match("Watchpoint created: Watchpoint (.*):", self.res.GetOutput().splitlines()[0]) + if match: + expected_wp_id = int(match.group(1), 0) + else: + self.fail("Grokking watchpoint id faailed!") + + self.runCmd("expr unsigned val = *g_char_ptr; val") + self.expect(self.res.GetOutput().splitlines()[0], exe=False, + endstr = ' = 0') + + self.runCmd("watchpoint set expression -w write -s 4 -- &threads[0]") + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type), but + # only once. The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', + 'stop reason = watchpoint %d' % expected_wp_id]) + + # Switch to the thread stopped due to watchpoint and issue some commands. + self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint) + self.runCmd("thread backtrace") + self.expect("frame info", + substrs = [self.violating_func]) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) + + self.runCmd("thread backtrace all") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp new file mode 100644 index 0000000..59b0afc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp @@ -0,0 +1,106 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <condition_variable> +#include <cstdio> +#include <random> +#include <thread> + +std::default_random_engine g_random_engine{std::random_device{}()}; +std::uniform_int_distribution<> g_distribution{0, 3000000}; +std::condition_variable g_condition_variable; +std::mutex g_mutex; +int g_count; + +char *g_char_ptr = nullptr; + +void +barrier_wait() +{ + std::unique_lock<std::mutex> lock{g_mutex}; + if (--g_count > 0) + g_condition_variable.wait(lock); + else + g_condition_variable.notify_all(); +} + +void +do_bad_thing_with_location(char *char_ptr, char new_val) +{ + unsigned what = new_val; + printf("new value written to location(%p) = %u\n", char_ptr, what); + *char_ptr = new_val; +} + +uint32_t +access_pool (bool flag = false) +{ + static std::mutex g_access_mutex; + if (!flag) + g_access_mutex.lock(); + + char old_val = *g_char_ptr; + if (flag) + do_bad_thing_with_location(g_char_ptr, old_val + 1); + + if (!flag) + g_access_mutex.unlock(); + return *g_char_ptr; +} + +void +thread_func (uint32_t thread_index) +{ + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + barrier_wait(); + + uint32_t count = 0; + uint32_t val; + while (count++ < 15) + { + // random micro second sleep from zero to 3 seconds + int usec = g_distribution(g_random_engine); + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::this_thread::sleep_for(std::chrono::microseconds{usec}); + + if (count < 7) + val = access_pool (); + else + val = access_pool (true); + + printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); +} + + +int main (int argc, char const *argv[]) +{ + g_count = 4; + std::thread threads[3]; + + g_char_ptr = new char{}; + + // Create 3 threads + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + printf ("Before turning all three threads loose...\n"); // Set break point at this line. + barrier_wait(); + + // Join all of our threads + for (auto &thread : threads) + thread.join(); + + delete g_char_ptr; + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py new file mode 100644 index 0000000..57467c3 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py @@ -0,0 +1,84 @@ +""" +Test my first lldb watchpoint. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class HelloWatchpointTestCase(TestBase): + + def getCategories (self): + return ['basic_process'] + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + self.exe_name = 'a.out' + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") + def test_hello_watchpoint_using_watchpoint_set(self): + """Test a simple sequence of watchpoint creation and watchpoint hit.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a write-type watchpoint for 'global'. + # There should be only one watchpoint hit (see main.c). + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type), but + # only once. The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', + 'stop reason = watchpoint']) + + self.runCmd("process continue") + + # Don't expect the read of 'global' to trigger a stop exception. + process = self.dbg.GetSelectedTarget().GetProcess() + if process.GetState() == lldb.eStateStopped: + self.assertFalse(lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/main.c new file mode 100644 index 0000000..11a738a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/main.c @@ -0,0 +1,30 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 10; // Watchpoint variable declaration. +char gchar1 = 'a'; +char gchar2 = 'b'; + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + // When stopped, watch 'global' for write. + global = 20; + gchar1 += 1; + gchar2 += 1; + local += argc; + ++local; + printf("local: %d\n", local); + printf("global=%d\n", global); + printf("gchar1='%c'\n", gchar1); + printf("gchar2='%c'\n", gchar2); +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/Makefile new file mode 100644 index 0000000..8817fff --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py new file mode 100644 index 0000000..2318214 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py @@ -0,0 +1,137 @@ +""" +Test that lldb watchpoint works for multiple threads. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointForMultipleThreadsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchpoint_multiple_threads(self): + """Test that lldb watchpoint works for multiple threads.""" + self.build() + self.setTearDownCleanup() + self.hello_multiple_threads() + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): + """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" + self.build() + self.setTearDownCleanup() + self.hello_multiple_threads_wp_set_and_then_delete() + + 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, '// Set break point at this line') + + def hello_multiple_threads(self): + """Test that lldb watchpoint works for multiple threads.""" + self.runCmd("file %s" % os.path.join(os.getcwd(), 'a.out'), CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + 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 let's set a write-type watchpoint for variable 'g_val'. + # The main.cpp, by design, misbehaves by not following the agreed upon + # protocol of using a mutex while accessing the global pool and by not + # writing to the variable. + self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + while True: + self.runCmd("process continue") + + self.runCmd("thread list") + if "stop reason = watchpoint" in self.res.GetOutput(): + # Good, we verified that the watchpoint works! + self.runCmd("thread backtrace all") + break + else: + self.fail("The stop reason should be either break or watchpoint") + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) + + def hello_multiple_threads_wp_set_and_then_delete(self): + """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" + self.runCmd("file %s" % os.path.join(os.getcwd(), 'a.out'), CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + 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 let's set a write-type watchpoint for variable 'g_val'. + # The main.cpp, by design, misbehaves by not following the agreed upon + # protocol of using a mutex while accessing the global pool and by not + # writing to the variable. + self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + watchpoint_stops = 0 + while True: + self.runCmd("process continue") + self.runCmd("process status") + if re.search("Process .* exited", self.res.GetOutput()): + # Great, we are done with this test! + break + + self.runCmd("thread list") + if "stop reason = watchpoint" in self.res.GetOutput(): + self.runCmd("thread backtrace all") + watchpoint_stops += 1 + if watchpoint_stops > 1: + self.fail("Watchpoint hits not supposed to exceed 1 by design!") + # Good, we verified that the watchpoint works! Now delete the watchpoint. + if self.TraceOn(): + print("watchpoint_stops=%d at the moment we delete the watchpoint" % watchpoint_stops) + self.runCmd("watchpoint delete 1") + self.expect("watchpoint list -v", + substrs = ['No watchpoints currently set.']) + continue + else: + self.fail("The stop reason should be either break or watchpoint") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp new file mode 100644 index 0000000..8a31041 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp @@ -0,0 +1,83 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <cstdio> +#include <mutex> +#include <random> +#include <thread> + +std::default_random_engine g_random_engine{std::random_device{}()}; +std::uniform_int_distribution<> g_distribution{0, 3000000}; + +uint32_t g_val = 0; + + +uint32_t +access_pool (bool flag = false) +{ + static std::mutex g_access_mutex; + if (!flag) + g_access_mutex.lock(); + + uint32_t old_val = g_val; + if (flag) + { + printf("changing g_val to %d...\n", old_val + 1); + g_val = old_val + 1; + } + + if (!flag) + g_access_mutex.unlock(); + return g_val; +} + +void +thread_func (uint32_t thread_index) +{ + // Break here in order to allow the thread + // to inherit the global watchpoint state. + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + uint32_t count = 0; + uint32_t val; + while (count++ < 15) + { + // random micro second sleep from zero to 3 seconds + int usec = g_distribution(g_random_engine); + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::this_thread::sleep_for(std::chrono::microseconds{usec}); + + if (count < 7) + val = access_pool (); + else + val = access_pool (true); + + printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); +} + + +int main (int argc, char const *argv[]) +{ + std::thread threads[3]; + + printf ("Before turning all three threads loose...\n"); // Set break point at this line, + // in order to set our watchpoint. + // Create 3 threads + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + // Join all of our threads + for (auto &thread : threads) + thread.join(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py new file mode 100644 index 0000000..dd18a64 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py @@ -0,0 +1,113 @@ +"""Test stepping over watchpoints.""" + +from __future__ import print_function + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestStepOverWatchpoint(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def getCategories(self): + return ['basic_process'] + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") + def test(self): + """Test stepping over watchpoints.""" + self.build() + exe = os.path.join(os.getcwd(), 'a.out') + + target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + lldbutil.run_break_set_by_symbol(self, 'main') + + process = target.LaunchSimple(None, None, + self.get_process_working_directory()) + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + thread = lldbutil.get_stopped_thread(process, + lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "Failed to get thread.") + + frame = thread.GetFrameAtIndex(0) + self.assertTrue(frame.IsValid(), "Failed to get frame.") + + read_value = frame.FindValue('g_watch_me_read', + lldb.eValueTypeVariableGlobal) + self.assertTrue(read_value.IsValid(), "Failed to find read value.") + + error = lldb.SBError() + + # resolve_location=True, read=True, write=False + read_watchpoint = read_value.Watch(True, True, False, error) + self.assertTrue(error.Success(), + "Error while setting watchpoint: %s" % + error.GetCString()) + self.assertTrue(read_watchpoint, "Failed to set read watchpoint.") + + thread.StepOver() + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonWatchpoint, + STOPPED_DUE_TO_WATCHPOINT) + self.assertTrue(thread.GetStopDescription(20) == 'watchpoint 1') + + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + self.assertTrue(thread.GetStopDescription(20) == 'step over') + + self.step_inst_for_watchpoint(1) + + write_value = frame.FindValue('g_watch_me_write', + lldb.eValueTypeVariableGlobal) + self.assertTrue(write_value, "Failed to find write value.") + + # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet + arch = self.getArchitecture() + if arch in ['mips', 'mipsel', 'mips64', 'mips64el']: + self.runCmd("watchpoint delete 1") + + # resolve_location=True, read=False, write=True + write_watchpoint = write_value.Watch(True, False, True, error) + self.assertTrue(read_watchpoint, "Failed to set write watchpoint.") + self.assertTrue(error.Success(), + "Error while setting watchpoint: %s" % + error.GetCString()) + + thread.StepOver() + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonWatchpoint, + STOPPED_DUE_TO_WATCHPOINT) + self.assertTrue(thread.GetStopDescription(20) == 'watchpoint 2') + + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + self.assertTrue(thread.GetStopDescription(20) == 'step over') + + self.step_inst_for_watchpoint(2) + + def step_inst_for_watchpoint(self, wp_id): + watchpoint_hit = False + current_line = self.frame().GetLineEntry().GetLine() + while self.frame().GetLineEntry().GetLine() == current_line: + self.thread().StepInstruction(False) # step_over=False + stop_reason = self.thread().GetStopReason() + if stop_reason == lldb.eStopReasonWatchpoint: + self.assertFalse(watchpoint_hit, "Watchpoint already hit.") + expected_stop_desc = "watchpoint %d" % wp_id + actual_stop_desc = self.thread().GetStopDescription(20) + self.assertTrue(actual_stop_desc == expected_stop_desc, + "Watchpoint ID didn't match.") + watchpoint_hit = True + else: + self.assertTrue(stop_reason == lldb.eStopReasonPlanComplete, + STOPPED_DUE_TO_STEP_IN) + self.assertTrue(watchpoint_hit, "Watchpoint never hit.") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/main.c new file mode 100644 index 0000000..2d87d9a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/main.c @@ -0,0 +1,19 @@ +char g_watch_me_read; +char g_watch_me_write; +char g_temp; + +void watch_read() { + g_temp = g_watch_me_read; +} + +void watch_write() { + g_watch_me_write = g_temp; +} + +int main() { + watch_read(); + g_temp = g_watch_me_read; + watch_write(); + g_watch_me_write = g_temp; + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py new file mode 100644 index 0000000..21f1fb6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/TestWatchedVarHitWhenInScope.py @@ -0,0 +1,83 @@ +""" +Test that a variable watchpoint should only hit when in scope. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchedVariableHitWhenInScopeTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # + # This test depends on not tracking watchpoint expression hits if we have + # left the watchpoint scope. We will provide such an ability at some point + # but the way this was done was incorrect, and it is unclear that for the + # most part that's not what folks mostly want, so we have to provide a + # clearer API to express this. + # + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + self.exe_name = self.testMethodName + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + @unittest2.expectedFailure("rdar://problem/18685649") + def test_watched_var_should_only_hit_when_in_scope(self): + """Test that a variable watchpoint should only hit when in scope.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped in main. + lldbutil.run_break_set_by_symbol (self, "main", 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 let's set a watchpoint for 'c.a'. + # There should be only one watchpoint hit (see main.c). + self.expect("watchpoint set variable c.a", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type), but + # only once. The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', + 'stop reason = watchpoint']) + + self.runCmd("process continue") + # Don't expect the read of 'global' to trigger a stop exception. + # The process status should be 'exited'. + self.expect("process status", + substrs = ['exited']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/main.c new file mode 100644 index 0000000..1bf7a00 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/variable_out_of_scope/main.c @@ -0,0 +1,15 @@ +typedef struct +{ + int a; + float b; +} mystruct; + +int main() +{ + mystruct c; + + c.a = 5; + c.b = 3.6; + + return 0; +}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py new file mode 100644 index 0000000..339de45 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py @@ -0,0 +1,313 @@ +""" +Test watchpoint list, enable, disable, and delete commands. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointCommandsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + self.line2 = line_number(self.source, '// Set 2nd break point for disable_then_enable test case.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + # Build dictionary to have unique executable names for each test method. + self.exe_name = self.testMethodName + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_rw_watchpoint(self): + """Test read_write watchpoint and expect to stop two times.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a read_write-type watchpoint for 'global'. + # There should be two watchpoint hits (see main.c). + self.expect("watchpoint set variable -w read_write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = rw', + '%s:%d' % (self.source, self.decl)]) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['Number of supported hardware watchpoints:', + 'hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (read_write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (read_write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 2. + self.expect("watchpoint list -v", + substrs = ['hit_count = 2']) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_rw_watchpoint_delete(self): + """Test delete watchpoint and expect not to stop for watchpoint.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a read_write-type watchpoint for 'global'. + # There should be two watchpoint hits (see main.c). + self.expect("watchpoint set variable -w read_write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = rw', + '%s:%d' % (self.source, self.decl)]) + + # Delete the watchpoint immediately, but set auto-confirm to true first. + self.runCmd("settings set auto-confirm true") + self.expect("watchpoint delete", + substrs = ['All watchpoints removed.']) + # Restore the original setting of auto-confirm. + self.runCmd("settings clear auto-confirm") + + # Use the '-v' option to do verbose listing of the watchpoint. + self.runCmd("watchpoint list -v") + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_rw_watchpoint_set_ignore_count(self): + """Test watchpoint ignore count and expect to not to stop at all.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a read_write-type watchpoint for 'global'. + # There should be two watchpoint hits (see main.c). + self.expect("watchpoint set variable -w read_write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = rw', + '%s:%d' % (self.source, self.decl)]) + + # Set the ignore count of the watchpoint immediately. + self.expect("watchpoint ignore -i 2", + substrs = ['All watchpoints ignored.']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # Expect to find an ignore_count of 2. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0', 'ignore_count = 2']) + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # Expect to find a hit_count of 2 as well. + self.expect("watchpoint list -v", + substrs = ['hit_count = 2', 'ignore_count = 2']) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_rw_disable_after_first_stop(self): + """Test read_write watchpoint but disable it after the first stop.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a read_write-type watchpoint for 'global'. + # There should be two watchpoint hits (see main.c). + self.expect("watchpoint set variable -w read_write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = rw', + '%s:%d' % (self.source, self.decl)]) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['state = enabled', 'hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (read_write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + # Before continuing, we'll disable the watchpoint, which means we won't + # stop again after this. + self.runCmd("watchpoint disable") + + self.expect("watchpoint list -v", + substrs = ['state = disabled', 'hit_count = 1']) + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_rw_disable_then_enable(self): + """Test read_write watchpoint, disable initially, then enable it.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line (self, None, self.line2, 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 let's set a read_write-type watchpoint for 'global'. + # There should be two watchpoint hits (see main.c). + self.expect("watchpoint set variable -w read_write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = rw', + '%s:%d' % (self.source, self.decl)]) + + # Immediately, we disable the watchpoint. We won't be stopping due to a + # watchpoint after this. + self.runCmd("watchpoint disable") + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['state = disabled', 'hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the breakpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stop reason = breakpoint']) + + # Before continuing, we'll enable the watchpoint, which means we will + # stop again after this. + self.runCmd("watchpoint enable") + + self.expect("watchpoint list -v", + substrs = ['state = enabled', 'hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (read_write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/Makefile new file mode 100644 index 0000000..ee6b9cc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py new file mode 100644 index 0000000..f2bf908 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py @@ -0,0 +1,139 @@ +""" +Test 'watchpoint command'. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointLLDBCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + # Build dictionary to have unique executable names for each test method. + self.exe_name = 'a%d.out' % self.test_number + self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchpoint_command(self): + """Test 'watchpoint command'.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a write-type watchpoint for 'global'. + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + self.runCmd('watchpoint command add 1 -o "expr -- cookie = 777"') + + # List the watchpoint command we just added. + self.expect("watchpoint command list 1", + substrs = ['expr -- cookie = 777']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + # Check that the watchpoint snapshoting mechanism is working. + self.expect("watchpoint list -v", + substrs = ['old value:', ' = 0', + 'new value:', ' = 1']) + + # The watchpoint command "forced" our global variable 'cookie' to become 777. + self.expect("frame variable --show-globals cookie", + substrs = ['(int32_t)', 'cookie = 777']) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchpoint_command_can_disable_a_watchpoint(self): + """Test that 'watchpoint command' action can disable a watchpoint after it is triggered.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a write-type watchpoint for 'global'. + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + self.runCmd('watchpoint command add 1 -o "watchpoint disable 1"') + + # List the watchpoint command we just added. + self.expect("watchpoint command list 1", + substrs = ['watchpoint disable 1']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + # Check that the watchpoint has been disabled. + self.expect("watchpoint list -v", + substrs = ['disabled']) + + self.runCmd("process continue") + + # There should be no more watchpoint hit and the process status should + # be 'exited'. + self.expect("process status", + substrs = ['exited']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py new file mode 100644 index 0000000..a476aeb --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py @@ -0,0 +1,87 @@ +""" +Test 'watchpoint command'. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointPythonCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + # Build dictionary to have unique executable names for each test method. + self.exe_name = self.testMethodName + self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + + @skipIfFreeBSD # timing out on buildbot + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + def test_watchpoint_command(self): + """Test 'watchpoint command'.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1) +# self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED, +# startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" % +# (self.source, self.line))# + + # 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 let's set a write-type watchpoint for 'global'. + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + self.runCmd('watchpoint command add -s python 1 -o \'frame.EvaluateExpression("cookie = 777")\'') + + # List the watchpoint command we just added. + self.expect("watchpoint command list 1", + substrs = ['frame.EvaluateExpression', 'cookie = 777']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + # Check that the watchpoint snapshoting mechanism is working. + self.expect("watchpoint list -v", + substrs = ['old value:', ' = 0', + 'new value:', ' = 1']) + + # The watchpoint command "forced" our global variable 'cookie' to become 777. + self.expect("frame variable --show-globals cookie", + substrs = ['(int32_t)', 'cookie = 777']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/main.cpp new file mode 100644 index 0000000..6cb80c6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/main.cpp @@ -0,0 +1,28 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 0; // Watchpoint variable declaration. +int32_t cookie = 0; + +static void modify(int32_t &var) { + ++var; +} + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + for (int i = 0; i < 10; ++i) + modify(global); + + printf("global=%d\n", global); + printf("cookie=%d\n", cookie); +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/Makefile new file mode 100644 index 0000000..ee6b9cc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py new file mode 100644 index 0000000..355204a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py @@ -0,0 +1,78 @@ +""" +Test watchpoint modify command to set condition on a watchpoint. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointConditionCmdTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + # Build dictionary to have unique executable names for each test method. + self.exe_name = self.testMethodName + self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchpoint_cond(self): + """Test watchpoint condition.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a write-type watchpoint for 'global'. + # With a condition of 'global==5'. + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + self.runCmd("watchpoint modify -c 'global==5'") + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0', 'global==5']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + self.expect("frame variable --show-globals global", + substrs = ['(int32_t)', 'global = 5']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 2. + self.expect("watchpoint list -v", + substrs = ['hit_count = 5']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp new file mode 100644 index 0000000..f4c3527 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp @@ -0,0 +1,28 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 0; // Watchpoint variable declaration. + +static void modify(int32_t &var) { + ++var; +} + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + // When stopped, watch 'global', + // for the condition "global == 5". + for (int i = 0; i < 10; ++i) + modify(global); + + printf("global=%d\n", global); +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/main.c new file mode 100644 index 0000000..b20eaf4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/main.c @@ -0,0 +1,24 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 10; // Watchpoint variable declaration. + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + // When stopped, watch 'global'. + global = 20; + local += argc; + ++local; // Set 2nd break point for disable_then_enable test case. + printf("local: %d\n", local); + printf("global=%d\n", global); +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py new file mode 100644 index 0000000..e4d6e01 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py @@ -0,0 +1,89 @@ +"""Test that adding, deleting and modifying watchpoints sends the appropriate events.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestWatchpointEvents (TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers that we will step to in main: + self.main_source = "main.c" + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_with_python_api(self): + """Test that adding, deleting and modifying watchpoints sends the appropriate events.""" + self.build() + + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.main_source_spec = lldb.SBFileSpec (self.main_source) + + break_in_main = target.BreakpointCreateBySourceRegex ('// Put a breakpoint here.', self.main_source_spec) + self.assertTrue(break_in_main, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_main) + + if len(threads) != 1: + self.fail ("Failed to stop at first breakpoint in main.") + + thread = threads[0] + frame = thread.GetFrameAtIndex(0) + local_var = frame.FindVariable ("local_var") + self.assertTrue (local_var.IsValid()) + + self.listener = lldb.SBListener("com.lldb.testsuite_listener") + self.target_bcast = target.GetBroadcaster() + self.target_bcast.AddListener (self.listener, lldb.SBTarget.eBroadcastBitWatchpointChanged) + self.listener.StartListeningForEvents (self.target_bcast, lldb.SBTarget.eBroadcastBitWatchpointChanged) + + error = lldb.SBError() + local_watch = local_var.Watch(True, True, True, error) + if not error.Success(): + self.fail ("Failed to make watchpoint for local_var: %s"%(error.GetCString())) + + self.GetWatchpointEvent (lldb.eWatchpointEventTypeAdded) + # Now change some of the features of this watchpoint and make sure we get events: + local_watch.SetEnabled(False) + self.GetWatchpointEvent (lldb.eWatchpointEventTypeDisabled) + + local_watch.SetIgnoreCount(10) + self.GetWatchpointEvent (lldb.eWatchpointEventTypeIgnoreChanged) + + local_watch.SetCondition ("1 == 2") + self.GetWatchpointEvent (lldb.eWatchpointEventTypeConditionChanged) + + def GetWatchpointEvent (self, event_type): + # We added a watchpoint so we should get a watchpoint added event. + event = lldb.SBEvent() + success = self.listener.WaitForEvent (1, event) + self.assertTrue(success == True, "Successfully got watchpoint event") + self.assertTrue (lldb.SBWatchpoint.EventIsWatchpointEvent(event), "Event is a watchpoint event.") + found_type = lldb.SBWatchpoint.GetWatchpointEventTypeFromEvent (event) + self.assertTrue (found_type == event_type, "Event is not correct type, expected: %d, found: %d"%(event_type, found_type)) + # There shouldn't be another event waiting around: + found_event = self.listener.PeekAtNextEventForBroadcasterWithType (self.target_bcast, lldb.SBTarget.eBroadcastBitBreakpointChanged, event) + if found_event: + print("Found an event I didn't expect: ", event) + + self.assertTrue (not found_event, "Only one event per change.") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/main.c new file mode 100644 index 0000000..4b91753 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/main.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +main (int argc, char **argv) +{ + int local_var = 10; + printf ("local_var is: %d.\n", local_var++); // Put a breakpoint here. + return local_var; +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py new file mode 100644 index 0000000..73752d2 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py @@ -0,0 +1,47 @@ +""" +Test displayed value of a vector variable while doing watchpoint operations +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestValueOfVectorVariableTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_value_of_vector_variable_using_watchpoint_set(self): + """Test verify displayed value of vector variable.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + self.value_of_vector_variable_with_watchpoint_set() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + self.exe_name = 'a.out' + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + def value_of_vector_variable_with_watchpoint_set(self): + """Test verify displayed value of vector variable""" + exe = os.path.join(os.getcwd(), 'a.out') + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Set break to get a frame + self.runCmd("b main") + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Value of a vector variable should be displayed correctly + self.expect("watchpoint set variable global_vector", WATCHPOINT_CREATED, + substrs = ['new value: (1, 2, 3, 4)']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c new file mode 100644 index 0000000..98f8c47 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c @@ -0,0 +1,16 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +typedef char v4i8 __attribute__ ((vector_size(4))); +v4i8 global_vector = {1, 2, 3, 4}; + +int +main () +{ + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/Makefile new file mode 100644 index 0000000..8817fff --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py new file mode 100644 index 0000000..6bdac70 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py @@ -0,0 +1,89 @@ +""" +Test lldb watchpoint that uses 'watchpoint set -w write -s size' to watch a pointed location with size. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchLocationUsingWatchpointSetTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # This is for verifying that watch location works. + self.violating_func = "do_bad_thing_with_location"; + # Build dictionary to have unique executable names for each test method. + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watchlocation_using_watchpoint_set(self): + """Test watching a location with 'watchpoint set expression -w write -s size' option.""" + self.build() + self.setTearDownCleanup() + + exe = os.path.join(os.getcwd(), 'a.out') + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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 let's set a write-type watchpoint pointed to by 'g_char_ptr' and + # with offset as 7. + # The main.cpp, by design, misbehaves by not following the agreed upon + # protocol of only accessing the allowable index range of [0, 6]. + self.expect("watchpoint set expression -w write -s 1 -- g_char_ptr + 7", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 1', 'type = w']) + self.runCmd("expr unsigned val = g_char_ptr[7]; val") + self.expect(self.res.GetOutput().splitlines()[0], exe=False, + endstr = ' = 0') + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", + substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type), but + # only once. The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', + 'stop reason = watchpoint', + self.violating_func]) + + # Switch to the thread stopped due to watchpoint and issue some commands. + self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint) + self.runCmd("thread backtrace") + self.runCmd("expr unsigned val = g_char_ptr[7]; val") + self.expect(self.res.GetOutput().splitlines()[0], exe=False, + endstr = ' = 99') + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be the same as the number of threads that + # stopped on a watchpoint. + threads = lldbutil.get_stopped_threads(self.process(), lldb.eStopReasonWatchpoint) + self.expect("watchpoint list -v", + substrs = ['hit_count = %d' % len(threads)]) + + self.runCmd("thread backtrace all") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py new file mode 100644 index 0000000..27c759e --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py @@ -0,0 +1,67 @@ +""" +Test error cases for the 'watchpoint set' command to make sure it errors out when necessary. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class WatchpointSetErrorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + 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.line = line_number(self.source, '// Set break point at this line.') + # Build dictionary to have unique executable names for each test method. + + def test_error_cases_with_watchpoint_set(self): + """Test error cases with the 'watchpoint set' command.""" + self.build() + self.setTearDownCleanup() + + exe = os.path.join(os.getcwd(), 'a.out') + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, 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']) + + # Try some error conditions: + + # 'watchpoint set' is now a multiword command. + self.expect("watchpoint set", + substrs = ['The following subcommands are supported:', + 'expression', + 'variable']) + self.runCmd("watchpoint set variable -w read_write", check=False) + + # 'watchpoint set expression' with '-w' or '-s' specified now needs + # an option terminator and a raw expression after that. + self.expect("watchpoint set expression -w write --", error=True, + startstr = 'error: ') + + # It's an error if the expression did not evaluate to an address. + self.expect("watchpoint set expression MyAggregateDataType", error=True, + startstr = 'error: expression did not evaluate to an address') + + # Wrong size parameter is an error. + self.expect("watchpoint set variable -s -128", error=True, + substrs = ['invalid enumeration value']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/main.cpp new file mode 100644 index 0000000..796c0ef --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/main.cpp @@ -0,0 +1,121 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <condition_variable> +#include <cstdio> +#include <random> +#include <thread> + +std::default_random_engine g_random_engine{std::random_device{}()}; +std::uniform_int_distribution<> g_distribution{0, 3000000}; +std::condition_variable g_condition_variable; +std::mutex g_mutex; +int g_count; + +char *g_char_ptr = nullptr; + +void +barrier_wait() +{ + std::unique_lock<std::mutex> lock{g_mutex}; + if (--g_count > 0) + g_condition_variable.wait(lock); + else + g_condition_variable.notify_all(); +} + +void +do_bad_thing_with_location(unsigned index, char *char_ptr, char new_val) +{ + unsigned what = new_val; + printf("new value written to array(%p) and index(%u) = %u\n", char_ptr, index, what); + char_ptr[index] = new_val; +} + +uint32_t +access_pool (bool flag = false) +{ + static std::mutex g_access_mutex; + static unsigned idx = 0; // Well-behaving thread only writes into indexs from 0..6. + if (!flag) + g_access_mutex.lock(); + + // idx valid range is [0, 6]. + if (idx > 6) + idx = 0; + + if (flag) + { + // Write into a forbidden area. + do_bad_thing_with_location(7, g_char_ptr, 99); + } + + unsigned index = idx++; + + if (!flag) + g_access_mutex.unlock(); + return g_char_ptr[index]; +} + +void +thread_func (uint32_t thread_index) +{ + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + barrier_wait(); + + uint32_t count = 0; + uint32_t val; + while (count++ < 15) + { + // random micro second sleep from zero to 3 seconds + int usec = g_distribution(g_random_engine); + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::this_thread::sleep_for(std::chrono::microseconds{usec}); + + if (count < 7) + val = access_pool (); + else + val = access_pool (true); + + printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); +} + + +int main (int argc, char const *argv[]) +{ + g_count = 4; + std::thread threads[3]; + + g_char_ptr = new char[10]{}; + + // Create 3 threads + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + struct { + int a; + int b; + int c; + } MyAggregateDataType; + + printf ("Before turning all three threads loose...\n"); // Set break point at this line. + barrier_wait(); + + // Join all of our threads + for (auto &thread : threads) + thread.join(); + + delete[] g_char_ptr; + + return 0; +} |