1""" 2Test that we read the function starts section. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11exe_name = "StripMe" # Must match Makefile 12 13 14class FunctionStartsTestCase(TestBase): 15 NO_DEBUG_INFO_TESTCASE = True 16 17 @skipIfRemote 18 @skipUnlessDarwin 19 @skipIf(compiler="clang", compiler_version=["<", "13.0"]) 20 def test_function_starts_binary(self): 21 """Test that we make synthetic symbols when we have the binary.""" 22 self.build(dictionary={"CODESIGN": ""}) # Binary is getting stripped later. 23 self.do_function_starts(False) 24 25 @skipIfRemote 26 @skipUnlessDarwin 27 @skipIf(compiler="clang", compiler_version=["<", "13.0"]) 28 def test_function_starts_no_binary(self): 29 """Test that we make synthetic symbols when we don't have the binary""" 30 self.build(dictionary={"CODESIGN": ""}) # Binary is getting stripped later. 31 self.do_function_starts(True) 32 33 def do_function_starts(self, in_memory): 34 """Run the binary, stop at our unstripped function, 35 make sure the caller has synthetic symbols""" 36 37 exe = os.path.realpath(self.getBuildArtifact(exe_name)) 38 # Now strip the binary, but leave externals so we can break on dont_strip_me. 39 self.runBuildCommand(["strip", "-u", "-x", "-S", exe]) 40 41 # Use a file as a synchronization point between test and inferior. 42 pid_file_path = lldbutil.append_to_process_working_directory( 43 self, "token_pid_%d" % (int(os.getpid())) 44 ) 45 self.addTearDownHook( 46 lambda: self.run_platform_command("rm %s" % (pid_file_path)) 47 ) 48 49 popen = self.spawnSubprocess(exe, [pid_file_path]) 50 51 # Wait until process has fully started up. 52 pid = lldbutil.wait_for_file_on_target(self, pid_file_path) 53 54 if in_memory: 55 remove_file(exe) 56 57 target = self.dbg.CreateTarget(None) 58 self.assertTrue(target.IsValid(), "Got a vaid empty target.") 59 error = lldb.SBError() 60 attach_info = lldb.SBAttachInfo() 61 attach_info.SetProcessID(popen.pid) 62 attach_info.SetIgnoreExisting(False) 63 process = target.Attach(attach_info, error) 64 self.assertSuccess(error, "Didn't attach successfully to %d" % (popen.pid)) 65 66 bkpt = target.BreakpointCreateByName("dont_strip_me", exe) 67 self.assertGreater( 68 bkpt.GetNumLocations(), 0, "Didn't set the dont_strip_me bkpt." 69 ) 70 71 threads = lldbutil.continue_to_breakpoint(process, bkpt) 72 self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.") 73 74 # Our caller frame should have been stripped. Make sure we made a synthetic symbol 75 # for it: 76 thread = threads[0] 77 self.assertGreater(thread.num_frames, 1, "Couldn't backtrace.") 78 name = thread.frame[1].GetFunctionName() 79 self.assertTrue(name.startswith("___lldb_unnamed_symbol")) 80