Skip to content

Commit

Permalink
[lldb] NFC add comments and test case for ObjectFileMachO delay-init (#…
Browse files Browse the repository at this point in the history
…95067)

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

rdar://126885033
  • Loading branch information
jasonmolenda authored Jun 11, 2024
1 parent 39cf880 commit 1934208
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions lldb/test/API/macosx/delay-init-dependency/Makefile
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""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)
1 change: 1 addition & 0 deletions lldb/test/API/macosx/delay-init-dependency/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo() { return 5; }
9 changes: 9 additions & 0 deletions lldb/test/API/macosx/delay-init-dependency/main.c
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 1934208

Please sign in to comment.