summaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/tools/lldb-server
diff options
context:
space:
mode:
Diffstat (limited to 'packages/Python/lldbsuite/test/tools/lldb-server')
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/.clang-format1
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteHostInfo.py (renamed from packages/Python/lldbsuite/test/tools/lldb-server/host-info/TestGdbRemoteHostInfo.py)0
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py119
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py60
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/exit-code/main.cpp630
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py18
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/main.cpp50
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/main.cpp639
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/main.cpp7
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py115
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp37
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/thread-name/Makefile (renamed from packages/Python/lldbsuite/test/tools/lldb-server/host-info/Makefile)4
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py41
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp22
15 files changed, 1027 insertions, 721 deletions
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/.clang-format b/packages/Python/lldbsuite/test/tools/lldb-server/.clang-format
new file mode 100644
index 0000000000000..9b3aa8b7213b2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: LLVM
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/host-info/TestGdbRemoteHostInfo.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteHostInfo.py
index 5089ee85773f5..5089ee85773f5 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/host-info/TestGdbRemoteHostInfo.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteHostInfo.py
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
index 57d4d5ab4bb1c..b361b9e6d9157 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
@@ -1,11 +1,13 @@
from __future__ import print_function
+import json
+import re
+
import gdbremote_testcase
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-
class TestGdbRemoteThreadsInStopReply(
gdbremote_testcase.GdbRemoteTestCaseBase):
@@ -16,7 +18,8 @@ class TestGdbRemoteThreadsInStopReply(
"send packet: $OK#00",
]
- def gather_stop_reply_threads(self, post_startup_log_lines, thread_count):
+ def gather_stop_reply_fields(self, post_startup_log_lines, thread_count,
+ field_names):
# Set up the inferior args.
inferior_args = []
for i in range(thread_count - 1):
@@ -25,6 +28,9 @@ class TestGdbRemoteThreadsInStopReply(
procs = self.prep_debug_monitor_and_inferior(
inferior_args=inferior_args)
+ self.add_register_info_collection_packets()
+ self.add_process_info_collection_packets()
+
# Assumes test_sequence has anything added needed to setup the initial state.
# (Like optionally enabling QThreadsInStopReply.)
if post_startup_log_lines:
@@ -34,6 +40,7 @@ class TestGdbRemoteThreadsInStopReply(
], True)
context = self.expect_gdbremote_sequence()
self.assertIsNotNone(context)
+ hw_info = self.parse_hw_info(context)
# Give threads time to start up, then break.
time.sleep(1)
@@ -77,14 +84,89 @@ class TestGdbRemoteThreadsInStopReply(
kv_dict = self.parse_key_val_dict(key_vals_text)
self.assertIsNotNone(kv_dict)
+ result = dict();
+ result["pc_register"] = hw_info["pc_register"]
+ result["little_endian"] = hw_info["little_endian"]
+ for key_field in field_names:
+ result[key_field] = kv_dict.get(key_field)
+
+ return result
+
+ def gather_stop_reply_threads(self, post_startup_log_lines, thread_count):
# Pull out threads from stop response.
- stop_reply_threads_text = kv_dict.get("threads")
+ stop_reply_threads_text = self.gather_stop_reply_fields(
+ post_startup_log_lines, thread_count, ["threads"])["threads"]
if stop_reply_threads_text:
return [int(thread_id, 16)
for thread_id in stop_reply_threads_text.split(",")]
else:
return []
+ def gather_stop_reply_pcs(self, post_startup_log_lines, thread_count):
+ results = self.gather_stop_reply_fields( post_startup_log_lines,
+ thread_count, ["threads", "thread-pcs"])
+ if not results:
+ return []
+
+ threads_text = results["threads"]
+ pcs_text = results["thread-pcs"]
+ thread_ids = threads_text.split(",")
+ pcs = pcs_text.split(",")
+ self.assertTrue(len(thread_ids) == len(pcs))
+
+ thread_pcs = dict()
+ for i in range(0, len(pcs)):
+ thread_pcs[int(thread_ids[i], 16)] = pcs[i]
+
+ result = dict()
+ result["thread_pcs"] = thread_pcs
+ result["pc_register"] = results["pc_register"]
+ result["little_endian"] = results["little_endian"]
+ return result
+
+ def switch_endian(self, egg):
+ return "".join(reversed(re.findall("..", egg)))
+
+ def parse_hw_info(self, context):
+ self.assertIsNotNone(context)
+ process_info = self.parse_process_info_response(context)
+ endian = process_info.get("endian")
+ reg_info = self.parse_register_info_packets(context)
+ (pc_lldb_reg_index, pc_reg_info) = self.find_pc_reg_info(reg_info)
+
+ hw_info = dict()
+ hw_info["pc_register"] = pc_lldb_reg_index
+ hw_info["little_endian"] = (endian == "little")
+ return hw_info
+
+ def gather_threads_info_pcs(self, pc_register, little_endian):
+ self.reset_test_sequence()
+ self.test_sequence.add_log_lines(
+ [
+ "read packet: $jThreadsInfo#c1",
+ {
+ "direction": "send",
+ "regex": r"^\$(.*)#[0-9a-fA-F]{2}$",
+ "capture": {
+ 1: "threads_info"}},
+ ],
+ True)
+
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+ threads_info = context.get("threads_info")
+ register = str(pc_register)
+ # The jThreadsInfo response is not valid JSON data, so we have to
+ # clean it up first.
+ jthreads_info = json.loads(re.sub(r"}]", "}", threads_info))
+ thread_pcs = dict()
+ for thread_info in jthreads_info:
+ tid = thread_info["tid"]
+ pc = thread_info["registers"][register]
+ thread_pcs[tid] = self.switch_endian(pc) if little_endian else pc
+
+ return thread_pcs
+
def QListThreadsInStopReply_supported(self):
procs = self.prep_debug_monitor_and_inferior()
self.test_sequence.add_log_lines(
@@ -183,3 +265,34 @@ class TestGdbRemoteThreadsInStopReply(
self.build()
self.set_inferior_startup_launch()
self.stop_reply_reports_correct_threads(5)
+
+ def stop_reply_contains_thread_pcs(self, thread_count):
+ results = self.gather_stop_reply_pcs(
+ self.ENABLE_THREADS_IN_STOP_REPLY_ENTRIES, thread_count)
+ stop_reply_pcs = results["thread_pcs"]
+ pc_register = results["pc_register"]
+ little_endian = results["little_endian"]
+ self.assertEqual(len(stop_reply_pcs), thread_count)
+
+ threads_info_pcs = self.gather_threads_info_pcs(pc_register,
+ little_endian)
+
+ self.assertEqual(len(threads_info_pcs), thread_count)
+ for thread_id in stop_reply_pcs:
+ self.assertTrue(thread_id in threads_info_pcs)
+ self.assertTrue(int(stop_reply_pcs[thread_id], 16)
+ == int(threads_info_pcs[thread_id], 16))
+
+ @llgs_test
+ def test_stop_reply_contains_thread_pcs_llgs(self):
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ self.stop_reply_contains_thread_pcs(5)
+
+ @debugserver_test
+ def test_stop_reply_contains_thread_pcs_debugserver(self):
+ self.init_debugserver_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ self.stop_reply_contains_thread_pcs(5)
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
index b69ac3f8d2a30..6f36fbea470b0 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
@@ -1082,7 +1082,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
self.set_inferior_startup_launch()
self.qMemoryRegionInfo_reports_heap_address_as_readable_writeable()
- def software_breakpoint_set_and_remove_work(self):
+ def breakpoint_set_and_remove_work(self, want_hardware=False):
# Start up the inferior.
procs = self.prep_debug_monitor_and_inferior(
inferior_args=[
@@ -1126,15 +1126,27 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
self.assertIsNotNone(context.get("function_address"))
function_address = int(context.get("function_address"), 16)
+ # Get current target architecture
+ target_arch = self.getArchitecture()
+
# Set the breakpoint.
- if self.getArchitecture() == "arm":
+ if (target_arch == "arm") or (target_arch == "aarch64"):
# TODO: Handle case when setting breakpoint in thumb code
BREAKPOINT_KIND = 4
else:
BREAKPOINT_KIND = 1
+
+ # Set default packet type to Z0 (software breakpoint)
+ z_packet_type = 0
+
+ # If hardware breakpoint is requested set packet type to Z1
+ if want_hardware == True:
+ z_packet_type = 1
+
self.reset_test_sequence()
self.add_set_breakpoint_packets(
function_address,
+ z_packet_type,
do_continue=True,
breakpoint_kind=BREAKPOINT_KIND)
@@ -1182,13 +1194,15 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
# Verify that a breakpoint remove and continue gets us the expected
# output.
self.reset_test_sequence()
+
+ # Add breakpoint remove packets
+ self.add_remove_breakpoint_packets(
+ function_address,
+ z_packet_type,
+ breakpoint_kind=BREAKPOINT_KIND)
+
self.test_sequence.add_log_lines(
[
- # Remove the breakpoint.
- "read packet: $z0,{0:x},{1}#00".format(
- function_address, BREAKPOINT_KIND),
- # Verify the stub could unset it.
- "send packet: $OK#00",
# Continue running.
"read packet: $c#63",
# We should now receive the output from the call.
@@ -1209,7 +1223,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
else:
self.build()
self.set_inferior_startup_launch()
- self.software_breakpoint_set_and_remove_work()
+ self.breakpoint_set_and_remove_work(want_hardware=False)
@llgs_test
@expectedFlakeyLinux("llvm.org/pr25652")
@@ -1221,7 +1235,35 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
else:
self.build()
self.set_inferior_startup_launch()
- self.software_breakpoint_set_and_remove_work()
+ self.breakpoint_set_and_remove_work(want_hardware=False)
+
+ @debugserver_test
+ @skipUnlessPlatform(oslist=['linux'])
+ @expectedFailureAndroid
+ @skipIf(archs=no_match(['arm', 'aarch64']))
+ def test_hardware_breakpoint_set_and_remove_work_debugserver(self):
+ self.init_debugserver_test()
+ if self.getArchitecture() == "arm":
+ # TODO: Handle case when setting breakpoint in thumb code
+ self.build(dictionary={'CFLAGS_EXTRAS': '-marm'})
+ else:
+ self.build()
+ self.set_inferior_startup_launch()
+ self.breakpoint_set_and_remove_work(want_hardware=True)
+
+ @llgs_test
+ @skipUnlessPlatform(oslist=['linux'])
+ @expectedFailureAndroid
+ @skipIf(archs=no_match(['arm', 'aarch64']))
+ def test_hardware_breakpoint_set_and_remove_work_llgs(self):
+ self.init_llgs_test()
+ if self.getArchitecture() == "arm":
+ # TODO: Handle case when setting breakpoint in thumb code
+ self.build(dictionary={'CFLAGS_EXTRAS': '-marm'})
+ else:
+ self.build()
+ self.set_inferior_startup_launch()
+ self.breakpoint_set_and_remove_work(want_hardware=True)
def qSupported_returns_known_stub_features(self):
# Start up the stub and start/prep the inferior.
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/main.cpp
index b97c6ebc18e33..a3691a8d42b90 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/main.cpp
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/main.cpp
@@ -15,22 +15,24 @@
#if defined(__APPLE__)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_threadid_np(pthread_t,__uint64_t*);
+int pthread_threadid_np(pthread_t, __uint64_t *);
#elif defined(__linux__)
#include <sys/syscall.h>
+#elif defined(__NetBSD__)
+#include <lwp.h>
#endif
-static const char *const RETVAL_PREFIX = "retval:";
-static const char *const SLEEP_PREFIX = "sleep:";
-static const char *const STDERR_PREFIX = "stderr:";
-static const char *const SET_MESSAGE_PREFIX = "set-message:";
-static const char *const PRINT_MESSAGE_COMMAND = "print-message:";
-static const char *const GET_DATA_ADDRESS_PREFIX = "get-data-address-hex:";
-static const char *const GET_STACK_ADDRESS_COMMAND = "get-stack-address-hex:";
-static const char *const GET_HEAP_ADDRESS_COMMAND = "get-heap-address-hex:";
+static const char *const RETVAL_PREFIX = "retval:";
+static const char *const SLEEP_PREFIX = "sleep:";
+static const char *const STDERR_PREFIX = "stderr:";
+static const char *const SET_MESSAGE_PREFIX = "set-message:";
+static const char *const PRINT_MESSAGE_COMMAND = "print-message:";
+static const char *const GET_DATA_ADDRESS_PREFIX = "get-data-address-hex:";
+static const char *const GET_STACK_ADDRESS_COMMAND = "get-stack-address-hex:";
+static const char *const GET_HEAP_ADDRESS_COMMAND = "get-heap-address-hex:";
-static const char *const GET_CODE_ADDRESS_PREFIX = "get-code-address-hex:";
-static const char *const CALL_FUNCTION_PREFIX = "call-function:";
+static const char *const GET_CODE_ADDRESS_PREFIX = "get-code-address-hex:";
+static const char *const CALL_FUNCTION_PREFIX = "call-function:";
static const char *const THREAD_PREFIX = "thread:";
static const char *const THREAD_COMMAND_NEW = "new";
@@ -50,342 +52,304 @@ static char g_message[256];
static volatile char g_c1 = '0';
static volatile char g_c2 = '1';
-static void
-print_thread_id ()
-{
- // Put in the right magic here for your platform to spit out the thread id (tid) that debugserver/lldb-gdbserver would see as a TID.
- // Otherwise, let the else clause print out the unsupported text so that the unit test knows to skip verifying thread ids.
+static void print_thread_id() {
+// Put in the right magic here for your platform to spit out the thread id (tid)
+// that debugserver/lldb-gdbserver would see as a TID. Otherwise, let the else
+// clause print out the unsupported text so that the unit test knows to skip
+// verifying thread ids.
#if defined(__APPLE__)
- __uint64_t tid = 0;
- pthread_threadid_np(pthread_self(), &tid);
- printf ("%" PRIx64, tid);
-#elif defined (__linux__)
- // This is a call to gettid() via syscall.
- printf ("%" PRIx64, static_cast<uint64_t> (syscall (__NR_gettid)));
+ __uint64_t tid = 0;
+ pthread_threadid_np(pthread_self(), &tid);
+ printf("%" PRIx64, tid);
+#elif defined(__linux__)
+ // This is a call to gettid() via syscall.
+ printf("%" PRIx64, static_cast<uint64_t>(syscall(__NR_gettid)));
+#elif defined(__NetBSD__)
+ // Technically lwpid_t is 32-bit signed integer
+ printf("%" PRIx64, static_cast<uint64_t>(_lwp_self()));
#else
- printf("{no-tid-support}");
+ printf("{no-tid-support}");
#endif
}
-static void
-signal_handler (int signo)
-{
- const char *signal_name = nullptr;
- switch (signo)
- {
- case SIGUSR1: signal_name = "SIGUSR1"; break;
- case SIGSEGV: signal_name = "SIGSEGV"; break;
- default: signal_name = nullptr;
- }
-
- // Print notice that we received the signal on a given thread.
- pthread_mutex_lock (&g_print_mutex);
- if (signal_name)
- printf ("received %s on thread id: ", signal_name);
- else
- printf ("received signo %d (%s) on thread id: ", signo, strsignal (signo));
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
-
- // Reset the signal handler if we're one of the expected signal handlers.
- switch (signo)
- {
- case SIGSEGV:
- if (g_is_segfaulting)
- {
- // Fix up the pointer we're writing to. This needs to happen if nothing intercepts the SIGSEGV
- // (i.e. if somebody runs this from the command line).
- longjmp(g_jump_buffer, 1);
- }
- break;
- case SIGUSR1:
- if (g_is_segfaulting)
- {
- // Fix up the pointer we're writing to. This is used to test gdb remote signal delivery.
- // A SIGSEGV will be raised when the thread is created, switched out for a SIGUSR1, and
- // then this code still needs to fix the seg fault.
- // (i.e. if somebody runs this from the command line).
- longjmp(g_jump_buffer, 1);
- }
- break;
- }
-
- // Reset the signal handler.
- sig_t sig_result = signal (signo, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set signal handler: errno=%d\n", errno);
- exit (1);
- }
+static void signal_handler(int signo) {
+ const char *signal_name = nullptr;
+ switch (signo) {
+ case SIGUSR1:
+ signal_name = "SIGUSR1";
+ break;
+ case SIGSEGV:
+ signal_name = "SIGSEGV";
+ break;
+ default:
+ signal_name = nullptr;
+ }
+
+ // Print notice that we received the signal on a given thread.
+ pthread_mutex_lock(&g_print_mutex);
+ if (signal_name)
+ printf("received %s on thread id: ", signal_name);
+ else
+ printf("received signo %d (%s) on thread id: ", signo, strsignal(signo));
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+
+ // Reset the signal handler if we're one of the expected signal handlers.
+ switch (signo) {
+ case SIGSEGV:
+ if (g_is_segfaulting) {
+ // Fix up the pointer we're writing to. This needs to happen if nothing
+ // intercepts the SIGSEGV (i.e. if somebody runs this from the command
+ // line).
+ longjmp(g_jump_buffer, 1);
+ }
+ break;
+ case SIGUSR1:
+ if (g_is_segfaulting) {
+ // Fix up the pointer we're writing to. This is used to test gdb remote
+ // signal delivery. A SIGSEGV will be raised when the thread is created,
+ // switched out for a SIGUSR1, and then this code still needs to fix the
+ // seg fault. (i.e. if somebody runs this from the command line).
+ longjmp(g_jump_buffer, 1);
+ }
+ break;
+ }
+
+ // Reset the signal handler.
+ sig_t sig_result = signal(signo, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set signal handler: errno=%d\n", errno);
+ exit(1);
+ }
}
-static void
-swap_chars ()
-{
- g_c1 = '1';
- g_c2 = '0';
+static void swap_chars() {
+ g_c1 = '1';
+ g_c2 = '0';
- g_c1 = '0';
- g_c2 = '1';
+ g_c1 = '0';
+ g_c2 = '1';
}
-static void
-hello ()
-{
- pthread_mutex_lock (&g_print_mutex);
- printf ("hello, world\n");
- pthread_mutex_unlock (&g_print_mutex);
+static void hello() {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("hello, world\n");
+ pthread_mutex_unlock(&g_print_mutex);
}
-static void*
-thread_func (void *arg)
-{
- static pthread_mutex_t s_thread_index_mutex = PTHREAD_MUTEX_INITIALIZER;
- static int s_thread_index = 1;
-
- pthread_mutex_lock (&s_thread_index_mutex);
- const int this_thread_index = s_thread_index++;
- pthread_mutex_unlock (&s_thread_index_mutex);
-
- if (g_print_thread_ids)
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread %d id: ", this_thread_index);
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
-
- if (g_threads_do_segfault)
- {
- // Sleep for a number of seconds based on the thread index.
- // TODO add ability to send commands to test exe so we can
- // handle timing more precisely. This is clunky. All we're
- // trying to do is add predictability as to the timing of
- // signal generation by created threads.
- int sleep_seconds = 2 * (this_thread_index - 1);
- while (sleep_seconds > 0)
- sleep_seconds = sleep(sleep_seconds);
-
- // Test creating a SEGV.
- pthread_mutex_lock (&g_jump_buffer_mutex);
- g_is_segfaulting = true;
- int *bad_p = nullptr;
- if (setjmp(g_jump_buffer) == 0)
- {
- // Force a seg fault signal on this thread.
- *bad_p = 0;
- }
- else
- {
- // Tell the system we're no longer seg faulting.
- // Used by the SIGUSR1 signal handler that we inject
- // in place of the SIGSEGV so it only tries to
- // recover from the SIGSEGV if this seg fault code
- // was in play.
- g_is_segfaulting = false;
- }
- pthread_mutex_unlock (&g_jump_buffer_mutex);
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread ");
- print_thread_id ();
- printf (": past SIGSEGV\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
-
- int sleep_seconds_remaining = 60;
- while (sleep_seconds_remaining > 0)
- {
- sleep_seconds_remaining = sleep (sleep_seconds_remaining);
- }
-
- return nullptr;
+static void *thread_func(void *arg) {
+ static pthread_mutex_t s_thread_index_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static int s_thread_index = 1;
+
+ pthread_mutex_lock(&s_thread_index_mutex);
+ const int this_thread_index = s_thread_index++;
+ pthread_mutex_unlock(&s_thread_index_mutex);
+
+ if (g_print_thread_ids) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread %d id: ", this_thread_index);
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+
+ if (g_threads_do_segfault) {
+ // Sleep for a number of seconds based on the thread index.
+ // TODO add ability to send commands to test exe so we can
+ // handle timing more precisely. This is clunky. All we're
+ // trying to do is add predictability as to the timing of
+ // signal generation by created threads.
+ int sleep_seconds = 2 * (this_thread_index - 1);
+ while (sleep_seconds > 0)
+ sleep_seconds = sleep(sleep_seconds);
+
+ // Test creating a SEGV.
+ pthread_mutex_lock(&g_jump_buffer_mutex);
+ g_is_segfaulting = true;
+ int *bad_p = nullptr;
+ if (setjmp(g_jump_buffer) == 0) {
+ // Force a seg fault signal on this thread.
+ *bad_p = 0;
+ } else {
+ // Tell the system we're no longer seg faulting.
+ // Used by the SIGUSR1 signal handler that we inject
+ // in place of the SIGSEGV so it only tries to
+ // recover from the SIGSEGV if this seg fault code
+ // was in play.
+ g_is_segfaulting = false;
+ }
+ pthread_mutex_unlock(&g_jump_buffer_mutex);
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread ");
+ print_thread_id();
+ printf(": past SIGSEGV\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+
+ int sleep_seconds_remaining = 60;
+ while (sleep_seconds_remaining > 0) {
+ sleep_seconds_remaining = sleep(sleep_seconds_remaining);
+ }
+
+ return nullptr;
}
-int main (int argc, char **argv)
-{
- lldb_enable_attach();
-
- std::vector<pthread_t> threads;
- std::unique_ptr<uint8_t[]> heap_array_up;
- int return_value = 0;
-
- // Set the signal handler.
- sig_t sig_result = signal (SIGALRM, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGALRM signal handler: errno=%d\n", errno);
- exit (1);
- }
-
- sig_result = signal (SIGUSR1, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
- exit (1);
- }
-
- sig_result = signal (SIGSEGV, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
- exit (1);
- }
-
- // Process command line args.
- for (int i = 1; i < argc; ++i)
- {
- if (std::strstr (argv[i], STDERR_PREFIX))
- {
- // Treat remainder as text to go to stderr.
- fprintf (stderr, "%s\n", (argv[i] + strlen (STDERR_PREFIX)));
- }
- else if (std::strstr (argv[i], RETVAL_PREFIX))
- {
- // Treat as the return value for the program.
- return_value = std::atoi (argv[i] + strlen (RETVAL_PREFIX));
- }
- else if (std::strstr (argv[i], SLEEP_PREFIX))
- {
- // Treat as the amount of time to have this process sleep (in seconds).
- int sleep_seconds_remaining = std::atoi (argv[i] + strlen (SLEEP_PREFIX));
-
- // Loop around, sleeping until all sleep time is used up. Note that
- // signals will cause sleep to end early with the number of seconds remaining.
- for (int i = 0; sleep_seconds_remaining > 0; ++i)
- {
- sleep_seconds_remaining = sleep (sleep_seconds_remaining);
- // std::cout << "sleep result (call " << i << "): " << sleep_seconds_remaining << std::endl;
- }
- }
- else if (std::strstr (argv[i], SET_MESSAGE_PREFIX))
- {
- // Copy the contents after "set-message:" to the g_message buffer.
- // Used for reading inferior memory and verifying contents match expectations.
- strncpy (g_message, argv[i] + strlen (SET_MESSAGE_PREFIX), sizeof (g_message));
-
- // Ensure we're null terminated.
- g_message[sizeof (g_message) - 1] = '\0';
-
- }
- else if (std::strstr (argv[i], PRINT_MESSAGE_COMMAND))
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("message: %s\n", g_message);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_DATA_ADDRESS_PREFIX))
- {
- volatile void *data_p = nullptr;
-
- if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_message"))
- data_p = &g_message[0];
- else if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_c1"))
- data_p = &g_c1;
- else if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_c2"))
- data_p = &g_c2;
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("data address: %p\n", data_p);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_HEAP_ADDRESS_COMMAND))
- {
- // Create a byte array if not already present.
- if (!heap_array_up)
- heap_array_up.reset (new uint8_t[32]);
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("heap address: %p\n", heap_array_up.get ());
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_STACK_ADDRESS_COMMAND))
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("stack address: %p\n", &return_value);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_CODE_ADDRESS_PREFIX))
- {
- void (*func_p)() = nullptr;
-
- if (std::strstr (argv[i] + strlen (GET_CODE_ADDRESS_PREFIX), "hello"))
- func_p = hello;
- else if (std::strstr (argv[i] + strlen (GET_CODE_ADDRESS_PREFIX), "swap_chars"))
- func_p = swap_chars;
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("code address: %p\n", func_p);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], CALL_FUNCTION_PREFIX))
- {
- // Defaut to providing the address of main.
- if (std::strcmp (argv[i] + strlen (CALL_FUNCTION_PREFIX), "hello") == 0)
- hello();
- else if (std::strcmp (argv[i] + strlen (CALL_FUNCTION_PREFIX), "swap_chars") == 0)
- swap_chars();
- else
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("unknown function: %s\n", argv[i] + strlen (CALL_FUNCTION_PREFIX));
- pthread_mutex_unlock (&g_print_mutex);
- }
- }
- else if (std::strstr (argv[i], THREAD_PREFIX))
- {
- // Check if we're creating a new thread.
- if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_NEW))
- {
- // Create a new thread.
- pthread_t new_thread;
- const int err = ::pthread_create (&new_thread, nullptr, thread_func, nullptr);
- if (err)
- {
- fprintf (stderr, "pthread_create() failed with error code %d\n", err);
- exit (err);
- }
- threads.push_back (new_thread);
- }
- else if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_PRINT_IDS))
- {
- // Turn on thread id announcing.
- g_print_thread_ids = true;
-
- // And announce us.
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread 0 id: ");
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_SEGFAULT))
- {
- g_threads_do_segfault = true;
- }
- else
- {
- // At this point we don't do anything else with threads.
- // Later use thread index and send command to thread.
- }
- }
- else
- {
- // Treat the argument as text for stdout.
- printf("%s\n", argv[i]);
+int main(int argc, char **argv) {
+ lldb_enable_attach();
+
+ std::vector<pthread_t> threads;
+ std::unique_ptr<uint8_t[]> heap_array_up;
+ int return_value = 0;
+
+ // Set the signal handler.
+ sig_t sig_result = signal(SIGALRM, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGALRM signal handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ sig_result = signal(SIGUSR1, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ sig_result = signal(SIGSEGV, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ // Process command line args.
+ for (int i = 1; i < argc; ++i) {
+ if (std::strstr(argv[i], STDERR_PREFIX)) {
+ // Treat remainder as text to go to stderr.
+ fprintf(stderr, "%s\n", (argv[i] + strlen(STDERR_PREFIX)));
+ } else if (std::strstr(argv[i], RETVAL_PREFIX)) {
+ // Treat as the return value for the program.
+ return_value = std::atoi(argv[i] + strlen(RETVAL_PREFIX));
+ } else if (std::strstr(argv[i], SLEEP_PREFIX)) {
+ // Treat as the amount of time to have this process sleep (in seconds).
+ int sleep_seconds_remaining = std::atoi(argv[i] + strlen(SLEEP_PREFIX));
+
+ // Loop around, sleeping until all sleep time is used up. Note that
+ // signals will cause sleep to end early with the number of seconds
+ // remaining.
+ for (int i = 0; sleep_seconds_remaining > 0; ++i) {
+ sleep_seconds_remaining = sleep(sleep_seconds_remaining);
+ // std::cout << "sleep result (call " << i << "): " <<
+ // sleep_seconds_remaining << std::endl;
+ }
+ } else if (std::strstr(argv[i], SET_MESSAGE_PREFIX)) {
+ // Copy the contents after "set-message:" to the g_message buffer.
+ // Used for reading inferior memory and verifying contents match
+ // expectations.
+ strncpy(g_message, argv[i] + strlen(SET_MESSAGE_PREFIX),
+ sizeof(g_message));
+
+ // Ensure we're null terminated.
+ g_message[sizeof(g_message) - 1] = '\0';
+
+ } else if (std::strstr(argv[i], PRINT_MESSAGE_COMMAND)) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("message: %s\n", g_message);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_DATA_ADDRESS_PREFIX)) {
+ volatile void *data_p = nullptr;
+
+ if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_message"))
+ data_p = &g_message[0];
+ else if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_c1"))
+ data_p = &g_c1;
+ else if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_c2"))
+ data_p = &g_c2;
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("data address: %p\n", data_p);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_HEAP_ADDRESS_COMMAND)) {
+ // Create a byte array if not already present.
+ if (!heap_array_up)
+ heap_array_up.reset(new uint8_t[32]);
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("heap address: %p\n", heap_array_up.get());
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_STACK_ADDRESS_COMMAND)) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("stack address: %p\n", &return_value);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_CODE_ADDRESS_PREFIX)) {
+ void (*func_p)() = nullptr;
+
+ if (std::strstr(argv[i] + strlen(GET_CODE_ADDRESS_PREFIX), "hello"))
+ func_p = hello;
+ else if (std::strstr(argv[i] + strlen(GET_CODE_ADDRESS_PREFIX),
+ "swap_chars"))
+ func_p = swap_chars;
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("code address: %p\n", func_p);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], CALL_FUNCTION_PREFIX)) {
+ // Defaut to providing the address of main.
+ if (std::strcmp(argv[i] + strlen(CALL_FUNCTION_PREFIX), "hello") == 0)
+ hello();
+ else if (std::strcmp(argv[i] + strlen(CALL_FUNCTION_PREFIX),
+ "swap_chars") == 0)
+ swap_chars();
+ else {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("unknown function: %s\n",
+ argv[i] + strlen(CALL_FUNCTION_PREFIX));
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+ } else if (std::strstr(argv[i], THREAD_PREFIX)) {
+ // Check if we're creating a new thread.
+ if (std::strstr(argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_NEW)) {
+ // Create a new thread.
+ pthread_t new_thread;
+ const int err =
+ ::pthread_create(&new_thread, nullptr, thread_func, nullptr);
+ if (err) {
+ fprintf(stderr, "pthread_create() failed with error code %d\n", err);
+ exit(err);
}
+ threads.push_back(new_thread);
+ } else if (std::strstr(argv[i] + strlen(THREAD_PREFIX),
+ THREAD_COMMAND_PRINT_IDS)) {
+ // Turn on thread id announcing.
+ g_print_thread_ids = true;
+
+ // And announce us.
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread 0 id: ");
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i] + strlen(THREAD_PREFIX),
+ THREAD_COMMAND_SEGFAULT)) {
+ g_threads_do_segfault = true;
+ } else {
+ // At this point we don't do anything else with threads.
+ // Later use thread index and send command to thread.
+ }
+ } else {
+ // Treat the argument as text for stdout.
+ printf("%s\n", argv[i]);
}
-
- // If we launched any threads, join them
- for (std::vector<pthread_t>::iterator it = threads.begin (); it != threads.end (); ++it)
- {
- void *thread_retval = nullptr;
- const int err = ::pthread_join (*it, &thread_retval);
- if (err != 0)
- fprintf (stderr, "pthread_join() failed with error code %d\n", err);
- }
-
- return return_value;
+ }
+
+ // If we launched any threads, join them
+ for (std::vector<pthread_t>::iterator it = threads.begin();
+ it != threads.end(); ++it) {
+ void *thread_retval = nullptr;
+ const int err = ::pthread_join(*it, &thread_retval);
+ if (err != 0)
+ fprintf(stderr, "pthread_join() failed with error code %d\n", err);
+ }
+
+ return return_value;
}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
index ef6a0a21aaeb5..23cb869358572 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -883,12 +883,13 @@ class GdbRemoteTestCaseBase(TestBase):
def add_set_breakpoint_packets(
self,
address,
+ z_packet_type=0,
do_continue=True,
breakpoint_kind=1):
self.test_sequence.add_log_lines(
[ # Set the breakpoint.
- "read packet: $Z0,{0:x},{1}#00".format(
- address, breakpoint_kind),
+ "read packet: $Z{2},{0:x},{1}#00".format(
+ address, breakpoint_kind, z_packet_type),
# Verify the stub could set it.
"send packet: $OK#00",
], True)
@@ -904,11 +905,15 @@ class GdbRemoteTestCaseBase(TestBase):
2: "stop_thread_id"}},
], True)
- def add_remove_breakpoint_packets(self, address, breakpoint_kind=1):
+ def add_remove_breakpoint_packets(
+ self,
+ address,
+ z_packet_type=0,
+ breakpoint_kind=1):
self.test_sequence.add_log_lines(
[ # Remove the breakpoint.
- "read packet: $z0,{0:x},{1}#00".format(
- address, breakpoint_kind),
+ "read packet: $z{2},{0:x},{1}#00".format(
+ address, breakpoint_kind, z_packet_type),
# Verify the stub could unset it.
"send packet: $OK#00",
], True)
@@ -929,7 +934,8 @@ class GdbRemoteTestCaseBase(TestBase):
"qXfer:libraries:read",
"qXfer:libraries-svr4:read",
"qXfer:features:read",
- "qEcho"
+ "qEcho",
+ "QPassSignals"
]
def parse_qSupported_response(self, context):
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/main.cpp
index 69d60071aa455..ced7f7125088e 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/main.cpp
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/main.cpp
@@ -2,38 +2,30 @@
#include <cstring>
#include <iostream>
-namespace
-{
- const char *const SEGFAULT_COMMAND = "segfault";
- const char *const ABORT_COMMAND = "abort";
+namespace {
+const char *const SEGFAULT_COMMAND = "segfault";
+const char *const ABORT_COMMAND = "abort";
}
-int main (int argc, char **argv)
-{
- if (argc < 2)
- {
- std::cout << "expected at least one command provided on the command line" << std::endl;
- }
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ std::cout << "expected at least one command provided on the command line"
+ << std::endl;
+ }
- // Process command line args.
- for (int i = 1; i < argc; ++i)
- {
- const char *const command = argv[i];
- if (std::strstr (command, SEGFAULT_COMMAND))
- {
- // Perform a null pointer access.
- int *const null_int_ptr = nullptr;
- *null_int_ptr = 0xDEAD;
- }
- else if (std::strstr (command, ABORT_COMMAND))
- {
- std::abort();
- }
- else
- {
- std::cout << "Unsupported command: " << command << std::endl;
- }
+ // Process command line args.
+ for (int i = 1; i < argc; ++i) {
+ const char *const command = argv[i];
+ if (std::strstr(command, SEGFAULT_COMMAND)) {
+ // Perform a null pointer access.
+ int *const null_int_ptr = nullptr;
+ *null_int_ptr = 0xDEAD;
+ } else if (std::strstr(command, ABORT_COMMAND)) {
+ std::abort();
+ } else {
+ std::cout << "Unsupported command: " << command << std::endl;
}
+ }
- return 0;
+ return 0;
}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/main.cpp
index b97c6ebc18e33..a574b41abf670 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/main.cpp
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/main.cpp
@@ -1,3 +1,12 @@
+//===-- 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 <cstdlib>
#include <cstring>
#include <errno.h>
@@ -15,22 +24,24 @@
#if defined(__APPLE__)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_threadid_np(pthread_t,__uint64_t*);
+int pthread_threadid_np(pthread_t, __uint64_t *);
#elif defined(__linux__)
#include <sys/syscall.h>
+#elif defined(__NetBSD__)
+#include <lwp.h>
#endif
-static const char *const RETVAL_PREFIX = "retval:";
-static const char *const SLEEP_PREFIX = "sleep:";
-static const char *const STDERR_PREFIX = "stderr:";
-static const char *const SET_MESSAGE_PREFIX = "set-message:";
-static const char *const PRINT_MESSAGE_COMMAND = "print-message:";
-static const char *const GET_DATA_ADDRESS_PREFIX = "get-data-address-hex:";
-static const char *const GET_STACK_ADDRESS_COMMAND = "get-stack-address-hex:";
-static const char *const GET_HEAP_ADDRESS_COMMAND = "get-heap-address-hex:";
+static const char *const RETVAL_PREFIX = "retval:";
+static const char *const SLEEP_PREFIX = "sleep:";
+static const char *const STDERR_PREFIX = "stderr:";
+static const char *const SET_MESSAGE_PREFIX = "set-message:";
+static const char *const PRINT_MESSAGE_COMMAND = "print-message:";
+static const char *const GET_DATA_ADDRESS_PREFIX = "get-data-address-hex:";
+static const char *const GET_STACK_ADDRESS_COMMAND = "get-stack-address-hex:";
+static const char *const GET_HEAP_ADDRESS_COMMAND = "get-heap-address-hex:";
-static const char *const GET_CODE_ADDRESS_PREFIX = "get-code-address-hex:";
-static const char *const CALL_FUNCTION_PREFIX = "call-function:";
+static const char *const GET_CODE_ADDRESS_PREFIX = "get-code-address-hex:";
+static const char *const CALL_FUNCTION_PREFIX = "call-function:";
static const char *const THREAD_PREFIX = "thread:";
static const char *const THREAD_COMMAND_NEW = "new";
@@ -50,342 +61,304 @@ static char g_message[256];
static volatile char g_c1 = '0';
static volatile char g_c2 = '1';
-static void
-print_thread_id ()
-{
- // Put in the right magic here for your platform to spit out the thread id (tid) that debugserver/lldb-gdbserver would see as a TID.
- // Otherwise, let the else clause print out the unsupported text so that the unit test knows to skip verifying thread ids.
+static void print_thread_id() {
+// Put in the right magic here for your platform to spit out the thread id (tid)
+// that debugserver/lldb-gdbserver would see as a TID. Otherwise, let the else
+// clause print out the unsupported text so that the unit test knows to skip
+// verifying thread ids.
#if defined(__APPLE__)
- __uint64_t tid = 0;
- pthread_threadid_np(pthread_self(), &tid);
- printf ("%" PRIx64, tid);
-#elif defined (__linux__)
- // This is a call to gettid() via syscall.
- printf ("%" PRIx64, static_cast<uint64_t> (syscall (__NR_gettid)));
+ __uint64_t tid = 0;
+ pthread_threadid_np(pthread_self(), &tid);
+ printf("%" PRIx64, tid);
+#elif defined(__linux__)
+ // This is a call to gettid() via syscall.
+ printf("%" PRIx64, static_cast<uint64_t>(syscall(__NR_gettid)));
+#elif defined(__NetBSD__)
+ // Technically lwpid_t is 32-bit signed integer
+ printf("%" PRIx64, static_cast<uint64_t>(_lwp_self()));
#else
- printf("{no-tid-support}");
+ printf("{no-tid-support}");
#endif
}
-static void
-signal_handler (int signo)
-{
- const char *signal_name = nullptr;
- switch (signo)
- {
- case SIGUSR1: signal_name = "SIGUSR1"; break;
- case SIGSEGV: signal_name = "SIGSEGV"; break;
- default: signal_name = nullptr;
- }
-
- // Print notice that we received the signal on a given thread.
- pthread_mutex_lock (&g_print_mutex);
- if (signal_name)
- printf ("received %s on thread id: ", signal_name);
- else
- printf ("received signo %d (%s) on thread id: ", signo, strsignal (signo));
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
-
- // Reset the signal handler if we're one of the expected signal handlers.
- switch (signo)
- {
- case SIGSEGV:
- if (g_is_segfaulting)
- {
- // Fix up the pointer we're writing to. This needs to happen if nothing intercepts the SIGSEGV
- // (i.e. if somebody runs this from the command line).
- longjmp(g_jump_buffer, 1);
- }
- break;
- case SIGUSR1:
- if (g_is_segfaulting)
- {
- // Fix up the pointer we're writing to. This is used to test gdb remote signal delivery.
- // A SIGSEGV will be raised when the thread is created, switched out for a SIGUSR1, and
- // then this code still needs to fix the seg fault.
- // (i.e. if somebody runs this from the command line).
- longjmp(g_jump_buffer, 1);
- }
- break;
- }
-
- // Reset the signal handler.
- sig_t sig_result = signal (signo, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set signal handler: errno=%d\n", errno);
- exit (1);
- }
+static void signal_handler(int signo) {
+ const char *signal_name = nullptr;
+ switch (signo) {
+ case SIGUSR1:
+ signal_name = "SIGUSR1";
+ break;
+ case SIGSEGV:
+ signal_name = "SIGSEGV";
+ break;
+ default:
+ signal_name = nullptr;
+ }
+
+ // Print notice that we received the signal on a given thread.
+ pthread_mutex_lock(&g_print_mutex);
+ if (signal_name)
+ printf("received %s on thread id: ", signal_name);
+ else
+ printf("received signo %d (%s) on thread id: ", signo, strsignal(signo));
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+
+ // Reset the signal handler if we're one of the expected signal handlers.
+ switch (signo) {
+ case SIGSEGV:
+ if (g_is_segfaulting) {
+ // Fix up the pointer we're writing to. This needs to happen if nothing
+ // intercepts the SIGSEGV (i.e. if somebody runs this from the command
+ // line).
+ longjmp(g_jump_buffer, 1);
+ }
+ break;
+ case SIGUSR1:
+ if (g_is_segfaulting) {
+ // Fix up the pointer we're writing to. This is used to test gdb remote
+ // signal delivery. A SIGSEGV will be raised when the thread is created,
+ // switched out for a SIGUSR1, and then this code still needs to fix the
+ // seg fault. (i.e. if somebody runs this from the command line).
+ longjmp(g_jump_buffer, 1);
+ }
+ break;
+ }
+
+ // Reset the signal handler.
+ sig_t sig_result = signal(signo, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set signal handler: errno=%d\n", errno);
+ exit(1);
+ }
}
-static void
-swap_chars ()
-{
- g_c1 = '1';
- g_c2 = '0';
+static void swap_chars() {
+ g_c1 = '1';
+ g_c2 = '0';
- g_c1 = '0';
- g_c2 = '1';
+ g_c1 = '0';
+ g_c2 = '1';
}
-static void
-hello ()
-{
- pthread_mutex_lock (&g_print_mutex);
- printf ("hello, world\n");
- pthread_mutex_unlock (&g_print_mutex);
+static void hello() {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("hello, world\n");
+ pthread_mutex_unlock(&g_print_mutex);
}
-static void*
-thread_func (void *arg)
-{
- static pthread_mutex_t s_thread_index_mutex = PTHREAD_MUTEX_INITIALIZER;
- static int s_thread_index = 1;
-
- pthread_mutex_lock (&s_thread_index_mutex);
- const int this_thread_index = s_thread_index++;
- pthread_mutex_unlock (&s_thread_index_mutex);
-
- if (g_print_thread_ids)
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread %d id: ", this_thread_index);
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
-
- if (g_threads_do_segfault)
- {
- // Sleep for a number of seconds based on the thread index.
- // TODO add ability to send commands to test exe so we can
- // handle timing more precisely. This is clunky. All we're
- // trying to do is add predictability as to the timing of
- // signal generation by created threads.
- int sleep_seconds = 2 * (this_thread_index - 1);
- while (sleep_seconds > 0)
- sleep_seconds = sleep(sleep_seconds);
-
- // Test creating a SEGV.
- pthread_mutex_lock (&g_jump_buffer_mutex);
- g_is_segfaulting = true;
- int *bad_p = nullptr;
- if (setjmp(g_jump_buffer) == 0)
- {
- // Force a seg fault signal on this thread.
- *bad_p = 0;
- }
- else
- {
- // Tell the system we're no longer seg faulting.
- // Used by the SIGUSR1 signal handler that we inject
- // in place of the SIGSEGV so it only tries to
- // recover from the SIGSEGV if this seg fault code
- // was in play.
- g_is_segfaulting = false;
- }
- pthread_mutex_unlock (&g_jump_buffer_mutex);
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread ");
- print_thread_id ();
- printf (": past SIGSEGV\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
-
- int sleep_seconds_remaining = 60;
- while (sleep_seconds_remaining > 0)
- {
- sleep_seconds_remaining = sleep (sleep_seconds_remaining);
- }
-
- return nullptr;
+static void *thread_func(void *arg) {
+ static pthread_mutex_t s_thread_index_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static int s_thread_index = 1;
+
+ pthread_mutex_lock(&s_thread_index_mutex);
+ const int this_thread_index = s_thread_index++;
+ pthread_mutex_unlock(&s_thread_index_mutex);
+
+ if (g_print_thread_ids) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread %d id: ", this_thread_index);
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+
+ if (g_threads_do_segfault) {
+ // Sleep for a number of seconds based on the thread index.
+ // TODO add ability to send commands to test exe so we can
+ // handle timing more precisely. This is clunky. All we're
+ // trying to do is add predictability as to the timing of
+ // signal generation by created threads.
+ int sleep_seconds = 2 * (this_thread_index - 1);
+ while (sleep_seconds > 0)
+ sleep_seconds = sleep(sleep_seconds);
+
+ // Test creating a SEGV.
+ pthread_mutex_lock(&g_jump_buffer_mutex);
+ g_is_segfaulting = true;
+ int *bad_p = nullptr;
+ if (setjmp(g_jump_buffer) == 0) {
+ // Force a seg fault signal on this thread.
+ *bad_p = 0;
+ } else {
+ // Tell the system we're no longer seg faulting.
+ // Used by the SIGUSR1 signal handler that we inject
+ // in place of the SIGSEGV so it only tries to
+ // recover from the SIGSEGV if this seg fault code
+ // was in play.
+ g_is_segfaulting = false;
+ }
+ pthread_mutex_unlock(&g_jump_buffer_mutex);
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread ");
+ print_thread_id();
+ printf(": past SIGSEGV\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+
+ int sleep_seconds_remaining = 60;
+ while (sleep_seconds_remaining > 0) {
+ sleep_seconds_remaining = sleep(sleep_seconds_remaining);
+ }
+
+ return nullptr;
}
-int main (int argc, char **argv)
-{
- lldb_enable_attach();
-
- std::vector<pthread_t> threads;
- std::unique_ptr<uint8_t[]> heap_array_up;
- int return_value = 0;
-
- // Set the signal handler.
- sig_t sig_result = signal (SIGALRM, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGALRM signal handler: errno=%d\n", errno);
- exit (1);
- }
-
- sig_result = signal (SIGUSR1, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
- exit (1);
- }
-
- sig_result = signal (SIGSEGV, signal_handler);
- if (sig_result == SIG_ERR)
- {
- fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
- exit (1);
- }
-
- // Process command line args.
- for (int i = 1; i < argc; ++i)
- {
- if (std::strstr (argv[i], STDERR_PREFIX))
- {
- // Treat remainder as text to go to stderr.
- fprintf (stderr, "%s\n", (argv[i] + strlen (STDERR_PREFIX)));
- }
- else if (std::strstr (argv[i], RETVAL_PREFIX))
- {
- // Treat as the return value for the program.
- return_value = std::atoi (argv[i] + strlen (RETVAL_PREFIX));
- }
- else if (std::strstr (argv[i], SLEEP_PREFIX))
- {
- // Treat as the amount of time to have this process sleep (in seconds).
- int sleep_seconds_remaining = std::atoi (argv[i] + strlen (SLEEP_PREFIX));
-
- // Loop around, sleeping until all sleep time is used up. Note that
- // signals will cause sleep to end early with the number of seconds remaining.
- for (int i = 0; sleep_seconds_remaining > 0; ++i)
- {
- sleep_seconds_remaining = sleep (sleep_seconds_remaining);
- // std::cout << "sleep result (call " << i << "): " << sleep_seconds_remaining << std::endl;
- }
- }
- else if (std::strstr (argv[i], SET_MESSAGE_PREFIX))
- {
- // Copy the contents after "set-message:" to the g_message buffer.
- // Used for reading inferior memory and verifying contents match expectations.
- strncpy (g_message, argv[i] + strlen (SET_MESSAGE_PREFIX), sizeof (g_message));
-
- // Ensure we're null terminated.
- g_message[sizeof (g_message) - 1] = '\0';
-
- }
- else if (std::strstr (argv[i], PRINT_MESSAGE_COMMAND))
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("message: %s\n", g_message);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_DATA_ADDRESS_PREFIX))
- {
- volatile void *data_p = nullptr;
-
- if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_message"))
- data_p = &g_message[0];
- else if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_c1"))
- data_p = &g_c1;
- else if (std::strstr (argv[i] + strlen (GET_DATA_ADDRESS_PREFIX), "g_c2"))
- data_p = &g_c2;
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("data address: %p\n", data_p);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_HEAP_ADDRESS_COMMAND))
- {
- // Create a byte array if not already present.
- if (!heap_array_up)
- heap_array_up.reset (new uint8_t[32]);
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("heap address: %p\n", heap_array_up.get ());
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_STACK_ADDRESS_COMMAND))
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("stack address: %p\n", &return_value);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], GET_CODE_ADDRESS_PREFIX))
- {
- void (*func_p)() = nullptr;
-
- if (std::strstr (argv[i] + strlen (GET_CODE_ADDRESS_PREFIX), "hello"))
- func_p = hello;
- else if (std::strstr (argv[i] + strlen (GET_CODE_ADDRESS_PREFIX), "swap_chars"))
- func_p = swap_chars;
-
- pthread_mutex_lock (&g_print_mutex);
- printf ("code address: %p\n", func_p);
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i], CALL_FUNCTION_PREFIX))
- {
- // Defaut to providing the address of main.
- if (std::strcmp (argv[i] + strlen (CALL_FUNCTION_PREFIX), "hello") == 0)
- hello();
- else if (std::strcmp (argv[i] + strlen (CALL_FUNCTION_PREFIX), "swap_chars") == 0)
- swap_chars();
- else
- {
- pthread_mutex_lock (&g_print_mutex);
- printf ("unknown function: %s\n", argv[i] + strlen (CALL_FUNCTION_PREFIX));
- pthread_mutex_unlock (&g_print_mutex);
- }
- }
- else if (std::strstr (argv[i], THREAD_PREFIX))
- {
- // Check if we're creating a new thread.
- if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_NEW))
- {
- // Create a new thread.
- pthread_t new_thread;
- const int err = ::pthread_create (&new_thread, nullptr, thread_func, nullptr);
- if (err)
- {
- fprintf (stderr, "pthread_create() failed with error code %d\n", err);
- exit (err);
- }
- threads.push_back (new_thread);
- }
- else if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_PRINT_IDS))
- {
- // Turn on thread id announcing.
- g_print_thread_ids = true;
-
- // And announce us.
- pthread_mutex_lock (&g_print_mutex);
- printf ("thread 0 id: ");
- print_thread_id ();
- printf ("\n");
- pthread_mutex_unlock (&g_print_mutex);
- }
- else if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_SEGFAULT))
- {
- g_threads_do_segfault = true;
- }
- else
- {
- // At this point we don't do anything else with threads.
- // Later use thread index and send command to thread.
- }
- }
- else
- {
- // Treat the argument as text for stdout.
- printf("%s\n", argv[i]);
+int main(int argc, char **argv) {
+ lldb_enable_attach();
+
+ std::vector<pthread_t> threads;
+ std::unique_ptr<uint8_t[]> heap_array_up;
+ int return_value = 0;
+
+ // Set the signal handler.
+ sig_t sig_result = signal(SIGALRM, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGALRM signal handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ sig_result = signal(SIGUSR1, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ sig_result = signal(SIGSEGV, signal_handler);
+ if (sig_result == SIG_ERR) {
+ fprintf(stderr, "failed to set SIGUSR1 handler: errno=%d\n", errno);
+ exit(1);
+ }
+
+ // Process command line args.
+ for (int i = 1; i < argc; ++i) {
+ if (std::strstr(argv[i], STDERR_PREFIX)) {
+ // Treat remainder as text to go to stderr.
+ fprintf(stderr, "%s\n", (argv[i] + strlen(STDERR_PREFIX)));
+ } else if (std::strstr(argv[i], RETVAL_PREFIX)) {
+ // Treat as the return value for the program.
+ return_value = std::atoi(argv[i] + strlen(RETVAL_PREFIX));
+ } else if (std::strstr(argv[i], SLEEP_PREFIX)) {
+ // Treat as the amount of time to have this process sleep (in seconds).
+ int sleep_seconds_remaining = std::atoi(argv[i] + strlen(SLEEP_PREFIX));
+
+ // Loop around, sleeping until all sleep time is used up. Note that
+ // signals will cause sleep to end early with the number of seconds
+ // remaining.
+ for (int i = 0; sleep_seconds_remaining > 0; ++i) {
+ sleep_seconds_remaining = sleep(sleep_seconds_remaining);
+ // std::cout << "sleep result (call " << i << "): " <<
+ // sleep_seconds_remaining << std::endl;
+ }
+ } else if (std::strstr(argv[i], SET_MESSAGE_PREFIX)) {
+ // Copy the contents after "set-message:" to the g_message buffer.
+ // Used for reading inferior memory and verifying contents match
+ // expectations.
+ strncpy(g_message, argv[i] + strlen(SET_MESSAGE_PREFIX),
+ sizeof(g_message));
+
+ // Ensure we're null terminated.
+ g_message[sizeof(g_message) - 1] = '\0';
+
+ } else if (std::strstr(argv[i], PRINT_MESSAGE_COMMAND)) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("message: %s\n", g_message);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_DATA_ADDRESS_PREFIX)) {
+ volatile void *data_p = nullptr;
+
+ if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_message"))
+ data_p = &g_message[0];
+ else if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_c1"))
+ data_p = &g_c1;
+ else if (std::strstr(argv[i] + strlen(GET_DATA_ADDRESS_PREFIX), "g_c2"))
+ data_p = &g_c2;
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("data address: %p\n", data_p);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_HEAP_ADDRESS_COMMAND)) {
+ // Create a byte array if not already present.
+ if (!heap_array_up)
+ heap_array_up.reset(new uint8_t[32]);
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("heap address: %p\n", heap_array_up.get());
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_STACK_ADDRESS_COMMAND)) {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("stack address: %p\n", &return_value);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], GET_CODE_ADDRESS_PREFIX)) {
+ void (*func_p)() = nullptr;
+
+ if (std::strstr(argv[i] + strlen(GET_CODE_ADDRESS_PREFIX), "hello"))
+ func_p = hello;
+ else if (std::strstr(argv[i] + strlen(GET_CODE_ADDRESS_PREFIX),
+ "swap_chars"))
+ func_p = swap_chars;
+
+ pthread_mutex_lock(&g_print_mutex);
+ printf("code address: %p\n", func_p);
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i], CALL_FUNCTION_PREFIX)) {
+ // Defaut to providing the address of main.
+ if (std::strcmp(argv[i] + strlen(CALL_FUNCTION_PREFIX), "hello") == 0)
+ hello();
+ else if (std::strcmp(argv[i] + strlen(CALL_FUNCTION_PREFIX),
+ "swap_chars") == 0)
+ swap_chars();
+ else {
+ pthread_mutex_lock(&g_print_mutex);
+ printf("unknown function: %s\n",
+ argv[i] + strlen(CALL_FUNCTION_PREFIX));
+ pthread_mutex_unlock(&g_print_mutex);
+ }
+ } else if (std::strstr(argv[i], THREAD_PREFIX)) {
+ // Check if we're creating a new thread.
+ if (std::strstr(argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_NEW)) {
+ // Create a new thread.
+ pthread_t new_thread;
+ const int err =
+ ::pthread_create(&new_thread, nullptr, thread_func, nullptr);
+ if (err) {
+ fprintf(stderr, "pthread_create() failed with error code %d\n", err);
+ exit(err);
}
+ threads.push_back(new_thread);
+ } else if (std::strstr(argv[i] + strlen(THREAD_PREFIX),
+ THREAD_COMMAND_PRINT_IDS)) {
+ // Turn on thread id announcing.
+ g_print_thread_ids = true;
+
+ // And announce us.
+ pthread_mutex_lock(&g_print_mutex);
+ printf("thread 0 id: ");
+ print_thread_id();
+ printf("\n");
+ pthread_mutex_unlock(&g_print_mutex);
+ } else if (std::strstr(argv[i] + strlen(THREAD_PREFIX),
+ THREAD_COMMAND_SEGFAULT)) {
+ g_threads_do_segfault = true;
+ } else {
+ // At this point we don't do anything else with threads.
+ // Later use thread index and send command to thread.
+ }
+ } else {
+ // Treat the argument as text for stdout.
+ printf("%s\n", argv[i]);
}
-
- // If we launched any threads, join them
- for (std::vector<pthread_t>::iterator it = threads.begin (); it != threads.end (); ++it)
- {
- void *thread_retval = nullptr;
- const int err = ::pthread_join (*it, &thread_retval);
- if (err != 0)
- fprintf (stderr, "pthread_join() failed with error code %d\n", err);
- }
-
- return return_value;
+ }
+
+ // If we launched any threads, join them
+ for (std::vector<pthread_t>::iterator it = threads.begin();
+ it != threads.end(); ++it) {
+ void *thread_retval = nullptr;
+ const int err = ::pthread_join(*it, &thread_retval);
+ if (err != 0)
+ fprintf(stderr, "pthread_join() failed with error code %d\n", err);
+ }
+
+ return return_value;
}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/main.cpp
index 70ae5094fde77..c7ebe0759a403 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/main.cpp
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/main.cpp
@@ -1,7 +1,6 @@
#include <cstdio>
-int main (int argc, char **argv)
-{
- printf("argc: %d\n", argc);
- return argv[0][0];
+int main(int argc, char **argv) {
+ printf("argc: %d\n", argc);
+ return argv[0][0];
}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile
new file mode 100644
index 0000000000000..314f1cb2f077b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py
new file mode 100644
index 0000000000000..7105bcb078bc6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py
@@ -0,0 +1,115 @@
+# This test makes sure that lldb-server supports and properly handles
+# QPassSignals GDB protocol package.
+from __future__ import print_function
+
+import gdbremote_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestGdbRemote_QPassSignals(gdbremote_testcase.GdbRemoteTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def expect_signal(self, expected_signo):
+ self.test_sequence.add_log_lines(["read packet: $vCont;c#a8",
+ {"direction": "send",
+ "regex": r"^\$T([0-9a-fA-F]{2}).*#[0-9a-fA-F]{2}$",
+ "capture": {1: "hex_exit_code"}},
+ ],
+ True)
+
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ hex_exit_code = context.get("hex_exit_code")
+ self.assertIsNotNone(hex_exit_code)
+ self.assertEqual(int(hex_exit_code, 16), expected_signo)
+
+ def expect_exit_code(self, exit_code):
+ self.test_sequence.add_log_lines(
+ ["read packet: $vCont;c#a8",
+ "send packet: $W{0:02x}#00".format(exit_code)],
+ True)
+ self.expect_gdbremote_sequence()
+
+
+ def ignore_signals(self, signals):
+ def signal_name_to_hex(signame):
+ return format(lldbutil.get_signal_number(signame), 'x')
+ signals_str = ";".join(map(signal_name_to_hex, signals))
+
+ self.test_sequence.add_log_lines(["read packet: $QPassSignals:"
+ + signals_str + " #00",
+ "send packet: $OK#00"],
+ True)
+
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ @llgs_test
+ @skipUnlessPlatform(["linux", "android"])
+ def test_q_pass_signals(self):
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ procs = self.prep_debug_monitor_and_inferior()
+ expected_signals = ["SIGSEGV",
+ "SIGALRM", "SIGFPE", "SIGBUS", "SIGINT", "SIGHUP"]
+ signals_to_ignore = ["SIGUSR1", "SIGUSR2"]
+ self.ignore_signals(signals_to_ignore)
+ for signal_name in expected_signals:
+ signo = lldbutil.get_signal_number(signal_name)
+ self.expect_signal(signo)
+ self.expect_exit_code(len(signals_to_ignore))
+
+ @llgs_test
+ @skipUnlessPlatform(["linux", "android"])
+ def test_change_signals_at_runtime(self):
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ procs = self.prep_debug_monitor_and_inferior()
+ expected_signals = ["SIGSEGV", "SIGUSR1", "SIGUSR2",
+ "SIGALRM", "SIGHUP"]
+ signals_to_ignore = ["SIGFPE", "SIGBUS", "SIGINT"]
+
+ for signal_name in expected_signals:
+ signo = lldbutil.get_signal_number(signal_name)
+ self.expect_signal(signo)
+ if signal_name == "SIGALRM":
+ self.ignore_signals(signals_to_ignore)
+ self.expect_exit_code(len(signals_to_ignore))
+
+ @llgs_test
+ def test_default_signals_behavior(self):
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ procs = self.prep_debug_monitor_and_inferior()
+ expected_signals = ["SIGSEGV", "SIGUSR1", "SIGUSR2",
+ "SIGALRM", "SIGFPE", "SIGBUS", "SIGINT", "SIGHUP"]
+ for signal_name in expected_signals:
+ signo = lldbutil.get_signal_number(signal_name)
+ self.expect_signal(signo)
+ self.expect_exit_code(0)
+
+
+ @llgs_test
+ @skipUnlessPlatform(["linux", "android"])
+ def test_support_q_pass_signals(self):
+ self.init_llgs_test()
+ self.build()
+
+ # Start up the stub and start/prep the inferior.
+ self.set_inferior_startup_launch()
+ procs = self.prep_debug_monitor_and_inferior()
+ self.add_qSupported_packets()
+
+ # Run the packet stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Retrieve the qSupported features and check QPassSignals+
+ supported_dict = self.parse_qSupported_response(context)
+ self.assertEqual(supported_dict["QPassSignals"], "+")
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp
new file mode 100644
index 0000000000000..4991259fe46ed
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/signal-filtering/main.cpp
@@ -0,0 +1,37 @@
+//===-- 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 <signal.h>
+#include <stdio.h>
+#include <vector>
+
+static int signal_counter = 0;
+
+static void count_signal(int signo) {
+ ++signal_counter;
+ printf("Signal %d\n", signo);
+}
+
+static void raise_signals() {
+ std::vector<int> signals(
+ {SIGSEGV, SIGUSR1, SIGUSR2, SIGALRM, SIGFPE, SIGBUS, SIGINT, SIGHUP});
+
+ for (int signal_num : signals) {
+ signal(signal_num, count_signal);
+ }
+
+ for (int signal_num : signals) {
+ raise(signal_num);
+ }
+}
+
+int main() {
+ raise_signals();
+ return signal_counter;
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/host-info/Makefile b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/Makefile
index 1370b53b5a67a..8817fff55e8c0 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/host-info/Makefile
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/Makefile
@@ -1,10 +1,6 @@
LEVEL = ../../../make
-VPATH = ..
-
-override CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS
ENABLE_THREADS := YES
CXX_SOURCES := main.cpp
-MAKE_DSYM :=NO
include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py
new file mode 100644
index 0000000000000..5bfcd660c2ace
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py
@@ -0,0 +1,41 @@
+from __future__ import print_function
+
+import gdbremote_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestGdbRemoteThreadName(gdbremote_testcase.GdbRemoteTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def run_and_check_name(self, expected_name):
+ self.test_sequence.add_log_lines(["read packet: $vCont;c#a8",
+ {"direction": "send",
+ "regex":
+ r"^\$T([0-9a-fA-F]{2})([^#]+)#[0-9a-fA-F]{2}$",
+ "capture": {
+ 1: "signal",
+ 2: "key_vals_text"}},
+ ],
+ True)
+
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ sigint = lldbutil.get_signal_number("SIGINT")
+ self.assertEqual(sigint, int(context.get("signal"), 16))
+ kv_dict = self.parse_key_val_dict(context.get("key_vals_text"))
+ self.assertEqual(expected_name, kv_dict.get("name"))
+
+ @llgs_test
+ def test(self):
+ """ Make sure lldb-server can retrieve inferior thread name"""
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ procs = self.prep_debug_monitor_and_inferior()
+
+ self.run_and_check_name("hello world")
+ self.run_and_check_name("goodbye world")
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp
new file mode 100644
index 0000000000000..0403031143ba5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp
@@ -0,0 +1,22 @@
+#include <pthread.h>
+#include <signal.h>
+
+void set_thread_name(const char *name) {
+#if defined(__APPLE__)
+ ::pthread_setname_np(name);
+#elif defined(__FreeBSD__)
+ ::pthread_set_name_np(::pthread_self(), name);
+#elif defined(__linux__)
+ ::pthread_setname_np(::pthread_self(), name);
+#elif defined(__NetBSD__)
+ ::pthread_setname_np(::pthread_self(), "%s", name);
+#endif
+}
+
+int main() {
+ set_thread_name("hello world");
+ raise(SIGINT);
+ set_thread_name("goodbye world");
+ raise(SIGINT);
+ return 0;
+}