This test requires compiling its input program without debug information. To do so, it uses certain Makefile variables that are never populated with custom libcxx paths (if present). Doing so would not necessarily be correct: we cannot guarantee that said standard library has no debug symbols. As such, we keep using the system libraries but disable the tests in clang versions that are too old to work with more modern system libraries, as in the case of the lldb-matrix bot. Differential Revision: https://reviews.llvm.org/D136178
82 lines
2.9 KiB
Python
82 lines
2.9 KiB
Python
"""
|
|
Test that we read the function starts section.
|
|
"""
|
|
|
|
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
exe_name = "StripMe" # Must match Makefile
|
|
|
|
class FunctionStartsTestCase(TestBase):
|
|
|
|
NO_DEBUG_INFO_TESTCASE = True
|
|
|
|
@skipIfRemote
|
|
@skipUnlessDarwin
|
|
@skipIf(compiler="clang", compiler_version=['<', '13.0'])
|
|
def test_function_starts_binary(self):
|
|
"""Test that we make synthetic symbols when we have the binary."""
|
|
self.build(dictionary={'CODESIGN': ''}) # Binary is getting stripped later.
|
|
self.do_function_starts(False)
|
|
|
|
@skipIfRemote
|
|
@skipUnlessDarwin
|
|
@skipIf(compiler="clang", compiler_version=['<', '13.0'])
|
|
def test_function_starts_no_binary(self):
|
|
"""Test that we make synthetic symbols when we don't have the binary"""
|
|
self.build(dictionary={'CODESIGN': ''}) # Binary is getting stripped later.
|
|
self.do_function_starts(True)
|
|
|
|
def do_function_starts(self, in_memory):
|
|
"""Run the binary, stop at our unstripped function,
|
|
make sure the caller has synthetic symbols"""
|
|
|
|
exe = os.path.realpath(self.getBuildArtifact(exe_name))
|
|
# Now strip the binary, but leave externals so we can break on dont_strip_me.
|
|
self.runBuildCommand(["strip", "-u", "-x", "-S", exe])
|
|
|
|
# Use a file as a synchronization point between test and inferior.
|
|
pid_file_path = lldbutil.append_to_process_working_directory(self,
|
|
"token_pid_%d" % (int(os.getpid())))
|
|
self.addTearDownHook(
|
|
lambda: self.run_platform_command(
|
|
"rm %s" %
|
|
(pid_file_path)))
|
|
|
|
popen = self.spawnSubprocess(exe, [pid_file_path])
|
|
|
|
# Wait until process has fully started up.
|
|
pid = lldbutil.wait_for_file_on_target(self, pid_file_path)
|
|
|
|
if in_memory:
|
|
remove_file(exe)
|
|
|
|
target = self.dbg.CreateTarget(None)
|
|
self.assertTrue(target.IsValid(), "Got a vaid empty target.")
|
|
error = lldb.SBError()
|
|
attach_info = lldb.SBAttachInfo()
|
|
attach_info.SetProcessID(popen.pid)
|
|
attach_info.SetIgnoreExisting(False)
|
|
process = target.Attach(attach_info, error)
|
|
self.assertSuccess(error, "Didn't attach successfully to %d"%(popen.pid))
|
|
|
|
bkpt = target.BreakpointCreateByName("dont_strip_me", exe)
|
|
self.assertTrue(bkpt.GetNumLocations() > 0, "Didn't set the dont_strip_me bkpt.")
|
|
|
|
threads = lldbutil.continue_to_breakpoint(process, bkpt)
|
|
self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.")
|
|
|
|
# Our caller frame should have been stripped. Make sure we made a synthetic symbol
|
|
# for it:
|
|
thread = threads[0]
|
|
self.assertTrue(thread.num_frames > 1, "Couldn't backtrace.")
|
|
name = thread.frame[1].GetFunctionName()
|
|
self.assertTrue(name.startswith("___lldb_unnamed_symbol"))
|
|
|
|
|
|
|