Skip to content

Commit e247502

Browse files
Merge pull request #3311 from adrian-prantl/81135636
Support debugging Swift dylibs that were loaded after SwiftASTContext
2 parents b068ac5 + 1348ae3 commit e247502

File tree

11 files changed

+161
-1
lines changed

11 files changed

+161
-1
lines changed

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,7 @@ static lldb::ModuleSP GetUnitTestModule(lldb_private::ModuleList &modules) {
19491949
/// Scan a newly added lldb::Module fdor Swift modules and report any errors in
19501950
/// its module SwiftASTContext to Target.
19511951
static void
1952-
ProcessModule(ModuleSP &&module_sp, std::string m_description,
1952+
ProcessModule(ModuleSP module_sp, std::string m_description,
19531953
bool use_all_compiler_flags, Target &target,
19541954
std::vector<std::string> &module_search_paths,
19551955
std::vector<std::pair<std::string, bool>> &framework_search_paths,
@@ -5069,6 +5069,37 @@ void SwiftASTContext::PrintDiagnostics(DiagnosticManager &diagnostic_manager,
50695069

50705070
void SwiftASTContext::ModulesDidLoad(ModuleList &module_list) {
50715071
ClearModuleDependentCaches();
5072+
5073+
// Scan the new modules for Swift contents and try to import it if
5074+
// safe, otherwise poison this context.
5075+
TargetSP target_sp = GetTarget().lock();
5076+
if (!target_sp)
5077+
return;
5078+
5079+
bool use_all_compiler_flags = target_sp->GetUseAllCompilerFlags();
5080+
unsigned num_images = module_list.GetSize();
5081+
for (size_t mi = 0; mi != num_images; ++mi) {
5082+
std::vector<std::string> module_search_paths;
5083+
std::vector<std::pair<std::string, bool>> framework_search_paths;
5084+
std::vector<std::string> extra_clang_args;
5085+
lldb::ModuleSP module_sp = module_list.GetModuleAtIndex(mi);
5086+
ProcessModule(module_sp, m_description, use_all_compiler_flags, *target_sp,
5087+
module_search_paths, framework_search_paths,
5088+
extra_clang_args);
5089+
// If the use-all-compiler-flags setting is enabled, the expression
5090+
// context is supposed to merge all search paths form all dylibs.
5091+
if (use_all_compiler_flags && !extra_clang_args.empty()) {
5092+
// We cannot reconfigure ClangImporter after its creation.
5093+
// Instead poison the SwiftASTContext so it gets recreated.
5094+
m_fatal_errors.SetErrorStringWithFormat(
5095+
"New Swift image added: %s",
5096+
module_sp->GetFileSpec().GetPath().c_str());
5097+
}
5098+
5099+
// Scan the dylib for .swiftast sections.
5100+
std::vector<std::string> module_names;
5101+
RegisterSectionModules(*module_sp, module_names);
5102+
}
50725103
}
50735104

50745105
void SwiftASTContext::ClearModuleDependentCaches() {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# This Makefile recursively calls itself, hence the ?=.
2+
EXE ?= a.out
3+
C_SOURCES ?= loader.c
4+
all: dylib $(EXE)
5+
6+
include Makefile.rules
7+
8+
.PHONY: dylib
9+
dylib:
10+
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
11+
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
12+
VPATH=$(SRCDIR) -I $(SRCDIR) \
13+
-f $(SRCDIR)/Makefile \
14+
DYLIB_FILENAME=dylib.dylib \
15+
DYLIB_SWIFT_SOURCES=dylib.swift \
16+
DYLIB_NAME=dylib \
17+
DYLIB_ONLY=YES \
18+
C_SOURCES= \
19+
LD_EXTRAS="-lSwiftCore -Xlinker -exported_symbol -Xlinker _f" \
20+
dylib.dylib
21+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from lldbsuite.test.lldbtest import *
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbutil as lldbutil
4+
5+
class TestSwiftLateDylib(TestBase):
6+
7+
mydir = TestBase.compute_mydir(__file__)
8+
9+
@skipUnlessDarwin
10+
@swiftTest
11+
@skipIfDarwinEmbedded
12+
def test(self):
13+
"""Test that a late loaded Swift dylib is debuggable"""
14+
self.build()
15+
target, process, _, _ = lldbutil.run_to_name_breakpoint(self, "main")
16+
# Initialize SwiftASTContext before loading the dylib.
17+
self.expect("expr -l Swift -- 0")
18+
bkpt = target.BreakpointCreateByLocation(lldb.SBFileSpec('dylib.swift'), 7)
19+
lldbutil.continue_to_breakpoint(process, bkpt)
20+
self.expect("v x", substrs=['Hello from the Dylib'])
21+
self.expect("expr x", substrs=['Hello from the Dylib'])
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
struct FromDylib {
2+
let msg = "Hello from the Dylib!"
3+
}
4+
5+
@_silgen_name("f") public func f() {
6+
let x = FromDylib()
7+
print(x) // line 7
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <dlfcn.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <libgen.h>
5+
6+
int main(int argc, const char **argv) {
7+
char *dylib_name = strcat(dirname(argv[0]),"/dylib.dylib");
8+
void *dylib = dlopen(dylib_name, RTLD_NOW);
9+
void (*f)() = dlsym(dylib, "f");
10+
f();
11+
return 0;
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
struct FromClang {
2+
int x;
3+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# This Makefile recursively calls itself, hence the ?=.
2+
EXE ?= a.out
3+
C_SOURCES ?= loader.c
4+
all: dylib $(EXE)
5+
6+
include Makefile.rules
7+
8+
.PHONY: dylib
9+
dylib:
10+
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
11+
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
12+
VPATH=$(SRCDIR) -I $(SRCDIR) \
13+
-f $(SRCDIR)/Makefile \
14+
DYLIB_FILENAME=dylib.dylib \
15+
DYLIB_SWIFT_SOURCES=dylib.swift \
16+
DYLIB_NAME=dylib \
17+
DYLIB_ONLY=YES \
18+
SWIFTFLAGS_EXTRAS="-Xcc -I$(SRCDIR)" \
19+
C_SOURCES= \
20+
LD_EXTRAS="-lSwiftCore -Xlinker -exported_symbol -Xlinker _f" \
21+
dylib.dylib
22+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from lldbsuite.test.lldbtest import *
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbutil as lldbutil
4+
5+
class TestSwiftLateDylibClangDeps(TestBase):
6+
7+
mydir = TestBase.compute_mydir(__file__)
8+
9+
@skipUnlessDarwin
10+
@swiftTest
11+
@skipIfDarwinEmbedded
12+
def test(self):
13+
"""Test that a late loaded Swift dylib with Clang dependencies is debuggable"""
14+
self.build()
15+
target, process, _, _ = lldbutil.run_to_name_breakpoint(self, "main")
16+
# Initialize SwiftASTContext before loading the dylib.
17+
self.expect("expr -l Swift -- 0")
18+
bkpt = target.BreakpointCreateByLocation(lldb.SBFileSpec('dylib.swift'), 5)
19+
lldbutil.continue_to_breakpoint(process, bkpt)
20+
self.expect("v x", substrs=['42'])
21+
self.expect("expr x", substrs=['42'])
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import ClangMod
2+
3+
@_silgen_name("f") public func f() {
4+
let x = FromClang(x: 42)
5+
print(x) // line 5
6+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <dlfcn.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <libgen.h>
5+
6+
int main(int argc, const char **argv) {
7+
char *dylib_name = strcat(dirname(argv[0]),"/dylib.dylib");
8+
void *dylib = dlopen(dylib_name, RTLD_NOW);
9+
void (*f)() = dlsym(dylib, "f");
10+
f();
11+
return 0;
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module ClangMod {
2+
header "ClangMod.h"
3+
}

0 commit comments

Comments
 (0)