1952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen"""Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb."""
2952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
3952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenimport os, sys
4952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenimport unittest2
5952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenimport lldb
6952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenimport pexpect
7952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenfrom lldbbench import *
8952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
964b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chendef is_exe(fpath):
1064b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen    """Returns true if fpath is an executable."""
1164b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
1264b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen
13952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenclass DisassembleDriverMainLoop(BenchBase):
14952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
153a9c0967d3987d50e5f0a30fbbcdfce2e9c7dccaJohnny Chen    mydir = os.path.join("benchmarks", "disassembly")
16952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
17952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    def setUp(self):
1864b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        """
1964b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        Note that lldbExec can be specified with the LLDB_EXEC env variable (see
2064b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        dotest.py), and gdbExec can be specified with the GDB_EXEC env variable.
2164b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        This provides a flexibility in specifying different versions of gdb for
2264b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        comparison purposes.
2364b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        """
24952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        BenchBase.setUp(self)
2564b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your
2664b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        # PATH env var.
2764b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]):
2864b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen            self.gdbExec = os.environ["GDB_EXEC"]
2964b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        else:
3064b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen            self.gdbExec = "gdb"
3164b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen
326033bedc163bc57b5e5c3c1aee8ba81f64b4f11eJohnny Chen        self.exe = self.lldbHere
33952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.function = 'Driver::MainLoop()'
34952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.lldb_avg = None
35952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.gdb_avg = None
365f2ed17114c1711a23011c160832b318d77db888Johnny Chen        self.count = lldb.bmIterationCount
375f2ed17114c1711a23011c160832b318d77db888Johnny Chen        if self.count <= 0:
385f2ed17114c1711a23011c160832b318d77db888Johnny Chen            self.count = 5
39952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
40952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    @benchmarks_test
41952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    def test_run_lldb_then_gdb(self):
42952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        """Test disassembly on a large function with lldb vs. gdb."""
43952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print
44c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print "lldb path: %s" % self.lldbExec
45c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print "gdb path: %s" % self.gdbExec
46c6e328a322123a276524857242f99e019e56a5deJohnny Chen
47c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print
485f2ed17114c1711a23011c160832b318d77db888Johnny Chen        self.run_lldb_disassembly(self.exe, self.function, self.count)
49952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "lldb benchmark:", self.stopwatch
505f2ed17114c1711a23011c160832b318d77db888Johnny Chen        self.run_gdb_disassembly(self.exe, self.function, self.count)
51952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "gdb benchmark:", self.stopwatch
52952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg)
53952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
54952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    @benchmarks_test
55952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    def test_run_gdb_then_lldb(self):
56952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        """Test disassembly on a large function with lldb vs. gdb."""
57952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print
58c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print "lldb path: %s" % self.lldbExec
59c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print "gdb path: %s" % self.gdbExec
60c6e328a322123a276524857242f99e019e56a5deJohnny Chen
61c6e328a322123a276524857242f99e019e56a5deJohnny Chen        print
625f2ed17114c1711a23011c160832b318d77db888Johnny Chen        self.run_gdb_disassembly(self.exe, self.function, self.count)
63952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "gdb benchmark:", self.stopwatch
645f2ed17114c1711a23011c160832b318d77db888Johnny Chen        self.run_lldb_disassembly(self.exe, self.function, self.count)
65952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "lldb benchmark:", self.stopwatch
66952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        print "lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg)
67952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
68952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    def run_lldb_disassembly(self, exe, function, count):
69952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Set self.child_prompt, which is "(lldb) ".
70952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.child_prompt = '(lldb) '
71952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        prompt = self.child_prompt
72952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
73952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # So that the child gets torn down after the test.
747d7f447af7fba3eae442ab99c18f5ae532886099Johnny Chen        self.child = pexpect.spawn('%s %s %s' % (self.lldbExec, self.lldbOption, exe))
75952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child = self.child
76952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
77952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Turn on logging for what the child sends back.
78952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        if self.TraceOn():
79952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.logfile_read = sys.stdout
80952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
81952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
82952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('breakpoint set -F %s' % function)
83952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
84952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('run')
85952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
86952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
87952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Reset the stopwatch now.
88952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.stopwatch.reset()
89952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        for i in range(count):
90952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            with self.stopwatch:
91952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                # Disassemble the function.
92952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                child.sendline('disassemble -f')
93952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                child.expect_exact(prompt)
94952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.sendline('next')
95952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.expect_exact(prompt)
96952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
97952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('quit')
98952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        try:
99952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            self.child.expect(pexpect.EOF)
100952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        except:
101952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            pass
102952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
103952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.lldb_avg = self.stopwatch.avg()
104952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        if self.TraceOn():
105952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            print "lldb disassembly benchmark:", str(self.stopwatch)
106952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.child = None
107952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
108952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    def run_gdb_disassembly(self, exe, function, count):
109952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Set self.child_prompt, which is "(gdb) ".
110952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.child_prompt = '(gdb) '
111952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        prompt = self.child_prompt
112952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
113952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # So that the child gets torn down after the test.
11464b4f192a8e40b2a1e3573227522ee1de508c5b9Johnny Chen        self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe))
115952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child = self.child
116952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
117952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Turn on logging for what the child sends back.
118952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        if self.TraceOn():
119952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.logfile_read = sys.stdout
120952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
121952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
122952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('break %s' % function)
123952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
124952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('run')
125952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact(prompt)
126952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
127952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        # Reset the stopwatch now.
128952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.stopwatch.reset()
129952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        for i in range(count):
130952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            with self.stopwatch:
131952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                # Disassemble the function.
132952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                child.sendline('disassemble')
133952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen                child.expect_exact(prompt)
134952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.sendline('next')
135952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            child.expect_exact(prompt)
136952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
137952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('quit')
138952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.expect_exact('The program is running.  Exit anyway?')
139952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        child.sendline('y')
140952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        try:
141952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            self.child.expect(pexpect.EOF)
142952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        except:
143952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            pass
144952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
145952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.gdb_avg = self.stopwatch.avg()
146952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        if self.TraceOn():
147952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen            print "gdb disassembly benchmark:", str(self.stopwatch)
148952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen        self.child = None
149952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
150952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen
151952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chenif __name__ == '__main__':
152952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    import atexit
153952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    lldb.SBDebugger.Initialize()
154952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    atexit.register(lambda: lldb.SBDebugger.Terminate())
155952cc2b9f1fdbf4919e06d559d8d0ae27b4bc538Johnny Chen    unittest2.main()
156