Skip to content

Commit 14d6707

Browse files
committed
[lldb] [llgs] Add a test for multiprocess register read/write
Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.llvm.org/D128153
1 parent 75757c8 commit 14d6707

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import random
2+
13
import gdbremote_testcase
24
from lldbsuite.test.decorators import *
35
from lldbsuite.test.lldbtest import *
@@ -700,3 +702,118 @@ def test_memory_read_write(self):
700702
data = seven.unhexlify(ret.get("data"))
701703
self.assertEqual(data, name + "\0")
702704
self.reset_test_sequence()
705+
706+
@add_test_categories(["fork"])
707+
def test_register_read_write(self):
708+
self.build()
709+
self.prep_debug_monitor_and_inferior(
710+
inferior_args=["fork",
711+
"thread:new",
712+
"trap",
713+
])
714+
self.add_qSupported_packets(["multiprocess+",
715+
"fork-events+"])
716+
ret = self.expect_gdbremote_sequence()
717+
self.assertIn("fork-events+", ret["qSupported_response"])
718+
self.reset_test_sequence()
719+
720+
# continue and expect fork
721+
self.test_sequence.add_log_lines([
722+
"read packet: $c#00",
723+
{"direction": "send", "regex": self.fork_regex.format("fork"),
724+
"capture": self.fork_capture},
725+
], True)
726+
self.add_threadinfo_collection_packets()
727+
ret = self.expect_gdbremote_sequence()
728+
pidtids = [
729+
(ret["parent_pid"], ret["parent_tid"]),
730+
(ret["child_pid"], ret["child_tid"]),
731+
]
732+
self.reset_test_sequence()
733+
734+
for pidtid in pidtids:
735+
self.test_sequence.add_log_lines(
736+
["read packet: $Hcp{}.{}#00".format(*pidtid),
737+
"send packet: $OK#00",
738+
"read packet: $c#00",
739+
{"direction": "send",
740+
"regex": "^[$]T05thread:p{}.{}.*".format(*pidtid),
741+
},
742+
], True)
743+
744+
self.add_threadinfo_collection_packets()
745+
ret = self.expect_gdbremote_sequence()
746+
self.reset_test_sequence()
747+
748+
pidtids = set(self.parse_threadinfo_packets(ret))
749+
self.assertEqual(len(pidtids), 4)
750+
# first, save register values from all the threads
751+
thread_regs = {}
752+
for pidtid in pidtids:
753+
for regno in range(256):
754+
self.test_sequence.add_log_lines(
755+
["read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
756+
"send packet: $OK#00",
757+
"read packet: $p{:x}#00".format(regno),
758+
{"direction": "send",
759+
"regex": r"^[$](.+)#.*$",
760+
"capture": {1: "data"}},
761+
], True)
762+
ret = self.expect_gdbremote_sequence()
763+
data = ret.get("data")
764+
self.assertIsNotNone(data)
765+
# ignore registers shorter than 32 bits (this also catches
766+
# "Exx" errors)
767+
if len(data) >= 8:
768+
break
769+
else:
770+
self.skipTest("no usable register found")
771+
thread_regs[pidtid] = (regno, data)
772+
773+
vals = set(x[1] for x in thread_regs.values())
774+
# NB: cheap hack to make the loop below easier
775+
new_val = next(iter(vals))
776+
777+
# then, start altering them and verify that we don't unexpectedly
778+
# change the value from another thread
779+
for pidtid in pidtids:
780+
old_val = thread_regs[pidtid]
781+
regno = old_val[0]
782+
old_val_length = len(old_val[1])
783+
# generate a unique new_val
784+
while new_val in vals:
785+
new_val = ('{{:0{}x}}'.format(old_val_length)
786+
.format(random.getrandbits(old_val_length*4)))
787+
vals.add(new_val)
788+
789+
self.test_sequence.add_log_lines(
790+
["read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
791+
"send packet: $OK#00",
792+
"read packet: $p{:x}#00".format(regno),
793+
{"direction": "send",
794+
"regex": r"^[$](.+)#.*$",
795+
"capture": {1: "data"}},
796+
"read packet: $P{:x}={}#00".format(regno, new_val),
797+
"send packet: $OK#00",
798+
], True)
799+
ret = self.expect_gdbremote_sequence()
800+
data = ret.get("data")
801+
self.assertIsNotNone(data)
802+
self.assertEqual(data, old_val[1])
803+
thread_regs[pidtid] = (regno, new_val)
804+
805+
# finally, verify that new values took effect
806+
for pidtid in pidtids:
807+
old_val = thread_regs[pidtid]
808+
self.test_sequence.add_log_lines(
809+
["read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
810+
"send packet: $OK#00",
811+
"read packet: $p{:x}#00".format(old_val[0]),
812+
{"direction": "send",
813+
"regex": r"^[$](.+)#.*$",
814+
"capture": {1: "data"}},
815+
], True)
816+
ret = self.expect_gdbremote_sequence()
817+
data = ret.get("data")
818+
self.assertIsNotNone(data)
819+
self.assertEqual(data, old_val[1])

0 commit comments

Comments
 (0)