Skip to content

Commit

Permalink
[lldb] Fix TestModuleLoadedNotifys API test to work correctly on most…
Browse files Browse the repository at this point in the history
… of Linux targets (llvm#94672)

The different build configuration and target Linux system can load a
different number of .so libraries. Add and check own libraries.
  • Loading branch information
slydiman authored Jun 10, 2024
1 parent 58550a7 commit 3e39328
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
CXX_SOURCES := main.cpp

include Makefile.rules
CXX_SOURCES := main.cpp
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b

a.out: lib_b lib_a lib_c lib_d

include Makefile.rules

lib_a: lib_b
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
LD_EXTRAS="-L. -l_b"

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b

lib_c:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c

lib_d:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,47 @@
from lldbsuite.test import lldbutil


@skipUnlessPlatform(["linux"] + lldbplatformutil.getDarwinOSTriples())
class ModuleLoadedNotifysTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True

# At least DynamicLoaderDarwin and DynamicLoaderPOSIXDYLD should batch up
# notifications about newly added/removed libraries. Other DynamicLoaders may
# not be written this way.
@skipUnlessPlatform(["linux"] + lldbplatformutil.getDarwinOSTriples())
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number to break inside main().
self.line = line_number("main.cpp", "// breakpoint")

def setup_test(self, solibs):
if lldb.remote_platform:
path = lldb.remote_platform.GetWorkingDirectory()
for f in solibs:
lldbutil.install_to_target(self, self.getBuildArtifact(f))
else:
path = self.getBuildDir()
if self.dylibPath in os.environ:
sep = self.platformContext.shlib_path_separator
path = os.environ[self.dylibPath] + sep + path
self.runCmd(
"settings append target.env-vars '{}={}'".format(self.dylibPath, path)
)
self.default_path = path

def test_launch_notifications(self):
"""Test that lldb broadcasts newly loaded libraries in batches."""

expected_solibs = [
"lib_a." + self.platformContext.shlib_extension,
"lib_b." + self.platformContext.shlib_extension,
"lib_c." + self.platformContext.shlib_extension,
"lib_d." + self.platformContext.shlib_extension,
]

self.build()
self.setup_test(expected_solibs)

exe = self.getBuildArtifact("a.out")
self.dbg.SetAsync(False)

Expand Down Expand Up @@ -70,6 +95,8 @@ def test_launch_notifications(self):
total_modules_added_events = 0
total_modules_removed_events = 0
already_loaded_modules = []
max_solibs_per_event = 0
max_solib_chunk_per_event = []
while listener.GetNextEvent(event):
if lldb.SBTarget.EventIsTargetEvent(event):
if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded:
Expand All @@ -91,12 +118,17 @@ def test_launch_notifications(self):
"{} is already loaded".format(module),
)
already_loaded_modules.append(module)
if self.TraceOn():
added_files.append(module.GetFileSpec().GetFilename())
added_files.append(module.GetFileSpec().GetFilename())
if self.TraceOn():
# print all of the binaries that have been added
print("Loaded files: %s" % (", ".join(added_files)))

# We will check the latest biggest chunk of loaded solibs.
# We expect all of our solibs in the last chunk of loaded modules.
if solib_count >= max_solibs_per_event:
max_solib_chunk_per_event = added_files.copy()
max_solibs_per_event = solib_count

if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded:
solib_count = lldb.SBTarget.GetNumModulesFromEvent(event)
total_modules_removed_events += 1
Expand All @@ -115,9 +147,7 @@ def test_launch_notifications(self):
# binaries in batches. Check that we got back more than 1 solib per event.
# In practice on Darwin today, we get back two events for a do-nothing c
# program: a.out and dyld, and then all the rest of the system libraries.
# On Linux we get events for ld.so, [vdso], the binary and then all libraries.

avg_solibs_added_per_event = round(
float(total_solibs_added) / float(total_modules_added_events)
)
self.assertGreater(avg_solibs_added_per_event, 1)
# On Linux we get events for ld.so, [vdso], the binary and then all libraries,
# but the different configurations could load a different number of .so modules
# per event.
self.assertLessEqual(set(expected_solibs), set(max_solib_chunk_per_event))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extern "C" int b_function();

extern "C" int a_function() { return b_function(); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern "C" int b_function() { return 500; }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern "C" int c_function() { return 600; }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern "C" int d_function() { return 700; }
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
#include <stdio.h>
int main ()
{
puts("running"); // breakpoint here
return 0;
}
#include <stdio.h>

extern "C" int a_function();
extern "C" int c_function();
extern "C" int b_function();
extern "C" int d_function();

int main() {
a_function();
b_function();
c_function();
d_function();

puts("running"); // breakpoint here
return 0;
}

0 comments on commit 3e39328

Please sign in to comment.