Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | """ |
| 4 | Run a program via lldb until it fails. |
| 5 | The lldb executable is located via your PATH env variable, if not specified. |
| 6 | """ |
| 7 | |
| 8 | import os |
| 9 | import sys |
| 10 | from optparse import OptionParser |
| 11 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 12 | |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 13 | def is_exe(fpath): |
| 14 | """Check whether fpath is an executable.""" |
| 15 | return os.path.isfile(fpath) and os.access(fpath, os.X_OK) |
| 16 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 17 | |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 18 | def which(program): |
| 19 | """Find the full path to a program, or return None.""" |
| 20 | fpath, fname = os.path.split(program) |
| 21 | if fpath: |
| 22 | if is_exe(program): |
| 23 | return program |
| 24 | else: |
| 25 | for path in os.environ["PATH"].split(os.pathsep): |
| 26 | exe_file = os.path.join(path, program) |
| 27 | if is_exe(exe_file): |
| 28 | return exe_file |
| 29 | return None |
| 30 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 31 | |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 32 | def do_lldb_launch_loop(lldb_command, exe, exe_options): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 33 | from cStringIO import StringIO |
| 34 | import pexpect |
| 35 | import time |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 36 | |
| 37 | prompt = "\(lldb\) " |
| 38 | lldb = pexpect.spawn(lldb_command) |
| 39 | # Turn on logging for what lldb sends back. |
Johnny Chen | 8831e18 | 2011-06-01 22:12:27 +0000 | [diff] [blame] | 40 | lldb.logfile_read = sys.stdout |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 41 | lldb.expect(prompt) |
| 42 | |
| 43 | # Now issue the file command. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 44 | # print "sending 'file %s' command..." % exe |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 45 | lldb.sendline('file %s' % exe) |
| 46 | lldb.expect(prompt) |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 47 | |
| 48 | # Loop until it faults.... |
| 49 | count = 0 |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 50 | # while True: |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 51 | # count = count + 1 |
Johnny Chen | 8831e18 | 2011-06-01 22:12:27 +0000 | [diff] [blame] | 52 | for i in range(100): |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 53 | count = i |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 54 | # print "sending 'process launch -- %s' command... (iteration: %d)" % |
| 55 | # (exe_options, count) |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 56 | lldb.sendline('process launch -- %s' % exe_options) |
| 57 | index = lldb.expect(['Process .* exited with status', |
| 58 | 'Process .* stopped', |
| 59 | pexpect.TIMEOUT]) |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 60 | if index == 0: |
| 61 | # We'll try again later. |
| 62 | time.sleep(3) |
| 63 | elif index == 1: |
| 64 | # Perfect, our process had stopped; break out of the loop. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 65 | break |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 66 | elif index == 2: |
| 67 | # Something went wrong. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 68 | print "TIMEOUT occurred:", str(lldb) |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 69 | |
| 70 | # Give control of lldb shell to the user. |
| 71 | lldb.interact() |
| 72 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 73 | |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 74 | def main(): |
| 75 | # This is to set up the Python path to include the pexpect-2.4 dir. |
| 76 | # Remember to update this when/if things change. |
| 77 | scriptPath = sys.path[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 78 | sys.path.append( |
| 79 | os.path.join( |
| 80 | scriptPath, |
| 81 | os.pardir, |
| 82 | os.pardir, |
| 83 | 'test', |
| 84 | 'pexpect-2.4')) |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 85 | |
| 86 | parser = OptionParser(usage="""\ |
Johnny Chen | 8831e18 | 2011-06-01 22:12:27 +0000 | [diff] [blame] | 87 | %prog [options] |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 88 | Run a program via lldb until it fails. |
Johnny Chen | 8831e18 | 2011-06-01 22:12:27 +0000 | [diff] [blame] | 89 | The lldb executable is located via your PATH env variable, if not specified.\ |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 90 | """) |
| 91 | parser.add_option('-l', '--lldb-command', |
| 92 | type='string', action='store', metavar='LLDB_COMMAND', |
| 93 | default='lldb', dest='lldb_command', |
| 94 | help='Full path to your lldb command') |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 95 | parser.add_option( |
| 96 | '-e', |
| 97 | '--executable', |
| 98 | type='string', |
| 99 | action='store', |
| 100 | dest='exe', |
| 101 | help="""(Mandatory) The executable to launch via lldb.""") |
| 102 | parser.add_option( |
| 103 | '-o', |
| 104 | '--options', |
| 105 | type='string', |
| 106 | action='store', |
| 107 | default='', |
| 108 | dest='exe_options', |
| 109 | help="""The args/options passed to the launched program, if specified.""") |
Johnny Chen | 511e8c0 | 2011-04-02 01:20:28 +0000 | [diff] [blame] | 110 | |
| 111 | opts, args = parser.parse_args() |
| 112 | |
| 113 | lldb_command = which(opts.lldb_command) |
| 114 | |
| 115 | if not opts.exe: |
| 116 | parser.print_help() |
| 117 | sys.exit(1) |
| 118 | exe = opts.exe |
| 119 | |
| 120 | exe_options = opts.exe_options |
| 121 | |
| 122 | # We have parsed the options. |
| 123 | print "lldb command:", lldb_command |
| 124 | print "executable:", exe |
| 125 | print "executable options:", exe_options |
| 126 | |
| 127 | do_lldb_launch_loop(lldb_command, exe, exe_options) |
| 128 | |
| 129 | if __name__ == '__main__': |
| 130 | main() |