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