def __init__(self, target: lldb.SBTarget, args: lldb.SBStructuredData): super().__init__(target, args) self.backing_target_idx = args.GetValueForKey("backing_target_idx") self.corefile_target = None self.corefile_process = None if (self.backing_target_idx and self.backing_target_idx.IsValid()): if self.backing_target_idx.GetType( ) == lldb.eStructuredDataTypeInteger: idx = self.backing_target_idx.GetIntegerValue(42) if self.backing_target_idx.GetType( ) == lldb.eStructuredDataTypeString: idx = int(self.backing_target_idx.GetStringValue(100)) self.corefile_target = target.GetDebugger().GetTargetAtIndex(idx) self.corefile_process = self.corefile_target.GetProcess() for corefile_thread in self.corefile_process: structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( json.dumps({ "backing_target_idx": idx, "thread_idx": corefile_thread.GetIndexID() })) self.threads[ corefile_thread.GetThreadID()] = StackCoreScriptedThread( self, structured_data)
def array_struct_test(self, dict_struct): # Check API returning a valid SBStructuredData of 'array' type array_struct = lldb.SBStructuredData() array_struct = dict_struct.GetValueForKey("key_array") if not array_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not array_struct.GetType() == lldb.eStructuredDataTypeArray: self.fail("Wrong type returned: " + str(array_struct.GetType())) # Check Size API for 'array' type if not array_struct.GetSize() == 2: self.fail("Wrong no of elements returned: " + str(array_struct.GetSize())) # Check API returning a valid SBStructuredData for different 'array' # indices string_struct = array_struct.GetItemAtIndex(0) if not string_struct.IsValid(): self.fail("A valid object should have been returned") if not string_struct.GetType() == lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) if not output == "23": self.fail("wrong output: " + str(output)) string_struct = array_struct.GetItemAtIndex(1) if not string_struct.IsValid(): self.fail("A valid object should have been returned") if not string_struct.GetType() == lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) if not output == "arr": self.fail("wrong output: " + str(output))
def do_bad_args_to_python_command(self): error = lldb.SBError() self.target = self.createTestTarget() self.expect("command script import --allow-reload ./bktptcmd.py") bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(bkpt, VALID_BREAKPOINT) # Pass a breakpoint command function that doesn't take extra_args, # but pass it extra args: extra_args = lldb.SBStructuredData() stream = lldb.SBStream() stream.Print('{"side_effect" : "I am fancy"}') extra_args.SetFromJSON(stream) error = bkpt.SetScriptCallbackFunction("bktptcmd.function", extra_args) self.assertTrue( error.Fail(), "Can't pass extra args if the function doesn't take them") error = bkpt.SetScriptCallbackFunction("bktptcmd.useless_function", extra_args) self.assertTrue( error.Fail(), "Can't pass extra args if the function has wrong number of args.") error = bkpt.SetScriptCallbackFunction("bktptcmd.nosuch_function", extra_args) self.assertTrue( error.Fail(), "Can't pass extra args if the function doesn't exist.")
def make_extra_args(self): json_string = '{"symbol":"break_on_me", "test1": "value1"}' json_stream = lldb.SBStream() json_stream.Print(json_string) extra_args = lldb.SBStructuredData() error = extra_args.SetFromJSON(json_stream) self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) return extra_args
def test_launch_scripted_process_stack_frames(self): """Test that we can launch an lldb scripted process from the command line, check its process ID and read string from memory.""" self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) for module in target.modules: if 'a.out' in module.GetFileSpec().GetFilename(): main_module = module break self.assertTrue(main_module, "Invalid main module.") error = target.SetModuleLoadAddress(main_module, 0) self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' def cleanup(): del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] self.addTearDownHook(cleanup) scripted_process_example_relpath = 'stack_core_scripted_process.py' self.runCmd("command script import " + os.path.join(self.getSourceDir(), scripted_process_example_relpath)) corefile_process = None with tempfile.NamedTemporaryFile() as file: self.create_stack_skinny_corefile(file.name) corefile_target = self.dbg.CreateTarget(None) corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name)) self.assertTrue(corefile_process, PROCESS_IS_VALID) structured_data = lldb.SBStructuredData() structured_data.SetFromJSON(json.dumps({ "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) })) launch_info = lldb.SBLaunchInfo(None) launch_info.SetProcessPluginName("ScriptedProcess") launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess") launch_info.SetScriptedProcessDictionary(structured_data) error = lldb.SBError() process = target.Launch(launch_info, error) self.assertTrue(error.Success(), error.GetCString()) self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 42) self.assertEqual(process.GetNumThreads(), 1) thread = process.GetSelectedThread() self.assertTrue(thread, "Invalid thread.") self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1") self.assertEqual(thread.GetNumFrames(), 3) frame = thread.GetSelectedFrame() self.assertTrue(frame, "Invalid frame.") self.assertEqual(frame.GetFunctionName(), "bar") self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
def invalid_struct_test(self, example): invalid_struct = lldb.SBStructuredData() invalid_struct = example.GetValueForKey("invalid_key") if invalid_struct.IsValid(): self.fail("An invalid object should have been returned") # Check Type API if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid: self.fail("Wrong type returned: " + str(invalid_struct.GetType()))
def structured_data_api_test(self): error = lldb.SBError() s = lldb.SBStream() s.Print( "{\"key_dict\":{\"key_string\":\"STRING\",\"key_int\":3,\"key_float\":2.99,\"key_bool\":true,\"key_array\":[\"23\",\"arr\"]}}" ) example = lldb.SBStructuredData() # Check SetFromJSON API for dictionaries, integers, floating point # values, strings and arrays error = example.SetFromJSON(s) if not error.Success(): self.fail("FAILED: " + error.GetCString()) # Tests for invalid data type self.invalid_struct_test(example) # Test that GetDescription works: s.Clear() error = example.GetDescription(s) self.assertTrue(error.Success(), "GetDescription works") if not "key_float" in s.GetData(): self.fail("FAILED: could not find key_float in description output") dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") # Tests for dictionary data type self.dictionary_struct_test(example) # Tests for string data type self.string_struct_test(dict_struct) # Tests for integer data type self.int_struct_test(dict_struct) # Tests for floating point data type self.double_struct_test(dict_struct) # Tests for boolean data type self.bool_struct_test(dict_struct) # Tests for array data type self.array_struct_test(dict_struct)
def bool_struct_test(self, dict_struct): bool_struct = lldb.SBStructuredData() bool_struct = dict_struct.GetValueForKey("key_bool") if not bool_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean: self.fail("Wrong type returned: " + str(bool_struct.GetType())) # Check API returning 'bool' value output = bool_struct.GetBooleanValue() if not output: self.fail("wrong output: " + str(output))
def double_struct_test(self, dict_struct): floating_point_struct = lldb.SBStructuredData() floating_point_struct = dict_struct.GetValueForKey("key_float") if not floating_point_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat: self.fail("Wrong type returned: " + str(floating_point_struct.GetType())) # Check API returning 'double' value output = floating_point_struct.GetFloatValue() if not output == 2.99: self.fail("wrong output: " + str(output))
def dictionary_struct_test(self, example): # Check API returning a valid SBStructuredData of 'dictionary' type dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") if not dict_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary: self.fail("Wrong type returned: " + str(dict_struct.GetType())) # Check Size API for 'dictionary' type if not dict_struct.GetSize() == 5: self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize()))
def __init__(self, target: lldb.SBTarget, args: lldb.SBStructuredData): super().__init__(target, args) self.corefile_target = None self.corefile_process = None self.backing_target_idx = args.GetValueForKey("backing_target_idx") if (self.backing_target_idx and self.backing_target_idx.IsValid()): if self.backing_target_idx.GetType( ) == lldb.eStructuredDataTypeInteger: idx = self.backing_target_idx.GetIntegerValue(42) if self.backing_target_idx.GetType( ) == lldb.eStructuredDataTypeString: idx = int(self.backing_target_idx.GetStringValue(100)) self.corefile_target = target.GetDebugger().GetTargetAtIndex(idx) self.corefile_process = self.corefile_target.GetProcess() for corefile_thread in self.corefile_process: structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( json.dumps({ "backing_target_idx": idx, "thread_idx": corefile_thread.GetIndexID() })) self.threads[ corefile_thread.GetThreadID()] = StackCoreScriptedThread( self, structured_data) if len(self.threads) == 2: self.threads[len(self.threads) - 1].is_stopped = True corefile_module = self.get_module_with_name(self.corefile_target, "libbaz.dylib") if not corefile_module or not corefile_module.IsValid(): return module_path = os.path.join( corefile_module.GetFileSpec().GetDirectory(), corefile_module.GetFileSpec().GetFilename()) if not os.path.exists(module_path): return module_load_addr = corefile_module.GetObjectFileHeaderAddress( ).GetLoadAddress(self.corefile_target) self.loaded_images.append({ "path": module_path, "load_addr": module_load_addr })
def load_crashlog_in_scripted_process(debugger, crash_log_file): result = lldb.SBCommandReturnObject() crashlog_path = os.path.expanduser(crash_log_file) if not os.path.exists(crashlog_path): result.PutCString("error: crashlog file %s does not exist" % crashlog_path) try: crashlog = CrashLogParser().parse(debugger, crashlog_path, False) except Exception as e: result.PutCString("error: python exception: %s" % e) return if debugger.GetNumTargets() > 0: target = debugger.GetTargetAtIndex(0) else: target = crashlog.create_target() if not target: result.PutCString("error: couldn't create target") return ci = debugger.GetCommandInterpreter() if not ci: result.PutCString("error: couldn't get command interpreter") return res = lldb.SBCommandReturnObject() ci.HandleCommand( 'script from lldb.macosx import crashlog_scripted_process', res) if not res.Succeeded(): result.PutCString( "error: couldn't import crashlog scripted process module") return structured_data = lldb.SBStructuredData() structured_data.SetFromJSON(json.dumps({"crashlog_path": crashlog_path})) launch_info = lldb.SBLaunchInfo(None) launch_info.SetProcessPluginName("ScriptedProcess") launch_info.SetScriptedProcessClassName( "crashlog_scripted_process.CrashLogScriptedProcess") launch_info.SetScriptedProcessDictionary(structured_data) error = lldb.SBError() process = target.Launch(launch_info, error)
def string_struct_test(self, dict_struct): string_struct = lldb.SBStructuredData() string_struct = dict_struct.GetValueForKey("key_string") if not string_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not string_struct.GetType() == lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) # Check API returning 'string' value output = string_struct.GetStringValue(25) if not "STRING" in output: self.fail("wrong output: " + output) # Calling wrong API on a SBStructuredData # (e.g. getting an integer from a string type structure) output = string_struct.GetIntegerValue() if output: self.fail("Valid integer value " + str(output) + " returned for a string object")
def do_test_checking_variable(self, use_cli): self.build() (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) frame = thread.GetFrameAtIndex(0) self.assertEqual("foo", frame.GetFunctionName()) foo_val = frame.FindVariable("foo") self.assertTrue(foo_val.GetError().Success(), "Got the foo variable") self.assertEqual(foo_val.GetValueAsUnsigned(), 10, "foo starts at 10") if use_cli: result = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "thread step-scripted -C Steps.StepUntil -k variable_name -v foo", result) self.assertTrue(result.Succeeded()) else: args_data = lldb.SBStructuredData() data = lldb.SBStream() data.Print('{"variable_name" : "foo"}') error = args_data.SetFromJSON(data) self.assertTrue(error.Success(), "Made the args_data correctly") err = thread.StepUsingScriptedThreadPlan("Steps.StepUntil", args_data, True) self.assertTrue(err.Success(), err.GetCString()) # We should not have exited: self.assertEqual(process.GetState(), lldb.eStateStopped, "We are stopped") # We should still be in foo: self.assertEqual("foo", frame.GetFunctionName()) # And foo should have changed: self.assertTrue(foo_val.GetValueDidChange(), "Foo changed")
def int_struct_test(self, dict_struct): # Check a valid SBStructuredData containing an 'integer' by int_struct = lldb.SBStructuredData() int_struct = dict_struct.GetValueForKey("key_int") if not int_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if not int_struct.GetType() == lldb.eStructuredDataTypeInteger: self.fail("Wrong type returned: " + str(int_struct.GetType())) # Check API returning 'integer' value output = int_struct.GetIntegerValue() if not output == 3: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData # (e.g. getting a string value from an integer type structure) output = int_struct.GetStringValue(25) if output: self.fail("Valid string " + output + " returned for an integer object")
def test_launch_scripted_process_stack_frames(self): """Test that we can launch an lldb scripted process from the command line, check its process ID and read string from memory.""" self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) for module in target.modules: if 'a.out' in module.GetFileSpec().GetFilename(): main_module = module break self.assertTrue(main_module, "Invalid main module.") error = target.SetModuleLoadAddress(main_module, 0) self.assertSuccess(error, "Reloading main module at offset 0 failed.") os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' def cleanup(): del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"] self.addTearDownHook(cleanup) scripted_process_example_relpath = 'stack_core_scripted_process.py' self.runCmd("command script import " + os.path.join( self.getSourceDir(), scripted_process_example_relpath)) corefile_process = None with tempfile.NamedTemporaryFile() as file: self.create_stack_skinny_corefile(file.name) corefile_target = self.dbg.CreateTarget(None) corefile_process = corefile_target.LoadCore( self.getBuildArtifact(file.name)) self.assertTrue(corefile_process, PROCESS_IS_VALID) structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( json.dumps({ "backing_target_idx": self.dbg.GetIndexOfTarget(corefile_process.GetTarget()) })) launch_info = lldb.SBLaunchInfo(None) launch_info.SetProcessPluginName("ScriptedProcess") launch_info.SetScriptedProcessClassName( "stack_core_scripted_process.StackCoreScriptedProcess") launch_info.SetScriptedProcessDictionary(structured_data) error = lldb.SBError() process = target.Launch(launch_info, error) self.assertSuccess(error) self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 42) self.assertEqual(process.GetNumThreads(), 3) thread = process.GetSelectedThread() self.assertTrue(thread, "Invalid thread.") self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-2") self.assertTrue(target.triple, "Invalid target triple") arch = target.triple.split('-')[0] supported_arch = ['x86_64', 'arm64', 'arm64e'] self.assertIn(arch, supported_arch) # When creating a corefile of a arm process, lldb saves the exception # that triggers the breakpoint in the LC_NOTES of the corefile, so they # can be reloaded with the corefile on the next debug session. if arch in 'arm64e': self.assertTrue(thread.GetStopReason(), lldb.eStopReasonException) # However, it's architecture specific, and corefiles made from intel # process don't save any metadata to retrieve to stop reason. # To mitigate this, the StackCoreScriptedProcess will report a # eStopReasonSignal with a SIGTRAP, mimicking what debugserver does. else: self.assertTrue(thread.GetStopReason(), lldb.eStopReasonSignal) self.assertEqual(thread.GetNumFrames(), 6) frame = thread.GetSelectedFrame() self.assertTrue(frame, "Invalid frame.") self.assertIn("bar", frame.GetFunctionName()) self.assertEqual( int( frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) self.assertEqual( int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
def do_set_python_command_from_python(self): exe = self.getBuildArtifact("a.out") error = lldb.SBError() self.target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) body_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(body_bkpt, VALID_BREAKPOINT) func_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(func_bkpt, VALID_BREAKPOINT) fancy_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(fancy_bkpt, VALID_BREAKPOINT) fancier_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(fancier_bkpt, VALID_BREAKPOINT) not_so_fancy_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(not_so_fancy_bkpt, VALID_BREAKPOINT) # Also test that setting a source regex breakpoint with an empty file # spec list sets it on all files: no_files_bkpt = self.target.BreakpointCreateBySourceRegex( "Set a breakpoint here", lldb.SBFileSpecList(), lldb.SBFileSpecList()) self.assertTrue(no_files_bkpt, VALID_BREAKPOINT) num_locations = no_files_bkpt.GetNumLocations() self.assertTrue(num_locations >= 2, "Got at least two breakpoint locations") got_one_in_A = False got_one_in_B = False for idx in range(0, num_locations): comp_unit = no_files_bkpt.GetLocationAtIndex(idx).GetAddress( ).GetSymbolContext( lldb.eSymbolContextCompUnit).GetCompileUnit().GetFileSpec() print("Got comp unit: ", comp_unit.GetFilename()) if comp_unit.GetFilename() == "a.c": got_one_in_A = True elif comp_unit.GetFilename() == "b.c": got_one_in_B = True self.assertTrue(got_one_in_A, "Failed to match the pattern in A") self.assertTrue(got_one_in_B, "Failed to match the pattern in B") self.target.BreakpointDelete(no_files_bkpt.GetID()) error = lldb.SBError() error = body_bkpt.SetScriptCallbackBody( "import side_effect; side_effect.callback = 'callback was here'") self.assertTrue( error.Success(), "Failed to set the script callback body: %s." % (error.GetCString())) self.expect("command script import --allow-reload ./bktptcmd.py") func_bkpt.SetScriptCallbackFunction("bktptcmd.function") extra_args = lldb.SBStructuredData() stream = lldb.SBStream() stream.Print('{"side_effect" : "I am fancy"}') extra_args.SetFromJSON(stream) error = fancy_bkpt.SetScriptCallbackFunction( "bktptcmd.another_function", extra_args) self.assertTrue(error.Success(), "Failed to add callback %s" % (error.GetCString())) stream.Clear() stream.Print('{"side_effect" : "I am so much fancier"}') extra_args.SetFromJSON(stream) # Fancier's callback is set up from the command line id = fancier_bkpt.GetID() self.expect( "breakpoint command add -F bktptcmd.a_third_function -k side_effect -v 'I am fancier' %d" % (id)) # Not so fancy gets an empty extra_args: empty_args = lldb.SBStructuredData() error = not_so_fancy_bkpt.SetScriptCallbackFunction( "bktptcmd.empty_extra_args", empty_args) self.assertTrue(error.Success(), "Failed to add callback %s" % (error.GetCString())) # Clear out canary variables side_effect.bktptcmd = None side_effect.callback = None side_effect.fancy = None side_effect.fancier = None side_effect.not_so_fancy = None # Now launch the process, and do not stop at entry point. self.process = self.target.LaunchSimple( None, None, self.get_process_working_directory()) self.assertTrue(self.process, PROCESS_IS_VALID) # Now finish, and make sure the return value is correct. threads = lldbutil.get_threads_stopped_at_breakpoint( self.process, body_bkpt) self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.") self.thread = threads[0] self.assertEquals("callback was here", side_effect.callback) self.assertEquals("function was here", side_effect.bktptcmd) self.assertEquals("I am fancy", side_effect.fancy) self.assertEquals("I am fancier", side_effect.fancier) self.assertEquals("Not so fancy", side_effect.not_so_fancy)
def do_check_extra_args(self): import side_effect interp = self.dbg.GetCommandInterpreter() error = lldb.SBError() script_name = os.path.join(self.getSourceDir(), "resolver.py") command = "command script import " + script_name result = lldb.SBCommandReturnObject() interp.HandleCommand(command, result) self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) # First make sure a scripted breakpoint with no args works: bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", lldb.SBStructuredData(), lldb.SBFileSpecList(), lldb.SBFileSpecList()) self.assertTrue(bkpt.IsValid(), "Bkpt is valid") write_bps = lldb.SBBreakpointList(self.orig_target) error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) self.assertSuccess(error, "Failed writing breakpoints") side_effect.g_extra_args = None copy_bps = lldb.SBBreakpointList(self.copy_target) error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) self.assertSuccess(error, "Failed reading breakpoints") self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") no_keys = lldb.SBStringList() side_effect.g_extra_args.GetKeys(no_keys) self.assertEqual(no_keys.GetSize(), 0, "Should have no keys") self.orig_target.DeleteAllBreakpoints() self.copy_target.DeleteAllBreakpoints() # Now try one with extra args: extra_args = lldb.SBStructuredData() stream = lldb.SBStream() stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}') extra_args.SetFromJSON(stream) self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.") bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", extra_args, lldb.SBFileSpecList(), lldb.SBFileSpecList()) self.assertTrue(bkpt.IsValid(), "Bkpt is valid") write_bps = lldb.SBBreakpointList(self.orig_target) error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) self.assertSuccess(error, "Failed writing breakpoints") orig_extra_args = side_effect.g_extra_args self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid") orig_keys = lldb.SBStringList() orig_extra_args.GetKeys(orig_keys) self.assertEqual(2, orig_keys.GetSize(), "Should have two keys") side_effect.g_extra_args = None copy_bps = lldb.SBBreakpointList(self.copy_target) error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) self.assertSuccess(error, "Failed reading breakpoints") self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") copy_extra_args = side_effect.g_extra_args copy_keys = lldb.SBStringList() copy_extra_args.GetKeys(copy_keys) self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys") for idx in range(0, orig_keys.GetSize()): key = orig_keys.GetStringAtIndex(idx) copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100) if key == "first_arg": self.assertEqual(copy_value, "first_value") elif key == "second_arg": self.assertEqual(copy_value, "second_value") else: self.Fail("Unknown key: %s"%(key))