aboutsummaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py
blob: a18cb2a64c7674f887d6264ffb94271cc6774a3d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb."""

from __future__ import print_function



import os, sys
import lldb
from lldbsuite.test import configuration
from lldbsuite.test.lldbbench import *

def is_exe(fpath):
    """Returns true if fpath is an executable."""
    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

class DisassembleDriverMainLoop(BenchBase):

    mydir = TestBase.compute_mydir(__file__)

    def setUp(self):
        """
        Note that lldbtest_config.lldbExec can be specified with the LLDB_EXEC env variable (see
        dotest.py), and gdbExec can be specified with the GDB_EXEC env variable.
        This provides a flexibility in specifying different versions of gdb for
        comparison purposes.
        """
        BenchBase.setUp(self)
        # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your
        # PATH env var.
        if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]):
            self.gdbExec = os.environ["GDB_EXEC"]
        else:
            self.gdbExec = "gdb"

        self.exe = lldbtest_config.lldbExec
        self.function = 'Driver::MainLoop()'
        self.lldb_avg = None
        self.gdb_avg = None
        self.count = 5

    @benchmarks_test
    @no_debug_info_test
    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
    def test_run_lldb_then_gdb(self):
        """Test disassembly on a large function with lldb vs. gdb."""
        print()
        print("lldb path: %s" % lldbtest_config.lldbExec)
        print("gdb path: %s" % self.gdbExec)

        print()
        self.run_lldb_disassembly(self.exe, self.function, self.count)
        print("lldb benchmark:", self.stopwatch)
        self.run_gdb_disassembly(self.exe, self.function, self.count)
        print("gdb benchmark:", self.stopwatch)
        print("lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg))

    @benchmarks_test
    @no_debug_info_test
    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
    def test_run_gdb_then_lldb(self):
        """Test disassembly on a large function with lldb vs. gdb."""
        print()
        print("lldb path: %s" % lldbtest_config.lldbExec)
        print("gdb path: %s" % self.gdbExec)

        print()
        self.run_gdb_disassembly(self.exe, self.function, self.count)
        print("gdb benchmark:", self.stopwatch)
        self.run_lldb_disassembly(self.exe, self.function, self.count)
        print("lldb benchmark:", self.stopwatch)
        print("lldb_avg/gdb_avg: %f" % (self.lldb_avg/self.gdb_avg))

    def run_lldb_disassembly(self, exe, function, count):
        import pexpect
        # Set self.child_prompt, which is "(lldb) ".
        self.child_prompt = '(lldb) '
        prompt = self.child_prompt

        # So that the child gets torn down after the test.
        self.child = pexpect.spawn('%s %s %s' % (lldbtest_config.lldbExec, self.lldbOption, exe))
        child = self.child

        # Turn on logging for what the child sends back.
        if self.TraceOn():
            child.logfile_read = sys.stdout

        child.expect_exact(prompt)
        child.sendline('breakpoint set -F %s' % function)
        child.expect_exact(prompt)
        child.sendline('run')
        child.expect_exact(prompt)

        # Reset the stopwatch now.
        self.stopwatch.reset()
        for i in range(count):
            with self.stopwatch:
                # Disassemble the function.
                child.sendline('disassemble -f')
                child.expect_exact(prompt)
            child.sendline('next')
            child.expect_exact(prompt)

        child.sendline('quit')
        try:
            self.child.expect(pexpect.EOF)
        except:
            pass

        self.lldb_avg = self.stopwatch.avg()
        if self.TraceOn():
            print("lldb disassembly benchmark:", str(self.stopwatch))
        self.child = None

    def run_gdb_disassembly(self, exe, function, count):
        import pexpect
        # Set self.child_prompt, which is "(gdb) ".
        self.child_prompt = '(gdb) '
        prompt = self.child_prompt

        # So that the child gets torn down after the test.
        self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe))
        child = self.child

        # Turn on logging for what the child sends back.
        if self.TraceOn():
            child.logfile_read = sys.stdout

        child.expect_exact(prompt)
        child.sendline('break %s' % function)
        child.expect_exact(prompt)
        child.sendline('run')
        child.expect_exact(prompt)

        # Reset the stopwatch now.
        self.stopwatch.reset()
        for i in range(count):
            with self.stopwatch:
                # Disassemble the function.
                child.sendline('disassemble')
                child.expect_exact(prompt)
            child.sendline('next')
            child.expect_exact(prompt)

        child.sendline('quit')
        child.expect_exact('The program is running.  Exit anyway?')
        child.sendline('y')
        try:
            self.child.expect(pexpect.EOF)
        except:
            pass

        self.gdb_avg = self.stopwatch.avg()
        if self.TraceOn():
            print("gdb disassembly benchmark:", str(self.stopwatch))
        self.child = None