Skip to content

[LLDB] Add integration test for libsanitizers trace collection #134323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lldb/test/API/functionalities/asan/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
C_SOURCES := main.c
asan: CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info
asan: all
compiler_rt-asan: CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info
compiler_rt-asan: all

libsanitizers: CFLAGS_EXTRAS := -fsanitize=address -fsanitize-stable-abi -g -gcolumn-info
libsanitizers: all
libsanitizers-asan: CFLAGS_EXTRAS := -fsanitize=address -fsanitize-stable-abi -g -gcolumn-info
libsanitizers-asan: all

libsanitizers-traces: CFLAGS_EXTRAS := -g -gcolumn-info
libsanitizers-traces: all

include Makefile.rules
104 changes: 63 additions & 41 deletions lldb/test/API/functionalities/asan/TestMemoryHistory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,28 @@
from lldbsuite.test import lldbutil
from lldbsuite.test_event.build_exception import BuildError

class AsanTestCase(TestBase):
class MemoryHistoryTestCase(TestBase):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default
@expectedFailureNetBSD
@skipUnlessAddressSanitizer
def test(self):
self.build(make_targets=["asan"])
self.asan_tests()
def test_compiler_rt_asan(self):
self.build(make_targets=["compiler_rt-asan"])
self.compiler_rt_asan_tests()

@skipIf(oslist=no_match(["macosx"]))
@skipIf(bugnumber="rdar://144997976")
@skipUnlessDarwin
@skipIf(bugnumber="rdar://109913184&143590169")
def test_libsanitizers_asan(self):
try:
self.build(make_targets=["libsanitizers"])
self.build(make_targets=["libsanitizers-asan"])
except BuildError as e:
self.skipTest("failed to build with libsanitizers")
self.libsanitizer_tests()
self.libsanitizers_asan_tests()

@skipUnlessDarwin
@skipIf(macos_version=["<", "15.5"])
def test_libsanitizers_traces(self):
self.build(make_targets=["libsanitizers-traces"])
self.libsanitizers_traces_tests()

def setUp(self):
# Call super's setUp().
Expand All @@ -36,35 +42,60 @@ def setUp(self):
self.line_breakpoint = line_number("main.c", "// break line")

# Test line numbers: rdar://126237493
def libsanitizer_tests(self):
target = self.createTestTarget()

self.runCmd(
"env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0"
)

self.runCmd("run")

# In libsanitizers, memory history is not supported until a report has been generated
self.expect(
"thread list",
"Process should be stopped due to ASan report",
substrs=["stopped", "stop reason = Use of deallocated memory"],
)

# test the 'memory history' command
# for libsanitizers and remove `skip_line_numbers` parameter
def check_traces(self, skip_line_numbers=False):
self.expect(
"memory history 'pointer'",
substrs=[
"Memory deallocated by Thread",
"a.out`f2",
"main.c",
"main.c" if skip_line_numbers else f"main.c:{self.line_free}",
"Memory allocated by Thread",
"a.out`f1",
"main.c",
"main.c" if skip_line_numbers else f"main.c:{self.line_malloc}",
],
)

# Set breakpoint: after free, but before bug
def set_breakpoint(self, target):
bkpt = target.BreakpointCreateByLocation("main.c", self.line_breakpoint)
self.assertGreater(bkpt.GetNumLocations(), 0, "Set the breakpoint successfully")

def run_to_breakpoint(self, target):
self.set_breakpoint(target)
self.runCmd("run")
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT,
substrs=["stopped", "stop reason = breakpoint"],
)

def libsanitizers_traces_tests(self):
target = self.createTestTarget()

self.runCmd("env SanitizersAllocationTraces=all")

self.run_to_breakpoint(target)
self.check_traces(skip_line_numbers=True)

def libsanitizers_asan_tests(self):
target = self.createTestTarget()

self.runCmd("env SanitizersAddress=1 MallocSanitizerZone=1")

self.run_to_breakpoint(target)
self.check_traces(skip_line_numbers=True)

self.runCmd("continue")

# Stop on report
self.expect(
"thread list",
"Process should be stopped due to ASan report",
substrs=["stopped", "stop reason = Use of deallocated memory"],
)
self.check_traces(skip_line_numbers=True)

# do the same using SB API
process = self.dbg.GetSelectedTarget().process
val = (
Expand Down Expand Up @@ -97,12 +128,12 @@ def libsanitizer_tests(self):
"main.c",
)

def asan_tests(self):
def compiler_rt_asan_tests(self):
target = self.createTestTarget()

self.registerSanitizerLibrariesWithTarget(target)

self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)
self.set_breakpoint(target)

# "memory history" command should not work without a process
self.expect(
Expand Down Expand Up @@ -135,18 +166,7 @@ def asan_tests(self):
substrs=["1 match found"],
)

# test the 'memory history' command
self.expect(
"memory history 'pointer'",
substrs=[
"Memory deallocated by Thread",
"a.out`f2",
"main.c:%d" % self.line_free,
"Memory allocated by Thread",
"a.out`f1",
"main.c:%d" % self.line_malloc,
],
)
self.check_traces()

# do the same using SB API
process = self.dbg.GetSelectedTarget().process
Expand Down Expand Up @@ -198,6 +218,8 @@ def asan_tests(self):
substrs=["stopped", "stop reason = Use of deallocated memory"],
)

self.check_traces()

# make sure the 'memory history' command still works even when we're
# generating a report now
self.expect(
Expand Down
12 changes: 5 additions & 7 deletions lldb/test/API/functionalities/asan/TestReportData.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ class AsanTestReportDataCase(TestBase):
@skipUnlessAddressSanitizer
@skipIf(archs=["i386"], bugnumber="llvm.org/PR36710")
def test(self):
self.build(make_targets=["asan"])
self.build(make_targets=["compiler_rt-asan"])
self.asan_tests()

@skipIf(oslist=no_match(["macosx"]))
@skipIf(bugnumber="rdar://144997976")
@skipUnlessDarwin
@skipIf(bugnumber="rdar://109913184&143590169")
def test_libsanitizers_asan(self):
try:
self.build(make_targets=["libsanitizers"])
self.build(make_targets=["libsanitizers-asan"])
except BuildError as e:
self.skipTest("failed to build with libsanitizers")
self.asan_tests(libsanitizers=True)
Expand All @@ -42,9 +42,7 @@ def asan_tests(self, libsanitizers=False):
target = self.createTestTarget()

if libsanitizers:
self.runCmd(
"env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0"
)
self.runCmd("env SanitizersAddress=1 MallocSanitizerZone=1")
else:
self.registerSanitizerLibrariesWithTarget(target)

Expand Down