Home | History | Annotate | Download | only in disassembly
      1 """Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb."""
      2 
      3 import os, sys
      4 import unittest2
      5 import lldb
      6 import pexpect
      7 from lldbbench import *
      8 
      9 def is_exe(fpath):
     10     """Returns true if fpath is an executable."""
     11     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
     12 
     13 class DisassembleDriverMainLoop(BenchBase):
     14 
     15     mydir = os.path.join("benchmarks", "disassembly")
     16 
     17     def setUp(self):
     18         """
     19         Note that lldbExec can be specified with the LLDB_EXEC env variable (see
     20         dotest.py), and gdbExec can be specified with the GDB_EXEC env variable.
     21         This provides a flexibility in specifying different versions of gdb for
     22         comparison purposes.
     23         """
     24         BenchBase.setUp(self)
     25         # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your
     26         # PATH env var.
     27         if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]):
     28             self.gdbExec = os.environ["GDB_EXEC"]
     29         else:
     30             self.gdbExec = "gdb"
     31 
     32         self.exe = self.lldbHere
     33         self.function = 'Driver::MainLoop()'
     34         self.lldb_avg = None
     35         self.gdb_avg = None
     36         self.count = lldb.bmIterationCount
     37         if self.count <= 0:
     38             self.count = 5
     39 
     40     @benchmarks_test
     41     def test_run_lldb_then_gdb(self):
     42         """Test disassembly on a large function with lldb vs. gdb."""
     43         print
     44         print "lldb path: %s" % self.lldbExec
     45         print "gdb path: %s" % self.gdbExec
     46 
     47         print
     48         self.run_lldb_disassembly(self.exe, self.function, self.count)
     49         print "lldb benchmark:", self.stopwatch
     50         self.run_gdb_disassembly(self.exe, self.function, self.count)
     51         print "gdb benchmark:", self.stopwatch
     52         print "lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg)
     53 
     54     @benchmarks_test
     55     def test_run_gdb_then_lldb(self):
     56         """Test disassembly on a large function with lldb vs. gdb."""
     57         print
     58         print "lldb path: %s" % self.lldbExec
     59         print "gdb path: %s" % self.gdbExec
     60 
     61         print
     62         self.run_gdb_disassembly(self.exe, self.function, self.count)
     63         print "gdb benchmark:", self.stopwatch
     64         self.run_lldb_disassembly(self.exe, self.function, self.count)
     65         print "lldb benchmark:", self.stopwatch
     66         print "lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg)
     67 
     68     def run_lldb_disassembly(self, exe, function, count):
     69         # Set self.child_prompt, which is "(lldb) ".
     70         self.child_prompt = '(lldb) '
     71         prompt = self.child_prompt
     72 
     73         # So that the child gets torn down after the test.
     74         self.child = pexpect.spawn('%s %s %s' % (self.lldbExec, self.lldbOption, exe))
     75         child = self.child
     76 
     77         # Turn on logging for what the child sends back.
     78         if self.TraceOn():
     79             child.logfile_read = sys.stdout
     80 
     81         child.expect_exact(prompt)
     82         child.sendline('breakpoint set -F %s' % function)
     83         child.expect_exact(prompt)
     84         child.sendline('run')
     85         child.expect_exact(prompt)
     86 
     87         # Reset the stopwatch now.
     88         self.stopwatch.reset()
     89         for i in range(count):
     90             with self.stopwatch:
     91                 # Disassemble the function.
     92                 child.sendline('disassemble -f')
     93                 child.expect_exact(prompt)
     94             child.sendline('next')
     95             child.expect_exact(prompt)
     96 
     97         child.sendline('quit')
     98         try:
     99             self.child.expect(pexpect.EOF)
    100         except:
    101             pass
    102 
    103         self.lldb_avg = self.stopwatch.avg()
    104         if self.TraceOn():
    105             print "lldb disassembly benchmark:", str(self.stopwatch)
    106         self.child = None
    107 
    108     def run_gdb_disassembly(self, exe, function, count):
    109         # Set self.child_prompt, which is "(gdb) ".
    110         self.child_prompt = '(gdb) '
    111         prompt = self.child_prompt
    112 
    113         # So that the child gets torn down after the test.
    114         self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe))
    115         child = self.child
    116 
    117         # Turn on logging for what the child sends back.
    118         if self.TraceOn():
    119             child.logfile_read = sys.stdout
    120 
    121         child.expect_exact(prompt)
    122         child.sendline('break %s' % function)
    123         child.expect_exact(prompt)
    124         child.sendline('run')
    125         child.expect_exact(prompt)
    126 
    127         # Reset the stopwatch now.
    128         self.stopwatch.reset()
    129         for i in range(count):
    130             with self.stopwatch:
    131                 # Disassemble the function.
    132                 child.sendline('disassemble')
    133                 child.expect_exact(prompt)
    134             child.sendline('next')
    135             child.expect_exact(prompt)
    136 
    137         child.sendline('quit')
    138         child.expect_exact('The program is running.  Exit anyway?')
    139         child.sendline('y')
    140         try:
    141             self.child.expect(pexpect.EOF)
    142         except:
    143             pass
    144 
    145         self.gdb_avg = self.stopwatch.avg()
    146         if self.TraceOn():
    147             print "gdb disassembly benchmark:", str(self.stopwatch)
    148         self.child = None
    149 
    150 
    151 if __name__ == '__main__':
    152     import atexit
    153     lldb.SBDebugger.Initialize()
    154     atexit.register(lambda: lldb.SBDebugger.Terminate())
    155     unittest2.main()
    156