3 # ----------------------------------------------------------------------
4 # Be sure to add the python path that points to the LLDB shared library.
6 # # To use this in the embedded python interpreter using "lldb" just
7 # import it with the full path using the "command script import"
9 # (lldb) command script import /path/to/cmdtemplate.py
10 # ----------------------------------------------------------------------
19 # Just try for LLDB in case PYTHONPATH is already correctly setup
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
= subprocess
.check_output("xcode-select --print-path", shell
=True)
29 lldb_python_dirs
.append(
31 xcode_dir
+ "/../SharedFrameworks/LLDB.framework/Resources/Python"
34 lldb_python_dirs
.append(
35 xcode_dir
+ "/Library/PrivateFrameworks/LLDB.framework/Resources/Python"
37 lldb_python_dirs
.append(
38 "/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python"
41 for lldb_python_dir
in lldb_python_dirs
:
42 if os
.path
.exists(lldb_python_dir
):
43 if not (sys
.path
.__contains
__(lldb_python_dir
)):
44 sys
.path
.append(lldb_python_dir
)
50 print('imported lldb from: "%s"' % (lldb_python_dir
))
55 "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
66 def append_data_callback(option
, opt_str
, value
, parser
):
67 if opt_str
== "--uint8":
69 parser
.values
.data
+= struct
.pack("1B", int8
)
70 if opt_str
== "--uint16":
72 parser
.values
.data
+= struct
.pack("1H", int16
)
73 if opt_str
== "--uint32":
75 parser
.values
.data
+= struct
.pack("1I", int32
)
76 if opt_str
== "--uint64":
78 parser
.values
.data
+= struct
.pack("1Q", int64
)
79 if opt_str
== "--int8":
81 parser
.values
.data
+= struct
.pack("1b", int8
)
82 if opt_str
== "--int16":
84 parser
.values
.data
+= struct
.pack("1h", int16
)
85 if opt_str
== "--int32":
87 parser
.values
.data
+= struct
.pack("1i", int32
)
88 if opt_str
== "--int64":
90 parser
.values
.data
+= struct
.pack("1q", int64
)
93 def create_memfind_options():
94 usage
= "usage: %prog [options] STARTADDR [ENDADDR]"
95 description
= """This command can find data in a specified address range.
96 Options are used to specify the data that is to be looked for and the options
97 can be specified multiple times to look for longer streams of data.
99 parser
= optparse
.OptionParser(description
=description
, prog
="memfind", usage
=usage
)
106 help="Specify the byte size to search.",
112 callback
=append_data_callback
,
116 help="Specify a 8 bit signed integer value to search for in memory.",
122 callback
=append_data_callback
,
126 help="Specify a 16 bit signed integer value to search for in memory.",
132 callback
=append_data_callback
,
136 help="Specify a 32 bit signed integer value to search for in memory.",
142 callback
=append_data_callback
,
146 help="Specify a 64 bit signed integer value to search for in memory.",
152 callback
=append_data_callback
,
156 help="Specify a 8 bit unsigned integer value to search for in memory.",
162 callback
=append_data_callback
,
166 help="Specify a 16 bit unsigned integer value to search for in memory.",
172 callback
=append_data_callback
,
176 help="Specify a 32 bit unsigned integer value to search for in memory.",
182 callback
=append_data_callback
,
186 help="Specify a 64 bit unsigned integer value to search for in memory.",
192 def memfind_command(debugger
, command
, result
, dict):
193 # Use the Shell Lexer to properly parse up command options just like a
195 command_args
= shlex
.split(command
)
196 parser
= create_memfind_options()
197 (options
, args
) = parser
.parse_args(command_args
)
199 # (options, args) = parser.parse_args(command_args)
201 # # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
202 # # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
203 # result.SetStatus (lldb.eReturnStatusFailed)
204 # print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string
206 memfind(debugger
.GetSelectedTarget(), options
, args
, result
)
209 def print_error(str, show_usage
, result
):
210 print(str, file=result
)
212 print(create_memfind_options().format_help(), file=result
)
215 def memfind(target
, options
, args
, result
):
221 "error: --size must be specified if there is no ENDADDR argument",
226 start_addr
= int(args
[0], 0)
228 if options
.size
!= 0:
230 "error: --size can't be specified with an ENDADDR argument",
235 start_addr
= int(args
[0], 0)
236 end_addr
= int(args
[1], 0)
237 if start_addr
>= end_addr
:
239 "error: inavlid memory range [%#x - %#x)" % (start_addr
, end_addr
),
244 options
.size
= end_addr
- start_addr
246 print_error("error: memfind takes 1 or 2 arguments", True, result
)
250 print("error: no data specified to search for", file=result
)
254 print("error: invalid target", file=result
)
256 process
= target
.process
258 print("error: invalid process", file=result
)
261 error
= lldb
.SBError()
262 bytes
= process
.ReadMemory(start_addr
, options
.size
, error
)
266 "Searching memory range [%#x - %#x) for" % (start_addr
, end_addr
),
270 for byte
in options
.data
:
271 print("%2.2x" % ord(byte
), end
=" ", file=result
)
274 match_index
= string
.find(bytes
, options
.data
)
275 while match_index
!= -1:
276 num_matches
= num_matches
+ 1
278 "%#x: %#x + %u" % (start_addr
+ match_index
, start_addr
, match_index
),
281 match_index
= string
.find(bytes
, options
.data
, match_index
+ 1)
284 print("error: no matches found", file=result
)
286 print("error: %s" % (error
.GetCString()), file=result
)
289 if __name__
== "__main__":
291 "error: this script is designed to be used within the embedded script interpreter in LLDB"
295 def __lldb_init_module(debugger
, internal_dict
):
296 memfind_command
.__doc
__ = create_memfind_options().format_help()
297 debugger
.HandleCommand("command script add -o -f memory.memfind_command memfind")
298 print('"memfind" command installed, use the "--help" option for detailed help')