xref: /llvm-project/lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
1"""
2Test the lldb disassemble command on foundation framework.
3"""
4
5import os
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class FoundationDisassembleTestCase(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    @skipIfAsan
16    def test_foundation_disasm(self):
17        """Do 'disassemble -n func' on each and every 'Code' symbol entry from the Foundation.framework."""
18        self.build()
19
20        # Enable synchronous mode
21        self.dbg.SetAsync(False)
22
23        # Create a target by the debugger.
24        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
25        self.assertTrue(target, VALID_TARGET)
26
27        # Now launch the process, and do not stop at entry point.
28        process = target.LaunchSimple(None, None, self.get_process_working_directory())
29        self.assertTrue(process, PROCESS_IS_VALID)
30
31        foundation_framework = None
32        for module in target.modules:
33            if module.file.basename == "Foundation":
34                foundation_framework = module.file.fullpath
35                break
36
37        self.assertIsNotNone(foundation_framework, "Foundation.framework path located")
38        self.runCmd("image dump symtab '%s'" % foundation_framework)
39        raw_output = self.res.GetOutput()
40        # Now, grab every 'Code' symbol and feed it into the command:
41        # 'disassemble -n func'.
42        #
43        # The symbol name is on the last column and trails the flag column which
44        # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits.
45        codeRE = re.compile(
46            r"""
47                             \ Code\ {9}    # ' Code' followed by 9 SPCs,
48                             .*             # the wildcard chars,
49                             0x[0-9a-f]{8}  # the flag column, and
50                             \ (.+)$        # finally the function symbol.
51                             """,
52            re.VERBOSE,
53        )
54        for line in raw_output.split(os.linesep):
55            match = codeRE.search(line)
56            if match:
57                func = match.group(1)
58                self.runCmd('image lookup -s "%s"' % func)
59                self.runCmd('disassemble --force -n "%s"' % func)
60
61    @skipIfAsan
62    def test_simple_disasm(self):
63        """Test the lldb 'disassemble' command"""
64        self.build()
65
66        # Create a target by the debugger.
67        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
68        self.assertTrue(target, VALID_TARGET)
69
70        # Stop at +[NSString stringWithFormat:].
71        symbol_name = "+[NSString stringWithFormat:]"
72        break_results = lldbutil.run_break_set_command(
73            self, "_regexp-break %s" % (symbol_name)
74        )
75
76        lldbutil.check_breakpoint_result(
77            self, break_results, symbol_name=symbol_name, num_locations=1
78        )
79
80        # Stop at -[MyString initWithNSString:].
81        lldbutil.run_break_set_by_symbol(
82            self,
83            "-[MyString initWithNSString:]",
84            num_expected_locations=1,
85            sym_exact=True,
86        )
87
88        # Stop at the "description" selector.
89        lldbutil.run_break_set_by_selector(
90            self, "description", num_expected_locations=1, module_name="a.out"
91        )
92
93        # Stop at -[NSAutoreleasePool release].
94        break_results = lldbutil.run_break_set_command(
95            self, "_regexp-break -[NSAutoreleasePool release]"
96        )
97        lldbutil.check_breakpoint_result(
98            self,
99            break_results,
100            symbol_name="-[NSAutoreleasePool release]",
101            num_locations=1,
102        )
103
104        self.runCmd("run", RUN_SUCCEEDED)
105
106        # First stop is +[NSString stringWithFormat:].
107        self.expect(
108            "thread backtrace",
109            "Stop at +[NSString stringWithFormat:]",
110            substrs=["Foundation`+[NSString stringWithFormat:]"],
111        )
112
113        # Do the disassemble for the currently stopped function.
114        self.runCmd("disassemble -f")
115
116        self.runCmd("process continue")
117        # Skip another breakpoint for +[NSString stringWithFormat:].
118        self.runCmd("process continue")
119
120        # Followed by a.out`-[MyString initWithNSString:].
121        self.expect(
122            "thread backtrace",
123            "Stop at a.out`-[MyString initWithNSString:]",
124            substrs=["a.out`-[MyString initWithNSString:]"],
125        )
126
127        # Do the disassemble for the currently stopped function.
128        self.runCmd("disassemble -f")
129
130        self.runCmd("process continue")
131
132        # Followed by -[MyString description].
133        self.expect(
134            "thread backtrace",
135            "Stop at -[MyString description]",
136            substrs=["a.out`-[MyString description]"],
137        )
138
139        # Do the disassemble for the currently stopped function.
140        self.runCmd("disassemble -f")
141
142        self.runCmd("process continue")
143        # Skip another breakpoint for -[MyString description].
144        self.runCmd("process continue")
145
146        # Followed by -[NSAutoreleasePool release].
147        self.expect(
148            "thread backtrace",
149            "Stop at -[NSAutoreleasePool release]",
150            substrs=["Foundation`-[NSAutoreleasePool release]"],
151        )
152
153        # Do the disassemble for the currently stopped function.
154        self.runCmd("disassemble -f")
155