def ibreak(debugger, command, result, internal_dict): address = iraddress(debugger, command, result, internal_dict) returnObject = lldb.SBCommandReturnObject() debugger.GetCommandInterpreter().HandleCommand('br set -a %s' % address, returnObject) output = returnObject.GetOutput(); print output
def test_session_save(self): raw = "" interpreter = self.dbg.GetCommandInterpreter() settings = [ 'settings set interpreter.echo-commands true', 'settings set interpreter.echo-comment-commands true', 'settings set interpreter.stop-command-source-on-error false' ] for setting in settings: interpreter.HandleCommand(setting, lldb.SBCommandReturnObject()) inputs = [ '# This is a comment', # Comment 'help session', # Valid command 'Lorem ipsum' # Invalid command ] for cmd in inputs: res = lldb.SBCommandReturnObject() interpreter.HandleCommand(cmd, res) raw += self.raw_transcript_builder(cmd, res) self.assertTrue(interpreter.HasCommands()) self.assertTrue(len(raw) != 0) # Check for error cmd = 'session save /root/file' interpreter.HandleCommand(cmd, res) self.assertFalse(res.Succeeded()) raw += self.raw_transcript_builder(cmd, res) tf = tempfile.NamedTemporaryFile() output_file = tf.name res = lldb.SBCommandReturnObject() interpreter.HandleCommand('session save ' + output_file, res) self.assertTrue(res.Succeeded()) raw += self.raw_transcript_builder(cmd, res) with open(output_file, "r") as file: content = file.read() # Exclude last line, since session won't record it's own output lines = raw.splitlines()[:-1] for line in lines: self.assertIn(line, content) td = tempfile.TemporaryDirectory() res = lldb.SBCommandReturnObject() interpreter.HandleCommand( 'settings set interpreter.save-session-directory ' + td.name, res) self.assertTrue(res.Succeeded()) res = lldb.SBCommandReturnObject() interpreter.HandleCommand('session save', res) self.assertTrue(res.Succeeded()) raw += self.raw_transcript_builder(cmd, res) with open(os.path.join(td.name, os.listdir(td.name)[0]), "r") as file: content = file.read() # Exclude last line, since session won't record it's own output lines = raw.splitlines()[:-1] for line in lines: self.assertIn(line, content)
def dclass(debugger, command, result, internal_dict): ''' Dumps all the NSObject inherited classes in the process. If you give it a module, it will dump only the classes within that module. You can also filter out classes to only a certain type and can also generate a header file for a specific class. Example: # Dump ALL the NSObject classes within the process (lldb) dclass # Dump all the classes that are a UIViewController within the process (lldb) dclass -f UIViewController # Dump all the classes with the regex case insensitive search "viewcontroller" in the class name (lldb) dclass -r (?i)viewCoNtrolLer # Dump all the classes within the UIKit module (lldb) dclass -m UIKit # Dump all classes in CKConfettiEffect NSBundle that are UIView subclasses (lldb) dclass /System/Library/Messages/iMessageEffects/CKConfettiEffect.bundle/CKConfettiEffect -f UIView # Generate a header file for the class specified: (lldb) dclass -g UIView # Generate a protocol that you can cast an object to. Ideal when working with private classes at dev time (lldb) dclass -P UIView # Dump all classes and methods for a particular module, ideal for viewing changes in frameworks over time (lldb) dclass -o UIKit # Only dump classes whose superclass is of type class and in UIKit module. Ideal for going after specific classes (lldb) dclass -s NSObject -m UIKit ''' command_args = shlex.split(command, posix=False) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return if not args: # result.SetError('Usage: find NSObjectSubclass\n\nUse \'help find\' for more details') clean_command = None # return if not args and options.generate_header: result.SetError('Need to supply class for option') return else: clean_command = ('').join(args) res = lldb.SBCommandReturnObject() interpreter = debugger.GetCommandInterpreter() target = debugger.GetSelectedTarget() if options.dump_code_output: directory = '/tmp/{}_{}/'.format(ds.getTarget().executable.basename, datetime.datetime.now().time()) os.makedirs(directory) modules = ds.getTarget().modules if len(args) > 0 and args[0] == '__all': os.makedirs(directory + 'PrivateFrameworks') os.makedirs(directory + 'Frameworks') modules = [ i for i in ds.getTarget().modules if '/usr/lib/' not in i.file.fullpath and '__lldb_' not in i.file.fullpath ] outputMsg = "Dumping all private Objective-C frameworks" elif len(args) > 0 and args[0]: module = ds.getTarget().module[args[0]] if module is None: result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'" .format(args[0])) return modules = [module] outputMsg = "Dumping all private Objective-C frameworks" else: modules = [ ds.getTarget().module[ds.getTarget().executable.fullpath] ] for module in modules: command_script = generate_module_header_script( options, module.file.fullpath.replace('//', '/')) interpreter.HandleCommand( 'expression -lobjc -O -u0 -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -- ' + command_script) if '/System/Library/PrivateFrameworks/' in module.file.fullpath: subdir = 'PrivateFrameworks/' elif '/System/Library/Frameworks/' in module.file.fullpath: subdir = 'Frameworks/' else: subdir = '' ds.create_or_touch_filepath( directory + subdir + module.file.basename + '.txt', res.GetOutput()) print('Written output to: ' + directory + '... opening file') os.system('open -R ' + directory) return if options.module is not None: module = target.FindModule(lldb.SBFileSpec(options.module)) if not module.IsValid(): result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'" .format(str(options.module))) return if options.conforms_to_protocol is not None: interpreter.HandleCommand( 'expression -lobjc -O -- (id)NSProtocolFromString(@\"{}\")'.format( options.conforms_to_protocol), res) if 'nil' in res.GetOutput() or not res.GetOutput(): result.SetError("No such Protocol name '{}'".format( options.conforms_to_protocol)) return res.Clear() if options.generate_header or options.generate_protocol: command_script = generate_header_script(options, clean_command) else: command_script = generate_class_dump(debugger, options, clean_command) if options.generate_header or options.generate_protocol: interpreter.HandleCommand( 'expression -lobjc -O -- (Class)NSClassFromString(@\"{}\")'.format( clean_command), res) if 'nil' in res.GetOutput(): result.SetError( 'Can\'t find class named "{}". Womp womp...'.format( clean_command)) return res.Clear() if options.generate_protocol: filepath = "/tmp/DS_" + clean_command + "Protocol.h" else: filepath = "/tmp/" + clean_command + ".h" interpreter.HandleCommand('expression -lobjc -O -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -g -- ' + command_script) if res.GetError(): result.SetError(res.GetError()) return contents = res.GetOutput() ds.create_or_touch_filepath(filepath, contents) print('Written output to: ' + filepath + '... opening file') os.system('open -R ' + filepath) else: msg = "Dumping protocols" if options.search_protocols else "Dumping classes" result.AppendMessage(ds.attrStr(msg, 'cyan')) interpreter.HandleCommand('expression -lobjc -O -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -g -- ' + command_script) if res.GetError(): result.SetError(ds.attrStr(res.GetError(), 'red')) return result.AppendMessage( ds.attrStr( '************************************************************', 'cyan')) if res.Succeeded(): result.AppendMessage(res.GetOutput())
def do_test(self): target = self.createTestTarget() # Now create a breakpoint in main.c at the source matching # "Set a breakpoint here" breakpoint = target.BreakpointCreateBySourceRegex( "Set a breakpoint here", lldb.SBFileSpec("main.c")) self.assertTrue(breakpoint and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) error = lldb.SBError() # This is the launch info. If you want to launch with arguments or # environment variables, add them using SetArguments or # SetEnvironmentEntries launch_info = target.GetLaunchInfo() process = target.Launch(launch_info, error) self.assertTrue(process, PROCESS_IS_VALID) # Did we hit our breakpoint? from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint threads = get_threads_stopped_at_breakpoint(process, breakpoint) self.assertEqual(len(threads), 1, "There should be a thread stopped at our breakpoint") # The hit count for the breakpoint should be 1. self.assertEquals(breakpoint.GetHitCount(), 1) frame = threads[0].GetFrameAtIndex(0) command_result = lldb.SBCommandReturnObject() interp = self.dbg.GetCommandInterpreter() # Just get args: result = interp.HandleCommand("frame var -l", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertIn("argc", output, "Args didn't find argc") self.assertIn("argv", output, "Args didn't find argv") self.assertNotIn("test_var", output, "Args found a local") self.assertNotIn("g_var", output, "Args found a global") # Just get locals: result = interp.HandleCommand("frame var -a", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertNotIn("argc", output, "Locals found argc") self.assertNotIn("argv", output, "Locals found argv") self.assertIn("test_var", output, "Locals didn't find test_var") self.assertNotIn("g_var", output, "Locals found a global") # Get the file statics: result = interp.HandleCommand("frame var -l -a -g", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertNotIn("argc", output, "Globals found argc") self.assertNotIn("argv", output, "Globals found argv") self.assertNotIn("test_var", output, "Globals found test_var") self.assertIn("g_var", output, "Globals didn't find g_var")
def run_python_os_step_missing_thread(self, do_prune): """Test that the Python operating system plugin works correctly""" # Our OS plugin does NOT report all threads: result = self.dbg.HandleCommand( "settings set process.experimental.os-plugin-reports-all-threads false" ) python_os_plugin_path = os.path.join(self.getSourceDir(), "operating_system.py") (target, self.process, thread, thread_bkpt) = lldbutil.run_to_source_breakpoint( self, "first stop in thread - do a step out", self.main_file) main_bkpt = target.BreakpointCreateBySourceRegex( 'Stop here and do not make a memory thread for thread_1', self.main_file) self.assertEqual(main_bkpt.GetNumLocations(), 1, "Main breakpoint has one location") # There should not be an os thread before we load the plugin: self.assertFalse(self.get_os_thread().IsValid(), "No OS thread before loading plugin") # Now load the python OS plug-in which should update the thread list and we should have # an OS plug-in thread overlaying thread_1 with id 0x111111111 command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path self.dbg.HandleCommand(command) # Verify our OS plug-in threads showed up os_thread = self.get_os_thread() self.assertTrue( os_thread.IsValid(), "Make sure we added the thread 0x111111111 after we load the python OS plug-in" ) # Now we are going to step-out. This should get interrupted by main_bkpt. We've # set up the OS plugin so at this stop, we have lost the OS thread 0x111111111. # Make sure both of these are true: os_thread.StepOut() stopped_threads = lldbutil.get_threads_stopped_at_breakpoint( self.process, main_bkpt) self.assertEqual(len(stopped_threads), 1, "Stopped at main_bkpt") thread = self.process.GetThreadByID(0x111111111) self.assertFalse(thread.IsValid(), "No thread 0x111111111 on second stop.") # Make sure we still have the thread plans for this thread: # First, don't show unreported threads, that should fail: command = "thread plan list -t 0x111111111" result = lldb.SBCommandReturnObject() interp = self.dbg.GetCommandInterpreter() interp.HandleCommand(command, result) self.assertFalse(result.Succeeded(), "We found no plans for the unreported thread.") # Now do it again but with the -u flag: command = "thread plan list -u -t 0x111111111" result = lldb.SBCommandReturnObject() interp.HandleCommand(command, result) self.assertTrue(result.Succeeded(), "We found plans for the unreported thread.") if do_prune: # Prune the thread plan and continue, and we will run to exit. interp.HandleCommand("thread plan prune 0x111111111", result) self.assertTrue(result.Succeeded(), "Found the plan for 0x111111111 and pruned it") # List again, make sure it doesn't work: command = "thread plan list -u -t 0x111111111" interp.HandleCommand(command, result) self.assertFalse( result.Succeeded(), "We still found plans for the unreported thread.") self.process.Continue() self.assertState(self.process.GetState(), lldb.eStateExited, "We exited.") else: # Now we are going to continue, and when we hit the step-out breakpoint, we will # put the OS plugin thread back, lldb will recover its ThreadPlanStack, and # we will stop with a "step-out" reason. self.process.Continue() os_thread = self.get_os_thread() self.assertTrue(os_thread.IsValid(), "The OS thread is back after continue") self.assertIn("step out", os_thread.GetStopDescription(100), "Completed step out plan")
def test_command_abbreviations_and_aliases(self): command_interpreter = self.dbg.GetCommandInterpreter() self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER) result = lldb.SBCommandReturnObject() # Check that abbreviations are expanded to the full command. command_interpreter.ResolveCommand("ap script", result) self.assertTrue(result.Succeeded()) self.assertEqual("apropos script", result.GetOutput()) command_interpreter.ResolveCommand("h", result) self.assertTrue(result.Succeeded()) self.assertEqual("help", result.GetOutput()) # Check resolution of abbreviations for multi-word commands. command_interpreter.ResolveCommand("lo li", result) self.assertTrue(result.Succeeded()) self.assertEqual("log list", result.GetOutput()) command_interpreter.ResolveCommand("br s", result) self.assertTrue(result.Succeeded()) self.assertEqual("breakpoint set", result.GetOutput()) # Try an ambiguous abbreviation. # "pl" could be "platform" or "plugin". command_interpreter.ResolveCommand("pl", result) self.assertFalse(result.Succeeded()) self.assertTrue(result.GetError().startswith("Ambiguous command")) # Make sure an unabbreviated command is not mangled. command_interpreter.ResolveCommand( "breakpoint set --name main --line 123", result) self.assertTrue(result.Succeeded()) self.assertEqual("breakpoint set --name main --line 123", result.GetOutput()) # Create some aliases. self.runCmd("com a alias com al") self.runCmd("alias gurp help") # Check that an alias is replaced with the actual command command_interpreter.ResolveCommand("gurp target create", result) self.assertTrue(result.Succeeded()) self.assertEqual("help target create", result.GetOutput()) # Delete the alias and make sure it no longer has an effect. self.runCmd("com u gurp") command_interpreter.ResolveCommand("gurp", result) self.assertFalse(result.Succeeded()) # Check aliases with text replacement. self.runCmd("alias pltty process launch -s -o %1 -e %1") command_interpreter.ResolveCommand("pltty /dev/tty0", result) self.assertTrue(result.Succeeded()) self.assertEqual("process launch -s -o /dev/tty0 -e /dev/tty0", result.GetOutput()) self.runCmd("alias xyzzy breakpoint set -n %1 -l %2") command_interpreter.ResolveCommand("xyzzy main 123", result) self.assertTrue(result.Succeeded()) self.assertEqual("breakpoint set -n main -l 123", result.GetOutput().strip()) # And again, without enough parameters. command_interpreter.ResolveCommand("xyzzy main", result) self.assertFalse(result.Succeeded()) # Check a command that wants the raw input. command_interpreter.ResolveCommand(r'''sc print("\n\n\tHello!\n")''', result) self.assertTrue(result.Succeeded()) self.assertEqual(r'''script print("\n\n\tHello!\n")''', result.GetOutput())
def display_match_results(result, options, arg_str_description, expr_sbvalue, print_no_matches=True): if expr_sbvalue.error.Success(): if expr_sbvalue.unsigned: match_value = lldb.value(expr_sbvalue) i = 0 match_idx = 0 while 1: print_entry = True match_entry = match_value[i] i += 1 if i >= options.max_matches: result.AppendMessage( 'error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)) break malloc_addr = match_entry.addr.sbvalue.unsigned if malloc_addr == 0: break malloc_size = int(match_entry.size) offset = int(match_entry.offset) if options.offset >= 0 and options.offset != offset: print_entry = False else: match_addr = malloc_addr + offset dynamic_value = match_entry.addr.sbvalue.GetDynamicValue( lldb.eDynamicCanRunTarget) description = '[%u] %s: addr = 0x%x' % ( match_idx, arg_str_description, malloc_addr) if offset != 0: description += ' + %u' % (offset) description += ', size = %u' % (malloc_size) derefed_dynamic_value = None if dynamic_value.type.name == 'void *': if options.type == 'pointer' and malloc_size == 4096: error = lldb.SBError() data = bytearray( lldb.process.ReadMemory( malloc_addr, 16, error)) if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': description += ', type = (AUTORELEASE!)' else: derefed_dynamic_value = dynamic_value.deref if derefed_dynamic_value: derefed_dynamic_type = derefed_dynamic_value.type derefed_dynamic_type_size = derefed_dynamic_type.size derefed_dynamic_type_name = derefed_dynamic_type.name description += ', type = %s <%u>' % ( derefed_dynamic_type_name, derefed_dynamic_type_size) if offset < derefed_dynamic_type_size: member_list = list() get_member_types_for_offset( derefed_dynamic_type, offset, member_list) if member_list: member_path = '' for member in member_list: member_name = member.name if member_name: if member_path: member_path += '.' member_path += member_name if member_path: if options.ivar_regex_blacklist: for ivar_regex in options.ivar_regex_blacklist: if ivar_regex.match( member_path): print_entry = False description += ', ivar = %s' % ( member_path) if print_entry: match_idx += 1 result_output = '' if description: result_output += description if options.print_type and derefed_dynamic_value: result_output += '%s' % (derefed_dynamic_value) if options.print_object_description and dynamic_value: desc = dynamic_value.GetObjectDescription() if desc: result_output += ', po=%s' % (desc) if result_output: result.AppendMessage(result_output) if options.memory: cmd_result = lldb.SBCommandReturnObject() memory_command = "memory read -f %s 0x%x 0x%x" % ( options.format, malloc_addr, malloc_addr + malloc_size) lldb.debugger.GetCommandInterpreter().HandleCommand( memory_command, cmd_result) result.AppendMessage(cmd_result.GetOutput()) if options.stack_history: dump_stack_history_entries(result, malloc_addr, 1) elif options.stack: dump_stack_history_entries(result, malloc_addr, 0) return i elif print_no_matches: result.AppendMessage('no matches found for %s' % (arg_str_description)) else: result.AppendMessage(str(expr_sbvalue.error)) return 0
def decryptDump(debugger, command, result, dict): MH_MAGIC = 0xFEEDFACE MH_CIGAM = 0xCEFAEDFE MH_MAGIC_64 = 0xFEEDFACF MH_CIGAM_64 = 0xCFFAEDFE LC_ENCRYPTION_INFO = 0x21 LC_ENCRYPTION_INFO_64 = 0x2C MACHO_HEADER_SIZE = 28 MACHO_HEADER_SIZE_64 = 32 # 解析参数 usage = 'usage: %prog [options]' parser = optparse.OptionParser(prog='decryptDump', usage=usage) parser.add_option('-i', '--image', type='string', dest='image', help='The image to be decrypted.') parser.add_option('-o', '--output', type='string', dest='output', help='The decrypted file store path.') commandList = shlex.split(command) try: (options, args) = parser.parse_args(commandList) except Exception as e: print e return if options.output == None: raise Exception( "No specified output path,Please use -h to see the instructions.") elif options.image == None: raise Exception( "No module specified,Please use -h to see the instructions.") target = debugger.GetSelectedTarget() for module in target.modules: # print module if module.file.basename == options.image: image_load_address = module.GetObjectFileHeaderAddress( ).GetLoadAddress(target) print "INFO: image `%s` loaded at <0x%016x>" % (options.image, image_load_address) process = target.GetProcess() read_res = lldb.SBError() macho_memory = process.ReadMemory(image_load_address, 24, read_res) prefix = "" mach_header_size = 0x0 encryption_info_cmd = LC_ENCRYPTION_INFO encryption_info_description = "LC_ENCRYPTION_INFO" cryptoffset = 0 cryptsize = 0 cryptid = 0 if read_res.Success(): magic, = struct.unpack("<I", macho_memory[0:4]) print "%x" % (magic) print "%x" % (MH_MAGIC_64) if magic == MH_MAGIC or magic == MH_MAGIC_64: #小端 prefix = '<' elif magic == MH_CIGAM or magic == MH_CIGAM_64: #大端 prefix = '>' else: raise Exception("magic error ===> [0x%4x]" % (magic)) #64bit if magic == MH_CIGAM_64 or magic == MH_MAGIC_64: mach_header_size = MACHO_HEADER_SIZE_64 encryption_info_cmd = LC_ENCRYPTION_INFO_64 encryption_info_description = 'LC_ENCRYPTION_INFO_64' #读取`ncmds`和`sizecmds` ncmds, sizecmds = struct.unpack(prefix + '2I', macho_memory[16:24]) macho_memory = process.ReadMemory(image_load_address, sizecmds + mach_header_size, read_res) load_command_start = mach_header_size #读取各个`loadcommand`,寻找 `LC_ENCRYPTION_INFO` 或 `LC_ENCRYPTION_INFO_64` for i in range(ncmds): cmd, cmdsize = struct.unpack( prefix + '2I', macho_memory[load_command_start:load_command_start + 8]) if cmd == encryption_info_cmd: load_command_start = load_command_start + 8 cryptoffset, cryptsize, cryptid = struct.unpack( prefix + '3I', macho_memory[ load_command_start:load_command_start + 12]) print "INFO: cryptoffset: 0x%04x\n cryptsize: 0x%04x\n cryptid: 0x%04x\n" % ( cryptoffset, cryptsize, cryptid) break else: load_command_start = load_command_start + cmdsize ci = debugger.GetCommandInterpreter() res = lldb.SBCommandReturnObject() ci.HandleCommand( "memory read --force --outfile %s --binary --count %d 0x%016X" % (options.output, cryptsize, image_load_address + cryptoffset), res) if res.Succeeded(): print "INFO: 0x%4x bytes read as binary" % (cryptsize) else: print res else: #读取错误 print read_res #找到了相对应的模块,直接返回 break
def set_handle(self, signal, pass_signal, stop_at_signal, notify_signal): return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "process handle %s -p %s -s %s -n %s" % (signal, pass_signal, stop_at_signal, notify_signal), return_obj) self.assertTrue (return_obj.Succeeded() == True, "Setting signal handling failed")
def check_list_output(self, command, active_plans=[], completed_plans=[], discarded_plans=[]): # Check the "thread plan list" output against a list of active & completed and discarded plans. # If all three check arrays are empty, that means the command is expected to fail. interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() num_active = len(active_plans) num_completed = len(completed_plans) num_discarded = len(discarded_plans) interp.HandleCommand(command, result) print("Command: %s" % (command)) print(result.GetOutput()) if num_active == 0 and num_completed == 0 and num_discarded == 0: self.assertFalse( result.Succeeded(), "command: '%s' succeeded when it should have failed: '%s'" % (command, result.GetError())) return self.assertTrue( result.Succeeded(), "command: '%s' failed: '%s'" % (command, result.GetError())) result_arr = result.GetOutput().splitlines() num_results = len(result_arr) # Match the expected number of elements. # Adjust the count for the number of header lines we aren't matching: fudge = 0 if num_completed == 0 and num_discarded == 0: # The fudge is 3: Thread header, Active Plan header and base plan fudge = 3 elif num_completed == 0 or num_discarded == 0: # The fudge is 4: The above plus either the Completed or Discarded Plan header: fudge = 4 else: # The fudge is 5 since we have both headers: fudge = 5 self.assertEqual( num_results, num_active + num_completed + num_discarded + fudge, "Too many elements in match arrays for: \n%s\n" % result.GetOutput()) # Now iterate through the results array and pick out the results. result_idx = 0 self.assertIn("thread #", result_arr[result_idx], "Found thread header") result_idx += 1 self.assertIn("Active plan stack", result_arr[result_idx], "Found active header") result_idx += 1 self.assertIn("Element 0: Base thread plan", result_arr[result_idx], "Found base plan") result_idx += 1 for text in active_plans: self.assertFalse("Completed plan stack" in result_arr[result_idx], "Found Completed header too early.") self.assertIn(text, result_arr[result_idx], "Didn't find active plan: %s" % (text)) result_idx += 1 if len(completed_plans) > 0: self.assertIn("Completed plan stack:", result_arr[result_idx], "Found completed plan stack header") result_idx += 1 for text in completed_plans: self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s" % (text)) result_idx += 1 if len(discarded_plans) > 0: self.assertIn("Discarded plan stack:", result_arr[result_idx], "Found discarded plan stack header") result_idx += 1 for text in discarded_plans: self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s" % (text)) result_idx += 1
def is_continue(interpreter, command): ret = lldb.SBCommandReturnObject() interpreter.ResolveCommand(command, ret) return ret.GetOutput() == 'process continue'
def thread_plan_test(self): (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) # Now set a breakpoint in call_me and step over. We should have # two public thread plans call_me_bkpt = target.BreakpointCreateBySourceRegex( "Set another here", self.main_source_file) self.assertTrue(call_me_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") thread.StepOver() threads = lldbutil.get_threads_stopped_at_breakpoint( process, call_me_bkpt) self.assertEqual(len(threads), 1, "Hit my breakpoint while stepping over") current_id = threads[0].GetIndexID() current_tid = threads[0].GetThreadID() # Run thread plan list without the -i flag: command = "thread plan list %d" % (current_id) self.check_list_output(command, ["Stepping over line main.c"], []) # Run thread plan list with the -i flag: command = "thread plan list -i %d" % (current_id) self.check_list_output( command, ["Stepping over line main.c", "Stepping out from"]) # Run thread plan list providing TID, output should be the same: command = "thread plan list -t %d" % (current_tid) self.check_list_output(command, ["Stepping over line main.c"]) # Provide both index & tid, and make sure we only print once: command = "thread plan list -t %d %d" % (current_tid, current_id) self.check_list_output(command, ["Stepping over line main.c"]) # Try a fake TID, and make sure that fails: fake_tid = 0 for i in range(100, 10000, 100): fake_tid = current_tid + i thread = process.GetThreadByID(fake_tid) if not thread: break command = "thread plan list -t %d" % (fake_tid) self.check_list_output(command) # Now continue, and make sure we printed the completed plan: process.Continue() threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonPlanComplete) self.assertEqual(len(threads), 1, "One thread completed a step") # Run thread plan list - there aren't any private plans at this point: command = "thread plan list %d" % (current_id) self.check_list_output(command, [], ["Stepping over line main.c"]) # Set another breakpoint that we can run to, to try deleting thread plans. second_step_bkpt = target.BreakpointCreateBySourceRegex( "Run here to step over again", self.main_source_file) self.assertTrue(second_step_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") final_bkpt = target.BreakpointCreateBySourceRegex( "Make sure we get here on last continue", self.main_source_file) self.assertTrue(final_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") threads = lldbutil.continue_to_breakpoint(process, second_step_bkpt) self.assertEqual(len(threads), 1, "Hit the second step breakpoint") threads[0].StepOver() threads = lldbutil.get_threads_stopped_at_breakpoint( process, call_me_bkpt) result = lldb.SBCommandReturnObject() interp = self.dbg.GetCommandInterpreter() interp.HandleCommand("thread plan discard 1", result) self.assertTrue( result.Succeeded(), "Deleted the step over plan: %s" % (result.GetOutput())) # Make sure the plan gets listed in the discarded plans: command = "thread plan list %d" % (current_id) self.check_list_output(command, [], [], ["Stepping over line main.c:"]) process.Continue() threads = lldbutil.get_threads_stopped_at_breakpoint( process, final_bkpt) self.assertEqual(len(threads), 1, "Ran to final breakpoint") threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonPlanComplete) self.assertEqual(len(threads), 0, "Did NOT complete the step over plan")
def test(self): """ Test that lldb correctly fetches the target definition file in multiple chunks if the remote server only provides the content in small parts, and the small parts it provides is smaller than the maximum packet size that it declared at the start of the debug session. qemu does this. """ class MyResponder(MockGDBServerResponder): def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": return """<?xml version="1.0"?> <!DOCTYPE feature SYSTEM "gdb-target.dtd"> <target version="1.0"> <architecture>i386:x86-64</architecture> <xi:include href="i386-64bit-core.xml"/> </target>""", False if annex == "i386-64bit-core.xml" and offset == 0: return """<?xml version="1.0"?> <!-- Copyright (C) 2010-2015 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> <!DOCTYPE feature SYSTEM "gdb-target.dtd"> <feature name="org.gnu.gdb.i386.core"> <flags id="i386_eflags" size="4"> <field name="CF" start="0" end="0"/> <field name="" start="1" end="1"/> <field name="PF" start="2" end="2"/> <field name="AF" start="4" end="4"/> <field name="ZF" start="6" end="6"/> <field name="SF" start="7" end="7"/> <field name="TF" start="8" end="8"/> <field name="IF" start="9" end="9"/> <field name="DF" start="10" end="10"/> <field name="OF" start="11" end="11"/> <field name="NT" start="14" end="14"/> <field name="RF" start="16" end="16"/> <field name="VM" start="17" end="17"/> <field name="AC" start="18" end="18"/> <field name="VIF" start="19" end="19"/> <field name="VIP" start="20" end="20"/> <field name="ID" start="21" end="21"/> </flags> <reg name="rax" bitsize="64" type="int64"/> <reg name="rbx" bitsize="64" type="int64"/> <reg name="rcx" bitsize="64" type="int64"/> <reg name="rdx" bitsize="64" type="int64"/> <reg name="rsi" bitsize="64" type="int64"/> <reg name="rdi" bitsize="64" type="int64"/> <reg name="rbp" bitsize="64" type="data_ptr"/> <reg name="rsp" bitsize="64" type="data_ptr"/> <reg name="r8" bitsize="64" type="int64"/> <reg name="r9" bitsize="64" type="int64"/> <reg name="r10" bitsize="64" type="int64"/> <reg name="r11" bitsize="64" type="int64"/> <reg name="r12" bitsize="64" type="int64"/> <reg name="r13" bitsize="64" type="int64"/> <reg name="r14" bitsize="64" type="int64"/> <reg name="r15" bitsize="64" type="int64"/> <reg name="rip" bitsize="64" type="code_ptr"/> <reg name="eflags" bitsize="32" type="i386_eflags"/> <reg name="cs" bitsize="32" type="int32"/> <reg name="ss" bitsize="32" ty""", True if annex == "i386-64bit-core.xml" and offset == 2045: return """pe="int32"/> <reg name="ds" bitsize="32" type="int32"/> <reg name="es" bitsize="32" type="int32"/> <reg name="fs" bitsize="32" type="int32"/> <reg name="gs" bitsize="32" type="int32"/> <reg name="st0" bitsize="80" type="i387_ext"/> <reg name="st1" bitsize="80" type="i387_ext"/> <reg name="st2" bitsize="80" type="i387_ext"/> <reg name="st3" bitsize="80" type="i387_ext"/> <reg name="st4" bitsize="80" type="i387_ext"/> <reg name="st5" bitsize="80" type="i387_ext"/> <reg name="st6" bitsize="80" type="i387_ext"/> <reg name="st7" bitsize="80" type="i387_ext"/> <reg name="fctrl" bitsize="32" type="int" group="float"/> <reg name="fstat" bitsize="32" type="int" group="float"/> <reg name="ftag" bitsize="32" type="int" group="float"/> <reg name="fiseg" bitsize="32" type="int" group="float"/> <reg name="fioff" bitsize="32" type="int" group="float"/> <reg name="foseg" bitsize="32" type="int" group="float"/> <reg name="fooff" bitsize="32" type="int" group="float"/> <reg name="fop" bitsize="32" type="int" group="float"/> </feature>""", False return None, False def readRegister(self, regnum): return "" def readRegisters(self): return "0600000000000000c0b7c00080fffffff021c60080ffffff1a00000000000000020000000000000078b7c00080ffffff203f8ca090ffffff103f8ca090ffffff3025990a80ffffff809698000000000070009f0a80ffffff020000000000000000eae10080ffffff00000000000000001822d74f1a00000078b7c00080ffffff0e12410080ffff004602000011111111222222223333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000" def haltReason(self): return "T02thread:dead;threads:dead;" def qfThreadInfo(self): return "mdead" def qC(self): return "" def qSupported(self, client_supported): return "PacketSize=1000;qXfer:features:read+" def QThreadSuffixSupported(self): return "OK" def QListThreadsInStopReply(self): return "OK" self.server.responder = MyResponder() if self.TraceOn(): self.runCmd("log enable gdb-remote packets") time.sleep(10) self.addTearDownHook( lambda: self.runCmd("log disable gdb-remote packets")) target = self.dbg.CreateTargetWithFileAndArch(None, None) process = self.connect(target) if self.TraceOn(): interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() interp.HandleCommand("target list", result) print(result.GetOutput()) rip_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("rip") self.assertEqual(rip_valobj.GetValueAsUnsigned(), 0x00ffff800041120e) ss_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("ss") self.assertEqual(ss_valobj.GetValueAsUnsigned(), 0x22222222) if self.TraceOn(): print("rip is 0x%x" % rip_valobj.GetValueAsUnsigned()) print("ss is 0x%x" % ss_valobj.GetValueAsUnsigned())
def getCommandOutput(self, command, command_args=""): """ runs cmd in the command interpreter andreturns (status, result) """ result = lldb.SBCommandReturnObject() cmd = "%s %s" % (command, command_args) self.commandInterpreter.HandleCommand(cmd, result) return (result.Succeeded(), result.GetOutput() if result.Succeeded() else result.GetError())
def test(self): """ Test lldb's parsing of SEGGER J-Link v6.54 register definition for a Cortex M-4 dev board, and the fact that the J-Link only supports g/G for reading/writing register AND the J-Link v6.54 doesn't provide anything but the general purpose registers.""" class MyResponder(MockGDBServerResponder): def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": return """<?xml version="1.0"?> <!-- Copyright (C) 2008 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> <!DOCTYPE feature SYSTEM "gdb-target.dtd"> <target version="1.0"> <architecture>arm</architecture> <feature name="org.gnu.gdb.arm.m-profile"> <reg name="r0" bitsize="32" regnum="0" type="uint32" group="general"/> <reg name="r1" bitsize="32" regnum="1" type="uint32" group="general"/> <reg name="r2" bitsize="32" regnum="2" type="uint32" group="general"/> <reg name="r3" bitsize="32" regnum="3" type="uint32" group="general"/> <reg name="r4" bitsize="32" regnum="4" type="uint32" group="general"/> <reg name="r5" bitsize="32" regnum="5" type="uint32" group="general"/> <reg name="r6" bitsize="32" regnum="6" type="uint32" group="general"/> <reg name="r7" bitsize="32" regnum="7" type="uint32" group="general"/> <reg name="r8" bitsize="32" regnum="8" type="uint32" group="general"/> <reg name="r9" bitsize="32" regnum="9" type="uint32" group="general"/> <reg name="r10" bitsize="32" regnum="10" type="uint32" group="general"/> <reg name="r11" bitsize="32" regnum="11" type="uint32" group="general"/> <reg name="r12" bitsize="32" regnum="12" type="uint32" group="general"/> <reg name="sp" bitsize="32" regnum="13" type="data_ptr" group="general"/> <reg name="lr" bitsize="32" regnum="14" type="uint32" group="general"/> <reg name="pc" bitsize="32" regnum="15" type="code_ptr" group="general"/> <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/> </feature> <feature name="org.gnu.gdb.arm.m-system"> <reg name="msp" bitsize="32" regnum="26" type="uint32" group="general"/> <reg name="psp" bitsize="32" regnum="27" type="uint32" group="general"/> <reg name="primask" bitsize="32" regnum="28" type="uint32" group="general"/> <reg name="basepri" bitsize="32" regnum="29" type="uint32" group="general"/> <reg name="faultmask" bitsize="32" regnum="30" type="uint32" group="general"/> <reg name="control" bitsize="32" regnum="31" type="uint32" group="general"/> </feature> <feature name="org.gnu.gdb.arm.m-float"> <reg name="fpscr" bitsize="32" regnum="32" type="uint32" group="float"/> <reg name="s0" bitsize="32" regnum="33" type="float" group="float"/> <reg name="s1" bitsize="32" regnum="34" type="float" group="float"/> <reg name="s2" bitsize="32" regnum="35" type="float" group="float"/> <reg name="s3" bitsize="32" regnum="36" type="float" group="float"/> <reg name="s4" bitsize="32" regnum="37" type="float" group="float"/> <reg name="s5" bitsize="32" regnum="38" type="float" group="float"/> <reg name="s6" bitsize="32" regnum="39" type="float" group="float"/> <reg name="s7" bitsize="32" regnum="40" type="float" group="float"/> <reg name="s8" bitsize="32" regnum="41" type="float" group="float"/> <reg name="s9" bitsize="32" regnum="42" type="float" group="float"/> <reg name="s10" bitsize="32" regnum="43" type="float" group="float"/> <reg name="s11" bitsize="32" regnum="44" type="float" group="float"/> <reg name="s12" bitsize="32" regnum="45" type="float" group="float"/> <reg name="s13" bitsize="32" regnum="46" type="float" group="float"/> <reg name="s14" bitsize="32" regnum="47" type="float" group="float"/> <reg name="s15" bitsize="32" regnum="48" type="float" group="float"/> <reg name="s16" bitsize="32" regnum="49" type="float" group="float"/> <reg name="s17" bitsize="32" regnum="50" type="float" group="float"/> <reg name="s18" bitsize="32" regnum="51" type="float" group="float"/> <reg name="s19" bitsize="32" regnum="52" type="float" group="float"/> <reg name="s20" bitsize="32" regnum="53" type="float" group="float"/> <reg name="s21" bitsize="32" regnum="54" type="float" group="float"/> <reg name="s22" bitsize="32" regnum="55" type="float" group="float"/> <reg name="s23" bitsize="32" regnum="56" type="float" group="float"/> <reg name="s24" bitsize="32" regnum="57" type="float" group="float"/> <reg name="s25" bitsize="32" regnum="58" type="float" group="float"/> <reg name="s26" bitsize="32" regnum="59" type="float" group="float"/> <reg name="s27" bitsize="32" regnum="60" type="float" group="float"/> <reg name="s28" bitsize="32" regnum="61" type="float" group="float"/> <reg name="s29" bitsize="32" regnum="62" type="float" group="float"/> <reg name="s30" bitsize="32" regnum="63" type="float" group="float"/> <reg name="s31" bitsize="32" regnum="64" type="float" group="float"/> <reg name="d0" bitsize="64" regnum="65" type="ieee_double" group="float"/> <reg name="d1" bitsize="64" regnum="66" type="ieee_double" group="float"/> <reg name="d2" bitsize="64" regnum="67" type="ieee_double" group="float"/> <reg name="d3" bitsize="64" regnum="68" type="ieee_double" group="float"/> <reg name="d4" bitsize="64" regnum="69" type="ieee_double" group="float"/> <reg name="d5" bitsize="64" regnum="70" type="ieee_double" group="float"/> <reg name="d6" bitsize="64" regnum="71" type="ieee_double" group="float"/> <reg name="d7" bitsize="64" regnum="72" type="ieee_double" group="float"/> <reg name="d8" bitsize="64" regnum="73" type="ieee_double" group="float"/> <reg name="d9" bitsize="64" regnum="74" type="ieee_double" group="float"/> <reg name="d10" bitsize="64" regnum="75" type="ieee_double" group="float"/> <reg name="d11" bitsize="64" regnum="76" type="ieee_double" group="float"/> <reg name="d12" bitsize="64" regnum="77" type="ieee_double" group="float"/> <reg name="d13" bitsize="64" regnum="78" type="ieee_double" group="float"/> <reg name="d14" bitsize="64" regnum="79" type="ieee_double" group="float"/> <reg name="d15" bitsize="64" regnum="80" type="ieee_double" group="float"/> </feature> </target>""", False else: return None, False def readRegister(self, regnum): return "E01" # Initial r1 bytes, in little-endian order r1_bytes = "01000000" ## readRegisters only provides reg values up through xpsr (0x61000000) ## it doesn't send up any of the exception registers or floating point ## registers that the above register xml describes. def readRegisters(self): return "00000000" + self.r1_bytes + "010000000100000001000000000000008c080020a872012000000000a0790120000000008065012041ad0008a0720120692a00089e26000800000061" ## the J-Link accepts a register write packet with just the GPRs ## defined. def writeRegisters(self, registers_hex): # Check that lldb returns the full 704 hex-byte register context, # or the 136 hex-byte general purpose register reg ctx. if len(registers_hex) != 704 and len(register_hex) != 136: return "E06" if registers_hex.startswith( "0000000044332211010000000100000001000000000000008c080020a872012000000000a0790120000000008065012041ad0008a0720120692a00089e26000800000061" ): self.r1_bytes = "44332211" return "OK" else: return "E07" def haltReason(self): return "S05" def qfThreadInfo(self): return "mdead" def qC(self): return "" def qSupported(self, client_supported): return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;hwbreak+;qXfer:features:read+" def QThreadSuffixSupported(self): return "OK" def QListThreadsInStopReply(self): return "OK" self.server.responder = MyResponder() if self.TraceOn(): self.runCmd("log enable gdb-remote packets") self.addTearDownHook( lambda: self.runCmd("log disable gdb-remote packets")) self.dbg.SetDefaultArchitecture("armv7em") target = self.dbg.CreateTargetWithFileAndArch(None, None) process = self.connect(target) if self.TraceOn(): interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() interp.HandleCommand("target list", result) print(result.GetOutput()) r1_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("r1") self.assertEqual(r1_valobj.GetValueAsUnsigned(), 1) pc_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("pc") self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800269e) xpsr_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("xpsr") self.assertEqual(xpsr_valobj.GetValueAsUnsigned(), 0x61000000) msp_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("msp") err = msp_valobj.GetError() self.assertTrue(err.Fail(), "lldb should not be able to fetch the msp register") val = b'\x11\x22\x33\x44' error = lldb.SBError() data = lldb.SBData() data.SetData(error, val, lldb.eByteOrderBig, 4) self.assertEqual(r1_valobj.SetData(data, error), True) self.assertTrue(error.Success()) r1_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("r1") self.assertEqual(r1_valobj.GetValueAsUnsigned(), 0x11223344)
def signal_test(self, signal, test_passing): """Test that we handle inferior raising signals""" exe = os.path.join(os.getcwd(), "a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) lldbutil.run_break_set_by_symbol(self, "main") # launch process = self.launch(target, signal) signo = process.GetUnixSignals().GetSignalNumberFromName(signal) # retrieve default signal disposition return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand("process handle %s " % signal, return_obj) match = re.match('NAME *PASS *STOP *NOTIFY.*(false|true) *(false|true) *(false|true)', return_obj.GetOutput(), re.IGNORECASE | re.DOTALL) if not match: self.fail('Unable to retrieve default signal disposition.') default_pass = match.group(1) default_stop = match.group(2) default_notify = match.group(3) # Make sure we stop at the signal self.set_handle(signal, "false", "true", "true") process.Continue() self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) self.assertTrue(thread.IsValid(), "Thread should be stopped due to a signal") self.assertTrue(thread.GetStopReasonDataCount() >= 1, "There was data in the event.") self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo, "The stop signal was %s" % signal) # Continue until we exit. process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal. We should still get the notification. self.set_handle(signal, "false", "false", "true") self.expect("process continue", substrs=["stopped and restarted", signal]) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal, and we do not get the notification. self.set_handle(signal, "false", "false", "false") self.expect("process continue", substrs=["stopped and restarted"], matching=False) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) if not test_passing: # reset signal handling to default self.set_handle(signal, default_pass, default_stop, default_notify) return # launch again process = self.launch(target, signal) # Make sure we stop at the signal self.set_handle(signal, "true", "true", "true") process.Continue() self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) self.assertTrue(thread.IsValid(), "Thread should be stopped due to a signal") self.assertTrue(thread.GetStopReasonDataCount() >= 1, "There was data in the event.") self.assertEqual(thread.GetStopReasonDataAtIndex(0), process.GetUnixSignals().GetSignalNumberFromName(signal), "The stop signal was %s" % signal) # Continue until we exit. The process should receive the signal. process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal. We should still get the notification. Process # should receive the signal. self.set_handle(signal, "true", "false", "true") self.expect("process continue", substrs=["stopped and restarted", signal]) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal, and we do not get the notification. Process # should receive the signal. self.set_handle(signal, "true", "false", "false") self.expect("process continue", substrs=["stopped and restarted"], matching=False) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # reset signal handling to default self.set_handle(signal, default_pass, default_stop, default_notify)
def test(self): """ Test lldb's parsing of the <architecture> tag in the target.xml register description packet. """ class MyResponder(MockGDBServerResponder): def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": return """<?xml version="1.0"?> <target version="1.0"> <architecture>i386:x86-64</architecture> <feature name="org.gnu.gdb.i386.core"> <flags id="i386_eflags" size="4"> <field name="CF" start="0" end="0"/> <field name="" start="1" end="1"/> <field name="PF" start="2" end="2"/> <field name="AF" start="4" end="4"/> <field name="ZF" start="6" end="6"/> <field name="SF" start="7" end="7"/> <field name="TF" start="8" end="8"/> <field name="IF" start="9" end="9"/> <field name="DF" start="10" end="10"/> <field name="OF" start="11" end="11"/> <field name="NT" start="14" end="14"/> <field name="RF" start="16" end="16"/> <field name="VM" start="17" end="17"/> <field name="AC" start="18" end="18"/> <field name="VIF" start="19" end="19"/> <field name="VIP" start="20" end="20"/> <field name="ID" start="21" end="21"/> </flags> <reg name="rax" bitsize="64" regnum="0" type="int" group="general"/> <reg name="rbx" bitsize="64" regnum="1" type="int" group="general"/> <reg name="rcx" bitsize="64" regnum="2" type="int" group="general"/> <reg name="rdx" bitsize="64" regnum="3" type="int" group="general"/> <reg name="rsi" bitsize="64" regnum="4" type="int" group="general"/> <reg name="rdi" bitsize="64" regnum="5" type="int" group="general"/> <reg name="rbp" bitsize="64" regnum="6" type="data_ptr" group="general"/> <reg name="rsp" bitsize="64" regnum="7" type="data_ptr" group="general"/> <reg name="r8" bitsize="64" regnum="8" type="int" group="general"/> <reg name="r9" bitsize="64" regnum="9" type="int" group="general"/> <reg name="r10" bitsize="64" regnum="10" type="int" group="general"/> <reg name="r11" bitsize="64" regnum="11" type="int" group="general"/> <reg name="r12" bitsize="64" regnum="12" type="int" group="general"/> <reg name="r13" bitsize="64" regnum="13" type="int" group="general"/> <reg name="r14" bitsize="64" regnum="14" type="int" group="general"/> <reg name="r15" bitsize="64" regnum="15" type="int" group="general"/> <reg name="rip" bitsize="64" regnum="16" type="code_ptr" group="general"/> <reg name="eflags" bitsize="32" regnum="17" type="i386_eflags" group="general"/> <reg name="cs" bitsize="32" regnum="18" type="int" group="general"/> <reg name="ss" bitsize="32" regnum="19" type="int" group="general"/> <reg name="ds" bitsize="32" regnum="20" type="int" group="general"/> <reg name="es" bitsize="32" regnum="21" type="int" group="general"/> <reg name="fs" bitsize="32" regnum="22" type="int" group="general"/> <reg name="gs" bitsize="32" regnum="23" type="int" group="general"/> <reg name="st0" bitsize="80" regnum="24" type="i387_ext" group="float"/> <reg name="st1" bitsize="80" regnum="25" type="i387_ext" group="float"/> <reg name="st2" bitsize="80" regnum="26" type="i387_ext" group="float"/> <reg name="st3" bitsize="80" regnum="27" type="i387_ext" group="float"/> <reg name="st4" bitsize="80" regnum="28" type="i387_ext" group="float"/> <reg name="st5" bitsize="80" regnum="29" type="i387_ext" group="float"/> <reg name="st6" bitsize="80" regnum="30" type="i387_ext" group="float"/> <reg name="st7" bitsize="80" regnum="31" type="i387_ext" group="float"/> <reg name="fctrl" bitsize="32" regnum="32" type="int" group="float"/> <reg name="fstat" bitsize="32" regnum="33" type="int" group="float"/> <reg name="ftag" bitsize="32" regnum="34" type="int" group="float"/> <reg name="fiseg" bitsize="32" regnum="35" type="int" group="float"/> <reg name="fioff" bitsize="32" regnum="36" type="int" group="float"/> <reg name="foseg" bitsize="32" regnum="37" type="int" group="float"/> <reg name="fooff" bitsize="32" regnum="38" type="int" group="float"/> <reg name="fop" bitsize="32" regnum="39" type="int" group="float"/> </feature> </target>""", False else: return None, False def qC(self): return "QC1" def haltReason(self): return "T05thread:00000001;06:9038d60f00700000;07:98b4062680ffffff;10:c0d7bf1b80ffffff;" def readRegister(self, register): regs = { 0x0: "00b0060000610000", 0xa: "68fe471c80ffffff", 0xc: "60574a1c80ffffff", 0xd: "18f3042680ffffff", 0xe: "be8a4d7142000000", 0xf: "50df471c80ffffff", 0x10: "c0d7bf1b80ffffff" } if register in regs: return regs[register] else: return "0000000000000000" self.server.responder = MyResponder() interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() if self.TraceOn(): self.runCmd("log enable gdb-remote packets") self.addTearDownHook( lambda: self.runCmd("log disable gdb-remote packets")) target = self.dbg.CreateTarget('') self.assertEqual('', target.GetTriple()) process = self.connect(target) if self.TraceOn(): interp.HandleCommand("target list", result) print(result.GetOutput()) self.assertTrue( target.GetTriple().startswith('x86_64-unknown-unknown'))
def wait_for_hook_stop(): while True: res = lldb.SBCommandReturnObject() lldb.debugger.GetCommandInterpreter().HandleCommand("target stop-hook add -o \"HandleHookStopOnTarget\"", res) if res.Succeeded() == True: return time.sleep(0.05)
def test_SBCommandReturnObject(self): """SBCommandReturnObject object is valid after default construction.""" obj = lldb.SBCommandReturnObject() if self.TraceOn(): print obj self.assertTrue(obj)
def dbgcall(command): res = lldb.SBCommandReturnObject() lldb.debugger.GetCommandInterpreter().HandleCommand(command, res) return res.GetOutput()
def __init__(self): self.ci = lldb.debugger.GetCommandInterpreter() self.res = lldb.SBCommandReturnObject()
def test(self): """ Test lldb's parsing of the <architecture> tag in the target.xml register description packet. """ class MyResponder(MockGDBServerResponder): def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": return """<?xml version="1.0"?><!DOCTYPE target SYSTEM "gdb-target.dtd"><target><architecture>i386:x86-64</architecture><xi:include href="i386-64bit.xml"/></target>""", False if annex == "i386-64bit.xml": return """<?xml version="1.0"?> <!-- Copyright (C) 2010-2017 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> <!-- I386 64bit --> <!DOCTYPE target SYSTEM "gdb-target.dtd"> <feature name="org.gnu.gdb.i386.64bit"> <xi:include href="i386-64bit-core.xml"/> <xi:include href="i386-64bit-sse.xml"/> </feature>""", False if annex == "i386-64bit-core.xml": return """<?xml version="1.0"?> <!-- Copyright (C) 2010-2015 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> <!DOCTYPE feature SYSTEM "gdb-target.dtd"> <feature name="org.gnu.gdb.i386.core"> <flags id="i386_eflags" size="4"> <field name="CF" start="0" end="0"/> <field name="" start="1" end="1"/> <field name="PF" start="2" end="2"/> <field name="AF" start="4" end="4"/> <field name="ZF" start="6" end="6"/> <field name="SF" start="7" end="7"/> <field name="TF" start="8" end="8"/> <field name="IF" start="9" end="9"/> <field name="DF" start="10" end="10"/> <field name="OF" start="11" end="11"/> <field name="NT" start="14" end="14"/> <field name="RF" start="16" end="16"/> <field name="VM" start="17" end="17"/> <field name="AC" start="18" end="18"/> <field name="VIF" start="19" end="19"/> <field name="VIP" start="20" end="20"/> <field name="ID" start="21" end="21"/> </flags> <reg name="rax" bitsize="64" type="int64"/> <reg name="rbx" bitsize="64" type="int64"/> <reg name="rcx" bitsize="64" type="int64"/> <reg name="rdx" bitsize="64" type="int64"/> <reg name="rsi" bitsize="64" type="int64"/> <reg name="rdi" bitsize="64" type="int64"/> <reg name="rbp" bitsize="64" type="data_ptr"/> <reg name="rsp" bitsize="64" type="data_ptr"/> <reg name="r8" bitsize="64" type="int64"/> <reg name="r9" bitsize="64" type="int64"/> <reg name="r10" bitsize="64" type="int64"/> <reg name="r11" bitsize="64" type="int64"/> <reg name="r12" bitsize="64" type="int64"/> <reg name="r13" bitsize="64" type="int64"/> <reg name="r14" bitsize="64" type="int64"/> <reg name="r15" bitsize="64" type="int64"/> <reg name="rip" bitsize="64" type="code_ptr"/> <reg name="eflags" bitsize="32" type="i386_eflags"/> <reg name="cs" bitsize="32" type="int32"/> <reg name="ss" bitsize="32" type="int32"/> <reg name="ds" bitsize="32" type="int32"/> <reg name="es" bitsize="32" type="int32"/> <reg name="fs" bitsize="32" type="int32"/> <reg name="gs" bitsize="32" type="int32"/> <reg name="st0" bitsize="80" type="i387_ext"/> <reg name="st1" bitsize="80" type="i387_ext"/> <reg name="st2" bitsize="80" type="i387_ext"/> <reg name="st3" bitsize="80" type="i387_ext"/> <reg name="st4" bitsize="80" type="i387_ext"/> <reg name="st5" bitsize="80" type="i387_ext"/> <reg name="st6" bitsize="80" type="i387_ext"/> <reg name="st7" bitsize="80" type="i387_ext"/> <reg name="fctrl" bitsize="32" type="int" group="float"/> <reg name="fstat" bitsize="32" type="int" group="float"/> <reg name="ftag" bitsize="32" type="int" group="float"/> <reg name="fiseg" bitsize="32" type="int" group="float"/> <reg name="fioff" bitsize="32" type="int" group="float"/> <reg name="foseg" bitsize="32" type="int" group="float"/> <reg name="fooff" bitsize="32" type="int" group="float"/> <reg name="fop" bitsize="32" type="int" group="float"/> </feature>""", False if annex == "i386-64bit-sse.xml": return """<?xml version="1.0"?> <!-- Copyright (C) 2010-2017 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> <!DOCTYPE feature SYSTEM "gdb-target.dtd"> <feature name="org.gnu.gdb.i386.64bit.sse"> <vector id="v4f" type="ieee_single" count="4"/> <vector id="v2d" type="ieee_double" count="2"/> <vector id="v16i8" type="int8" count="16"/> <vector id="v8i16" type="int16" count="8"/> <vector id="v4i32" type="int32" count="4"/> <vector id="v2i64" type="int64" count="2"/> <union id="vec128"> <field name="v4_float" type="v4f"/> <field name="v2_double" type="v2d"/> <field name="v16_int8" type="v16i8"/> <field name="v8_int16" type="v8i16"/> <field name="v4_int32" type="v4i32"/> <field name="v2_int64" type="v2i64"/> <field name="uint128" type="uint128"/> </union> <flags id="i386_mxcsr" size="4"> <field name="IE" start="0" end="0"/> <field name="DE" start="1" end="1"/> <field name="ZE" start="2" end="2"/> <field name="OE" start="3" end="3"/> <field name="UE" start="4" end="4"/> <field name="PE" start="5" end="5"/> <field name="DAZ" start="6" end="6"/> <field name="IM" start="7" end="7"/> <field name="DM" start="8" end="8"/> <field name="ZM" start="9" end="9"/> <field name="OM" start="10" end="10"/> <field name="UM" start="11" end="11"/> <field name="PM" start="12" end="12"/> <field name="FZ" start="15" end="15"/> </flags> <reg name="xmm0" bitsize="128" type="vec128" regnum="40"/> <reg name="xmm1" bitsize="128" type="vec128"/> <reg name="xmm2" bitsize="128" type="vec128"/> <reg name="xmm3" bitsize="128" type="vec128"/> <reg name="xmm4" bitsize="128" type="vec128"/> <reg name="xmm5" bitsize="128" type="vec128"/> <reg name="xmm6" bitsize="128" type="vec128"/> <reg name="xmm7" bitsize="128" type="vec128"/> <reg name="xmm8" bitsize="128" type="vec128"/> <reg name="xmm9" bitsize="128" type="vec128"/> <reg name="xmm10" bitsize="128" type="vec128"/> <reg name="xmm11" bitsize="128" type="vec128"/> <reg name="xmm12" bitsize="128" type="vec128"/> <reg name="xmm13" bitsize="128" type="vec128"/> <reg name="xmm14" bitsize="128" type="vec128"/> <reg name="xmm15" bitsize="128" type="vec128"/> <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/> </feature>""", False return None, False def readRegister(self, regnum): return "" def readRegisters(self): return "0600000000000000c0b7c00080fffffff021c60080ffffff1a00000000000000020000000000000078b7c00080ffffff203f8ca090ffffff103f8ca090ffffff3025990a80ffffff809698000000000070009f0a80ffffff020000000000000000eae10080ffffff00000000000000001822d74f1a00000078b7c00080ffffff0e12410080ffff004602000008000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000" def haltReason(self): return "T02thread:dead;threads:dead;" def qfThreadInfo(self): return "mdead" def qC(self): return "" def qSupported(self, client_supported): return "PacketSize=4000;qXfer:features:read+" def QThreadSuffixSupported(self): return "OK" def QListThreadsInStopReply(self): return "OK" self.server.responder = MyResponder() if self.TraceOn(): self.runCmd("log enable gdb-remote packets") self.addTearDownHook( lambda: self.runCmd("log disable gdb-remote packets")) target = self.dbg.CreateTargetWithFileAndArch(None, None) process = self.connect(target) if self.TraceOn(): interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() interp.HandleCommand("target list", result) print(result.GetOutput()) rip_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("rip") self.assertEqual(rip_valobj.GetValueAsUnsigned(), 0x00ffff800041120e) r15_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("r15") self.assertEqual(r15_valobj.GetValueAsUnsigned(), 0xffffff8000c0b778) mxcsr_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).FindRegister("mxcsr") self.assertEqual(mxcsr_valobj.GetValueAsUnsigned(), 0x00001f80) gpr_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).GetRegisters().GetValueAtIndex(0).GetName() self.assertEqual(gpr_reg_set_name, "general") float_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).GetRegisters().GetValueAtIndex(1).GetName() self.assertEqual(float_reg_set_name, "float") vector_reg_set_name = process.GetThreadAtIndex(0).GetFrameAtIndex( 0).GetRegisters().GetValueAtIndex(2).GetName() self.assertEqual(vector_reg_set_name, "vector") if self.TraceOn(): print("rip is 0x%x" % rip_valobj.GetValueAsUnsigned()) print("r15 is 0x%x" % r15_valobj.GetValueAsUnsigned()) print("mxcsr is 0x%x" % mxcsr_valobj.GetValueAsUnsigned())
def image_lookup_addr(addr): res = lldb.SBCommandReturnObject() lldb.debugger.GetCommandInterpreter().HandleCommand( "image lookup --address 0x%x" % addr, res) return res.GetOutput()
def foo(cmd): ret = lldb.SBCommandReturnObject() self.driver.getCommandInterpreter().HandleCommand(cmd, ret)
def test_get_objc_dynamic_vals(self): """Test fetching ObjC dynamic values.""" if self.getArchitecture() == 'i386': # rdar://problem/9946499 self.skipTest("Dynamic types for ObjC V1 runtime not implemented") self.build() exe = self.getBuildArtifact("a.out") # Create a target from the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Set up our breakpoints: handle_SourceBase_bkpt = target.BreakpointCreateByLocation( self.source_name, self.handle_SourceBase) self.assertTrue( handle_SourceBase_bkpt and handle_SourceBase_bkpt.GetNumLocations() == 1, VALID_BREAKPOINT) main_before_setProperty_bkpt = target.BreakpointCreateByLocation( self.source_name, self.main_before_setProperty_line) self.assertTrue( main_before_setProperty_bkpt and main_before_setProperty_bkpt.GetNumLocations() == 1, VALID_BREAKPOINT) # Now launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) threads = lldbutil.get_threads_stopped_at_breakpoint( process, main_before_setProperty_bkpt) self.assertTrue(len(threads) == 1) thread = threads[0] # # At this point, myObserver has a Source pointer that is actually a KVO swizzled SourceDerived # make sure we can get that properly: frame = thread.GetFrameAtIndex(0) myObserver = frame.FindVariable('myObserver', lldb.eDynamicCanRunTarget) self.assertTrue(myObserver) myObserver_source = myObserver.GetChildMemberWithName( '_source', lldb.eDynamicCanRunTarget) self.examine_SourceDerived_ptr(myObserver_source) # # Make sure a static value can be correctly turned into a dynamic # value. frame = thread.GetFrameAtIndex(0) myObserver_static = frame.FindVariable('myObserver', lldb.eNoDynamicValues) self.assertTrue(myObserver_static) myObserver = myObserver_static.GetDynamicValue( lldb.eDynamicCanRunTarget) myObserver_source = myObserver.GetChildMemberWithName( '_source', lldb.eDynamicCanRunTarget) self.examine_SourceDerived_ptr(myObserver_source) # The "frame var" code uses another path to get into children, so let's # make sure that works as well: result = lldb.SBCommandReturnObject() self.expect('frame var -d run-target myObserver->_source', 'frame var finds its way into a child member', patterns=['\(SourceDerived \*\)']) # check that our ObjC GetISA() does a good job at hiding KVO swizzled # classes self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', substrs=['SourceDerived']) self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching=False, substrs=['NSKVONotify']) # This test is not entirely related to the main thrust of this test case, but since we're here, # try stepping into setProperty, and make sure we get into the version # in Source: thread.StepInto() threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonPlanComplete) self.assertTrue(len(threads) == 1) line_entry = threads[0].GetFrameAtIndex(0).GetLineEntry() self.assertEqual(line_entry.GetLine(), self.set_property_line) self.assertEqual(line_entry.GetFileSpec().GetFilename(), self.source_name) # Okay, back to the main business. Continue to the handle_SourceBase # and make sure we get the correct dynamic value. threads = lldbutil.continue_to_breakpoint(process, handle_SourceBase_bkpt) self.assertTrue(len(threads) == 1) thread = threads[0] frame = thread.GetFrameAtIndex(0) # Get "object" using FindVariable: noDynamic = lldb.eNoDynamicValues useDynamic = lldb.eDynamicCanRunTarget object_static = frame.FindVariable('object', noDynamic) object_dynamic = frame.FindVariable('object', useDynamic) # Delete this object to make sure that this doesn't cause havoc with # the dynamic object that depends on it. del (object_static) self.examine_SourceDerived_ptr(object_dynamic) # Get "this" using FindValue, make sure that works too: object_static = frame.FindValue('object', lldb.eValueTypeVariableArgument, noDynamic) object_dynamic = frame.FindValue('object', lldb.eValueTypeVariableArgument, useDynamic) del (object_static) self.examine_SourceDerived_ptr(object_dynamic) # Get "this" using the EvaluateExpression: object_static = frame.EvaluateExpression('object', noDynamic) object_dynamic = frame.EvaluateExpression('object', useDynamic) del (object_static) self.examine_SourceDerived_ptr(object_dynamic) # Continue again to the handle_SourceBase and make sure we get the correct dynamic value. # This one looks exactly the same, but in fact this is an "un-KVO'ed" version of SourceBase, so # its isa pointer points to SourceBase not NSKVOSourceBase or # whatever... threads = lldbutil.continue_to_breakpoint(process, handle_SourceBase_bkpt) self.assertTrue(len(threads) == 1) thread = threads[0] frame = thread.GetFrameAtIndex(0) # Get "object" using FindVariable: object_static = frame.FindVariable('object', noDynamic) object_dynamic = frame.FindVariable('object', useDynamic) # Delete this object to make sure that this doesn't cause havoc with # the dynamic object that depends on it. del (object_static) self.examine_SourceDerived_ptr(object_dynamic)
def delete_breakpoint(name): res = lldb.SBCommandReturnObject() getTarget().GetDebugger().GetCommandInterpreter().HandleCommand( 'break delete %s' % name, res) if res.Succeeded() != True: print(res.GetError())
def search(debugger, command, result, internal_dict): ''' Finds all subclasses of a class. This class must by dynamic (aka inherit from a NSObject class). Currently doesn't work with NSString or NSNumber (tagged pointer objects). NOTE: This script will leak memory Examples: # Find all UIViews and subclasses of UIViews find UIView # Find all UIStatusBar instances find UIStatusBar # Find all UIViews, ignore subclasses find UIView -e # Find all instances of UIViews (and subclasses) where tag == 5 find UIView -c "[obj tag] == 5" ''' command_args = shlex.split(command) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return if not args: result.SetError('Usage: find NSObjectSubclass\n\nUse \'help find\' for more details') return clean_command = ('').join(args) res = lldb.SBCommandReturnObject() interpreter = debugger.GetCommandInterpreter() if options.module: target = debugger.GetSelectedTarget() module = target.FindModule(lldb.SBFileSpec(options.module)) if not module.IsValid(): result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'".format(options.module)) return options.module = generate_module_search_sections_string(module, target) interpreter.HandleCommand('po (Class)NSClassFromString(@\"{}\")'.format(clean_command), res) if 'nil' in res.GetOutput(): result.SetError('Can\'t find class named "{}". Womp womp...'.format(clean_command)) return objectiveC_class = 'NSClassFromString(@"{}")'.format(clean_command) command_script = get_command_script(objectiveC_class, options) expr_options = lldb.SBExpressionOptions() expr_options.SetIgnoreBreakpoints(True); expr_options.SetFetchDynamicValue(lldb.eNoDynamicValues); expr_options.SetTimeoutInMicroSeconds (30*1000*1000) # 30 second timeout expr_options.SetTryAllThreads (True) expr_options.SetUnwindOnError(True) expr_options.SetGenerateDebugInfo(True) expr_options.SetLanguage (lldb.eLanguageTypeObjC_plus_plus) expr_options.SetCoerceResultToId(True) # expr_options.SetAutoApplyFixIts(True) frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() if frame is None: result.SetError('You must have the process suspended in order to execute this command') return # debugger.HandleCommand('po ' + command_script) # debugger.HandleCommand('expression -lobjc++ -g -O -- ' + command_script) expr_sbvalue = frame.EvaluateExpression (command_script, expr_options) count = expr_sbvalue.GetNumChildren() # Actually goes up to 2^32 but this is more than enough if not expr_sbvalue.error.success: result.SetError("\n***************************************\nerror: " + str(expr_sbvalue.error)) else: if count > 1000: result.AppendWarning('Exceeded 1000 hits, try narrowing your search with the --condition option') result.AppendMessage (expr_sbvalue) else: if options.barebones: for val in expr_sbvalue: val_description = str(val.GetTypeName()) + ' [' + str(val.GetValue()) + ']' result.AppendMessage(val_description) else: result.AppendMessage(expr_sbvalue.description)
def dump_memory(addr, size): res = lldb.SBCommandReturnObject() interpreter = getTarget().GetDebugger().GetCommandInterpreter() interpreter.HandleCommand('memory read %d -c %d' % (addr, size), res) return res.GetOutput()
def call_function(self): """Test calling function that hits a signal and restarts.""" exe_name = "a.out" exe = os.path.join(os.getcwd(), exe_name) target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) empty = lldb.SBFileSpec() breakpoint = target.BreakpointCreateBySourceRegex('Stop here in main.',self.main_source_spec) self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. process = target.LaunchSimple (None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) # Frame #0 should be at our breakpoint. threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) self.assertTrue(len(threads) == 1) self.thread = threads[0] # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 0", return_obj) self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop") # The sigchld_no variable should be 0 at this point. self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no") self.assertTrue (self.sigchld_no.IsValid(), "Got a value for sigchld_no") self.start_sigchld_no = self.sigchld_no.GetValueAsSigned (-1) self.assertTrue (self.start_sigchld_no != -1, "Got an actual value for sigchld_no") options = lldb.SBExpressionOptions() options.SetUnwindOnError(True) frame = self.thread.GetFrameAtIndex(0) # Store away the PC to check that the functions unwind to the right place after calls self.orig_frame_pc = frame.GetPC() num_sigchld = 30 value = frame.EvaluateExpression ("call_me (%d)"%(num_sigchld), options) self.assertTrue (value.IsValid()) self.assertTrue (value.GetError().Success() == True) self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now try with a breakpoint in the called code in the case where # we are ignoring breakpoint hits. handler_bkpt = target.BreakpointCreateBySourceRegex("Got sigchld %d.", self.main_source_spec) self.assertTrue (handler_bkpt.GetNumLocations() > 0) options.SetIgnoreBreakpoints(True) options.SetUnwindOnError(True) value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options) self.assertTrue (value.IsValid() and value.GetError().Success() == True) self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set the signal to print but not stop and make sure that calling still works: self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop, notify") value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options) self.assertTrue (value.IsValid() and value.GetError().Success() == True) self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set this unwind on error to false, and make sure that we still complete the call: options.SetUnwindOnError(False) value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options) self.assertTrue (value.IsValid() and value.GetError().Success() == True) self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now set UnwindOnError to true, and then make the signal behavior to stop # and see that now we do stop at the signal point: self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 1 -p 1 -n 1", return_obj) self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, stop, notify") value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options) self.assertTrue (value.IsValid() and value.GetError().Success() == False) # Set signal handling back to no-stop, and continue and we should end up back in out starting frame: self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop, notify") error = process.Continue() self.assertTrue (error.Success(), "Continuing after stopping for signal succeeds.") frame = self.thread.GetFrameAtIndex(0) self.assertTrue (frame.GetPC() == self.orig_frame_pc, "Continuing returned to the place we started.")
def test(self): """Test calling std::String member function.""" self.build() exe_name = "a.out" exe = os.path.join(os.getcwd(), exe_name) target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) breakpoint = target.BreakpointCreateBySourceRegex( 'stop here in main.', self.main_source_spec) self.assertTrue(breakpoint, VALID_BREAKPOINT) self.runCmd("breakpoint list") # Launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) # Frame #0 should be on self.step_out_of_malloc. threads = lldbutil.get_threads_stopped_at_breakpoint( process, breakpoint) self.assertTrue(len(threads) == 1) thread = threads[0] # First set the timeout too short, and make sure we fail. options = lldb.SBExpressionOptions() options.SetTimeoutInMicroSeconds(10) options.SetUnwindOnError(True) frame = thread.GetFrameAtIndex(0) value = frame.EvaluateExpression("wait_a_while (50000)", options) self.assertTrue(value.IsValid()) self.assertFalse(value.GetError().Success()) # Now do the same thing with the command line command, and make sure it works too. interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() return_value = interp.HandleCommand( "expr -t 100 -u true -- wait_a_while(50000)", result) self.assertTrue(return_value == lldb.eReturnStatusFailed) # Okay, now do it again with long enough time outs: options.SetTimeoutInMicroSeconds(1000000) value = frame.EvaluateExpression("wait_a_while (1000)", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success() == True) # Now do the same thingwith the command line command, and make sure it works too. interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() return_value = interp.HandleCommand( "expr -t 1000000 -u true -- wait_a_while(1000)", result) self.assertTrue(return_value == lldb.eReturnStatusSuccessFinishResult) # Finally set the one thread timeout and make sure that doesn't change things much: options.SetTimeoutInMicroSeconds(1000000) options.SetOneThreadTimeoutInMicroSeconds(500000) value = frame.EvaluateExpression("wait_a_while (1000)", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success() == True)