blob: ae78e24e2e29cf2de50a3aba5d3a9131e5e54360 [file] [log] [blame]
Greg Clayton04bd6842013-07-11 22:38:00 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# Be sure to add the python path that points to the LLDB shared library.
5#
6# # To use this in the embedded python interpreter using "lldb" just
7# import it with the full path using the "command script import"
8# command
9# (lldb) command script import /path/to/cmdtemplate.py
10#----------------------------------------------------------------------
11
12import commands
13import platform
14import os
15import re
16import sys
17
18try:
19 # Just try for LLDB in case PYTHONPATH is already correctly setup
20 import lldb
21except ImportError:
22 lldb_python_dirs = list()
23 # lldb is not in the PYTHONPATH, try some defaults for the current platform
24 platform_system = platform.system()
25 if platform_system == 'Darwin':
26 # On Darwin, try the currently selected Xcode directory
27 xcode_dir = commands.getoutput("xcode-select --print-path")
28 if xcode_dir:
29 lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
30 lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
31 lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
32 success = False
33 for lldb_python_dir in lldb_python_dirs:
34 if os.path.exists(lldb_python_dir):
35 if not (sys.path.__contains__(lldb_python_dir)):
36 sys.path.append(lldb_python_dir)
37 try:
38 import lldb
39 except ImportError:
40 pass
41 else:
42 print 'imported lldb from: "%s"' % (lldb_python_dir)
43 success = True
44 break
45 if not success:
46 print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
47 sys.exit(1)
48
49import commands
50import optparse
51import shlex
52import string
53import struct
54import time
55
56def append_data_callback(option, opt_str, value, parser):
57 if opt_str == "--uint8":
58 int8 = int(value, 0)
59 parser.values.data += struct.pack('1B',int8)
60 if opt_str == "--uint16":
61 int16 = int(value, 0)
62 parser.values.data += struct.pack('1H',int16)
63 if opt_str == "--uint32":
64 int32 = int(value, 0)
65 parser.values.data += struct.pack('1I',int32)
66 if opt_str == "--uint64":
67 int64 = int(value, 0)
68 parser.values.data += struct.pack('1Q',int64)
69 if opt_str == "--int8":
70 int8 = int(value, 0)
71 parser.values.data += struct.pack('1b',int8)
72 if opt_str == "--int16":
73 int16 = int(value, 0)
74 parser.values.data += struct.pack('1h',int16)
75 if opt_str == "--int32":
76 int32 = int(value, 0)
77 parser.values.data += struct.pack('1i',int32)
78 if opt_str == "--int64":
79 int64 = int(value, 0)
80 parser.values.data += struct.pack('1q',int64)
81
82def create_memfind_options():
83 usage = "usage: %prog [options] STARTADDR [ENDADDR]"
84 description='''This command can find data in a specified address range.
85Options are used to specify the data that is to be looked for and the options
86can be specified multiple times to look for longer streams of data.
87'''
88 parser = optparse.OptionParser(description=description, prog='memfind',usage=usage)
89 parser.add_option('-s', '--size', type='int', metavar='BYTESIZE', dest='size', help='Specify the byte size to search.', default=0)
90 parser.add_option('--int8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit signed integer value to search for in memory.', default='')
91 parser.add_option('--int16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit signed integer value to search for in memory.', default='')
92 parser.add_option('--int32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit signed integer value to search for in memory.', default='')
93 parser.add_option('--int64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit signed integer value to search for in memory.', default='')
94 parser.add_option('--uint8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit unsigned integer value to search for in memory.', default='')
95 parser.add_option('--uint16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit unsigned integer value to search for in memory.', default='')
96 parser.add_option('--uint32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit unsigned integer value to search for in memory.', default='')
97 parser.add_option('--uint64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit unsigned integer value to search for in memory.', default='')
98 return parser
99
100def memfind_command (debugger, command, result, dict):
101 # Use the Shell Lexer to properly parse up command options just like a
102 # shell would
103 command_args = shlex.split(command)
104 parser = create_memfind_options()
105 (options, args) = parser.parse_args(command_args)
106 # try:
107 # (options, args) = parser.parse_args(command_args)
108 # except:
109 # # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
110 # # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
111 # result.SetStatus (lldb.eReturnStatusFailed)
112 # print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string
113 # return
114 memfind (debugger.GetSelectedTarget(), options, args, result)
115
116def print_error(str, show_usage, result):
117 print >>result, str
118 if show_usage:
119 print >>result, create_memfind_options().format_help()
120
121def memfind (target, options, args, result):
122 num_args = len(args)
123 start_addr = 0
124 if num_args == 1:
125 if options.size > 0:
126 print_error ("error: --size must be specified if there is no ENDADDR argument", True, result)
127 return
128 start_addr = int(args[0], 0)
129 elif num_args == 2:
130 if options.size != 0:
131 print_error ("error: --size can't be specified with an ENDADDR argument", True, result)
132 return
133 start_addr = int(args[0], 0)
134 end_addr = int(args[1], 0)
135 if start_addr >= end_addr:
136 print_error ("error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr), True, result)
137 return
138 options.size = end_addr - start_addr
139 else:
140 print_error ("error: memfind takes 1 or 2 arguments", True, result)
141 return
142
143 if not options.data:
144 print >>result, 'error: no data specified to search for'
145 return
146
147 if not target:
148 print >>result, 'error: invalid target'
149 return
150 process = target.process
151 if not process:
152 print >>result, 'error: invalid process'
153 return
154
155 error = lldb.SBError()
156 bytes = process.ReadMemory (start_addr, options.size, error)
157 if error.Success():
158 num_matches = 0
159 print >>result, "Searching memory range [%#x - %#x) for" % (start_addr, end_addr),
160 for byte in options.data:
161 print >>result, '%2.2x' % ord(byte),
162 print >>result
163
164 match_index = string.find(bytes, options.data)
165 while match_index != -1:
166 num_matches = num_matches + 1
167 print >>result, '%#x: %#x + %u' % (start_addr + match_index, start_addr, match_index)
168 match_index = string.find(bytes, options.data, match_index + 1)
169
170 if num_matches == 0:
171 print >>result, "error: no matches found"
172 else:
173 print >>result, 'error: %s' % (error.GetCString())
174
175
176if __name__ == '__main__':
177 print 'error: this script is designed to be used within the embedded script interpreter in LLDB'
178elif getattr(lldb, 'debugger', None):
179 memfind_command.__doc__ = create_memfind_options().format_help()
180 lldb.debugger.HandleCommand('command script add -f memory.memfind_command memfind')
181 print '"memfind" command installed, use the "--help" option for detailed help'