xref: /llvm-project/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py (revision 4d9e7b14e45120557e57da2f00f6d23cf122dd95)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest lldb breakpoint command add/list/delete.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprechtimport lldb
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
9*4d9e7b14SDmitry Vasilyevfrom lldbsuite.test import lldbutil, lldbplatformutil
10dc9e6c52SJeffrey Tanimport json
11c0124084SGreg Claytonimport os
1299451b44SJordan Rupprechtimport side_effect
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprecht
1599451b44SJordan Rupprechtclass BreakpointCommandTestCase(TestBase):
1699451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
1799451b44SJordan Rupprecht
1899451b44SJordan Rupprecht    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
190a68443bSWalter Erquinigo    def test_breakpoint_command_sequence(self):
2099451b44SJordan Rupprecht        """Test a sequence of breakpoint command add, list, and delete."""
2199451b44SJordan Rupprecht        self.build()
2299451b44SJordan Rupprecht        self.breakpoint_command_sequence()
2399451b44SJordan Rupprecht
2499451b44SJordan Rupprecht    @skipIf(oslist=["windows"], bugnumber="llvm.org/pr44431")
2599451b44SJordan Rupprecht    def test_script_parameters(self):
2699451b44SJordan Rupprecht        """Test a sequence of breakpoint command add, list, and delete."""
2799451b44SJordan Rupprecht        self.build()
2899451b44SJordan Rupprecht        self.breakpoint_command_script_parameters()
2999451b44SJordan Rupprecht
3099451b44SJordan Rupprecht    def test_commands_on_creation(self):
3199451b44SJordan Rupprecht        self.build()
3299451b44SJordan Rupprecht        self.breakpoint_commands_on_creation()
3399451b44SJordan Rupprecht
34c0124084SGreg Clayton    @skipIf(oslist=["windows"])
35c0124084SGreg Clayton    @no_debug_info_test
36c0124084SGreg Clayton    def test_breakpoints_with_relative_path_line_tables(self):
37c0124084SGreg Clayton        """
38c0124084SGreg Clayton        Test that we can set breakpoints using a full or partial path when
39c0124084SGreg Clayton        line tables in the debug information has relative paths where the
40c0124084SGreg Clayton        relative path is either fully contained in the specified path, or if
41c0124084SGreg Clayton        the specified path also a relative path that is shorter than the
42c0124084SGreg Clayton        path in the debug info.
43c0124084SGreg Clayton
44c0124084SGreg Clayton        The "relative.yaml" contains a line table that is:
45c0124084SGreg Clayton
46c0124084SGreg Clayton        Line table for a/b/c/main.cpp in `a.out
47c0124084SGreg Clayton        0x0000000100003f94: a/b/c/main.cpp:1
48c0124084SGreg Clayton        0x0000000100003fb0: a/b/c/main.cpp:2:3
49c0124084SGreg Clayton        0x0000000100003fb8: a/b/c/main.cpp:2:3
50c0124084SGreg Clayton
51c0124084SGreg Clayton        So the line table contains relative paths. We should be able to set
52c0124084SGreg Clayton        breakpoints with any source path that matches this path which
53c0124084SGreg Clayton        includes paths that are longer than "a/b/c/main.cpp", but also any
54c0124084SGreg Clayton        relative path that is shorter than this while all specified relative
55c0124084SGreg Clayton        path components still match.
56c0124084SGreg Clayton        """
57c0124084SGreg Clayton        src_dir = self.getSourceDir()
58c0124084SGreg Clayton        yaml_path = os.path.join(src_dir, "relative.yaml")
59c0124084SGreg Clayton        yaml_base, ext = os.path.splitext(yaml_path)
60c0124084SGreg Clayton        obj_path = self.getBuildArtifact("a.out")
61c0124084SGreg Clayton        self.yaml2obj(yaml_path, obj_path)
62c0124084SGreg Clayton
63c0124084SGreg Clayton        # Create a target with the object file we just created from YAML
64c0124084SGreg Clayton        target = self.dbg.CreateTarget(obj_path)
65c0124084SGreg Clayton        # We now have debug information with line table paths that start are
66c0124084SGreg Clayton        # "./a/b/c/main.cpp".
67c0124084SGreg Clayton
68c0124084SGreg Clayton        # Make sure that all of the following paths create a breakpoint
69c0124084SGreg Clayton        # successfully. We have paths that are longer than our path, and also
70c0124084SGreg Clayton        # that are shorter where all relative directories still match.
71c0124084SGreg Clayton        valid_paths = [
72c0124084SGreg Clayton            "/x/a/b/c/main.cpp",
73c0124084SGreg Clayton            "/x/y/a/b/c/main.cpp",
74c0124084SGreg Clayton            "./x/y/a/b/c/main.cpp",
75c0124084SGreg Clayton            "x/y/a/b/c/main.cpp",
76c0124084SGreg Clayton            "./y/a/b/c/main.cpp",
77c0124084SGreg Clayton            "y/a/b/c/main.cpp",
78c0124084SGreg Clayton            "./a/b/c/main.cpp",
79c0124084SGreg Clayton            "a/b/c/main.cpp",
80c0124084SGreg Clayton            "./b/c/main.cpp",
81c0124084SGreg Clayton            "b/c/main.cpp",
82c0124084SGreg Clayton            "./c/main.cpp",
83c0124084SGreg Clayton            "c/main.cpp",
84c0124084SGreg Clayton            "./main.cpp",
85c0124084SGreg Clayton            "main.cpp",
86c0124084SGreg Clayton        ]
87c0124084SGreg Clayton        for path in valid_paths:
88c0124084SGreg Clayton            bkpt = target.BreakpointCreateByLocation(path, 2)
899c246882SJordan Rupprecht            self.assertGreater(
909c246882SJordan Rupprecht                bkpt.GetNumLocations(),
919c246882SJordan Rupprecht                0,
92c0124084SGreg Clayton                'Couldn\'t resolve breakpoint using full path "%s" in executate "%s" with '
932238dcc3SJonas Devlieghere                "debug info that has relative path with matching suffix"
942238dcc3SJonas Devlieghere                % (path, self.getBuildArtifact("a.out")),
952238dcc3SJonas Devlieghere            )
96c0124084SGreg Clayton        invalid_paths = [
97c0124084SGreg Clayton            "/x/b/c/main.cpp",
98c0124084SGreg Clayton            "/x/c/main.cpp",
99c0124084SGreg Clayton            "/x/main.cpp",
100c0124084SGreg Clayton            "./x/y/a/d/c/main.cpp",
101c0124084SGreg Clayton        ]
102dc9e6c52SJeffrey Tan        # Reset source map.
103dc9e6c52SJeffrey Tan        self.runCmd("settings clear target.source-map")
104c0124084SGreg Clayton        for path in invalid_paths:
105c0124084SGreg Clayton            bkpt = target.BreakpointCreateByLocation(path, 2)
1062238dcc3SJonas Devlieghere            self.assertEqual(
1072238dcc3SJonas Devlieghere                bkpt.GetNumLocations(),
1082238dcc3SJonas Devlieghere                0,
109c0124084SGreg Clayton                'Incorrectly resolved a breakpoint using full path "%s" with '
1102238dcc3SJonas Devlieghere                "debug info that has relative path with matching suffix" % (path),
1112238dcc3SJonas Devlieghere            )
112c0124084SGreg Clayton
113dd00c4dbSGreg Clayton    @no_debug_info_test
114dd00c4dbSGreg Clayton    def test_breakpoints_with_bad_aranges(self):
115dd00c4dbSGreg Clayton        """
116dd00c4dbSGreg Clayton        Test that we can set breakpoints in a file that has an invalid
117dd00c4dbSGreg Clayton        .debug_aranges. Older versions of LLDB would find a line entry
118dd00c4dbSGreg Clayton        in the line table and then would use the start address of the line
119dd00c4dbSGreg Clayton        entry to do an address lookup on the entry from the line table. If
120dd00c4dbSGreg Clayton        this address to symbol context lookup would fail, due to a bad
121dd00c4dbSGreg Clayton        .debug_aranges, it would cause the breakpoint to not get resolved.
122dd00c4dbSGreg Clayton        Verify that even in these conditions we are able to resolve a
123dd00c4dbSGreg Clayton        breakpoint.
124dd00c4dbSGreg Clayton
125dd00c4dbSGreg Clayton        The "bad_aranges.yaml" contains a line table that is:
126dd00c4dbSGreg Clayton
127dd00c4dbSGreg Clayton        Line table for /tmp/ab/main.cpp in `a.out
128dd00c4dbSGreg Clayton        0x0000000100003f94: /tmp/ab/main.cpp:1
129dd00c4dbSGreg Clayton        0x0000000100003fb0: /tmp/ab/main.cpp:2:3
130dd00c4dbSGreg Clayton        0x0000000100003fb8: /tmp/ab/main.cpp:2:3
131dd00c4dbSGreg Clayton
132dd00c4dbSGreg Clayton        The .debug_aranges has one range for this compile unit that is
133dd00c4dbSGreg Clayton        invalid: [0x0000000200003f94-0x0000000200003fb8). This will cause
134dd00c4dbSGreg Clayton        the resolving of the addresses to fail.
135dd00c4dbSGreg Clayton        """
136dd00c4dbSGreg Clayton        src_dir = self.getSourceDir()
137dd00c4dbSGreg Clayton        yaml_path = os.path.join(src_dir, "bad_aranges.yaml")
138dd00c4dbSGreg Clayton        yaml_base, ext = os.path.splitext(yaml_path)
139dd00c4dbSGreg Clayton        obj_path = self.getBuildArtifact("a.out")
140dd00c4dbSGreg Clayton        self.yaml2obj(yaml_path, obj_path)
141dd00c4dbSGreg Clayton
142dd00c4dbSGreg Clayton        # Create a target with the object file we just created from YAML
143dd00c4dbSGreg Clayton        target = self.dbg.CreateTarget(obj_path)
1442238dcc3SJonas Devlieghere        src_path = "/tmp/ab/main.cpp"
145dd00c4dbSGreg Clayton        bkpt = target.BreakpointCreateByLocation(src_path, 2)
1469c246882SJordan Rupprecht        self.assertGreater(
1479c246882SJordan Rupprecht            bkpt.GetNumLocations(),
1489c246882SJordan Rupprecht            0,
149dd00c4dbSGreg Clayton            'Couldn\'t resolve breakpoint using "%s" in executate "%s" with '
1502238dcc3SJonas Devlieghere            "debug info that has a bad .debug_aranges section"
1512238dcc3SJonas Devlieghere            % (src_path, self.getBuildArtifact("a.out")),
1522238dcc3SJonas Devlieghere        )
153c0124084SGreg Clayton
15499451b44SJordan Rupprecht    def setUp(self):
15599451b44SJordan Rupprecht        # Call super's setUp().
15699451b44SJordan Rupprecht        TestBase.setUp(self)
15799451b44SJordan Rupprecht        # Find the line number to break inside main().
1582238dcc3SJonas Devlieghere        self.line = line_number("main.c", "// Set break point at this line.")
15999451b44SJordan Rupprecht        # disable "There is a running process, kill it and restart?" prompt
16099451b44SJordan Rupprecht        self.runCmd("settings set auto-confirm true")
1612238dcc3SJonas Devlieghere        self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
16299451b44SJordan Rupprecht
16399451b44SJordan Rupprecht    def test_delete_all_breakpoints(self):
16499451b44SJordan Rupprecht        """Test that deleting all breakpoints works."""
16599451b44SJordan Rupprecht        self.build()
16699451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
16799451b44SJordan Rupprecht        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
16899451b44SJordan Rupprecht
16999451b44SJordan Rupprecht        lldbutil.run_break_set_by_symbol(self, "main")
17099451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
1712238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=True
1722238dcc3SJonas Devlieghere        )
17399451b44SJordan Rupprecht
17499451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
17599451b44SJordan Rupprecht
17699451b44SJordan Rupprecht        self.runCmd("breakpoint delete")
17799451b44SJordan Rupprecht        self.runCmd("process continue")
1782238dcc3SJonas Devlieghere        self.expect(
1792238dcc3SJonas Devlieghere            "process status",
1802238dcc3SJonas Devlieghere            PROCESS_STOPPED,
1812238dcc3SJonas Devlieghere            patterns=["Process .* exited with status = 0"],
1822238dcc3SJonas Devlieghere        )
18399451b44SJordan Rupprecht
18499451b44SJordan Rupprecht    def breakpoint_command_sequence(self):
18599451b44SJordan Rupprecht        """Test a sequence of breakpoint command add, list, and delete."""
18699451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
18799451b44SJordan Rupprecht        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
18899451b44SJordan Rupprecht
18999451b44SJordan Rupprecht        # Add three breakpoints on the same line.  The first time we don't specify the file,
19099451b44SJordan Rupprecht        # since the default file is the one containing main:
19199451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
1922238dcc3SJonas Devlieghere            self, None, self.line, num_expected_locations=1, loc_exact=True
1932238dcc3SJonas Devlieghere        )
19499451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
1952238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=True
1962238dcc3SJonas Devlieghere        )
19799451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
1982238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=True
1992238dcc3SJonas Devlieghere        )
20099451b44SJordan Rupprecht        # Breakpoint 4 - set at the same location as breakpoint 1 to test
20199451b44SJordan Rupprecht        # setting breakpoint commands on two breakpoints at a time
20299451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2032238dcc3SJonas Devlieghere            self, None, self.line, num_expected_locations=1, loc_exact=True
2042238dcc3SJonas Devlieghere        )
20599451b44SJordan Rupprecht        # Make sure relative path source breakpoints work as expected. We test
20699451b44SJordan Rupprecht        # with partial paths with and without "./" prefixes.
20799451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2082238dcc3SJonas Devlieghere            self, "./main.c", self.line, num_expected_locations=1, loc_exact=True
2092238dcc3SJonas Devlieghere        )
21099451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2112238dcc3SJonas Devlieghere            self,
2122238dcc3SJonas Devlieghere            "breakpoint_command/main.c",
2132238dcc3SJonas Devlieghere            self.line,
2142238dcc3SJonas Devlieghere            num_expected_locations=1,
2152238dcc3SJonas Devlieghere            loc_exact=True,
2162238dcc3SJonas Devlieghere        )
21799451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2182238dcc3SJonas Devlieghere            self,
2192238dcc3SJonas Devlieghere            "./breakpoint_command/main.c",
2202238dcc3SJonas Devlieghere            self.line,
2212238dcc3SJonas Devlieghere            num_expected_locations=1,
2222238dcc3SJonas Devlieghere            loc_exact=True,
2232238dcc3SJonas Devlieghere        )
22499451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2252238dcc3SJonas Devlieghere            self,
2262238dcc3SJonas Devlieghere            "breakpoint/breakpoint_command/main.c",
2272238dcc3SJonas Devlieghere            self.line,
2282238dcc3SJonas Devlieghere            num_expected_locations=1,
2292238dcc3SJonas Devlieghere            loc_exact=True,
2302238dcc3SJonas Devlieghere        )
23199451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2322238dcc3SJonas Devlieghere            self,
2332238dcc3SJonas Devlieghere            "./breakpoint/breakpoint_command/main.c",
2342238dcc3SJonas Devlieghere            self.line,
2352238dcc3SJonas Devlieghere            num_expected_locations=1,
2362238dcc3SJonas Devlieghere            loc_exact=True,
2372238dcc3SJonas Devlieghere        )
23899451b44SJordan Rupprecht        # Test relative breakpoints with incorrect paths and make sure we get
23999451b44SJordan Rupprecht        # no breakpoint locations
24099451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2412238dcc3SJonas Devlieghere            self, "invalid/main.c", self.line, num_expected_locations=0, loc_exact=True
2422238dcc3SJonas Devlieghere        )
24399451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
2442238dcc3SJonas Devlieghere            self,
2452238dcc3SJonas Devlieghere            "./invalid/main.c",
2462238dcc3SJonas Devlieghere            self.line,
2472238dcc3SJonas Devlieghere            num_expected_locations=0,
2482238dcc3SJonas Devlieghere            loc_exact=True,
2492238dcc3SJonas Devlieghere        )
25099451b44SJordan Rupprecht        # Now add callbacks for the breakpoints just created.
25199451b44SJordan Rupprecht        self.runCmd(
2522238dcc3SJonas Devlieghere            "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4"
2532238dcc3SJonas Devlieghere        )
25499451b44SJordan Rupprecht        self.runCmd(
2552238dcc3SJonas Devlieghere            "breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2"
2562238dcc3SJonas Devlieghere        )
25799451b44SJordan Rupprecht
25899451b44SJordan Rupprecht        import side_effect
2592238dcc3SJonas Devlieghere
26099451b44SJordan Rupprecht        self.runCmd("command script import --allow-reload ./bktptcmd.py")
26199451b44SJordan Rupprecht
2622238dcc3SJonas Devlieghere        self.runCmd("breakpoint command add --python-function bktptcmd.function 3")
26399451b44SJordan Rupprecht
26499451b44SJordan Rupprecht        # Check that the breakpoint commands are correctly set.
26599451b44SJordan Rupprecht
26699451b44SJordan Rupprecht        # The breakpoint list now only contains breakpoint 1.
26799451b44SJordan Rupprecht        self.expect(
2682238dcc3SJonas Devlieghere            "breakpoint list",
2692238dcc3SJonas Devlieghere            "Breakpoints 1 & 2 created",
2702238dcc3SJonas Devlieghere            substrs=[
2712238dcc3SJonas Devlieghere                "2: file = 'main.c', line = %d, exact_match = 0, locations = 1"
2722238dcc3SJonas Devlieghere                % self.line
2732238dcc3SJonas Devlieghere            ],
2742238dcc3SJonas Devlieghere            patterns=[
2752238dcc3SJonas Devlieghere                "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1"
2762238dcc3SJonas Devlieghere                % self.line
2772238dcc3SJonas Devlieghere            ],
2782238dcc3SJonas Devlieghere        )
27999451b44SJordan Rupprecht
28099451b44SJordan Rupprecht        self.expect(
28199451b44SJordan Rupprecht            "breakpoint list -f",
28299451b44SJordan Rupprecht            "Breakpoints 1 & 2 created",
28399451b44SJordan Rupprecht            substrs=[
2842238dcc3SJonas Devlieghere                "2: file = 'main.c', line = %d, exact_match = 0, locations = 1"
2852238dcc3SJonas Devlieghere                % self.line
2862238dcc3SJonas Devlieghere            ],
28799451b44SJordan Rupprecht            patterns=[
2882238dcc3SJonas Devlieghere                "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1"
2892238dcc3SJonas Devlieghere                % self.line,
2902238dcc3SJonas Devlieghere                "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % self.line,
2912238dcc3SJonas Devlieghere                "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % self.line,
2922238dcc3SJonas Devlieghere            ],
2932238dcc3SJonas Devlieghere        )
29499451b44SJordan Rupprecht
2952238dcc3SJonas Devlieghere        self.expect(
2962238dcc3SJonas Devlieghere            "breakpoint command list 1",
2972238dcc3SJonas Devlieghere            "Breakpoint 1 command ok",
2982238dcc3SJonas Devlieghere            substrs=["Breakpoint commands:", "frame variable --show-types --scope"],
2992238dcc3SJonas Devlieghere        )
3002238dcc3SJonas Devlieghere        self.expect(
3012238dcc3SJonas Devlieghere            "breakpoint command list 2",
3022238dcc3SJonas Devlieghere            "Breakpoint 2 command ok",
3032238dcc3SJonas Devlieghere            substrs=[
3042238dcc3SJonas Devlieghere                "Breakpoint commands (Python):",
30599451b44SJordan Rupprecht                "import side_effect",
3062238dcc3SJonas Devlieghere                "side_effect.one_liner",
3072238dcc3SJonas Devlieghere            ],
3082238dcc3SJonas Devlieghere        )
3092238dcc3SJonas Devlieghere        self.expect(
3102238dcc3SJonas Devlieghere            "breakpoint command list 3",
3112238dcc3SJonas Devlieghere            "Breakpoint 3 command ok",
3122238dcc3SJonas Devlieghere            substrs=[
3132238dcc3SJonas Devlieghere                "Breakpoint commands (Python):",
3142238dcc3SJonas Devlieghere                "bktptcmd.function(frame, bp_loc, internal_dict)",
3152238dcc3SJonas Devlieghere            ],
3162238dcc3SJonas Devlieghere        )
31799451b44SJordan Rupprecht
3182238dcc3SJonas Devlieghere        self.expect(
3192238dcc3SJonas Devlieghere            "breakpoint command list 4",
3202238dcc3SJonas Devlieghere            "Breakpoint 4 command ok",
3212238dcc3SJonas Devlieghere            substrs=["Breakpoint commands:", "frame variable --show-types --scope"],
3222238dcc3SJonas Devlieghere        )
32399451b44SJordan Rupprecht
32499451b44SJordan Rupprecht        self.runCmd("breakpoint delete 4")
32599451b44SJordan Rupprecht
32699451b44SJordan Rupprecht        # Next lets try some other breakpoint kinds.  First break with a regular expression
32799451b44SJordan Rupprecht        # and then specify only one file.  The first time we should get two locations,
32899451b44SJordan Rupprecht        # the second time only one:
32999451b44SJordan Rupprecht
33099451b44SJordan Rupprecht        lldbutil.run_break_set_by_regexp(
3312238dcc3SJonas Devlieghere            self, r"._MyFunction", num_expected_locations=2
3322238dcc3SJonas Devlieghere        )
33399451b44SJordan Rupprecht
33499451b44SJordan Rupprecht        lldbutil.run_break_set_by_regexp(
3352238dcc3SJonas Devlieghere            self, r"._MyFunction", extra_options="-f a.c", num_expected_locations=1
3362238dcc3SJonas Devlieghere        )
33799451b44SJordan Rupprecht
33899451b44SJordan Rupprecht        lldbutil.run_break_set_by_regexp(
33999451b44SJordan Rupprecht            self,
34099451b44SJordan Rupprecht            r"._MyFunction",
34199451b44SJordan Rupprecht            extra_options="-f a.c -f b.c",
3422238dcc3SJonas Devlieghere            num_expected_locations=2,
3432238dcc3SJonas Devlieghere        )
34499451b44SJordan Rupprecht
34599451b44SJordan Rupprecht        # Now try a source regex breakpoint:
34699451b44SJordan Rupprecht        lldbutil.run_break_set_by_source_regexp(
34799451b44SJordan Rupprecht            self,
34899451b44SJordan Rupprecht            r"is about to return [12]0",
34999451b44SJordan Rupprecht            extra_options="-f a.c -f b.c",
3502238dcc3SJonas Devlieghere            num_expected_locations=2,
3512238dcc3SJonas Devlieghere        )
35299451b44SJordan Rupprecht
35399451b44SJordan Rupprecht        lldbutil.run_break_set_by_source_regexp(
35499451b44SJordan Rupprecht            self,
35599451b44SJordan Rupprecht            r"is about to return [12]0",
35699451b44SJordan Rupprecht            extra_options="-f a.c",
3572238dcc3SJonas Devlieghere            num_expected_locations=1,
3582238dcc3SJonas Devlieghere        )
35999451b44SJordan Rupprecht
36099451b44SJordan Rupprecht        # Reset our canary variables and run the program.
36199451b44SJordan Rupprecht        side_effect.one_liner = None
36299451b44SJordan Rupprecht        side_effect.bktptcmd = None
36399451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
36499451b44SJordan Rupprecht
36599451b44SJordan Rupprecht        # Check the value of canary variables.
36680fcecb1SJonas Devlieghere        self.assertEqual("one liner was here", side_effect.one_liner)
36780fcecb1SJonas Devlieghere        self.assertEqual("function was here", side_effect.bktptcmd)
36899451b44SJordan Rupprecht
36999451b44SJordan Rupprecht        # Finish the program.
37099451b44SJordan Rupprecht        self.runCmd("process continue")
37199451b44SJordan Rupprecht
37299451b44SJordan Rupprecht        # Remove the breakpoint command associated with breakpoint 1.
37399451b44SJordan Rupprecht        self.runCmd("breakpoint command delete 1")
37499451b44SJordan Rupprecht
37599451b44SJordan Rupprecht        # Remove breakpoint 2.
37699451b44SJordan Rupprecht        self.runCmd("breakpoint delete 2")
37799451b44SJordan Rupprecht
37899451b44SJordan Rupprecht        self.expect(
37999451b44SJordan Rupprecht            "breakpoint command list 1",
3802238dcc3SJonas Devlieghere            startstr="Breakpoint 1 does not have an associated command.",
3812238dcc3SJonas Devlieghere        )
38299451b44SJordan Rupprecht        self.expect(
38399451b44SJordan Rupprecht            "breakpoint command list 2",
38499451b44SJordan Rupprecht            error=True,
3852238dcc3SJonas Devlieghere            startstr="error: '2' is not a currently valid breakpoint ID.",
3862238dcc3SJonas Devlieghere        )
38799451b44SJordan Rupprecht
38899451b44SJordan Rupprecht        # The breakpoint list now only contains breakpoint 1.
38999451b44SJordan Rupprecht        self.expect(
39099451b44SJordan Rupprecht            "breakpoint list -f",
39199451b44SJordan Rupprecht            "Breakpoint 1 exists",
39299451b44SJordan Rupprecht            patterns=[
3932238dcc3SJonas Devlieghere                "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1, resolved = 1"
3942238dcc3SJonas Devlieghere                % self.line,
3952238dcc3SJonas Devlieghere                "hit count = 1",
3962238dcc3SJonas Devlieghere            ],
3972238dcc3SJonas Devlieghere        )
39899451b44SJordan Rupprecht
39999451b44SJordan Rupprecht        # Not breakpoint 2.
40099451b44SJordan Rupprecht        self.expect(
40199451b44SJordan Rupprecht            "breakpoint list -f",
40299451b44SJordan Rupprecht            "No more breakpoint 2",
40399451b44SJordan Rupprecht            matching=False,
40499451b44SJordan Rupprecht            substrs=[
4052238dcc3SJonas Devlieghere                "2: file = 'main.c', line = %d, exact_match = 0, locations = 1, resolved = 1"
4062238dcc3SJonas Devlieghere                % self.line
4072238dcc3SJonas Devlieghere            ],
4082238dcc3SJonas Devlieghere        )
40999451b44SJordan Rupprecht
41099451b44SJordan Rupprecht        # Run the program again, with breakpoint 1 remaining.
41199451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
41299451b44SJordan Rupprecht
41399451b44SJordan Rupprecht        # We should be stopped again due to breakpoint 1.
41499451b44SJordan Rupprecht
41599451b44SJordan Rupprecht        # The stop reason of the thread should be breakpoint.
4162238dcc3SJonas Devlieghere        self.expect(
4172238dcc3SJonas Devlieghere            "thread list",
4182238dcc3SJonas Devlieghere            STOPPED_DUE_TO_BREAKPOINT,
4192238dcc3SJonas Devlieghere            substrs=["stopped", "stop reason = breakpoint"],
4202238dcc3SJonas Devlieghere        )
42199451b44SJordan Rupprecht
42297495874SFelipe de Azevedo Piovezan        # The breakpoint should have a hit count of 1, since we reset counts
42397495874SFelipe de Azevedo Piovezan        # for each run.
42497495874SFelipe de Azevedo Piovezan        lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1)
42599451b44SJordan Rupprecht
42699451b44SJordan Rupprecht    def breakpoint_command_script_parameters(self):
42799451b44SJordan Rupprecht        """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function."""
42899451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
42999451b44SJordan Rupprecht        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
43099451b44SJordan Rupprecht
43199451b44SJordan Rupprecht        # Add a breakpoint.
43299451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
4332238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=True
4342238dcc3SJonas Devlieghere        )
43599451b44SJordan Rupprecht
43699451b44SJordan Rupprecht        # Now add callbacks for the breakpoints just created.
4372238dcc3SJonas Devlieghere        self.runCmd(
4382238dcc3SJonas Devlieghere            "breakpoint command add -s python -o 'import side_effect; side_effect.frame = str(frame); side_effect.bp_loc = str(bp_loc)' 1"
4392238dcc3SJonas Devlieghere        )
44099451b44SJordan Rupprecht
44199451b44SJordan Rupprecht        # Reset canary variables and run.
44299451b44SJordan Rupprecht        side_effect.frame = None
44399451b44SJordan Rupprecht        side_effect.bp_loc = None
44499451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
44599451b44SJordan Rupprecht
44699451b44SJordan Rupprecht        self.expect(side_effect.frame, exe=False, startstr="frame #0:")
4472238dcc3SJonas Devlieghere        self.expect(
4482238dcc3SJonas Devlieghere            side_effect.bp_loc,
4492238dcc3SJonas Devlieghere            exe=False,
4502238dcc3SJonas Devlieghere            patterns=["1.* where = .*main .* resolved,( hardware,)? hit count = 1"],
4512238dcc3SJonas Devlieghere        )
45299451b44SJordan Rupprecht
45399451b44SJordan Rupprecht    def breakpoint_commands_on_creation(self):
45499451b44SJordan Rupprecht        """Test that setting breakpoint commands when creating the breakpoint works"""
45554c26872SRaphael Isemann        target = self.createTestTarget()
45699451b44SJordan Rupprecht
45799451b44SJordan Rupprecht        # Add a breakpoint.
45899451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
4592238dcc3SJonas Devlieghere            self,
4602238dcc3SJonas Devlieghere            "main.c",
4612238dcc3SJonas Devlieghere            self.line,
4622238dcc3SJonas Devlieghere            num_expected_locations=1,
4632238dcc3SJonas Devlieghere            loc_exact=True,
4642238dcc3SJonas Devlieghere            extra_options='-C bt -C "thread list" -C continue',
4652238dcc3SJonas Devlieghere        )
46699451b44SJordan Rupprecht
46799451b44SJordan Rupprecht        bkpt = target.FindBreakpointByID(1)
46899451b44SJordan Rupprecht        self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
46999451b44SJordan Rupprecht        com_list = lldb.SBStringList()
47099451b44SJordan Rupprecht        bkpt.GetCommandLineCommands(com_list)
47199451b44SJordan Rupprecht        self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands")
47299451b44SJordan Rupprecht        self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt")
4732238dcc3SJonas Devlieghere        self.assertEqual(
4742238dcc3SJonas Devlieghere            com_list.GetStringAtIndex(1), "thread list", "Next thread list"
4752238dcc3SJonas Devlieghere        )
47699451b44SJordan Rupprecht        self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue")
4773726ac41SJim Ingham
478d92f7f79SJim Ingham    def test_add_commands_by_breakpoint_name(self):
479d92f7f79SJim Ingham        """Make sure that when you specify a breakpoint name to "break command add"
480d92f7f79SJim Ingham        it gets added to all the breakpoints marked with that name."""
481d92f7f79SJim Ingham        self.build()
482d92f7f79SJim Ingham        target = self.createTestTarget()
483d92f7f79SJim Ingham
484d92f7f79SJim Ingham        bp_ids = []
485d92f7f79SJim Ingham        bp_names = ["main", "not_here", "main"]
486d92f7f79SJim Ingham        for bp_name in bp_names:
487d92f7f79SJim Ingham            bp = target.BreakpointCreateByName(bp_name)
488d92f7f79SJim Ingham            bp.AddName("MyBKPTS")
489d92f7f79SJim Ingham            bp_ids.append(bp.GetID())
490d92f7f79SJim Ingham        # First do it with a script one-liner:
491d92f7f79SJim Ingham        self.runCmd("breakpoint command add -s py -o 'print(\"some command\")' MyBKPTS")
492d92f7f79SJim Ingham        for id in bp_ids:
4932238dcc3SJonas Devlieghere            self.expect(
4942238dcc3SJonas Devlieghere                "breakpoint command list {0}".format(id), patterns=["some command"]
4952238dcc3SJonas Devlieghere            )
496d92f7f79SJim Ingham        # Now do the same thing with a python function:
497d92f7f79SJim Ingham        import side_effect
4982238dcc3SJonas Devlieghere
499d92f7f79SJim Ingham        self.runCmd("command script import --allow-reload ./bktptcmd.py")
500d92f7f79SJim Ingham
5012238dcc3SJonas Devlieghere        self.runCmd(
5022238dcc3SJonas Devlieghere            "breakpoint command add --python-function bktptcmd.function MyBKPTS"
5032238dcc3SJonas Devlieghere        )
504d92f7f79SJim Ingham        for id in bp_ids:
5052238dcc3SJonas Devlieghere            self.expect(
5062238dcc3SJonas Devlieghere                "breakpoint command list {0}".format(id), patterns=["bktptcmd.function"]
5072238dcc3SJonas Devlieghere            )
508d92f7f79SJim Ingham
5093726ac41SJim Ingham    def test_breakpoint_delete_disabled(self):
5103726ac41SJim Ingham        """Test 'break delete --disabled' works"""
5113726ac41SJim Ingham        self.build()
51254c26872SRaphael Isemann        target = self.createTestTarget()
5133726ac41SJim Ingham
5143726ac41SJim Ingham        bp_1 = target.BreakpointCreateByName("main")
5153726ac41SJim Ingham        bp_2 = target.BreakpointCreateByName("not_here")
5163726ac41SJim Ingham        bp_3 = target.BreakpointCreateByName("main")
5173726ac41SJim Ingham        bp_3.AddName("DeleteMeNot")
5183726ac41SJim Ingham
5193726ac41SJim Ingham        bp_1.SetEnabled(False)
5203726ac41SJim Ingham        bp_3.SetEnabled(False)
5213726ac41SJim Ingham
5223726ac41SJim Ingham        bp_id_1 = bp_1.GetID()
5233726ac41SJim Ingham        bp_id_2 = bp_2.GetID()
5243726ac41SJim Ingham        bp_id_3 = bp_3.GetID()
5253726ac41SJim Ingham
5263726ac41SJim Ingham        self.runCmd("breakpoint delete --disabled DeleteMeNot")
5273726ac41SJim Ingham
5283726ac41SJim Ingham        bp_1 = target.FindBreakpointByID(bp_id_1)
5293726ac41SJim Ingham        self.assertFalse(bp_1.IsValid(), "Didn't delete disabled breakpoint 1")
5303726ac41SJim Ingham
5313726ac41SJim Ingham        bp_2 = target.FindBreakpointByID(bp_id_2)
5323726ac41SJim Ingham        self.assertTrue(bp_2.IsValid(), "Deleted enabled breakpoint 2")
5333726ac41SJim Ingham
5343726ac41SJim Ingham        bp_3 = target.FindBreakpointByID(bp_id_3)
5352238dcc3SJonas Devlieghere        self.assertTrue(
5362238dcc3SJonas Devlieghere            bp_3.IsValid(), "DeleteMeNot didn't protect disabled breakpoint 3"
5372238dcc3SJonas Devlieghere        )
5380018c712SJim Ingham
5390018c712SJim Ingham        # Reset the first breakpoint, disable it, and do this again with no protected name:
5400018c712SJim Ingham        bp_1 = target.BreakpointCreateByName("main")
5410018c712SJim Ingham
5420018c712SJim Ingham        bp_1.SetEnabled(False)
5430018c712SJim Ingham
5440018c712SJim Ingham        bp_id_1 = bp_1.GetID()
5450018c712SJim Ingham
5460018c712SJim Ingham        self.runCmd("breakpoint delete --disabled")
5470018c712SJim Ingham
5480018c712SJim Ingham        bp_1 = target.FindBreakpointByID(bp_id_1)
5490018c712SJim Ingham        self.assertFalse(bp_1.IsValid(), "Didn't delete disabled breakpoint 1")
5500018c712SJim Ingham
5510018c712SJim Ingham        bp_2 = target.FindBreakpointByID(bp_id_2)
5520018c712SJim Ingham        self.assertTrue(bp_2.IsValid(), "Deleted enabled breakpoint 2")
5530018c712SJim Ingham
5540018c712SJim Ingham        bp_3 = target.FindBreakpointByID(bp_id_3)
5550018c712SJim Ingham        self.assertFalse(bp_3.IsValid(), "Didn't delete disabled breakpoint 3")
556dc9e6c52SJeffrey Tan
557dc9e6c52SJeffrey Tan    def get_source_map_json(self):
558dc9e6c52SJeffrey Tan        stream = lldb.SBStream()
559dc9e6c52SJeffrey Tan        self.dbg.GetSetting("target.source-map").GetAsJSON(stream)
560dc9e6c52SJeffrey Tan        return json.loads(stream.GetData())
561dc9e6c52SJeffrey Tan
562dc9e6c52SJeffrey Tan    def verify_source_map_entry_pair(self, entry, original, replacement):
56380fcecb1SJonas Devlieghere        self.assertEqual(
5642238dcc3SJonas Devlieghere            entry[0], original, "source map entry 'original' does not match"
5652238dcc3SJonas Devlieghere        )
56680fcecb1SJonas Devlieghere        self.assertEqual(
5672238dcc3SJonas Devlieghere            entry[1], replacement, "source map entry 'replacement' does not match"
5682238dcc3SJonas Devlieghere        )
569dc9e6c52SJeffrey Tan
570c5073ed5SJeffrey Tan    def verify_source_map_deduce_statistics(self, target, expected_count):
571c5073ed5SJeffrey Tan        stream = lldb.SBStream()
572c5073ed5SJeffrey Tan        res = target.GetStatistics().GetAsJSON(stream)
573c5073ed5SJeffrey Tan        self.assertTrue(res.Success())
574c5073ed5SJeffrey Tan        debug_stats = json.loads(stream.GetData())
5751eeeab82SJordan Rupprecht        self.assertIn(
5761eeeab82SJordan Rupprecht            "targets",
5771eeeab82SJordan Rupprecht            debug_stats,
5782238dcc3SJonas Devlieghere            'Make sure the "targets" key in in target.GetStatistics()',
5792238dcc3SJonas Devlieghere        )
5802238dcc3SJonas Devlieghere        target_stats = debug_stats["targets"][0]
581c5073ed5SJeffrey Tan        self.assertNotEqual(target_stats, None)
5822238dcc3SJonas Devlieghere        self.assertEqual(target_stats["sourceMapDeduceCount"], expected_count)
583c5073ed5SJeffrey Tan
584dc9e6c52SJeffrey Tan    @no_debug_info_test
585dc9e6c52SJeffrey Tan    def test_breakpoints_auto_source_map_relative(self):
586dc9e6c52SJeffrey Tan        """
587dc9e6c52SJeffrey Tan        Test that with target.auto-source-map-relative settings.
588dc9e6c52SJeffrey Tan
589dc9e6c52SJeffrey Tan        The "relative.yaml" contains a line table that is:
590dc9e6c52SJeffrey Tan
591dc9e6c52SJeffrey Tan        Line table for a/b/c/main.cpp in `a.out
592dc9e6c52SJeffrey Tan        0x0000000100003f94: a/b/c/main.cpp:1
593dc9e6c52SJeffrey Tan        0x0000000100003fb0: a/b/c/main.cpp:2:3
594dc9e6c52SJeffrey Tan        0x0000000100003fb8: a/b/c/main.cpp:2:3
595dc9e6c52SJeffrey Tan        """
596dc9e6c52SJeffrey Tan        src_dir = self.getSourceDir()
597dc9e6c52SJeffrey Tan        yaml_path = os.path.join(src_dir, "relative.yaml")
598dc9e6c52SJeffrey Tan        yaml_base, ext = os.path.splitext(yaml_path)
599dc9e6c52SJeffrey Tan        obj_path = self.getBuildArtifact("a.out")
600dc9e6c52SJeffrey Tan        self.yaml2obj(yaml_path, obj_path)
601dc9e6c52SJeffrey Tan
602dc9e6c52SJeffrey Tan        # Create a target with the object file we just created from YAML
603dc9e6c52SJeffrey Tan        target = self.dbg.CreateTarget(obj_path)
604dc9e6c52SJeffrey Tan        # We now have debug information with line table paths that start are
605dc9e6c52SJeffrey Tan        # "./a/b/c/main.cpp".
606dc9e6c52SJeffrey Tan
607dc9e6c52SJeffrey Tan        source_map_json = self.get_source_map_json()
60880fcecb1SJonas Devlieghere        self.assertEqual(
6092238dcc3SJonas Devlieghere            len(source_map_json), 0, "source map should be empty initially"
6102238dcc3SJonas Devlieghere        )
611c5073ed5SJeffrey Tan        self.verify_source_map_deduce_statistics(target, 0)
612dc9e6c52SJeffrey Tan
613dc9e6c52SJeffrey Tan        # Verify auto deduced source map when file path in debug info
614*4d9e7b14SDmitry Vasilyev        # is a suffix of request breakpoint file path.
615*4d9e7b14SDmitry Vasilyev        # Note the path must be absolute.
616*4d9e7b14SDmitry Vasilyev        path = (
617*4d9e7b14SDmitry Vasilyev            "/x/y/a/b/c/main.cpp"
618*4d9e7b14SDmitry Vasilyev            if lldbplatformutil.getHostPlatform() != "windows"
619*4d9e7b14SDmitry Vasilyev            else r"C:\x\y\a\b\c\main.cpp"
620*4d9e7b14SDmitry Vasilyev        )
621dc9e6c52SJeffrey Tan        bp = target.BreakpointCreateByLocation(path, 2)
6229c246882SJordan Rupprecht        self.assertGreater(
6239c246882SJordan Rupprecht            bp.GetNumLocations(),
6249c246882SJordan Rupprecht            0,
625dc9e6c52SJeffrey Tan            'Couldn\'t resolve breakpoint using full path "%s" in executate "%s" with '
6262238dcc3SJonas Devlieghere            "debug info that has relative path with matching suffix"
6272238dcc3SJonas Devlieghere            % (path, self.getBuildArtifact("a.out")),
6282238dcc3SJonas Devlieghere        )
629dc9e6c52SJeffrey Tan
630dc9e6c52SJeffrey Tan        source_map_json = self.get_source_map_json()
63180fcecb1SJonas Devlieghere        self.assertEqual(len(source_map_json), 1, "source map should not be empty")
632*4d9e7b14SDmitry Vasilyev        self.verify_source_map_entry_pair(
633*4d9e7b14SDmitry Vasilyev            source_map_json[0],
634*4d9e7b14SDmitry Vasilyev            ".",
635*4d9e7b14SDmitry Vasilyev            "/x/y" if lldbplatformutil.getHostPlatform() != "windows" else r"C:\x\y",
636*4d9e7b14SDmitry Vasilyev        )
637c5073ed5SJeffrey Tan        self.verify_source_map_deduce_statistics(target, 1)
638dc9e6c52SJeffrey Tan
639dc9e6c52SJeffrey Tan        # Reset source map.
640dc9e6c52SJeffrey Tan        self.runCmd("settings clear target.source-map")
641dc9e6c52SJeffrey Tan
642dc9e6c52SJeffrey Tan        # Verify source map will not auto deduced when file path of request breakpoint
643dc9e6c52SJeffrey Tan        # equals the file path in debug info.
644dc9e6c52SJeffrey Tan        path = "a/b/c/main.cpp"
645dc9e6c52SJeffrey Tan        bp = target.BreakpointCreateByLocation(path, 2)
6469c246882SJordan Rupprecht        self.assertGreater(
6479c246882SJordan Rupprecht            bp.GetNumLocations(),
6489c246882SJordan Rupprecht            0,
649dc9e6c52SJeffrey Tan            'Couldn\'t resolve breakpoint using full path "%s" in executate "%s" with '
6502238dcc3SJonas Devlieghere            "debug info that has relative path with matching suffix"
6512238dcc3SJonas Devlieghere            % (path, self.getBuildArtifact("a.out")),
6522238dcc3SJonas Devlieghere        )
653dc9e6c52SJeffrey Tan
654dc9e6c52SJeffrey Tan        source_map_json = self.get_source_map_json()
65580fcecb1SJonas Devlieghere        self.assertEqual(len(source_map_json), 0, "source map should not be deduced")
65683263aecSJeffrey Tan
65783263aecSJeffrey Tan    def test_breakpoint_statistics_hitcount(self):
65883263aecSJeffrey Tan        """Test breakpoints statistics have hitCount field."""
65983263aecSJeffrey Tan        self.build()
66083263aecSJeffrey Tan        target = self.createTestTarget()
66183263aecSJeffrey Tan
66283263aecSJeffrey Tan        lldbutil.run_break_set_by_file_and_line(
6632238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=True
6642238dcc3SJonas Devlieghere        )
66583263aecSJeffrey Tan
66683263aecSJeffrey Tan        stream = lldb.SBStream()
66783263aecSJeffrey Tan        res = target.GetStatistics().GetAsJSON(stream)
66883263aecSJeffrey Tan        self.assertTrue(res.Success())
66983263aecSJeffrey Tan        debug_stats = json.loads(stream.GetData())
6701eeeab82SJordan Rupprecht        self.assertIn(
6711eeeab82SJordan Rupprecht            "targets",
6721eeeab82SJordan Rupprecht            debug_stats,
6732238dcc3SJonas Devlieghere            'Make sure the "targets" key in in target.GetStatistics()',
6742238dcc3SJonas Devlieghere        )
6752238dcc3SJonas Devlieghere        target_stats = debug_stats["targets"][0]
67683263aecSJeffrey Tan        self.assertNotEqual(target_stats, None)
67783263aecSJeffrey Tan
6782238dcc3SJonas Devlieghere        breakpoints_stats = target_stats["breakpoints"]
67983263aecSJeffrey Tan        self.assertNotEqual(breakpoints_stats, None)
68083263aecSJeffrey Tan        for breakpoint_stats in breakpoints_stats:
68183263aecSJeffrey Tan            self.assertIn("hitCount", breakpoint_stats)
68260b90b52SZequan Wu
683d3993ac1SZequan Wu    @skipIf(oslist=no_match(["linux"]))
68460b90b52SZequan Wu    def test_break_at__dl_debug_state(self):
68560b90b52SZequan Wu        """
68660b90b52SZequan Wu        Test lldb is able to stop at _dl_debug_state if it is set before the
68760b90b52SZequan Wu        process is launched.
68860b90b52SZequan Wu        """
68960b90b52SZequan Wu        self.build()
69060b90b52SZequan Wu        exe = self.getBuildArtifact("a.out")
69160b90b52SZequan Wu        self.runCmd("target create %s" % exe)
69260b90b52SZequan Wu        bpid = lldbutil.run_break_set_by_symbol(
693d3993ac1SZequan Wu            self, "_dl_debug_state", num_expected_locations=-2
69460b90b52SZequan Wu        )
69560b90b52SZequan Wu        self.runCmd("run")
69660b90b52SZequan Wu        self.assertIsNotNone(
69760b90b52SZequan Wu            lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), bpid)
69860b90b52SZequan Wu        )
699