diff options
Diffstat (limited to 'packages/Python/lldbsuite/test/tools/lldb-server')
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 000000000000..9b3aa8b7213b --- /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 5089ee85773f..5089ee85773f 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 57d4d5ab4bb1..b361b9e6d915 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 b69ac3f8d2a3..6f36fbea470b 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 b97c6ebc18e3..a3691a8d42b9 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 ef6a0a21aaeb..23cb86935857 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 69d60071aa45..ced7f7125088 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 b97c6ebc18e3..a574b41abf67 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 70ae5094fde7..c7ebe0759a40 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 000000000000..314f1cb2f077 --- /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 000000000000..7105bcb078bc --- /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 000000000000..4991259fe46e --- /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 1370b53b5a67..8817fff55e8c 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 000000000000..5bfcd660c2ac --- /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 000000000000..0403031143ba --- /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; +}  | 
