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