summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/packages/Python/lldbsuite/test/api
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lldb/packages/Python/lldbsuite/test/api')
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/Makefile3
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py69
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/main.cpp.template23
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile3
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py34
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp33
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/Makefile4
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/TestListener.py63
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/main.c7
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/log/TestAPILog.py51
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/.categories1
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/Makefile6
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py43
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/multi-process-driver.cpp287
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/testprog.cpp12
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/Makefile6
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/TestMultipleTargets.py42
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/main.cpp31
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/Makefile7
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py109
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h68
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/driver.cpp.template51
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/inferior.cpp17
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/listener_test.cpp.template74
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_breakpoint_callback.cpp.template49
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_description.cpp.template97
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp.template63
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_resume.cpp.template53
28 files changed, 1306 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/Makefile
new file mode 100644
index 00000000000..99998b20bcb
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py
new file mode 100644
index 00000000000..6f95cd7959e
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py
@@ -0,0 +1,69 @@
+"""Test the integrity of the lldb public api directory containing SB*.h headers.
+
+There should be nothing unwanted there and a simpe main.cpp which includes SB*.h
+should compile and link with the LLDB framework."""
+
+from __future__ import print_function
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SBDirCheckerCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.source = 'main.cpp'
+ self.generateSource(self.source)
+
+ @skipIfNoSBHeaders
+ def test_sb_api_directory(self):
+ """Test the SB API directory and make sure there's no unwanted stuff."""
+
+ # Only proceed if this is an Apple OS, "x86_64", and local platform.
+ if not (self.platformIsDarwin() and self.getArchitecture() == "x86_64"):
+ self.skipTest("This test is only for LLDB.framework built 64-bit")
+ if self.getArchitecture() == "i386":
+ self.skipTest(
+ "LLDB is 64-bit and cannot be linked to 32-bit test program.")
+
+ exe_name = self.getBuildArtifact("a.out")
+ self.buildDriver(self.source, exe_name)
+ self.sanity_check_executable(exe_name)
+
+ def sanity_check_executable(self, exe_name):
+ """Sanity check executable compiled from the auto-generated program."""
+ exe_name = self.getBuildArtifact("a.out")
+ exe = self.getBuildArtifact(exe_name)
+ self.runCmd("file %s" % exe, CURRENT_EXECUTABLE_SET)
+
+ # This test uses a generated source file, so it's in the build directory.
+ self.line_to_break = line_number(
+ self.getBuildArtifact(self.source), '// Set breakpoint here.')
+
+ env_cmd = "settings set target.env-vars %s=%s" % (
+ self.dylibPath, self.getLLDBLibraryEnvVal())
+ if self.TraceOn():
+ print("Set environment to: ", env_cmd)
+ self.runCmd(env_cmd)
+ self.addTearDownHook(
+ lambda: self.dbg.HandleCommand(
+ "settings remove target.env-vars %s" %
+ self.dylibPath))
+
+ lldbutil.run_break_set_by_file_and_line(
+ self, self.source, self.line_to_break, num_expected_locations=-1)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped',
+ 'stop reason = breakpoint'])
+
+ self.runCmd('frame variable')
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/main.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/main.cpp.template
new file mode 100644
index 00000000000..7fced85cd3a
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/check_public_api_headers/main.cpp.template
@@ -0,0 +1,23 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+%include_SB_APIs%
+
+using namespace lldb;
+int
+main(int argc, char const *argv[])
+{
+ SBDebugger::Initialize();
+ SBDebugger dbg = SBDebugger::Create();
+
+ printf("Hello SBDebugger %llu\n", dbg.GetID()); // Set breakpoint here.
+
+ SBDebugger::Terminate();
+ return 0;
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile
new file mode 100644
index 00000000000..99998b20bcb
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py
new file mode 100644
index 00000000000..c7aa2eced83
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py
@@ -0,0 +1,34 @@
+"""Test the lldb public C++ api for returning SBCommandReturnObject."""
+
+from __future__ import print_function
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestSBCommandReturnObject(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIfNoSBHeaders
+ @expectedFailureAll(
+ oslist=["windows"],
+ bugnumber="llvm.org/pr43570")
+ def test_sb_command_return_object(self):
+ env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
+
+ self.driver_exe = self.getBuildArtifact("command-return-object")
+ self.buildDriver('main.cpp', self.driver_exe)
+ self.addTearDownHook(lambda: os.remove(self.driver_exe))
+ self.signBinary(self.driver_exe)
+
+ if self.TraceOn():
+ print("Running test %s" % self.driver_exe)
+ check_call([self.driver_exe, self.driver_exe], env=env)
+ else:
+ with open(os.devnull, 'w') as fnull:
+ check_call([self.driver_exe, self.driver_exe],
+ env=env, stdout=fnull, stderr=fnull)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp
new file mode 100644
index 00000000000..c1d4d246a43
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp
@@ -0,0 +1,33 @@
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBCommandReturnObject.h"
+#include "lldb/API/SBDebugger.h"
+
+using namespace lldb;
+
+static SBCommandReturnObject subcommand(SBDebugger &dbg, const char *cmd) {
+ SBCommandReturnObject Result;
+ dbg.GetCommandInterpreter().HandleCommand(cmd, Result);
+ return Result;
+}
+
+class CommandCrasher : public SBCommandPluginInterface {
+public:
+ bool DoExecute(SBDebugger dbg, char **command,
+ SBCommandReturnObject &result) {
+ // Test assignment from a different SBCommandReturnObject instance.
+ result = subcommand(dbg, "help");
+ // Test also whether self-assignment is handled correctly.
+ result = result;
+ return result.Succeeded();
+ }
+};
+
+int main() {
+ SBDebugger::Initialize();
+ SBDebugger dbg = SBDebugger::Create(false /*source_init_files*/);
+ SBCommandInterpreter interp = dbg.GetCommandInterpreter();
+ static CommandCrasher crasher;
+ interp.AddCommand("crasher", &crasher, nullptr /*help*/);
+ SBCommandReturnObject Result;
+ dbg.GetCommandInterpreter().HandleCommand("crasher", Result);
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/Makefile
new file mode 100644
index 00000000000..692ba173228
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c
+
+include Makefile.rules
+
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/TestListener.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/TestListener.py
new file mode 100644
index 00000000000..480041b3e1f
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/TestListener.py
@@ -0,0 +1,63 @@
+"""
+Test that we can listen to modules loaded events.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+import six
+
+
+class ListenToModuleLoadedEvents (TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test_receiving_breakpoint_added(self):
+ """Test that we get breakpoint added events, waiting on event classes on the debugger"""
+ self.build()
+
+ my_listener = lldb.SBListener("test_listener")
+
+ my_listener.StartListeningForEventClass(
+ self.dbg,
+ lldb.SBTarget.GetBroadcasterClassName(),
+ lldb.SBTarget.eBroadcastBitBreakpointChanged)
+
+ exe = self.getBuildArtifact("a.out")
+
+ target = self.dbg.CreateTarget(exe)
+
+ bkpt = target.BreakpointCreateByName("main")
+
+ event = lldb.SBEvent()
+ my_listener.WaitForEvent(1, event)
+
+ self.assertTrue(event.IsValid(), "Got a valid event.")
+ self.assertTrue(
+ lldb.SBBreakpoint.EventIsBreakpointEvent(event),
+ "It is a breakpoint event.")
+ self.assertTrue(lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(
+ event) == lldb.eBreakpointEventTypeAdded, "It is a breakpoint added event.")
+ self.assertTrue(
+ bkpt == lldb.SBBreakpoint.GetBreakpointFromEvent(event),
+ "It is our breakpoint.")
+
+ # Now make sure if we stop listening for events we don't get them:
+
+ my_listener.StopListeningForEventClass(
+ self.dbg,
+ lldb.SBTarget.GetBroadcasterClassName(),
+ lldb.SBTarget.eBroadcastBitBreakpointChanged)
+ my_listener.StopListeningForEvents(
+ target.GetBroadcaster(),
+ lldb.SBTarget.eBroadcastBitBreakpointChanged)
+
+ bkpt2 = target.BreakpointCreateByName("main")
+ my_listener.WaitForEvent(1, event)
+ self.assertTrue(
+ not event.IsValid(),
+ "We don't get events we aren't listening to.")
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/main.c
new file mode 100644
index 00000000000..f930e511915
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/listeners/main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int
+main()
+{
+ printf ("Hello there.\n");
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/log/TestAPILog.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/log/TestAPILog.py
new file mode 100644
index 00000000000..c0ffa2c6f50
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/log/TestAPILog.py
@@ -0,0 +1,51 @@
+"""
+Test API logging.
+"""
+
+import re
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class APILogTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_api_log(self):
+ """Test API logging"""
+ logfile = os.path.join(self.getBuildDir(), "api-log.txt")
+
+ def cleanup():
+ if os.path.exists(logfile):
+ os.unlink(logfile)
+
+ self.addTearDownHook(cleanup)
+ self.expect("log enable lldb api -f {}".format(logfile))
+
+ self.dbg.SetDefaultArchitecture(None)
+ self.dbg.GetScriptingLanguage(None)
+ target = self.dbg.CreateTarget(None)
+
+ print(logfile)
+ with open(logfile, 'r') as f:
+ log = f.read()
+
+ # Find the SBDebugger's address.
+ debugger_addr = re.findall(
+ r"lldb::SBDebugger::GetScriptingLanguage\([^)]*\) \(0x([0-9a-fA-F]+),",
+ log)
+
+ # Make sure we've found a match.
+ self.assertTrue(debugger_addr, log)
+
+ # Make sure the GetScriptingLanguage matches.
+ self.assertTrue(re.search(r'lldb::SBDebugger::GetScriptingLanguage\([^)]*\) \(0x{}, ""\)'.format(
+ debugger_addr[0]), log), log)
+
+ # Make sure the address matches.
+ self.assertTrue(re.search(r'lldb::SBDebugger::CreateTarget\([^)]*\) \(0x{}, ""\)'.format(
+ debugger_addr[0]), log), log)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/.categories b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/.categories
new file mode 100644
index 00000000000..6e70196ccd7
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/.categories
@@ -0,0 +1 @@
+stresstest
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/Makefile
new file mode 100644
index 00000000000..f40386a5227
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/Makefile
@@ -0,0 +1,6 @@
+MAKE_DSYM := NO
+
+ENABLE_THREADS := YES
+CXX_SOURCES := multi-process-driver.cpp testprog.cpp
+
+include Makefile.rules
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py
new file mode 100644
index 00000000000..1447bbdfe42
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py
@@ -0,0 +1,43 @@
+"""Test the lldb public C++ api when doing multiple debug sessions simultaneously."""
+
+from __future__ import print_function
+
+
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestMultipleSimultaneousDebuggers(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ # This test case fails non-deterministically.
+ @skipIfNoSBHeaders
+ @expectedFailureAll(bugnumber="llvm.org/pr20282")
+ def test_multiple_debuggers(self):
+ env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
+
+ self.driver_exe = self.getBuildArtifact("multi-process-driver")
+ self.buildDriver('multi-process-driver.cpp', self.driver_exe)
+ self.addTearDownHook(lambda: os.remove(self.driver_exe))
+ self.signBinary(self.driver_exe)
+
+ self.inferior_exe = self.getBuildArtifact("testprog")
+ self.buildDriver('testprog.cpp', self.inferior_exe)
+ self.addTearDownHook(lambda: os.remove(self.inferior_exe))
+
+# check_call will raise a CalledProcessError if multi-process-driver doesn't return
+# exit code 0 to indicate success. We can let this exception go - the test harness
+# will recognize it as a test failure.
+
+ if self.TraceOn():
+ print("Running test %s" % self.driver_exe)
+ check_call([self.driver_exe, self.inferior_exe], env=env)
+ else:
+ with open(os.devnull, 'w') as fnull:
+ check_call([self.driver_exe, self.inferior_exe],
+ env=env, stdout=fnull, stderr=fnull)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/multi-process-driver.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/multi-process-driver.cpp
new file mode 100644
index 00000000000..15170a3e5eb
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/multi-process-driver.cpp
@@ -0,0 +1,287 @@
+
+// This program creates NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS of pthreads,
+// creates an lldb Debugger on each thread, creates targets, inserts two
+// breakpoints, runs to the first breakpoint, backtraces, runs to the second
+// breakpoint, backtraces, kills the inferior process, closes down the
+// debugger.
+
+// The main thread keeps track of which pthreads have completed and which
+// pthreads have completed successfully, and exits when all pthreads have
+// completed successfully, or our time limit has been exceeded.
+
+// This test file helps to uncover race conditions and locking mistakes
+// that are hit when lldb is being used to debug multiple processes
+// simultaneously.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lldb/API/LLDB.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBCommandReturnObject.h"
+#include "lldb/API/SBDebugger.h"
+
+#include <chrono>
+#include <thread>
+
+#define NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS 10
+
+#define DEBUG 0
+
+using namespace lldb;
+
+bool *completed_threads_array = 0;
+bool *successful_threads_array = 0;
+
+const char *inferior_process_name = "testprog";
+
+bool
+wait_for_stop_event (SBProcess process, SBListener listener)
+{
+ bool stopped = false;
+ while (!stopped)
+ {
+ SBEvent event;
+ bool waitfor_ret = listener.WaitForEvent (2, event);
+ if (event.GetType() == SBProcess::eBroadcastBitStateChanged)
+ {
+ if (process.GetState() == StateType::eStateStopped
+ || process.GetState() == StateType::eStateCrashed
+ || process.GetState() == StateType::eStateDetached
+ || process.GetState() == StateType::eStateExited)
+ {
+ stopped = true;
+ }
+ }
+ }
+ return stopped;
+}
+
+bool
+walk_stack_to_main (SBThread thread)
+{
+ if (thread.IsValid() == 0)
+ {
+ return false;
+ }
+
+ bool found_main = false;
+ uint32_t curr_frame = 0;
+ const uint32_t framecount = thread.GetNumFrames();
+ while (!found_main && curr_frame < framecount)
+ {
+ SBFrame frame = thread.GetFrameAtIndex (curr_frame);
+ if (strcmp (frame.GetFunctionName(), "main") == 0)
+ {
+ found_main = true;
+ break;
+ }
+ curr_frame += 1;
+ }
+ return found_main;
+}
+
+void *do_one_debugger (void *in)
+{
+ uint64_t threadnum = (uint64_t) in;
+
+#if defined (__APPLE__)
+ char *threadname;
+ asprintf (&threadname, "thread #%lld", threadnum);
+ pthread_setname_np (threadname);
+ free (threadname);
+#endif
+
+#if DEBUG == 1
+ printf ("#%lld: Starting debug session\n", threadnum);
+#endif
+
+ SBDebugger debugger = lldb::SBDebugger::Create (false);
+ if (debugger.IsValid ())
+ {
+ debugger.SetAsync (true);
+ SBTarget target = debugger.CreateTargetWithFileAndArch(inferior_process_name, "x86_64");
+ SBCommandInterpreter command_interp = debugger.GetCommandInterpreter();
+ if (target.IsValid())
+ {
+ SBBreakpoint bar_br = target.BreakpointCreateByName ("bar", "testprog");
+ if (!bar_br.IsValid())
+ {
+ printf ("#%lld: failed to set breakpoint on bar, exiting.\n", threadnum);
+ exit (1);
+ }
+ SBBreakpoint foo_br = target.BreakpointCreateByName ("foo", "testprog");
+ if (!foo_br.IsValid())
+ {
+ printf ("#%lld: Failed to set breakpoint on foo()\n", threadnum);
+ }
+
+ SBLaunchInfo launch_info (NULL);
+ SBError error;
+ SBProcess process = target.Launch (launch_info, error);
+ if (process.IsValid())
+ {
+ SBListener listener = debugger.GetListener();
+ SBBroadcaster broadcaster = process.GetBroadcaster();
+ uint32_t rc = broadcaster.AddListener (listener, SBProcess::eBroadcastBitStateChanged);
+ if (rc == 0)
+ {
+ printf ("adding listener failed\n");
+ exit (1);
+ }
+
+ wait_for_stop_event (process, listener);
+
+ if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
+ {
+ printf ("#%lld: backtrace while @ foo() failed\n", threadnum);
+ completed_threads_array[threadnum] = true;
+ return (void *) 1;
+ }
+
+ if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "foo") != 0)
+ {
+#if DEBUG == 1
+ printf ("#%lld: First breakpoint did not stop at foo(), instead stopped at '%s'\n", threadnum, process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName());
+#endif
+ completed_threads_array[threadnum] = true;
+ return (void*) 1;
+ }
+
+ process.Continue();
+
+ wait_for_stop_event (process, listener);
+
+ if (process.GetState() == StateType::eStateExited)
+ {
+ printf ("#%lld: Process exited\n", threadnum);
+ completed_threads_array[threadnum] = true;
+ return (void *) 1;
+ }
+
+
+ if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
+ {
+ printf ("#%lld: backtrace while @ bar() failed\n", threadnum);
+ completed_threads_array[threadnum] = true;
+ return (void *) 1;
+ }
+
+ if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "bar") != 0)
+ {
+ printf ("#%lld: First breakpoint did not stop at bar()\n", threadnum);
+ completed_threads_array[threadnum] = true;
+ return (void*) 1;
+ }
+
+ process.Kill();
+
+ wait_for_stop_event (process, listener);
+
+ SBDebugger::Destroy(debugger);
+
+#if DEBUG == 1
+ printf ("#%lld: All good!\n", threadnum);
+#endif
+ successful_threads_array[threadnum] = true;
+ completed_threads_array[threadnum] = true;
+ return (void*) 0;
+ }
+ else
+ {
+ printf("#%lld: process failed to launch\n", threadnum);
+ successful_threads_array[threadnum] = false;
+ completed_threads_array[threadnum] = true;
+ return (void*) 0;
+ }
+ }
+ else
+ {
+ printf ("#%lld: did not get valid target\n", threadnum);
+ successful_threads_array[threadnum] = false;
+ completed_threads_array[threadnum] = true;
+ return (void*) 0;
+ }
+ }
+ else
+ {
+ printf ("#%lld: did not get debugger\n", threadnum);
+ successful_threads_array[threadnum] = false;
+ completed_threads_array[threadnum] = true;
+ return (void*) 0;
+ }
+ completed_threads_array[threadnum] = true;
+ return (void*) 1;
+}
+
+int main (int argc, char **argv)
+{
+#if !defined(_MSC_VER)
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ SBDebugger::Initialize();
+
+ completed_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+ memset (completed_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+ successful_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+ memset (successful_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+
+ if (argc > 1 && argv[1] != NULL)
+ {
+ inferior_process_name = argv[1];
+ }
+
+ std::thread threads[NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS];
+ for (uint64_t i = 0; i< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)
+ {
+ threads[i] = std::move(std::thread(do_one_debugger, (void*)i));
+ }
+
+
+ int max_time_to_wait = 20; // 20 iterations, or 60 seconds
+ int iter = 0;
+ while (1)
+ {
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ bool all_done = true;
+ int successful_threads = 0;
+ int total_completed_threads = 0;
+ for (uint64_t i = 0; i < NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)
+ {
+ if (successful_threads_array[i] == true)
+ successful_threads++;
+ if (completed_threads_array[i] == true)
+ total_completed_threads++;
+ if (completed_threads_array[i] == false)
+ {
+ all_done = false;
+ }
+ }
+ if (all_done)
+ {
+#if DEBUG == 1
+ printf ("All threads completed.\n");
+ printf ("%d threads completed successfully out of %d\n", successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+#endif
+ SBDebugger::Terminate();
+ exit(0);
+ }
+ else
+ {
+#if DEBUG == 1
+ printf ("%d threads completed so far (%d successfully), out of %d\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+#endif
+ }
+ if (iter++ == max_time_to_wait)
+ {
+ printf ("reached maximum timeout but only %d threads have completed so far (%d successfully), out of %d. Exiting.\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
+ break;
+ }
+ }
+
+
+ SBDebugger::Terminate();
+ exit (1);
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/testprog.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/testprog.cpp
new file mode 100644
index 00000000000..c9d1ea14f17
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-debuggers/testprog.cpp
@@ -0,0 +1,12 @@
+int bar ()
+{
+ return 5;
+}
+int foo ()
+{
+ return bar() + 5;
+}
+int main ()
+{
+ return foo();
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/Makefile
new file mode 100644
index 00000000000..3316b59b623
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/Makefile
@@ -0,0 +1,6 @@
+MAKE_DSYM := NO
+
+ENABLE_THREADS := YES
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/TestMultipleTargets.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/TestMultipleTargets.py
new file mode 100644
index 00000000000..1268ff9306a
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/TestMultipleTargets.py
@@ -0,0 +1,42 @@
+"""Test the lldb public C++ api when creating multiple targets simultaneously."""
+
+from __future__ import print_function
+
+
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestMultipleTargets(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIfNoSBHeaders
+ @skipIfHostIncompatibleWithRemote
+ @expectedFailureAll(
+ oslist=["windows", "freebsd"],
+ bugnumber="llvm.org/pr20282")
+ def test_multiple_targets(self):
+ env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
+
+ self.driver_exe = self.getBuildArtifact("multi-target")
+ self.buildDriver('main.cpp', self.driver_exe)
+ self.addTearDownHook(lambda: os.remove(self.driver_exe))
+ self.signBinary(self.driver_exe)
+
+# check_call will raise a CalledProcessError if multi-process-driver doesn't return
+# exit code 0 to indicate success. We can let this exception go - the test harness
+# will recognize it as a test failure.
+
+ if self.TraceOn():
+ print("Running test %s" % self.driver_exe)
+ check_call([self.driver_exe, self.driver_exe], env=env)
+ else:
+ with open(os.devnull, 'w') as fnull:
+ check_call([self.driver_exe, self.driver_exe],
+ env=env, stdout=fnull, stderr=fnull)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/main.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/main.cpp
new file mode 100644
index 00000000000..35fb4e0d613
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multiple-targets/main.cpp
@@ -0,0 +1,31 @@
+#include <thread>
+
+#include "lldb/API/LLDB.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBTarget.h"
+
+using namespace lldb;
+int main (int argc, char **argv)
+{
+ // We are expecting the program path and a path to an executable to load
+ if (argc != 2)
+ return 1;
+ const char *program_file = argv[1];
+ SBDebugger::Initialize();
+ SBDebugger debugger = SBDebugger::Create(false);
+ auto lambda = [&](){
+ SBError error;
+ SBTarget target = debugger.CreateTarget(program_file, nullptr, nullptr,
+ false, error);
+ };
+
+ // Create 3 targets at the same time and make sure we don't crash.
+ std::thread thread1(lambda);
+ std::thread thread2(lambda);
+ std::thread thread3(lambda);
+ thread1.join();
+ thread2.join();
+ thread3.join();
+ SBDebugger::Terminate();
+ return 0;
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/Makefile
new file mode 100644
index 00000000000..81767219067
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/Makefile
@@ -0,0 +1,7 @@
+ENABLE_THREADS := YES
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
+
+clean::
+ rm -rf $(wildcard *.o *.d *.dSYM)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
new file mode 100644
index 00000000000..436f645e652
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
@@ -0,0 +1,109 @@
+"""Test the lldb public C++ api breakpoint callbacks."""
+
+from __future__ import print_function
+
+# __package__ = "lldbsuite.test"
+
+
+import os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SBBreakpointCallbackCase(TestBase):
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.generateSource('driver.cpp')
+ self.generateSource('listener_test.cpp')
+ self.generateSource('test_breakpoint_callback.cpp')
+ self.generateSource('test_listener_event_description.cpp')
+ self.generateSource('test_listener_event_process_state.cpp')
+ self.generateSource('test_listener_resume.cpp')
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfRemote
+ @skipIfNoSBHeaders
+ # clang-cl does not support throw or catch (llvm.org/pr24538)
+ @skipIfWindows
+ def test_breakpoint_callback(self):
+ """Test the that SBBreakpoint callback is invoked when a breakpoint is hit. """
+ self.build_and_test('driver.cpp test_breakpoint_callback.cpp',
+ 'test_breakpoint_callback')
+
+ @skipIfRemote
+ @skipIfNoSBHeaders
+ # clang-cl does not support throw or catch (llvm.org/pr24538)
+ @skipIfWindows
+ @expectedFlakeyFreeBSD
+ def test_sb_api_listener_event_description(self):
+ """ Test the description of an SBListener breakpoint event is valid."""
+ self.build_and_test(
+ 'driver.cpp listener_test.cpp test_listener_event_description.cpp',
+ 'test_listener_event_description')
+
+ @skipIfRemote
+ @skipIfNoSBHeaders
+ # clang-cl does not support throw or catch (llvm.org/pr24538)
+ @skipIfWindows
+ @expectedFlakeyFreeBSD
+ def test_sb_api_listener_event_process_state(self):
+ """ Test that a registered SBListener receives events when a process
+ changes state.
+ """
+ self.build_and_test(
+ 'driver.cpp listener_test.cpp test_listener_event_process_state.cpp',
+ 'test_listener_event_process_state')
+
+ @skipIfRemote
+ @skipIfNoSBHeaders
+ # clang-cl does not support throw or catch (llvm.org/pr24538)
+ @skipIfWindows
+ @expectedFlakeyFreeBSD
+ @skipIf(oslist=["linux"]) # flakey
+ def test_sb_api_listener_resume(self):
+ """ Test that a process can be resumed from a non-main thread. """
+ self.build_and_test(
+ 'driver.cpp listener_test.cpp test_listener_resume.cpp',
+ 'test_listener_resume')
+
+ def build_and_test(self, sources, test_name, args=None):
+ """ Build LLDB test from sources, and run expecting 0 exit code """
+
+ # These tests link against host lldb API.
+ # Compiler's target triple must match liblldb triple
+ # because remote is disabled, we can assume that the os is the same
+ # still need to check architecture
+ if self.getLldbArchitecture() != self.getArchitecture():
+ self.skipTest(
+ "This test is only run if the target arch is the same as the lldb binary arch")
+
+ self.inferior = 'inferior_program'
+ self.buildProgram('inferior.cpp', self.inferior)
+ self.addTearDownHook(lambda:
+ os.remove(self.getBuildArtifact(self.inferior)))
+
+ self.buildDriver(sources, test_name)
+ self.addTearDownHook(lambda:
+ os.remove(self.getBuildArtifact(test_name)))
+
+ test_exe = self.getBuildArtifact(test_name)
+ self.signBinary(test_exe)
+ exe = [test_exe, self.getBuildArtifact(self.inferior)]
+
+ env = {self.dylibPath: self.getLLDBLibraryEnvVal()}
+ if 'LLDB_DEBUGSERVER_PATH' in os.environ:
+ env['LLDB_DEBUGSERVER_PATH'] = os.environ['LLDB_DEBUGSERVER_PATH']
+ if self.TraceOn():
+ print("Running test %s" % " ".join(exe))
+ check_call(exe, env=env)
+ else:
+ with open(os.devnull, 'w') as fnull:
+ check_call(exe, env=env, stdout=fnull, stderr=fnull)
+
+ def build_program(self, sources, program):
+ return self.buildDriver(sources, program)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h
new file mode 100644
index 00000000000..bd40bdd421a
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h
@@ -0,0 +1,68 @@
+#ifndef LLDB_TEST_API_COMMON_H
+#define LLDB_TEST_API_COMMON_H
+
+#include <condition_variable>
+#include <chrono>
+#include <exception>
+#include <iostream>
+#include <mutex>
+#include <string>
+#include <queue>
+
+#include <unistd.h>
+
+/// Simple exception class with a message
+struct Exception : public std::exception
+{
+ std::string s;
+ Exception(std::string ss) : s(ss) {}
+ virtual ~Exception() throw () { }
+ const char* what() const throw() { return s.c_str(); }
+};
+
+// Synchronized data structure for listener to send events through
+template<typename T>
+class multithreaded_queue {
+ std::condition_variable m_condition;
+ std::mutex m_mutex;
+ std::queue<T> m_data;
+ bool m_notified;
+
+public:
+
+ void push(T e) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_data.push(e);
+ m_notified = true;
+ m_condition.notify_all();
+ }
+
+ T pop(int timeout_seconds, bool &success) {
+ int count = 0;
+ while (count < timeout_seconds) {
+ std::unique_lock<std::mutex> lock(m_mutex);
+ if (!m_data.empty()) {
+ m_notified = false;
+ T ret = m_data.front();
+ m_data.pop();
+ success = true;
+ return ret;
+ } else if (!m_notified)
+ m_condition.wait_for(lock, std::chrono::seconds(1));
+ count ++;
+ }
+ success = false;
+ return T();
+ }
+};
+
+/// Allocates a char buffer with the current working directory
+inline char* get_working_dir() {
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ return getwd(0);
+#else
+ return get_current_dir_name();
+#endif
+}
+
+#endif // LLDB_TEST_API_COMMON_H
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/driver.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/driver.cpp.template
new file mode 100644
index 00000000000..32459425c88
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/driver.cpp.template
@@ -0,0 +1,51 @@
+
+/// LLDB C API Test Driver
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+#if !defined(_MSC_VER)
+ #include <signal.h>
+#endif
+
+%include_SB_APIs%
+
+#include "common.h"
+
+using namespace std;
+using namespace lldb;
+
+void test(SBDebugger &dbg, std::vector<string> args);
+
+int main(int argc, char** argv) {
+
+// Ignore SIGPIPE. The lldb driver does this as well,
+// because we seem to get spurious SIGPIPES on some
+// Unixen that take the driver down.
+#if !defined(_MSC_VER)
+ signal(SIGPIPE, SIG_IGN);
+#endif
+ int code = 0;
+
+ SBDebugger::Initialize();
+ SBDebugger dbg = SBDebugger::Create();
+ dbg.HandleCommand("settings set symbols.enable-external-lookup false");
+ dbg.HandleCommand(
+ "settings set plugin.process.gdb-remote.packet-timeout 60");
+
+ try {
+ if (!dbg.IsValid())
+ throw Exception("invalid debugger");
+ vector<string> args(argv + 1, argv + argc);
+
+ test(dbg, args);
+ } catch (Exception &e) {
+ cout << "ERROR: " << e.what() << endl;
+ code = 1;
+ }
+
+ SBDebugger::Destroy(dbg);
+ return code;
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/inferior.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/inferior.cpp
new file mode 100644
index 00000000000..9dbb289f98b
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/inferior.cpp
@@ -0,0 +1,17 @@
+
+#include <iostream>
+
+using namespace std;
+
+int next() {
+ static int i = 0;
+ cout << "incrementing " << i << endl;
+ return ++i;
+}
+
+int main() {
+ int i = 0;
+ while (i < 5)
+ i = next();
+ return 0;
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/listener_test.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/listener_test.cpp.template
new file mode 100644
index 00000000000..e305d1af489
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/listener_test.cpp.template
@@ -0,0 +1,74 @@
+// LLDB test snippet that registers a listener with a process that hits
+// a breakpoint.
+
+#include <atomic>
+#include <iostream>
+#include <string>
+#include <thread>
+#include <vector>
+
+%include_SB_APIs%
+#include "common.h"
+
+using namespace lldb;
+using namespace std;
+
+void listener_func();
+void check_listener(SBDebugger &dbg);
+
+// Listener thread and related variables
+atomic<bool> g_done;
+SBListener g_listener("test-listener");
+thread g_listener_thread;
+
+void shutdown_listener() {
+ g_done.store(true);
+ if (g_listener_thread.joinable())
+ g_listener_thread.join();
+}
+
+void test(SBDebugger &dbg, std::vector<string> args) {
+ try {
+ g_done.store(false);
+ SBTarget target = dbg.CreateTarget(args.at(0).c_str());
+ if (!target.IsValid()) throw Exception("invalid target");
+
+ SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
+ if (!breakpoint.IsValid()) throw Exception("invalid breakpoint");
+
+ std::unique_ptr<char> working_dir(get_working_dir());
+
+ SBError error;
+ SBProcess process = target.Launch(g_listener,
+ 0, 0, 0, 0, 0,
+ working_dir.get(),
+ 0,
+ false,
+ error);
+ if (!error.Success())
+ throw Exception("Error launching process.");
+
+ /* FIXME: the approach below deadlocks
+ SBProcess process = target.LaunchSimple (0, 0, working_dir.get());
+
+ // get debugger listener (which is attached to process by default)
+ g_listener = dbg.GetListener();
+ */
+
+ // FIXME: because a listener is attached to the process at launch-time,
+ // registering the listener below results in two listeners being attached,
+ // which is not supported by LLDB.
+ // register listener
+ // process.GetBroadcaster().AddListener(g_listener,
+ // SBProcess::eBroadcastBitStateChanged);
+
+ // start listener thread
+ g_listener_thread = thread(listener_func);
+ check_listener(dbg);
+
+ } catch (Exception &e) {
+ shutdown_listener();
+ throw e;
+ }
+ shutdown_listener();
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_breakpoint_callback.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_breakpoint_callback.cpp.template
new file mode 100644
index 00000000000..4133025aa49
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_breakpoint_callback.cpp.template
@@ -0,0 +1,49 @@
+
+// LLDB C++ API Test: verify that the function registered with
+// SBBreakpoint.SetCallback() is invoked when a breakpoint is hit.
+
+#include <mutex>
+#include <iostream>
+#include <vector>
+#include <string>
+
+%include_SB_APIs%
+
+#include "common.h"
+
+using namespace std;
+using namespace lldb;
+
+mutex g_mutex;
+condition_variable g_condition;
+int g_breakpoint_hit_count = 0;
+
+bool BPCallback (void *baton,
+ SBProcess &process,
+ SBThread &thread,
+ SBBreakpointLocation &location) {
+ lock_guard<mutex> lock(g_mutex);
+ g_breakpoint_hit_count += 1;
+ g_condition.notify_all();
+ return true;
+}
+
+void test(SBDebugger &dbg, vector<string> args) {
+ dbg.SetAsync(false);
+ SBTarget target = dbg.CreateTarget(args.at(0).c_str());
+ if (!target.IsValid()) throw Exception("invalid target");
+
+ SBBreakpoint breakpoint = target.BreakpointCreateByName("next");
+ if (!breakpoint.IsValid()) throw Exception("invalid breakpoint");
+ breakpoint.SetCallback(BPCallback, 0);
+
+ std::unique_ptr<char> working_dir(get_working_dir());
+ SBProcess process = target.LaunchSimple (0, 0, working_dir.get());
+
+ {
+ unique_lock<mutex> lock(g_mutex);
+ g_condition.wait_for(lock, chrono::seconds(5));
+ if (g_breakpoint_hit_count != 1)
+ throw Exception("Breakpoint hit count expected to be 1");
+ }
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_description.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_description.cpp.template
new file mode 100644
index 00000000000..63e3f3631e5
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_description.cpp.template
@@ -0,0 +1,97 @@
+
+// LLDB C++ API Test: verify the event description that is received by an
+// SBListener object registered with a process with a breakpoint.
+
+#include <atomic>
+#include <array>
+#include <iostream>
+#include <string>
+#include <thread>
+
+%include_SB_APIs%
+
+#include "common.h"
+
+using namespace lldb;
+using namespace std;
+
+// listener thread control
+extern atomic<bool> g_done;
+extern SBListener g_listener;
+
+multithreaded_queue<string> g_event_descriptions;
+string g_error_desc;
+
+void listener_func() {
+ while (!g_done) {
+ SBEvent event;
+ bool got_event = g_listener.WaitForEvent(1, event);
+
+ if (got_event) {
+ if (!event.IsValid())
+ throw Exception("event is not valid in listener thread");
+
+ SBStream description;
+ event.GetDescription(description);
+ string str(description.GetData());
+ g_event_descriptions.push(str);
+ }
+ }
+}
+
+bool check_state(string &state, string &desc, bool got_description)
+{
+ g_error_desc.clear();
+
+ if(!got_description)
+ {
+ g_error_desc.append("Did not get expected event description");
+ return false;
+ }
+
+ if (desc.find("state-changed") == desc.npos)
+ g_error_desc.append("Event description incorrect: missing 'state-changed' ");
+
+ if (desc.find("pid = ") == desc.npos)
+ g_error_desc.append("Event description incorrect: missing process pid ");
+
+ string state_search_str = "state = " + state;
+ if (desc.find(state_search_str) == desc.npos)
+ {
+ string errString = ("Event description incorrect: expected state "
+ + state
+ + " but desc was "
+ + desc);
+ g_error_desc.append(errString);
+ }
+
+ if (g_error_desc.length() > 0)
+ return false;
+
+ cout << "check_state: " << state << " OK\n";
+ return true;
+}
+
+void check_listener(SBDebugger &dbg)
+{
+ bool got_description;
+ string state;
+
+ // check for "launching" state, this may or may not be present
+ string desc = g_event_descriptions.pop(5, got_description);
+ state = "launching";
+ if (check_state(state, desc, got_description))
+ {
+ // found a 'launching' state, pop next one from queue
+ desc = g_event_descriptions.pop(5, got_description);
+ }
+
+ state = "running";
+ if( !check_state(state, desc, got_description) )
+ throw Exception(g_error_desc);
+
+ desc = g_event_descriptions.pop(5, got_description);
+ state = "stopped";
+ if( !check_state(state, desc, got_description) )
+ throw Exception(g_error_desc);
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp.template
new file mode 100644
index 00000000000..2926ece4d8d
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp.template
@@ -0,0 +1,63 @@
+
+// LLDB C++ API Test: verify the event description as obtained by calling
+// SBEvent::GetCStringFromEvent that is received by an
+// SBListener object registered with a process with a breakpoint.
+
+#include <atomic>
+#include <iostream>
+#include <string>
+#include <thread>
+
+%include_SB_APIs%
+
+#include "common.h"
+
+using namespace lldb;
+using namespace std;
+
+// listener thread control
+extern atomic<bool> g_done;
+
+multithreaded_queue<string> g_frame_functions;
+
+extern SBListener g_listener;
+
+void listener_func() {
+ while (!g_done) {
+ SBEvent event;
+ bool got_event = g_listener.WaitForEvent(1, event);
+ if (got_event) {
+ if (!event.IsValid())
+ throw Exception("event is not valid in listener thread");
+ // send process description
+ SBProcess process = SBProcess::GetProcessFromEvent(event);
+ if (!process.IsValid())
+ throw Exception("process is not valid");
+ if (SBProcess::GetStateFromEvent(event) != lldb::eStateStopped || SBProcess::GetRestartedFromEvent(event))
+ continue; // Only interested in "stopped" events.
+
+ SBStream description;
+
+ for (int i = 0; i < process.GetNumThreads(); ++i) {
+ // send each thread description
+ SBThread thread = process.GetThreadAtIndex(i);
+ // send each frame function name
+ uint32_t num_frames = thread.GetNumFrames();
+ for(int j = 0; j < num_frames; ++j) {
+ const char* function_name = thread.GetFrameAtIndex(j).GetSymbol().GetName();
+ if (function_name)
+ g_frame_functions.push(string(function_name));
+ }
+ }
+ }
+ }
+}
+
+void check_listener(SBDebugger &dbg) {
+ // check thread description
+ bool got_description = false;
+ string func_name = g_frame_functions.pop(5, got_description);
+
+ if(got_description == false)
+ throw Exception("Expected at least one frame function");
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_resume.cpp.template b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_resume.cpp.template
new file mode 100644
index 00000000000..4adc9b33887
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/api/multithreaded/test_listener_resume.cpp.template
@@ -0,0 +1,53 @@
+
+// LLDB C++ API Test: verify the event description as obtained by calling
+// SBEvent::GetCStringFromEvent that is received by an
+// SBListener object registered with a process with a breakpoint.
+
+#include <atomic>
+#include <iostream>
+#include <string>
+#include <thread>
+
+%include_SB_APIs%
+
+#include "common.h"
+
+using namespace lldb;
+using namespace std;
+
+// listener thread control
+extern atomic<bool> g_done;
+
+// used by listener thread to communicate a successful process continue command
+// back to the checking thread.
+
+multithreaded_queue<bool> g_process_started;
+
+extern SBListener g_listener;
+
+void listener_func() {
+ while (!g_done) {
+ SBEvent event;
+ bool got_event = g_listener.WaitForEvent(1, event);
+ if (got_event) {
+ if (!event.IsValid())
+ throw Exception("event is not valid in listener thread");
+
+ SBProcess process = SBProcess::GetProcessFromEvent(event);
+ if (process.GetState() == eStateStopped) {
+ SBError error = process.Continue();
+ if (!error.Success())
+ throw Exception(string("Cannot continue process from listener thread: ")
+ + error.GetCString());
+ g_process_started.push(true);
+ }
+ }
+ }
+}
+
+void check_listener(SBDebugger &dbg) {
+ bool got_message = false;
+ while (!got_message)
+ g_process_started.pop(5, got_message);
+ g_done = true;
+}