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