Added gdb-remote memory read ($m) test.
authorTodd Fiala <todd.fiala@gmail.com>
Tue, 3 Jun 2014 18:09:56 +0000 (18:09 +0000)
committerTodd Fiala <todd.fiala@gmail.com>
Tue, 3 Jun 2014 18:09:56 +0000 (18:09 +0000)
Added set-memory:{content} and get-memory-address-hex: commands
to the test exe for gdb-remote.  Added a test that sets the content
via the inferior command line, then reads it back via gdb-remote
with $m.

Passing on debugserver.  Marked as fail on llgs.  Implementing
in the llgs branch next.

llvm-svn: 210116

lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py
lldb/test/tools/lldb-gdbserver/main.cpp

index 8aae233..122bf87 100644 (file)
@@ -49,9 +49,8 @@ class LldbGdbServerTestCase(TestBase):
         self.set_inferior_startup_launch()
 
         # Uncomment this code to force only a single test to run (by name).
-        # if self._testMethodName != "test_Hc_then_Csignal_signals_correct_thread_launch_debugserver_dsym":
-        #   # print "skipping test {}".format(self._testMethodName)
-        #   self.skipTest("focusing on one test")
+        # if not re.search(r"m_packet_reads_memory", self._testMethodName):
+        #     self.skipTest("focusing on one test")
 
     def reset_test_sequence(self):
         self.test_sequence = GdbRemoteTestSequence(self.logger)
@@ -1223,6 +1222,68 @@ class LldbGdbServerTestCase(TestBase):
         self.set_inferior_startup_launch()
         self.Hc_then_Csignal_signals_correct_thread()
 
+    def m_packet_reads_memory(self):
+        # This is the memory we will write into the inferior and then ensure we can read back with $m.
+        MEMORY_CONTENTS = "Test contents 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
+
+        # Start up the inferior.
+        procs = self.prep_debug_monitor_and_inferior(
+            inferior_args=["set-message:%s" % MEMORY_CONTENTS, "get-message-address-hex:", "sleep:5"])
+
+        # Run the process
+        self.test_sequence.add_log_lines(
+            [
+             # Start running after initial stop.
+             "read packet: $c#00",
+             # Match output line that prints the memory address of the message buffer within the inferior. 
+             # Note we require launch-only testing so we can get inferior otuput.
+             { "type":"output_match", "regex":r"^message address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"message_address"} },
+             # Now stop the inferior.
+             "read packet: {}".format(chr(03)),
+             # And wait for the stop notification.
+             {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} }],
+            True)
+
+        # Run the packet stream.
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        # Grab the message address.
+        self.assertIsNotNone(context.get("message_address"))
+        message_address = int(context.get("message_address"), 16)
+
+        # Grab contents from the inferior.
+        self.reset_test_sequence()
+        self.test_sequence.add_log_lines(
+            ["read packet: $m{0:x},{1:x}#00".format(message_address, len(MEMORY_CONTENTS)),
+             {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"read_contents"} }],
+            True)
+
+        # Run the packet stream.
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        # Ensure what we read from inferior memory is what we wrote.
+        self.assertIsNotNone(context.get("read_contents"))
+        read_contents = context.get("read_contents").decode("hex")
+        self.assertEquals(read_contents, MEMORY_CONTENTS)
+        
+    @debugserver_test
+    @dsym_test
+    def test_m_packet_reads_memory_debugserver_dsym(self):
+        self.init_debugserver_test()
+        self.buildDsym()
+        self.set_inferior_startup_launch()
+        self.m_packet_reads_memory()
+
+    @llgs_test
+    @dwarf_test
+    @unittest2.expectedFailure()
+    def test_m_packet_reads_memory_llgs_dwarf(self):
+        self.init_llgs_test()
+        self.buildDwarf()
+        self.set_inferior_startup_launch()
+        self.m_packet_reads_memory()
 
 if __name__ == '__main__':
     unittest2.main()
index e7ae168..874a69d 100644 (file)
@@ -7,6 +7,8 @@
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <vector>
 
@@ -20,6 +22,8 @@ int pthread_threadid_np(pthread_t,__uint64_t*);
 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 GET_MESSAGE_ADDRESS_COMMAND = "get-message-address-hex:";
 
 static const char *const THREAD_PREFIX = "thread:";
 static const char *const THREAD_COMMAND_NEW = "new"; 
@@ -34,6 +38,8 @@ static pthread_mutex_t g_jump_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
 static jmp_buf g_jump_buffer;
 static bool g_is_segfaulting = false;
 
+static char g_message[256];
+
 static void
 print_thread_id ()
 {
@@ -220,6 +226,22 @@ int main (int argc, char **argv)
                                // 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], GET_MESSAGE_ADDRESS_COMMAND))
+        {
+                       pthread_mutex_lock (&g_print_mutex);
+            printf ("message address: %p\n", &g_message[0]);
+                       pthread_mutex_unlock (&g_print_mutex);
+        }
                else if (std::strstr (argv[i], THREAD_PREFIX))
                {
                        // Check if we're creating a new thread.