summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py139
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py5
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py62
3 files changed, 206 insertions, 0 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py
new file mode 100644
index 00000000000..c112c588625
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestRecognizeBreakpoint.py
@@ -0,0 +1,139 @@
+from __future__ import print_function
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestRecognizeBreakpoint(GDBRemoteTestBase):
+ """ This tests the case where the gdb-remote server doesn't support any
+ of the thread-info packets, and just tells which thread got the stop
+ signal with:
+ T05thread:01;
+ There was a bug in lldb that we would set the stop reason from this
+ packet too early - before we had updated the thread list. So when we
+ later updated the thread list, we would throw away this info. Normally
+ we would be able to reconstruct it from the thread info, but not if the
+ stub doesn't support it """
+
+ def test(self):
+ class MyResponder(MockGDBServerResponder):
+ def __init__(self):
+ MockGDBServerResponder.__init__(self)
+ self.thread_info_count = 0
+ self.after_cont = False
+ self.current_thread = 0
+
+ def cont(self):
+ # Simulate process stopping due to a breakpoint:
+ self.after_cont = True
+ return "T05thread:01;"
+
+ def vCont(self, packet):
+ self.after_cont = True
+ return "T05thread:01;"
+
+ def haltReason(self):
+ return "T02thread:01;"
+
+ def threadStopInfo(self, num):
+ return ""
+
+ def QThreadSuffixSupported(self):
+ return ""
+
+ def QListThreadsInStopReply(self):
+ return ""
+
+ def setBreakpoint(self, packet):
+ return "OK"
+
+ def qfThreadInfo(self):
+ return "m1"
+
+ def qsThreadInfo(self):
+ if (self.thread_info_count % 2) == 0:
+ str = "m2"
+ else:
+ str = "l"
+ self.thread_info_count += 1
+ return str
+
+ def readRegisters(self):
+ if self.after_cont and self.current_thread == 1:
+ return "c01e990080ffffff"
+ else:
+ return "badcfe10325476980"
+
+ def readRegister(self, regno):
+ return ""
+
+ def qXferRead(self, obj, annex, offset, length):
+ if annex == "target.xml":
+ return """<?xml version="1.0"?>
+ <target version="1.0">
+ <architecture>i386:x86-64</architecture>
+ <feature name="org.gnu.gdb.i386.core">
+ <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
+ </feature>
+ </target>""", False
+ else:
+ return None, False
+
+ def selectThread(self, op, thread):
+ if op != 'g':
+ return ''
+
+ self.current_thread = thread
+ return "OK"
+
+ def other (self, packet):
+ if packet == "vCont?":
+ return "vCont;c;C;s;S"
+ return ''
+
+ python_os_plugin_path = os.path.join(self.getSourceDir(),
+ 'operating_system_2.py')
+ command ="settings set target.process.python-os-plugin-path '{}'".format(
+ python_os_plugin_path)
+ self.runCmd(command)
+
+ self.server.responder = MyResponder()
+ target = self.dbg.CreateTarget("")
+ process = self.connect(target)
+
+ bkpt = target.BreakpointCreateByAddress(0xffffff8000991ec0)
+ self.assertEqual(bkpt.GetNumLocations(), 1, "Fake breakpoint was resolved.")
+
+ # Get the initial stop, and we should have two threads.
+ num_threads = len(process.threads)
+ self.assertEqual(num_threads, 2, "Got two threads")
+
+ thread_0 = process.threads[0]
+ self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason")
+ self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one")
+
+ thread_1 = process.threads[1]
+ self.assertEqual(thread_1.GetStopReason(), 5, "Thread_0 stopped for SIGSTOP")
+ self.assertEqual(thread_1.GetName(), "two", "Thread_0 is called two")
+
+ # Now continue and we will fake hitting a breakpoint.
+ process.Continue()
+
+ self.assertEqual(process.GetState(),lldb.eStateStopped, "Process is stopped")
+ num_threads = len(process.threads)
+
+ num_threads = len(process.threads)
+ self.assertEqual(num_threads, 2, "Got two threads")
+
+ thread_0 = process.threads[0]
+ self.assertEqual(thread_0.GetStopReason(), 1, "Thread_0 stopped for no reason")
+ self.assertEqual(thread_0.GetName(), "one", "Thread_0 is called one")
+
+ thread_1 = process.threads[1]
+ self.assertEqual(thread_1.GetStopReason(), 3, "Thread_0 stopped for SIGTRAP")
+ self.assertEqual(thread_1.GetName(), "three", "Thread_0 is called three")
+
+ self.assertTrue(thread_1.IsValid(), "Thread_1 is valid")
+ self.assertEqual(thread_1.GetStopReason(), lldb.eStopReasonBreakpoint, "Stopped at breakpoint")
+
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
index fb8f61bdf8c..f0875c9c995 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
@@ -103,6 +103,8 @@ class MockGDBServerResponder:
return self.interrupt()
if packet == "c":
return self.cont()
+ if packet.startswith("vCont;c"):
+ return self.vCont(packet)
if packet[0] == "g":
return self.readRegisters()
if packet[0] == "G":
@@ -168,6 +170,9 @@ class MockGDBServerResponder:
def cont(self):
raise self.UnexpectedPacketException()
+ def vCont(self, packet):
+ raise self.UnexpectedPacketException()
+
def readRegisters(self):
return "00000000" * self.registerCount
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py
new file mode 100644
index 00000000000..d8ebed610da
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/operating_system_2.py
@@ -0,0 +1,62 @@
+import lldb
+import struct
+
+
+class OperatingSystemPlugIn(object):
+ """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class
+ This version stops once with threads 0x111 and 0x222, then stops a second time with threads
+ 0x111 and 0x333."""
+
+ def __init__(self, process):
+ '''Initialization needs a valid.SBProcess object.
+
+ This plug-in will get created after a live process is valid and has stopped for the first time.
+ '''
+ self.process = None
+ self.registers = None
+ self.threads = None
+ self.times_called = 0
+ if isinstance(process, lldb.SBProcess) and process.IsValid():
+ self.process = process
+ self.threads = None # Will be an dictionary containing info for each thread
+
+ def get_target(self):
+ return self.process.target
+
+ def get_thread_info(self):
+ self.times_called += 1
+
+ if self.times_called == 1:
+ self.threads = [{
+ 'tid': 0x111,
+ 'name': 'one',
+ 'queue': 'queue1',
+ 'state': 'stopped',
+ 'stop_reason': 'none',
+ 'core': 1
+ }, {
+ 'tid': 0x222,
+ 'name': 'two',
+ 'queue': 'queue2',
+ 'state': 'stopped',
+ 'stop_reason': 'none',
+ 'core': 0
+ }]
+ else:
+ self.threads = [{
+ 'tid': 0x111,
+ 'name': 'one',
+ 'queue': 'queue1',
+ 'state': 'stopped',
+ 'stop_reason': 'none',
+ 'core': 1
+ }, {
+ 'tid': 0x333,
+ 'name': 'three',
+ 'queue': 'queue3',
+ 'state': 'stopped',
+ 'stop_reason': 'none',
+ 'core': 0
+ }]
+ return self.threads
+
OpenPOWER on IntegriCloud