1be691f3bSpatrick#!/usr/bin/env python 2061da546Spatrick 3061da546Spatrick#---------------------------------------------------------------------- 4061da546Spatrick# Be sure to add the python path that points to the LLDB shared library. 5061da546Spatrick# 6061da546Spatrick# # To use this in the embedded python interpreter using "lldb" just 7061da546Spatrick# import it with the full path using the "command script import" 8061da546Spatrick# command 9061da546Spatrick# (lldb) command script import /path/to/cmdtemplate.py 10061da546Spatrick#---------------------------------------------------------------------- 11061da546Spatrick 12061da546Spatrickimport platform 13061da546Spatrickimport os 14061da546Spatrickimport re 15061da546Spatrickimport sys 16061da546Spatrickimport subprocess 17061da546Spatrick 18061da546Spatricktry: 19061da546Spatrick # Just try for LLDB in case PYTHONPATH is already correctly setup 20061da546Spatrick import lldb 21061da546Spatrickexcept ImportError: 22061da546Spatrick lldb_python_dirs = list() 23061da546Spatrick # lldb is not in the PYTHONPATH, try some defaults for the current platform 24061da546Spatrick platform_system = platform.system() 25061da546Spatrick if platform_system == 'Darwin': 26061da546Spatrick # On Darwin, try the currently selected Xcode directory 27061da546Spatrick xcode_dir = subprocess.check_output("xcode-select --print-path", shell=True) 28061da546Spatrick if xcode_dir: 29061da546Spatrick lldb_python_dirs.append( 30061da546Spatrick os.path.realpath( 31061da546Spatrick xcode_dir + 32061da546Spatrick '/../SharedFrameworks/LLDB.framework/Resources/Python')) 33061da546Spatrick lldb_python_dirs.append( 34061da546Spatrick xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 35061da546Spatrick lldb_python_dirs.append( 36061da546Spatrick '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 37061da546Spatrick success = False 38061da546Spatrick for lldb_python_dir in lldb_python_dirs: 39061da546Spatrick if os.path.exists(lldb_python_dir): 40061da546Spatrick if not (sys.path.__contains__(lldb_python_dir)): 41061da546Spatrick sys.path.append(lldb_python_dir) 42061da546Spatrick try: 43061da546Spatrick import lldb 44061da546Spatrick except ImportError: 45061da546Spatrick pass 46061da546Spatrick else: 47061da546Spatrick print('imported lldb from: "%s"' % (lldb_python_dir)) 48061da546Spatrick success = True 49061da546Spatrick break 50061da546Spatrick if not success: 51061da546Spatrick print("error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly") 52061da546Spatrick sys.exit(1) 53061da546Spatrick 54061da546Spatrickimport optparse 55061da546Spatrickimport shlex 56061da546Spatrickimport string 57061da546Spatrickimport struct 58061da546Spatrickimport time 59061da546Spatrick 60061da546Spatrick 61061da546Spatrickdef append_data_callback(option, opt_str, value, parser): 62061da546Spatrick if opt_str == "--uint8": 63061da546Spatrick int8 = int(value, 0) 64061da546Spatrick parser.values.data += struct.pack('1B', int8) 65061da546Spatrick if opt_str == "--uint16": 66061da546Spatrick int16 = int(value, 0) 67061da546Spatrick parser.values.data += struct.pack('1H', int16) 68061da546Spatrick if opt_str == "--uint32": 69061da546Spatrick int32 = int(value, 0) 70061da546Spatrick parser.values.data += struct.pack('1I', int32) 71061da546Spatrick if opt_str == "--uint64": 72061da546Spatrick int64 = int(value, 0) 73061da546Spatrick parser.values.data += struct.pack('1Q', int64) 74061da546Spatrick if opt_str == "--int8": 75061da546Spatrick int8 = int(value, 0) 76061da546Spatrick parser.values.data += struct.pack('1b', int8) 77061da546Spatrick if opt_str == "--int16": 78061da546Spatrick int16 = int(value, 0) 79061da546Spatrick parser.values.data += struct.pack('1h', int16) 80061da546Spatrick if opt_str == "--int32": 81061da546Spatrick int32 = int(value, 0) 82061da546Spatrick parser.values.data += struct.pack('1i', int32) 83061da546Spatrick if opt_str == "--int64": 84061da546Spatrick int64 = int(value, 0) 85061da546Spatrick parser.values.data += struct.pack('1q', int64) 86061da546Spatrick 87061da546Spatrick 88061da546Spatrickdef create_memfind_options(): 89061da546Spatrick usage = "usage: %prog [options] STARTADDR [ENDADDR]" 90061da546Spatrick description = '''This command can find data in a specified address range. 91061da546SpatrickOptions are used to specify the data that is to be looked for and the options 92061da546Spatrickcan be specified multiple times to look for longer streams of data. 93061da546Spatrick''' 94061da546Spatrick parser = optparse.OptionParser( 95061da546Spatrick description=description, 96061da546Spatrick prog='memfind', 97061da546Spatrick usage=usage) 98061da546Spatrick parser.add_option( 99061da546Spatrick '-s', 100061da546Spatrick '--size', 101061da546Spatrick type='int', 102061da546Spatrick metavar='BYTESIZE', 103061da546Spatrick dest='size', 104061da546Spatrick help='Specify the byte size to search.', 105061da546Spatrick default=0) 106061da546Spatrick parser.add_option( 107061da546Spatrick '--int8', 108061da546Spatrick action="callback", 109061da546Spatrick callback=append_data_callback, 110061da546Spatrick type='string', 111061da546Spatrick metavar='INT', 112061da546Spatrick dest='data', 113061da546Spatrick help='Specify a 8 bit signed integer value to search for in memory.', 114061da546Spatrick default='') 115061da546Spatrick parser.add_option( 116061da546Spatrick '--int16', 117061da546Spatrick action="callback", 118061da546Spatrick callback=append_data_callback, 119061da546Spatrick type='string', 120061da546Spatrick metavar='INT', 121061da546Spatrick dest='data', 122061da546Spatrick help='Specify a 16 bit signed integer value to search for in memory.', 123061da546Spatrick default='') 124061da546Spatrick parser.add_option( 125061da546Spatrick '--int32', 126061da546Spatrick action="callback", 127061da546Spatrick callback=append_data_callback, 128061da546Spatrick type='string', 129061da546Spatrick metavar='INT', 130061da546Spatrick dest='data', 131061da546Spatrick help='Specify a 32 bit signed integer value to search for in memory.', 132061da546Spatrick default='') 133061da546Spatrick parser.add_option( 134061da546Spatrick '--int64', 135061da546Spatrick action="callback", 136061da546Spatrick callback=append_data_callback, 137061da546Spatrick type='string', 138061da546Spatrick metavar='INT', 139061da546Spatrick dest='data', 140061da546Spatrick help='Specify a 64 bit signed integer value to search for in memory.', 141061da546Spatrick default='') 142061da546Spatrick parser.add_option( 143061da546Spatrick '--uint8', 144061da546Spatrick action="callback", 145061da546Spatrick callback=append_data_callback, 146061da546Spatrick type='string', 147061da546Spatrick metavar='INT', 148061da546Spatrick dest='data', 149061da546Spatrick help='Specify a 8 bit unsigned integer value to search for in memory.', 150061da546Spatrick default='') 151061da546Spatrick parser.add_option( 152061da546Spatrick '--uint16', 153061da546Spatrick action="callback", 154061da546Spatrick callback=append_data_callback, 155061da546Spatrick type='string', 156061da546Spatrick metavar='INT', 157061da546Spatrick dest='data', 158061da546Spatrick help='Specify a 16 bit unsigned integer value to search for in memory.', 159061da546Spatrick default='') 160061da546Spatrick parser.add_option( 161061da546Spatrick '--uint32', 162061da546Spatrick action="callback", 163061da546Spatrick callback=append_data_callback, 164061da546Spatrick type='string', 165061da546Spatrick metavar='INT', 166061da546Spatrick dest='data', 167061da546Spatrick help='Specify a 32 bit unsigned integer value to search for in memory.', 168061da546Spatrick default='') 169061da546Spatrick parser.add_option( 170061da546Spatrick '--uint64', 171061da546Spatrick action="callback", 172061da546Spatrick callback=append_data_callback, 173061da546Spatrick type='string', 174061da546Spatrick metavar='INT', 175061da546Spatrick dest='data', 176061da546Spatrick help='Specify a 64 bit unsigned integer value to search for in memory.', 177061da546Spatrick default='') 178061da546Spatrick return parser 179061da546Spatrick 180061da546Spatrick 181061da546Spatrickdef memfind_command(debugger, command, result, dict): 182061da546Spatrick # Use the Shell Lexer to properly parse up command options just like a 183061da546Spatrick # shell would 184061da546Spatrick command_args = shlex.split(command) 185061da546Spatrick parser = create_memfind_options() 186061da546Spatrick (options, args) = parser.parse_args(command_args) 187061da546Spatrick # try: 188061da546Spatrick # (options, args) = parser.parse_args(command_args) 189061da546Spatrick # except: 190061da546Spatrick # # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit 191061da546Spatrick # # (courtesy of OptParse dealing with argument errors by throwing SystemExit) 192061da546Spatrick # result.SetStatus (lldb.eReturnStatusFailed) 193061da546Spatrick # print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string 194061da546Spatrick # return 195061da546Spatrick memfind(debugger.GetSelectedTarget(), options, args, result) 196061da546Spatrick 197061da546Spatrick 198061da546Spatrickdef print_error(str, show_usage, result): 199061da546Spatrick print(str, file=result) 200061da546Spatrick if show_usage: 201061da546Spatrick print(create_memfind_options().format_help(), file=result) 202061da546Spatrick 203061da546Spatrick 204061da546Spatrickdef memfind(target, options, args, result): 205061da546Spatrick num_args = len(args) 206061da546Spatrick start_addr = 0 207061da546Spatrick if num_args == 1: 208061da546Spatrick if options.size > 0: 209061da546Spatrick print_error( 210061da546Spatrick "error: --size must be specified if there is no ENDADDR argument", 211061da546Spatrick True, 212061da546Spatrick result) 213061da546Spatrick return 214061da546Spatrick start_addr = int(args[0], 0) 215061da546Spatrick elif num_args == 2: 216061da546Spatrick if options.size != 0: 217061da546Spatrick print_error( 218061da546Spatrick "error: --size can't be specified with an ENDADDR argument", 219061da546Spatrick True, 220061da546Spatrick result) 221061da546Spatrick return 222061da546Spatrick start_addr = int(args[0], 0) 223061da546Spatrick end_addr = int(args[1], 0) 224061da546Spatrick if start_addr >= end_addr: 225061da546Spatrick print_error( 226061da546Spatrick "error: inavlid memory range [%#x - %#x)" % 227061da546Spatrick (start_addr, end_addr), True, result) 228061da546Spatrick return 229061da546Spatrick options.size = end_addr - start_addr 230061da546Spatrick else: 231061da546Spatrick print_error("error: memfind takes 1 or 2 arguments", True, result) 232061da546Spatrick return 233061da546Spatrick 234061da546Spatrick if not options.data: 235061da546Spatrick print('error: no data specified to search for', file=result) 236061da546Spatrick return 237061da546Spatrick 238061da546Spatrick if not target: 239061da546Spatrick print('error: invalid target', file=result) 240061da546Spatrick return 241061da546Spatrick process = target.process 242061da546Spatrick if not process: 243061da546Spatrick print('error: invalid process', file=result) 244061da546Spatrick return 245061da546Spatrick 246061da546Spatrick error = lldb.SBError() 247061da546Spatrick bytes = process.ReadMemory(start_addr, options.size, error) 248061da546Spatrick if error.Success(): 249061da546Spatrick num_matches = 0 250061da546Spatrick print("Searching memory range [%#x - %#x) for" % ( 251061da546Spatrick start_addr, end_addr), end=' ', file=result) 252061da546Spatrick for byte in options.data: 253061da546Spatrick print('%2.2x' % ord(byte), end=' ', file=result) 254061da546Spatrick print(file=result) 255061da546Spatrick 256061da546Spatrick match_index = string.find(bytes, options.data) 257061da546Spatrick while match_index != -1: 258061da546Spatrick num_matches = num_matches + 1 259061da546Spatrick print('%#x: %#x + %u' % (start_addr + 260061da546Spatrick match_index, start_addr, match_index), file=result) 261061da546Spatrick match_index = string.find(bytes, options.data, match_index + 1) 262061da546Spatrick 263061da546Spatrick if num_matches == 0: 264061da546Spatrick print("error: no matches found", file=result) 265061da546Spatrick else: 266061da546Spatrick print('error: %s' % (error.GetCString()), file=result) 267061da546Spatrick 268061da546Spatrick 269061da546Spatrickif __name__ == '__main__': 270061da546Spatrick print('error: this script is designed to be used within the embedded script interpreter in LLDB') 271*f6aab3d8Srobert 272*f6aab3d8Srobertdef __lldb_init_module(debugger, internal_dict): 273061da546Spatrick memfind_command.__doc__ = create_memfind_options().format_help() 274*f6aab3d8Srobert debugger.HandleCommand( 275*f6aab3d8Srobert 'command script add -o -f memory.memfind_command memfind') 276061da546Spatrick print('"memfind" command installed, use the "--help" option for detailed help') 277