[Lldb-commits] [lldb] [lldb] NFC add comments and test case for ObjectFileMachO delay-init (PR #95067)

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Mon Jun 10 19:54:45 PDT 2024


https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/95067

>From 6b67c214ea95418e3f246c694d0a40009176fc07 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jason at molenda.com>
Date: Mon, 10 Jun 2024 17:52:42 -0700
Subject: [PATCH 1/2] [lldb] NFC add comments and test case for ObjectFileMachO
 delay-init

Add comments and a test for delay-init libraries on macOS.  I
originally added the support in 954d00e87cdd77d0e9e367be52e62340467bd779
a month ago, but without these additional clarifications.

rdar://126885033
---
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp     |  8 +++
 .../API/macosx/delay-init-dependency/Makefile | 11 ++++
 .../TestDelayInitDependency.py                | 63 +++++++++++++++++++
 .../API/macosx/delay-init-dependency/foo.c    |  1 +
 .../API/macosx/delay-init-dependency/main.c   |  9 +++
 5 files changed, 92 insertions(+)
 create mode 100644 lldb/test/API/macosx/delay-init-dependency/Makefile
 create mode 100644 lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
 create mode 100644 lldb/test/API/macosx/delay-init-dependency/foo.c
 create mode 100644 lldb/test/API/macosx/delay-init-dependency/main.c

diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 4dd23bb1e4dbe..2979bf69bf762 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -5140,12 +5140,20 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
       case LC_LOADFVMLIB:
       case LC_LOAD_UPWARD_DYLIB: {
         uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
+        // For LC_LOAD_DYLIB there is an alternate encoding
+        // which adds a uint32_t `flags` field for `DYLD_USE_*`
+        // flags.  This can be detected by a timestamp field with
+        // the `DYLIB_USE_MARKER` constant value.
         bool is_delayed_init = false;
         uint32_t use_command_marker = m_data.GetU32(&offset);
         if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */) {
           offset += 4; /* uint32_t current_version */
           offset += 4; /* uint32_t compat_version */
           uint32_t flags = m_data.GetU32(&offset);
+          // If this LC_LOAD_DYLIB is marked delay-init,
+          // don't report it as a dependent library -- it
+          // may be loaded in the process at some point,
+          // but will most likely not be load at launch.
           if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */)
             is_delayed_init = true;
         }
diff --git a/lldb/test/API/macosx/delay-init-dependency/Makefile b/lldb/test/API/macosx/delay-init-dependency/Makefile
new file mode 100644
index 0000000000000..246ea0f34e1a1
--- /dev/null
+++ b/lldb/test/API/macosx/delay-init-dependency/Makefile
@@ -0,0 +1,11 @@
+C_SOURCES := main.c
+LD_EXTRAS := -L. -Wl,-delay_library,libfoo.dylib
+
+.PHONY: build-libfoo
+all: build-libfoo a.out
+
+include Makefile.rules
+
+build-libfoo: foo.c
+	$(MAKE) -f $(MAKEFILE_RULES) \
+		DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES
diff --git a/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py b/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
new file mode 100644
index 0000000000000..9b9b1618ba6de
--- /dev/null
+++ b/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
@@ -0,0 +1,63 @@
+"""Test binaries with delay-init dependencies."""
+
+import subprocess
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestDelayInitDependencies(TestBase):
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessDarwin
+    def test_delay_init_dependency(self):
+        TestBase.setUp(self)
+        out = subprocess.run(
+            ["xcrun", "ld", "-delay_library"],
+            universal_newlines=True,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+        )
+        if "delay_library missing" not in out.stderr:
+            self.skipTest(
+                "Skipped because the linker doesn't know about -delay_library"
+            )
+        self.build()
+        main_source = "main.c"
+        exe = self.getBuildArtifact("a.out")
+        lib = self.getBuildArtifact("libfoo.dylib")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        # libfoo.dylib should not be in the target pre-execution
+        for m in target.modules:
+            self.assertNotEqual(m.GetFileSpec().GetFilename(), "libfoo.dylib")
+
+        # This run without arguments will not load libfoo.dylib
+        li = lldb.SBLaunchInfo([])
+        li.SetWorkingDirectory(self.getBuildDir())
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.c"), li
+        )
+        for m in target.modules:
+            self.assertNotEqual(m.GetFileSpec().GetFilename(), "libfoo.dylib")
+
+        process.Kill()
+        self.dbg.DeleteTarget(target)
+
+        # This run with one argument will load libfoo.dylib
+        li = lldb.SBLaunchInfo([])
+        li.SetWorkingDirectory(self.getBuildDir())
+        li.SetArguments(["one-argument"], True)
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.c"), li
+        )
+
+        found_libfoo = False
+        for m in target.modules:
+            if m.GetFileSpec().GetFilename() == "libfoo.dylib":
+                found_libfoo = True
+        self.assertTrue(found_libfoo)
diff --git a/lldb/test/API/macosx/delay-init-dependency/foo.c b/lldb/test/API/macosx/delay-init-dependency/foo.c
new file mode 100644
index 0000000000000..de1cbc4c4648a
--- /dev/null
+++ b/lldb/test/API/macosx/delay-init-dependency/foo.c
@@ -0,0 +1 @@
+int foo() { return 5; }
diff --git a/lldb/test/API/macosx/delay-init-dependency/main.c b/lldb/test/API/macosx/delay-init-dependency/main.c
new file mode 100644
index 0000000000000..57d251e6b2abe
--- /dev/null
+++ b/lldb/test/API/macosx/delay-init-dependency/main.c
@@ -0,0 +1,9 @@
+int foo();
+int main(int argc, char **argv) {
+  int retval = 0;
+  // Only call foo() if one argument is passed
+  if (argc == 2)
+    retval = foo();
+
+  return retval; // break here
+}

>From 4a022af1f34347750b0067e2754d01f8737ddcd6 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jason at molenda.com>
Date: Mon, 10 Jun 2024 19:54:31 -0700
Subject: [PATCH 2/2] ws

---
 .../API/macosx/delay-init-dependency/TestDelayInitDependency.py  | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py b/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
index 9b9b1618ba6de..44ed2b1d21f18 100644
--- a/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
+++ b/lldb/test/API/macosx/delay-init-dependency/TestDelayInitDependency.py
@@ -8,7 +8,6 @@
 
 
 class TestDelayInitDependencies(TestBase):
-
     NO_DEBUG_INFO_TESTCASE = True
 
     @skipUnlessDarwin



More information about the lldb-commits mailing list