"""
Test lldb breakpoint with symlinks/realpath and source-map.
"""
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil, lldbplatformutil
class BreakpointTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number to break inside main().
self.line_in_main = line_number("main.c", "// Set break point at this line.")
self.line_in_foo = line_number("real/foo.h", "// Set break point at this line.")
self.line_in_bar = line_number("real/bar.h", "// Set break point at this line.")
self.line_in_qux = line_number("real/qux.h", "// Set break point at this line.")
# disable "There is a running process, kill it and restart?" prompt
self.runCmd("settings set auto-confirm true")
self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
def buildAndCreateTarget(self):
self.build()
exe = self.getBuildArtifact("a.out")
# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
@skipIf(oslist=["windows"])
@skipIf(hostoslist=["windows"])
def test_file_line_breakpoint_realpath_and_source_map(self):
"""Test file/line breakpoint with realpathing and source-mapping."""
self.buildAndCreateTarget()
cwd = os.getcwd()
######################################################################
# Baseline
# --------------------------------------------------------------------
# Breakpoints should be resolved with paths which are in the line-table.
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line_in_main, num_expected_locations=1, loc_exact=True
)
lldbutil.run_break_set_by_file_and_line(
self,
"symlink1/foo.h",
self.line_in_foo,
num_expected_locations=1,
loc_exact=True,
)
lldbutil.run_break_set_by_file_and_line(
self,
"symlink2/bar.h",
self.line_in_bar,
num_expected_locations=1,
loc_exact=True,
)
lldbutil.run_break_set_by_file_and_line(
self,
"symlink2/qux.h",
self.line_in_qux,
num_expected_locations=1,
loc_exact=True,
)
######################################################################
# Symlinked file
# --------------------------------------------------------------------
# - `symlink1/foo.h` is a symlink file, pointing at `real/foo.h`
# - main.c includes `symlink1/foo.h`.
# - As a result, the line-table contains a support file `(test_base_dir)/symlink1/foo.h`
# - Setting a breakpoint for `real/foo.h` won't be resolved, because it doesn't match the above path.
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/foo.h`
# - Now setting a breakpoint for `real/foo.h` will be resolved.
lldbutil.run_break_set_by_file_and_line(
self,
"real/foo.h",
self.line_in_foo,
num_expected_locations=0,
loc_exact=True,
)
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
lldbutil.run_break_set_by_file_and_line(
self,
"real/foo.h",
self.line_in_foo,
num_expected_locations=1,
loc_exact=True,
)
# Clear settings so that the test below won't be affected.
self.runCmd("settings clear target.source-realpath-prefixes")
######################################################################
# Symlinked directory
# --------------------------------------------------------------------
# - `symlink2` is a symlink directory, pointing at `real`.
# - So, `symlink2/bar.h` will be realpath'ed to `real/bar.h`.
# - main.c includes `symlink2/bar.h`.
# - As a result, the line-table contains a support file `(test_base_dir)/symlink2/bar.h`
# - Setting a breakpoint for `real/bar.h` won't be resolved, because it doesn't match the above path.
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/bar.h`
# - Now setting a breakpoint for `real/bar.h` will be resolved.
lldbutil.run_break_set_by_file_and_line(
self,
"real/bar.h",
self.line_in_foo,
num_expected_locations=0,
loc_exact=True,
)
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
lldbutil.run_break_set_by_file_and_line(
self,
"real/bar.h",
self.line_in_foo,
num_expected_locations=1,
loc_exact=True,
)
# Clear settings so that the test below won't be affected.
self.runCmd("settings clear target.source-realpath-prefixes")
######################################################################
# Symlink + source-map
# --------------------------------------------------------------------
# - `symlink2` is a symlink directory, pointing at `real`.
# - So, `symlink2/qux.h` will be realpath'ed to `real/qux.h`.
# - main.c includes `symlink2/qux.h`.
# - As a result, the line-table contains a support file `(test_base_dir)/symlink2/qux.h`
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/qux.h`
# - Setting a breakpoint for `to-be-mapped/qux.h` won't be resolved, because it doesn't match the above path.
# - After setting a source-map, setting the same breakpoint will be resolved, because the input path `to-be-mapped/qux.h` is reverse-mapped to `real/qux.h`, which matches the realpath'ed support file.
lldbutil.run_break_set_by_file_and_line(
self,
"real/qux.h",
self.line_in_foo,
num_expected_locations=0,
loc_exact=True,
)
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
lldbutil.run_break_set_by_file_and_line(
self,
"to-be-mapped/qux.h",
self.line_in_foo,
num_expected_locations=0,
loc_exact=True,
)
self.runCmd('settings set target.source-map "real" "to-be-mapped"')
lldbutil.run_break_set_by_file_and_line(
self,
"to-be-mapped/qux.h",
self.line_in_foo,
num_expected_locations=1,
loc_exact=True,
)
# Clear settings so that the test below won't be affected.
self.runCmd("settings clear target.source-realpath-prefixes")