xref: /llvm-project/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
114d67073SMichał Górnyimport random
214d67073SMichał Górny
3bbae0c1fSMichał Górnyfrom lldbsuite.test.decorators import *
4bbae0c1fSMichał Górnyfrom lldbsuite.test.lldbtest import *
5bbae0c1fSMichał Górny
67fc12da8SMichał Górnyfrom fork_testbase import GdbRemoteForkTestBase
7bbae0c1fSMichał Górny
8313d9c15SMichał Górny
97fc12da8SMichał Górnyclass TestGdbRemoteFork(GdbRemoteForkTestBase):
10ba14e4d6SMuhammad Omair Javaid    def setUp(self):
11ba14e4d6SMuhammad Omair Javaid        GdbRemoteForkTestBase.setUp(self)
12*2238dcc3SJonas Devlieghere        if self.getPlatform() == "linux" and self.getArchitecture() in [
13*2238dcc3SJonas Devlieghere            "arm",
14*2238dcc3SJonas Devlieghere            "aarch64",
15*2238dcc3SJonas Devlieghere        ]:
16ba14e4d6SMuhammad Omair Javaid            self.skipTest("Unsupported for Arm/AArch64 Linux")
17ba14e4d6SMuhammad Omair Javaid
18c1829e0eSMichał Górny    @add_test_categories(["fork"])
19c1829e0eSMichał Górny    def test_fork_multithreaded(self):
20c1829e0eSMichał Górny        _, _, child_pid, _ = self.start_fork_test(["thread:new"] * 2 + ["fork"])
21c1829e0eSMichał Górny
22c1829e0eSMichał Górny        # detach the forked child
23*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
24*2238dcc3SJonas Devlieghere            [
25c1829e0eSMichał Górny                "read packet: $D;{}#00".format(child_pid),
26c1829e0eSMichał Górny                "send packet: $OK#00",
27c1829e0eSMichał Górny                "read packet: $k#00",
28*2238dcc3SJonas Devlieghere            ],
29*2238dcc3SJonas Devlieghere            True,
30*2238dcc3SJonas Devlieghere        )
31c1829e0eSMichał Górny        self.expect_gdbremote_sequence()
32c1829e0eSMichał Górny
33bbae0c1fSMichał Górny    @add_test_categories(["fork"])
34bbae0c1fSMichał Górny    def test_fork(self):
35313d9c15SMichał Górny        parent_pid, _ = self.fork_and_detach_test("fork")
36bbae0c1fSMichał Górny
37bbae0c1fSMichał Górny        # resume the parent
38*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
39*2238dcc3SJonas Devlieghere            [
40bbae0c1fSMichał Górny                "read packet: $c#00",
41313d9c15SMichał Górny                "send packet: $W00;process:{}#00".format(parent_pid),
42*2238dcc3SJonas Devlieghere            ],
43*2238dcc3SJonas Devlieghere            True,
44*2238dcc3SJonas Devlieghere        )
45bbae0c1fSMichał Górny        self.expect_gdbremote_sequence()
46bbae0c1fSMichał Górny
47bbae0c1fSMichał Górny    @add_test_categories(["fork"])
48bbae0c1fSMichał Górny    def test_vfork(self):
49313d9c15SMichał Górny        parent_pid, parent_tid = self.fork_and_detach_test("vfork")
50bbae0c1fSMichał Górny
51bbae0c1fSMichał Górny        # resume the parent
52*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
53*2238dcc3SJonas Devlieghere            [
54bbae0c1fSMichał Górny                "read packet: $c#00",
55*2238dcc3SJonas Devlieghere                {
56*2238dcc3SJonas Devlieghere                    "direction": "send",
57*2238dcc3SJonas Devlieghere                    "regex": r"[$]T[0-9a-fA-F]{{2}}thread:p{}[.]{}.*vforkdone.*".format(
58*2238dcc3SJonas Devlieghere                        parent_pid, parent_tid
59*2238dcc3SJonas Devlieghere                    ),
60313d9c15SMichał Górny                },
61bbae0c1fSMichał Górny                "read packet: $c#00",
62313d9c15SMichał Górny                "send packet: $W00;process:{}#00".format(parent_pid),
63*2238dcc3SJonas Devlieghere            ],
64*2238dcc3SJonas Devlieghere            True,
65*2238dcc3SJonas Devlieghere        )
66bbae0c1fSMichał Górny        self.expect_gdbremote_sequence()
67b7c14033SMichał Górny
68b415f8e3SMichał Górny    @add_test_categories(["fork"])
69b7c14033SMichał Górny    def test_fork_follow(self):
70b7c14033SMichał Górny        self.fork_and_follow_test("fork")
71b7c14033SMichał Górny
72b7c14033SMichał Górny    @add_test_categories(["fork"])
73b7c14033SMichał Górny    def test_vfork_follow(self):
74b7c14033SMichał Górny        self.fork_and_follow_test("vfork")
75b7c14033SMichał Górny
76b7c14033SMichał Górny    @add_test_categories(["fork"])
77b7c14033SMichał Górny    def test_select_wrong_pid(self):
78b7c14033SMichał Górny        self.build()
79b7c14033SMichał Górny        self.prep_debug_monitor_and_inferior()
80b7c14033SMichał Górny        self.add_qSupported_packets(["multiprocess+"])
81b7c14033SMichał Górny        ret = self.expect_gdbremote_sequence()
82b7c14033SMichał Górny        self.assertIn("multiprocess+", ret["qSupported_response"])
83b7c14033SMichał Górny        self.reset_test_sequence()
84b7c14033SMichał Górny
85b7c14033SMichał Górny        # get process pid
86*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
87*2238dcc3SJonas Devlieghere            [
88b7c14033SMichał Górny                "read packet: $qC#00",
89*2238dcc3SJonas Devlieghere                {
90*2238dcc3SJonas Devlieghere                    "direction": "send",
91*2238dcc3SJonas Devlieghere                    "regex": "[$]QCp([0-9a-f]+).([0-9a-f]+)#.*",
92*2238dcc3SJonas Devlieghere                    "capture": {1: "pid", 2: "tid"},
93*2238dcc3SJonas Devlieghere                },
94*2238dcc3SJonas Devlieghere            ],
95*2238dcc3SJonas Devlieghere            True,
96*2238dcc3SJonas Devlieghere        )
97b7c14033SMichał Górny        ret = self.expect_gdbremote_sequence()
98b7c14033SMichał Górny        pid, tid = (int(ret[x], 16) for x in ("pid", "tid"))
99b7c14033SMichał Górny        self.reset_test_sequence()
100b7c14033SMichał Górny
101*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
102*2238dcc3SJonas Devlieghere            [
103b7c14033SMichał Górny                # try switching to correct pid
104b7c14033SMichał Górny                "read packet: $Hgp{:x}.{:x}#00".format(pid, tid),
105313d9c15SMichał Górny                "send packet: $OK#00",
106b7c14033SMichał Górny                "read packet: $Hcp{:x}.{:x}#00".format(pid, tid),
107313d9c15SMichał Górny                "send packet: $OK#00",
108b7c14033SMichał Górny                # try switching to invalid tid
109b7c14033SMichał Górny                "read packet: $Hgp{:x}.{:x}#00".format(pid, tid + 1),
110313d9c15SMichał Górny                "send packet: $E15#00",
111b7c14033SMichał Górny                "read packet: $Hcp{:x}.{:x}#00".format(pid, tid + 1),
112313d9c15SMichał Górny                "send packet: $E15#00",
113b7c14033SMichał Górny                # try switching to invalid pid
114b7c14033SMichał Górny                "read packet: $Hgp{:x}.{:x}#00".format(pid + 1, tid),
115313d9c15SMichał Górny                "send packet: $Eff#00",
116b7c14033SMichał Górny                "read packet: $Hcp{:x}.{:x}#00".format(pid + 1, tid),
117313d9c15SMichał Górny                "send packet: $Eff#00",
118*2238dcc3SJonas Devlieghere            ],
119*2238dcc3SJonas Devlieghere            True,
120*2238dcc3SJonas Devlieghere        )
121313d9c15SMichał Górny        self.expect_gdbremote_sequence()
122b7c14033SMichał Górny
1234d2503cdSMichał Górny    @add_test_categories(["fork"])
124b7c14033SMichał Górny    def test_detach_current(self):
125b7c14033SMichał Górny        self.build()
126b7c14033SMichał Górny        self.prep_debug_monitor_and_inferior()
127b7c14033SMichał Górny        self.add_qSupported_packets(["multiprocess+"])
128b7c14033SMichał Górny        ret = self.expect_gdbremote_sequence()
129b7c14033SMichał Górny        self.assertIn("multiprocess+", ret["qSupported_response"])
130b7c14033SMichał Górny        self.reset_test_sequence()
131b7c14033SMichał Górny
132b7c14033SMichał Górny        # get process pid
133*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
134*2238dcc3SJonas Devlieghere            [
135630da0e3SMichał Górny                "read packet: $qC#00",
136*2238dcc3SJonas Devlieghere                {
137*2238dcc3SJonas Devlieghere                    "direction": "send",
138*2238dcc3SJonas Devlieghere                    "regex": "[$]QCp([0-9a-f]+).[0-9a-f]+#.*",
139*2238dcc3SJonas Devlieghere                    "capture": {1: "pid"},
140*2238dcc3SJonas Devlieghere                },
141*2238dcc3SJonas Devlieghere            ],
142*2238dcc3SJonas Devlieghere            True,
143*2238dcc3SJonas Devlieghere        )
144b7c14033SMichał Górny        ret = self.expect_gdbremote_sequence()
145313d9c15SMichał Górny        pid = ret["pid"]
146b7c14033SMichał Górny        self.reset_test_sequence()
147b7c14033SMichał Górny
148b7c14033SMichał Górny        # detach the process
149*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
150*2238dcc3SJonas Devlieghere            [
151313d9c15SMichał Górny                "read packet: $D;{}#00".format(pid),
152313d9c15SMichał Górny                "send packet: $OK#00",
153b7c14033SMichał Górny                "read packet: $qC#00",
154313d9c15SMichał Górny                "send packet: $E44#00",
155*2238dcc3SJonas Devlieghere            ],
156*2238dcc3SJonas Devlieghere            True,
157*2238dcc3SJonas Devlieghere        )
158313d9c15SMichał Górny        self.expect_gdbremote_sequence()
15913eb5b34SMichał Górny
160e8fe7e93SMichał Górny    @add_test_categories(["fork"])
161b415f8e3SMichał Górny    def test_detach_all(self):
162b415f8e3SMichał Górny        self.detach_all_test()
163b415f8e3SMichał Górny
164b415f8e3SMichał Górny    @add_test_categories(["fork"])
165e8fe7e93SMichał Górny    def test_kill_all(self):
166c1829e0eSMichał Górny        parent_pid, _, child_pid, _ = self.start_fork_test(["fork"])
167e8fe7e93SMichał Górny
168e8fe7e93SMichał Górny        exit_regex = "[$]X09;process:([0-9a-f]+)#.*"
169*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
170*2238dcc3SJonas Devlieghere            [
171e8fe7e93SMichał Górny                # kill all processes
172e8fe7e93SMichał Górny                "read packet: $k#00",
173*2238dcc3SJonas Devlieghere                {"direction": "send", "regex": exit_regex, "capture": {1: "pid1"}},
174*2238dcc3SJonas Devlieghere                {"direction": "send", "regex": exit_regex, "capture": {1: "pid2"}},
175*2238dcc3SJonas Devlieghere            ],
176*2238dcc3SJonas Devlieghere            True,
177*2238dcc3SJonas Devlieghere        )
178e8fe7e93SMichał Górny        ret = self.expect_gdbremote_sequence()
179*2238dcc3SJonas Devlieghere        self.assertEqual(set([ret["pid1"], ret["pid2"]]), set([parent_pid, child_pid]))
180c18784baSMichał Górny
181b415f8e3SMichał Górny    @add_test_categories(["fork"])
182c18784baSMichał Górny    def test_vkill_child(self):
183c18784baSMichał Górny        self.vkill_test(kill_child=True)
184c18784baSMichał Górny
185c18784baSMichał Górny    @add_test_categories(["fork"])
186c18784baSMichał Górny    def test_vkill_parent(self):
187c18784baSMichał Górny        self.vkill_test(kill_parent=True)
188c18784baSMichał Górny
189c18784baSMichał Górny    @add_test_categories(["fork"])
190c18784baSMichał Górny    def test_vkill_both(self):
191c18784baSMichał Górny        self.vkill_test(kill_parent=True, kill_child=True)
1923266b117SMichał Górny
1933266b117SMichał Górny    @add_test_categories(["fork"])
1943266b117SMichał Górny    def test_c_parent(self):
1953266b117SMichał Górny        self.resume_one_test(run_order=["parent", "parent"])
1963266b117SMichał Górny
1973266b117SMichał Górny    @add_test_categories(["fork"])
1983266b117SMichał Górny    def test_c_child(self):
1993266b117SMichał Górny        self.resume_one_test(run_order=["child", "child"])
2003266b117SMichał Górny
2013266b117SMichał Górny    @add_test_categories(["fork"])
2023266b117SMichał Górny    def test_c_parent_then_child(self):
2033266b117SMichał Górny        self.resume_one_test(run_order=["parent", "parent", "child", "child"])
2043266b117SMichał Górny
2053266b117SMichał Górny    @add_test_categories(["fork"])
2063266b117SMichał Górny    def test_c_child_then_parent(self):
2073266b117SMichał Górny        self.resume_one_test(run_order=["child", "child", "parent", "parent"])
2083266b117SMichał Górny
2093266b117SMichał Górny    @add_test_categories(["fork"])
2103266b117SMichał Górny    def test_c_interspersed(self):
2113266b117SMichał Górny        self.resume_one_test(run_order=["parent", "child", "parent", "child"])
212a3422793SMichał Górny
213a3422793SMichał Górny    @add_test_categories(["fork"])
214a3422793SMichał Górny    def test_vCont_parent(self):
215a3422793SMichał Górny        self.resume_one_test(run_order=["parent", "parent"], use_vCont=True)
216a3422793SMichał Górny
217a3422793SMichał Górny    @add_test_categories(["fork"])
218a3422793SMichał Górny    def test_vCont_child(self):
219a3422793SMichał Górny        self.resume_one_test(run_order=["child", "child"], use_vCont=True)
220a3422793SMichał Górny
221a3422793SMichał Górny    @add_test_categories(["fork"])
222a3422793SMichał Górny    def test_vCont_parent_then_child(self):
223*2238dcc3SJonas Devlieghere        self.resume_one_test(
224*2238dcc3SJonas Devlieghere            run_order=["parent", "parent", "child", "child"], use_vCont=True
225*2238dcc3SJonas Devlieghere        )
226a3422793SMichał Górny
227a3422793SMichał Górny    @add_test_categories(["fork"])
228a3422793SMichał Górny    def test_vCont_child_then_parent(self):
229*2238dcc3SJonas Devlieghere        self.resume_one_test(
230*2238dcc3SJonas Devlieghere            run_order=["child", "child", "parent", "parent"], use_vCont=True
231*2238dcc3SJonas Devlieghere        )
232a3422793SMichał Górny
233a3422793SMichał Górny    @add_test_categories(["fork"])
234a3422793SMichał Górny    def test_vCont_interspersed(self):
235*2238dcc3SJonas Devlieghere        self.resume_one_test(
236*2238dcc3SJonas Devlieghere            run_order=["parent", "child", "parent", "child"], use_vCont=True
237*2238dcc3SJonas Devlieghere        )
238a3422793SMichał Górny
239a3422793SMichał Górny    @add_test_categories(["fork"])
240a3422793SMichał Górny    def test_vCont_two_processes(self):
241*2238dcc3SJonas Devlieghere        parent_pid, parent_tid, child_pid, child_tid = self.start_fork_test(
242*2238dcc3SJonas Devlieghere            ["fork", "stop"]
243*2238dcc3SJonas Devlieghere        )
244a3422793SMichał Górny
245*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
246*2238dcc3SJonas Devlieghere            [
247a3422793SMichał Górny                # try to resume both processes
248a3422793SMichał Górny                "read packet: $vCont;c:p{}.{};c:p{}.{}#00".format(
249*2238dcc3SJonas Devlieghere                    parent_pid, parent_tid, child_pid, child_tid
250*2238dcc3SJonas Devlieghere                ),
251a3422793SMichał Górny                "send packet: $E03#00",
252*2238dcc3SJonas Devlieghere            ],
253*2238dcc3SJonas Devlieghere            True,
254*2238dcc3SJonas Devlieghere        )
255a3422793SMichał Górny        self.expect_gdbremote_sequence()
256a3422793SMichał Górny
257a3422793SMichał Górny    @add_test_categories(["fork"])
258a3422793SMichał Górny    def test_vCont_all_processes_explicit(self):
259251165b2SMichał Górny        self.start_fork_test(["fork", "stop"])
260a3422793SMichał Górny
261*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
262*2238dcc3SJonas Devlieghere            [
263a3422793SMichał Górny                # try to resume all processes implicitly
264a3422793SMichał Górny                "read packet: $vCont;c:p-1.-1#00",
265a3422793SMichał Górny                "send packet: $E03#00",
266*2238dcc3SJonas Devlieghere            ],
267*2238dcc3SJonas Devlieghere            True,
268*2238dcc3SJonas Devlieghere        )
269a3422793SMichał Górny        self.expect_gdbremote_sequence()
270a3422793SMichał Górny
271a3422793SMichał Górny    @add_test_categories(["fork"])
272a3422793SMichał Górny    def test_vCont_all_processes_implicit(self):
273251165b2SMichał Górny        self.start_fork_test(["fork", "stop"])
274a3422793SMichał Górny
275*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
276*2238dcc3SJonas Devlieghere            [
277a3422793SMichał Górny                # try to resume all processes implicitly
278a3422793SMichał Górny                "read packet: $vCont;c#00",
279a3422793SMichał Górny                "send packet: $E03#00",
280*2238dcc3SJonas Devlieghere            ],
281*2238dcc3SJonas Devlieghere            True,
282*2238dcc3SJonas Devlieghere        )
283a3422793SMichał Górny        self.expect_gdbremote_sequence()
2840481d8efSMichał Górny
2850481d8efSMichał Górny    @add_test_categories(["fork"])
28675757c86SMichał Górny    def test_threadinfo(self):
287*2238dcc3SJonas Devlieghere        parent_pid, parent_tid, child_pid, child_tid = self.start_fork_test(
288*2238dcc3SJonas Devlieghere            ["fork", "thread:new", "stop"]
289*2238dcc3SJonas Devlieghere        )
290c1829e0eSMichał Górny        pidtids = [
291c1829e0eSMichał Górny            (parent_pid, parent_tid),
292c1829e0eSMichał Górny            (child_pid, child_tid),
293c1829e0eSMichał Górny        ]
29475757c86SMichał Górny
29575757c86SMichał Górny        self.add_threadinfo_collection_packets()
29675757c86SMichał Górny        ret = self.expect_gdbremote_sequence()
29775757c86SMichał Górny        prev_pidtids = set(self.parse_threadinfo_packets(ret))
298*2238dcc3SJonas Devlieghere        self.assertEqual(
299*2238dcc3SJonas Devlieghere            prev_pidtids,
300*2238dcc3SJonas Devlieghere            frozenset((int(pid, 16), int(tid, 16)) for pid, tid in pidtids),
301*2238dcc3SJonas Devlieghere        )
30275757c86SMichał Górny        self.reset_test_sequence()
30375757c86SMichał Górny
30475757c86SMichał Górny        for pidtid in pidtids:
30575757c86SMichał Górny            self.test_sequence.add_log_lines(
306*2238dcc3SJonas Devlieghere                [
307*2238dcc3SJonas Devlieghere                    "read packet: $Hcp{}.{}#00".format(*pidtid),
30875757c86SMichał Górny                    "send packet: $OK#00",
30975757c86SMichał Górny                    "read packet: $c#00",
310*2238dcc3SJonas Devlieghere                    {
311*2238dcc3SJonas Devlieghere                        "direction": "send",
312251165b2SMichał Górny                        "regex": self.stop_regex.format(*pidtid),
31375757c86SMichał Górny                    },
314*2238dcc3SJonas Devlieghere                ],
315*2238dcc3SJonas Devlieghere                True,
316*2238dcc3SJonas Devlieghere            )
31775757c86SMichał Górny            self.add_threadinfo_collection_packets()
31875757c86SMichał Górny            ret = self.expect_gdbremote_sequence()
31975757c86SMichał Górny            self.reset_test_sequence()
32075757c86SMichał Górny            new_pidtids = set(self.parse_threadinfo_packets(ret))
32175757c86SMichał Górny            added_pidtid = new_pidtids - prev_pidtids
32275757c86SMichał Górny            prev_pidtids = new_pidtids
32375757c86SMichał Górny
32475757c86SMichał Górny            # verify that we've got exactly one new thread, and that
32575757c86SMichał Górny            # the PID matches
32675757c86SMichał Górny            self.assertEqual(len(added_pidtid), 1)
32775757c86SMichał Górny            self.assertEqual(added_pidtid.pop()[0], int(pidtid[0], 16))
32875757c86SMichał Górny
32975757c86SMichał Górny        for pidtid in new_pidtids:
33075757c86SMichał Górny            self.test_sequence.add_log_lines(
331*2238dcc3SJonas Devlieghere                [
332*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
33375757c86SMichał Górny                    "send packet: $OK#00",
334*2238dcc3SJonas Devlieghere                ],
335*2238dcc3SJonas Devlieghere                True,
336*2238dcc3SJonas Devlieghere            )
33775757c86SMichał Górny        self.expect_gdbremote_sequence()
33875757c86SMichał Górny
33975757c86SMichał Górny    @add_test_categories(["fork"])
3400481d8efSMichał Górny    def test_memory_read_write(self):
3410481d8efSMichał Górny        self.build()
3420481d8efSMichał Górny        INITIAL_DATA = "Initial message"
3430481d8efSMichał Górny        self.prep_debug_monitor_and_inferior(
344*2238dcc3SJonas Devlieghere            inferior_args=[
345*2238dcc3SJonas Devlieghere                "set-message:{}".format(INITIAL_DATA),
3460481d8efSMichał Górny                "get-data-address-hex:g_message",
3470481d8efSMichał Górny                "fork",
3480481d8efSMichał Górny                "print-message:",
349251165b2SMichał Górny                "stop",
350*2238dcc3SJonas Devlieghere            ]
351*2238dcc3SJonas Devlieghere        )
352*2238dcc3SJonas Devlieghere        self.add_qSupported_packets(["multiprocess+", "fork-events+"])
3530481d8efSMichał Górny        ret = self.expect_gdbremote_sequence()
3540481d8efSMichał Górny        self.assertIn("fork-events+", ret["qSupported_response"])
3550481d8efSMichał Górny        self.reset_test_sequence()
3560481d8efSMichał Górny
3570481d8efSMichał Górny        # continue and expect fork
358*2238dcc3SJonas Devlieghere        self.test_sequence.add_log_lines(
359*2238dcc3SJonas Devlieghere            [
3600481d8efSMichał Górny                "read packet: $c#00",
361*2238dcc3SJonas Devlieghere                {
362*2238dcc3SJonas Devlieghere                    "type": "output_match",
363*2238dcc3SJonas Devlieghere                    "regex": self.maybe_strict_output_regex(
364*2238dcc3SJonas Devlieghere                        r"data address: 0x([0-9a-fA-F]+)\r\n"
365*2238dcc3SJonas Devlieghere                    ),
366*2238dcc3SJonas Devlieghere                    "capture": {1: "addr"},
367*2238dcc3SJonas Devlieghere                },
368*2238dcc3SJonas Devlieghere                {
369*2238dcc3SJonas Devlieghere                    "direction": "send",
370*2238dcc3SJonas Devlieghere                    "regex": self.fork_regex.format("fork"),
371*2238dcc3SJonas Devlieghere                    "capture": self.fork_capture,
372*2238dcc3SJonas Devlieghere                },
373*2238dcc3SJonas Devlieghere            ],
374*2238dcc3SJonas Devlieghere            True,
375*2238dcc3SJonas Devlieghere        )
3760481d8efSMichał Górny        ret = self.expect_gdbremote_sequence()
3770481d8efSMichał Górny        pidtids = {
3780481d8efSMichał Górny            "parent": (ret["parent_pid"], ret["parent_tid"]),
3790481d8efSMichał Górny            "child": (ret["child_pid"], ret["child_tid"]),
3800481d8efSMichał Górny        }
3810481d8efSMichał Górny        addr = ret["addr"]
3820481d8efSMichał Górny        self.reset_test_sequence()
3830481d8efSMichał Górny
3840481d8efSMichał Górny        for name, pidtid in pidtids.items():
3850481d8efSMichał Górny            self.test_sequence.add_log_lines(
386*2238dcc3SJonas Devlieghere                [
387*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{}.{}#00".format(*pidtid),
3880481d8efSMichał Górny                    "send packet: $OK#00",
3890481d8efSMichał Górny                    # read the current memory contents
390*2238dcc3SJonas Devlieghere                    "read packet: $m{},{:x}#00".format(addr, len(INITIAL_DATA) + 1),
391*2238dcc3SJonas Devlieghere                    {
392*2238dcc3SJonas Devlieghere                        "direction": "send",
3930481d8efSMichał Górny                        "regex": r"^[$](.+)#.*$",
394*2238dcc3SJonas Devlieghere                        "capture": {1: "data"},
395*2238dcc3SJonas Devlieghere                    },
3960481d8efSMichał Górny                    # write a new value
397*2238dcc3SJonas Devlieghere                    "read packet: $M{},{:x}:{}#00".format(
398*2238dcc3SJonas Devlieghere                        addr, len(name) + 1, seven.hexlify(name + "\0")
399*2238dcc3SJonas Devlieghere                    ),
4000481d8efSMichał Górny                    "send packet: $OK#00",
4010481d8efSMichał Górny                    # resume the process and wait for the trap
4020481d8efSMichał Górny                    "read packet: $Hcp{}.{}#00".format(*pidtid),
4030481d8efSMichał Górny                    "send packet: $OK#00",
4040481d8efSMichał Górny                    "read packet: $c#00",
405*2238dcc3SJonas Devlieghere                    {
406*2238dcc3SJonas Devlieghere                        "type": "output_match",
4070481d8efSMichał Górny                        "regex": self.maybe_strict_output_regex(r"message: (.*)\r\n"),
408*2238dcc3SJonas Devlieghere                        "capture": {1: "printed_message"},
409*2238dcc3SJonas Devlieghere                    },
410*2238dcc3SJonas Devlieghere                    {
411*2238dcc3SJonas Devlieghere                        "direction": "send",
412251165b2SMichał Górny                        "regex": self.stop_regex.format(*pidtid),
4130481d8efSMichał Górny                    },
414*2238dcc3SJonas Devlieghere                ],
415*2238dcc3SJonas Devlieghere                True,
416*2238dcc3SJonas Devlieghere            )
4170481d8efSMichał Górny            ret = self.expect_gdbremote_sequence()
4180481d8efSMichał Górny            data = seven.unhexlify(ret["data"])
4190481d8efSMichał Górny            self.assertEqual(data, INITIAL_DATA + "\0")
420*2238dcc3SJonas Devlieghere            self.assertEqual(ret["printed_message"], name)
4210481d8efSMichał Górny            self.reset_test_sequence()
4220481d8efSMichał Górny
4230481d8efSMichał Górny        # we do the second round separately to make sure that initial data
4240481d8efSMichał Górny        # is correctly preserved while writing into the first process
4250481d8efSMichał Górny
4260481d8efSMichał Górny        for name, pidtid in pidtids.items():
4270481d8efSMichał Górny            self.test_sequence.add_log_lines(
428*2238dcc3SJonas Devlieghere                [
429*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{}.{}#00".format(*pidtid),
4300481d8efSMichał Górny                    "send packet: $OK#00",
4310481d8efSMichał Górny                    # read the current memory contents
432*2238dcc3SJonas Devlieghere                    "read packet: $m{},{:x}#00".format(addr, len(name) + 1),
433*2238dcc3SJonas Devlieghere                    {
434*2238dcc3SJonas Devlieghere                        "direction": "send",
4350481d8efSMichał Górny                        "regex": r"^[$](.+)#.*$",
436*2238dcc3SJonas Devlieghere                        "capture": {1: "data"},
437*2238dcc3SJonas Devlieghere                    },
438*2238dcc3SJonas Devlieghere                ],
439*2238dcc3SJonas Devlieghere                True,
440*2238dcc3SJonas Devlieghere            )
4410481d8efSMichał Górny            ret = self.expect_gdbremote_sequence()
4420481d8efSMichał Górny            self.assertIsNotNone(ret.get("data"))
4430481d8efSMichał Górny            data = seven.unhexlify(ret.get("data"))
4440481d8efSMichał Górny            self.assertEqual(data, name + "\0")
4450481d8efSMichał Górny            self.reset_test_sequence()
44614d67073SMichał Górny
44714d67073SMichał Górny    @add_test_categories(["fork"])
44814d67073SMichał Górny    def test_register_read_write(self):
449*2238dcc3SJonas Devlieghere        parent_pid, parent_tid, child_pid, child_tid = self.start_fork_test(
450*2238dcc3SJonas Devlieghere            ["fork", "thread:new", "stop"]
451*2238dcc3SJonas Devlieghere        )
45214d67073SMichał Górny        pidtids = [
453c1829e0eSMichał Górny            (parent_pid, parent_tid),
454c1829e0eSMichał Górny            (child_pid, child_tid),
45514d67073SMichał Górny        ]
45614d67073SMichał Górny
45714d67073SMichał Górny        for pidtid in pidtids:
45814d67073SMichał Górny            self.test_sequence.add_log_lines(
459*2238dcc3SJonas Devlieghere                [
460*2238dcc3SJonas Devlieghere                    "read packet: $Hcp{}.{}#00".format(*pidtid),
46114d67073SMichał Górny                    "send packet: $OK#00",
46214d67073SMichał Górny                    "read packet: $c#00",
463*2238dcc3SJonas Devlieghere                    {
464*2238dcc3SJonas Devlieghere                        "direction": "send",
465251165b2SMichał Górny                        "regex": self.stop_regex.format(*pidtid),
46614d67073SMichał Górny                    },
467*2238dcc3SJonas Devlieghere                ],
468*2238dcc3SJonas Devlieghere                True,
469*2238dcc3SJonas Devlieghere            )
47014d67073SMichał Górny
47114d67073SMichał Górny        self.add_threadinfo_collection_packets()
47214d67073SMichał Górny        ret = self.expect_gdbremote_sequence()
47314d67073SMichał Górny        self.reset_test_sequence()
47414d67073SMichał Górny
47514d67073SMichał Górny        pidtids = set(self.parse_threadinfo_packets(ret))
47614d67073SMichał Górny        self.assertEqual(len(pidtids), 4)
47714d67073SMichał Górny        # first, save register values from all the threads
47814d67073SMichał Górny        thread_regs = {}
47914d67073SMichał Górny        for pidtid in pidtids:
48014d67073SMichał Górny            for regno in range(256):
48114d67073SMichał Górny                self.test_sequence.add_log_lines(
482*2238dcc3SJonas Devlieghere                    [
483*2238dcc3SJonas Devlieghere                        "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
48414d67073SMichał Górny                        "send packet: $OK#00",
48514d67073SMichał Górny                        "read packet: $p{:x}#00".format(regno),
486*2238dcc3SJonas Devlieghere                        {
487*2238dcc3SJonas Devlieghere                            "direction": "send",
48814d67073SMichał Górny                            "regex": r"^[$](.+)#.*$",
489*2238dcc3SJonas Devlieghere                            "capture": {1: "data"},
490*2238dcc3SJonas Devlieghere                        },
491*2238dcc3SJonas Devlieghere                    ],
492*2238dcc3SJonas Devlieghere                    True,
493*2238dcc3SJonas Devlieghere                )
49414d67073SMichał Górny                ret = self.expect_gdbremote_sequence()
49514d67073SMichał Górny                data = ret.get("data")
49614d67073SMichał Górny                self.assertIsNotNone(data)
49714d67073SMichał Górny                # ignore registers shorter than 32 bits (this also catches
49814d67073SMichał Górny                # "Exx" errors)
49914d67073SMichał Górny                if len(data) >= 8:
50014d67073SMichał Górny                    break
50114d67073SMichał Górny            else:
50214d67073SMichał Górny                self.skipTest("no usable register found")
50314d67073SMichał Górny            thread_regs[pidtid] = (regno, data)
50414d67073SMichał Górny
50514d67073SMichał Górny        vals = set(x[1] for x in thread_regs.values())
50614d67073SMichał Górny        # NB: cheap hack to make the loop below easier
50714d67073SMichał Górny        new_val = next(iter(vals))
50814d67073SMichał Górny
50914d67073SMichał Górny        # then, start altering them and verify that we don't unexpectedly
51014d67073SMichał Górny        # change the value from another thread
51114d67073SMichał Górny        for pidtid in pidtids:
51214d67073SMichał Górny            old_val = thread_regs[pidtid]
51314d67073SMichał Górny            regno = old_val[0]
51414d67073SMichał Górny            old_val_length = len(old_val[1])
51514d67073SMichał Górny            # generate a unique new_val
51614d67073SMichał Górny            while new_val in vals:
517*2238dcc3SJonas Devlieghere                new_val = "{{:0{}x}}".format(old_val_length).format(
518*2238dcc3SJonas Devlieghere                    random.getrandbits(old_val_length * 4)
519*2238dcc3SJonas Devlieghere                )
52014d67073SMichał Górny            vals.add(new_val)
52114d67073SMichał Górny
52214d67073SMichał Górny            self.test_sequence.add_log_lines(
523*2238dcc3SJonas Devlieghere                [
524*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
52514d67073SMichał Górny                    "send packet: $OK#00",
52614d67073SMichał Górny                    "read packet: $p{:x}#00".format(regno),
527*2238dcc3SJonas Devlieghere                    {
528*2238dcc3SJonas Devlieghere                        "direction": "send",
52914d67073SMichał Górny                        "regex": r"^[$](.+)#.*$",
530*2238dcc3SJonas Devlieghere                        "capture": {1: "data"},
531*2238dcc3SJonas Devlieghere                    },
53214d67073SMichał Górny                    "read packet: $P{:x}={}#00".format(regno, new_val),
53314d67073SMichał Górny                    "send packet: $OK#00",
534*2238dcc3SJonas Devlieghere                ],
535*2238dcc3SJonas Devlieghere                True,
536*2238dcc3SJonas Devlieghere            )
53714d67073SMichał Górny            ret = self.expect_gdbremote_sequence()
53814d67073SMichał Górny            data = ret.get("data")
53914d67073SMichał Górny            self.assertIsNotNone(data)
54014d67073SMichał Górny            self.assertEqual(data, old_val[1])
54114d67073SMichał Górny            thread_regs[pidtid] = (regno, new_val)
54214d67073SMichał Górny
54314d67073SMichał Górny        # finally, verify that new values took effect
54414d67073SMichał Górny        for pidtid in pidtids:
54514d67073SMichał Górny            old_val = thread_regs[pidtid]
54614d67073SMichał Górny            self.test_sequence.add_log_lines(
547*2238dcc3SJonas Devlieghere                [
548*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
54914d67073SMichał Górny                    "send packet: $OK#00",
55014d67073SMichał Górny                    "read packet: $p{:x}#00".format(old_val[0]),
551*2238dcc3SJonas Devlieghere                    {
552*2238dcc3SJonas Devlieghere                        "direction": "send",
55314d67073SMichał Górny                        "regex": r"^[$](.+)#.*$",
554*2238dcc3SJonas Devlieghere                        "capture": {1: "data"},
555*2238dcc3SJonas Devlieghere                    },
556*2238dcc3SJonas Devlieghere                ],
557*2238dcc3SJonas Devlieghere                True,
558*2238dcc3SJonas Devlieghere            )
55914d67073SMichał Górny            ret = self.expect_gdbremote_sequence()
56014d67073SMichał Górny            data = ret.get("data")
56114d67073SMichał Górny            self.assertIsNotNone(data)
56214d67073SMichał Górny            self.assertEqual(data, old_val[1])
563630da0e3SMichał Górny
564630da0e3SMichał Górny    @add_test_categories(["fork"])
565630da0e3SMichał Górny    def test_qC(self):
566*2238dcc3SJonas Devlieghere        parent_pid, parent_tid, child_pid, child_tid = self.start_fork_test(
567*2238dcc3SJonas Devlieghere            ["fork", "thread:new", "stop"]
568*2238dcc3SJonas Devlieghere        )
569630da0e3SMichał Górny        pidtids = [
570c1829e0eSMichał Górny            (parent_pid, parent_tid),
571c1829e0eSMichał Górny            (child_pid, child_tid),
572630da0e3SMichał Górny        ]
573630da0e3SMichał Górny
574630da0e3SMichał Górny        for pidtid in pidtids:
575630da0e3SMichał Górny            self.test_sequence.add_log_lines(
576*2238dcc3SJonas Devlieghere                [
577*2238dcc3SJonas Devlieghere                    "read packet: $Hcp{}.{}#00".format(*pidtid),
578630da0e3SMichał Górny                    "send packet: $OK#00",
579630da0e3SMichał Górny                    "read packet: $c#00",
580*2238dcc3SJonas Devlieghere                    {
581*2238dcc3SJonas Devlieghere                        "direction": "send",
582251165b2SMichał Górny                        "regex": self.stop_regex.format(*pidtid),
583630da0e3SMichał Górny                    },
584*2238dcc3SJonas Devlieghere                ],
585*2238dcc3SJonas Devlieghere                True,
586*2238dcc3SJonas Devlieghere            )
587630da0e3SMichał Górny
588630da0e3SMichał Górny        self.add_threadinfo_collection_packets()
589630da0e3SMichał Górny        ret = self.expect_gdbremote_sequence()
590630da0e3SMichał Górny        self.reset_test_sequence()
591630da0e3SMichał Górny
592630da0e3SMichał Górny        pidtids = set(self.parse_threadinfo_packets(ret))
593630da0e3SMichał Górny        self.assertEqual(len(pidtids), 4)
594630da0e3SMichał Górny        for pidtid in pidtids:
595630da0e3SMichał Górny            self.test_sequence.add_log_lines(
596*2238dcc3SJonas Devlieghere                [
597*2238dcc3SJonas Devlieghere                    "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
598630da0e3SMichał Górny                    "send packet: $OK#00",
599630da0e3SMichał Górny                    "read packet: $qC#00",
600630da0e3SMichał Górny                    "send packet: $QCp{:x}.{:x}#00".format(*pidtid),
601*2238dcc3SJonas Devlieghere                ],
602*2238dcc3SJonas Devlieghere                True,
603*2238dcc3SJonas Devlieghere            )
604630da0e3SMichał Górny        self.expect_gdbremote_sequence()
605e827e518SMichał Górny
606e827e518SMichał Górny    @add_test_categories(["fork"])
607e827e518SMichał Górny    def test_T(self):
608*2238dcc3SJonas Devlieghere        parent_pid, parent_tid, child_pid, child_tid = self.start_fork_test(
609*2238dcc3SJonas Devlieghere            ["fork", "thread:new", "stop"]
610*2238dcc3SJonas Devlieghere        )
611e827e518SMichał Górny        pidtids = [
612c1829e0eSMichał Górny            (parent_pid, parent_tid),
613c1829e0eSMichał Górny            (child_pid, child_tid),
614e827e518SMichał Górny        ]
615e827e518SMichał Górny
616e827e518SMichał Górny        for pidtid in pidtids:
617e827e518SMichał Górny            self.test_sequence.add_log_lines(
618*2238dcc3SJonas Devlieghere                [
619*2238dcc3SJonas Devlieghere                    "read packet: $Hcp{}.{}#00".format(*pidtid),
620e827e518SMichał Górny                    "send packet: $OK#00",
621e827e518SMichał Górny                    "read packet: $c#00",
622*2238dcc3SJonas Devlieghere                    {
623*2238dcc3SJonas Devlieghere                        "direction": "send",
624251165b2SMichał Górny                        "regex": self.stop_regex.format(*pidtid),
625e827e518SMichał Górny                    },
626*2238dcc3SJonas Devlieghere                ],
627*2238dcc3SJonas Devlieghere                True,
628*2238dcc3SJonas Devlieghere            )
629e827e518SMichał Górny
630e827e518SMichał Górny        self.add_threadinfo_collection_packets()
631e827e518SMichał Górny        ret = self.expect_gdbremote_sequence()
632e827e518SMichał Górny        self.reset_test_sequence()
633e827e518SMichał Górny
634e827e518SMichał Górny        pidtids = set(self.parse_threadinfo_packets(ret))
635e827e518SMichał Górny        self.assertEqual(len(pidtids), 4)
636e827e518SMichał Górny        max_pid = max(pid for pid, tid in pidtids)
637e827e518SMichał Górny        max_tid = max(tid for pid, tid in pidtids)
638e827e518SMichał Górny        bad_pidtids = (
639e827e518SMichał Górny            (max_pid, max_tid + 1, "E02"),
640e827e518SMichał Górny            (max_pid + 1, max_tid, "E01"),
641e827e518SMichał Górny            (max_pid + 1, max_tid + 1, "E01"),
642e827e518SMichał Górny        )
643e827e518SMichał Górny
644e827e518SMichał Górny        for pidtid in pidtids:
645e827e518SMichał Górny            self.test_sequence.add_log_lines(
646e827e518SMichał Górny                [
647e827e518SMichał Górny                    # test explicit PID+TID
648e827e518SMichał Górny                    "read packet: $Tp{:x}.{:x}#00".format(*pidtid),
649e827e518SMichał Górny                    "send packet: $OK#00",
650e827e518SMichał Górny                    # test implicit PID via Hg
651e827e518SMichał Górny                    "read packet: $Hgp{:x}.{:x}#00".format(*pidtid),
652e827e518SMichał Górny                    "send packet: $OK#00",
653e827e518SMichał Górny                    "read packet: $T{:x}#00".format(max_tid + 1),
654e827e518SMichał Górny                    "send packet: $E02#00",
655e827e518SMichał Górny                    "read packet: $T{:x}#00".format(pidtid[1]),
656e827e518SMichał Górny                    "send packet: $OK#00",
657*2238dcc3SJonas Devlieghere                ],
658*2238dcc3SJonas Devlieghere                True,
659*2238dcc3SJonas Devlieghere            )
660e827e518SMichał Górny        for pid, tid, expected in bad_pidtids:
661e827e518SMichał Górny            self.test_sequence.add_log_lines(
662*2238dcc3SJonas Devlieghere                [
663*2238dcc3SJonas Devlieghere                    "read packet: $Tp{:x}.{:x}#00".format(pid, tid),
664e827e518SMichał Górny                    "send packet: ${}#00".format(expected),
665*2238dcc3SJonas Devlieghere                ],
666*2238dcc3SJonas Devlieghere                True,
667*2238dcc3SJonas Devlieghere            )
668e827e518SMichał Górny        self.expect_gdbremote_sequence()
669