From 16217b26f27ff082d1ca74d778833beb3c1982a4 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 19 Jan 2023 17:50:04 -0800 Subject: [PATCH 1/4] Split playgrounds test into multiple test functions --- lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py b/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py index c73380f0377f1..f8889327f8086 100644 --- a/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py +++ b/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py @@ -100,8 +100,7 @@ def test_concurrency(self): def test_import(self): """Test that a dylib can be imported in playgrounds""" self.launch(True) - self.do_concurrency_test() - + self.do_import_test() def launch(self, force_target): """Test that playgrounds work""" From ba81700a84a2b0c4ad5334988b63d1ebd4a17fa9 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 19 Jan 2023 13:46:00 -0800 Subject: [PATCH 2/4] Work around an infinite recursion with deadlock that only exists on the swift branch. The function IRExecutionUnit::PopulateSymtab() is only implemented in swift-lldb. One thing it does is resolve any unresolved global symbols in the JIT module. This global search can cause the JIT module to recursively be asked for its symtab. This patch works around the problem by removing the JIT module from the list of modules being searched while in PopulateSymtab. That isn't done in the most elegant fashion, as it does so by changing the state of the IRExecutionUnit object. (lldb) bt * thread #2, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP frame #0: 0x00007ff80dc2a0ce libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007ff80dc66758 libsystem_pthread.dylib`_pthread_cond_wait + 1242 frame #2: 0x00007ff80dba51fd libc++.1.dylib`std::__1::__call_once(unsigned long volatile&, void*, void (*)(void*)) + 70 frame #3: 0x000000014ff9235d LLDB`lldb_private::ObjectFile::GetSymtab() at mutex:676:9 [opt] * frame #4: 0x000000014ff92334 LLDB`lldb_private::ObjectFile::GetSymtab() [inlined] void llvm::call_once(flag=, F=)::$_0&&) at Threading.h:89:5 [opt] frame #5: 0x000000014ff92334 LLDB`lldb_private::ObjectFile::GetSymtab(this=0x0000600003d04f18) at ObjectFile.cpp:758:5 [opt] frame #6: 0x0000000150531d67 LLDB`SymbolFileSymtab::CalculateAbilities(this=0x0000600003e20600) at SymbolFileSymtab.cpp:60:42 [opt] frame #7: 0x000000015053001d LLDB`lldb_private::SymbolFileCommon::GetAbilities(this=0x0000600003e20600) at SymbolFile.h:478:21 [opt] frame #8: 0x000000014ff9a8cd LLDB`lldb_private::SymbolFile::FindPlugin(objfile_sp=std::__1::shared_ptr::element_type @ 0x0000600003d04f18 strong=7 weak=2) at SymbolFile.cpp:71:62 [opt] frame #9: 0x000000014ff9f4bd LLDB`lldb_private::SymbolVendor::AddSymbolFileRepresentation(this=0x00006000002b05a0, objfile_sp=std::__1::shared_ptr::element_type @ 0x0000600003d04f18 strong=7 weak=2) at SymbolVendor.cpp:71:27 [opt] frame #10: 0x000000014ff9f419 LLDB`lldb_private::SymbolVendor::FindPlugin(module_sp=std::__1::shared_ptr::element_type @ 0x0000000106589ca0 strong=12 weak=26, feedback_strm=0x0000000000000000) at SymbolVendor.cpp:57:16 [opt] frame #11: 0x000000014fe8d2a0 LLDB`lldb_private::Module::GetSymbolFile(this=0x0000000106589ca0, can_create=, feedback_strm=0x0000000000000000) at Module.cpp:1083:13 [opt] frame #12: 0x000000014fe8c4c0 LLDB`lldb_private::Module::FindFunctions(lldb_private::ConstString, lldb_private::CompilerDeclContext const&, lldb::FunctionNameType, lldb_private::ModuleFunctionSearchOptions const&, lldb_private::SymbolContextList&) at Module.cpp:857:29 [opt] frame #13: 0x000000014fe8c4b0 LLDB`lldb_private::Module::FindFunctions(this=0x0000000106589ca0, name=, parent_decl_ctx=0x00007ff7bfef98d0, name_type_mask=eFunctionNameTypeFull, options=0x00007ff7bfef9990, sc_list=0x00007ff7bfef9960) at Module.cpp:878:3 [opt] frame #14: 0x000000014fe92ba1 LLDB`lldb_private::ModuleList::FindFunctions(this=, name=, name_type_mask=, options=0x00007ff7bfef9990, sc_list=0x00007ff7bfef9960) const at ModuleList.cpp:554:18 [opt] frame #15: 0x000000014fef36cb LLDB`lldb_private::IRExecutionUnit::FindInSymbols(this=, names=, sc=0x00000001004db950, symbol_was_missing_weak=) at IRExecutionUnit.cpp:843:33 [opt] frame #16: 0x000000014fef3c36 LLDB`lldb_private::IRExecutionUnit::FindSymbol(this=0x00000001004db860, name=, missing_weak=0x00007ff7bfef9a97) at IRExecutionUnit.cpp:915:22 [opt] frame #17: 0x000000014fef43f3 LLDB`lldb_private::IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(this=0x0000000107c71000, Name="_$sBoWV", missing_weak=0x00007ff7bfef9a97) at IRExecutionUnit.cpp:1010:31 [opt] frame #18: 0x000000014fef4490 LLDB`non-virtual thunk to lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string, std::__1::allocator > const&) [inlined] lldb_private::IRExecutionUnit::MemoryManager::findSymbol(this=, Name=) at IRExecutionUnit.cpp:988:21 [opt] frame #19: 0x000000014fef447d LLDB`non-virtual thunk to lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string, std::__1::allocator > const&) at IRExecutionUnit.cpp:0 [opt] frame #20: 0x0000000154ab3a5c LLDB`llvm::LinkingSymbolResolver::findSymbol(this=0x0000000107e0ecc0, Name="_$sBoWV") at MCJIT.cpp:681:26 [opt] frame #21: 0x0000000154abd458 LLDB`llvm::LegacyJITSymbolResolver::lookup(this=, Symbols=, OnResolved=)>) at JITSymbol.cpp:125:22 [opt] frame #22: 0x0000000154abf6f3 LLDB`llvm::RuntimeDyldImpl::resolveExternalSymbols(this=0x000000013cfeea20) at RuntimeDyld.cpp:1195:16 [opt] frame #23: 0x0000000154abecde LLDB`llvm::RuntimeDyldImpl::resolveRelocations(this=0x000000013cfeea20) at RuntimeDyld.cpp:131:18 [opt] frame #24: 0x0000000154ab1482 LLDB`llvm::MCJIT::finalizeLoadedModules(this=0x0000000107e0ea00) at MCJIT.cpp:242:8 [opt] frame #25: 0x0000000154ab24ec LLDB`llvm::MCJIT::getGlobalValueAddress(this=0x0000000107e0ea00, Name=) at MCJIT.cpp:400:5 [opt] frame #26: 0x000000014fef499d LLDB`lldb_private::IRExecutionUnit::PopulateSymtab(this=0x00000001004db860, obj_file=, symtab=0x0000600003342f80) at IRExecutionUnit.cpp:1246:34 [opt] frame #27: 0x00000001503e4bf1 LLDB`ObjectFileJIT::ParseSymtab(this=0x0000600003d04f18, symtab=0x0000600003342f80) at ObjectFileJIT.cpp:112:18 [opt] frame #28: 0x000000014ff93a14 LLDB`void std::__1::__call_once_proxy >(void*) at ObjectFile.cpp:764:9 [opt] frame #29: 0x000000014ff93998 LLDB`void std::__1::__call_once_proxy >(void*) [inlined] decltype(__f=0x00007ff7bfefa180)::$_0>(fp)()) std::__1::__invoke(lldb_private::ObjectFile::GetSymtab()::$_0&&) at type_traits:3918:1 [opt] frame #30: 0x000000014ff93998 LLDB`void std::__1::__call_once_proxy >(void*) [inlined] void std::__1::__call_once_param >::__execute<>(this=, (null)=) at mutex:630:9 [opt] frame #31: 0x000000014ff93984 LLDB`void std::__1::__call_once_proxy >(void*) [inlined] std::__1::__call_once_param >::operator(this=)() at mutex:622:9 [opt] frame #32: 0x000000014ff93984 LLDB`void std::__1::__call_once_proxy >(__vp=) at mutex:658:5 [opt] frame #33: 0x00007ff80dba5242 libc++.1.dylib`std::__1::__call_once(unsigned long volatile&, void*, void (*)(void*)) + 139 frame #34: 0x000000014ff9235d LLDB`lldb_private::ObjectFile::GetSymtab() at mutex:676:9 [opt] frame #35: 0x000000014ff92334 LLDB`lldb_private::ObjectFile::GetSymtab() [inlined] void llvm::call_once(flag=, F=)::$_0&&) at Threading.h:89:5 [opt] frame #36: 0x000000014ff92334 LLDB`lldb_private::ObjectFile::GetSymtab(this=0x0000600003d04f18) at ObjectFile.cpp:758:5 [opt] frame #37: 0x0000000150531d67 LLDB`SymbolFileSymtab::CalculateAbilities(this=0x0000600003e20100) at SymbolFileSymtab.cpp:60:42 [opt] frame #38: 0x000000015053001d LLDB`lldb_private::SymbolFileCommon::GetAbilities(this=0x0000600003e20100) at SymbolFile.h:478:21 [opt] frame #39: 0x000000014ff9a8cd LLDB`lldb_private::SymbolFile::FindPlugin(objfile_sp=std::__1::shared_ptr::element_type @ 0x0000600003d04f18 strong=7 weak=2) at SymbolFile.cpp:71:62 [opt] frame #40: 0x000000014ff9f4bd LLDB`lldb_private::SymbolVendor::AddSymbolFileRepresentation(this=0x00006000002b0560, objfile_sp=std::__1::shared_ptr::element_type @ 0x0000600003d04f18 strong=7 weak=2) at SymbolVendor.cpp:71:27 [opt] frame #41: 0x000000014ff9f419 LLDB`lldb_private::SymbolVendor::FindPlugin(module_sp=std::__1::shared_ptr::element_type @ 0x0000000106589ca0 strong=12 weak=26, feedback_strm=0x0000000000000000) at SymbolVendor.cpp:57:16 [opt] frame #42: 0x000000014fe8d2a0 LLDB`lldb_private::Module::GetSymbolFile(this=0x0000000106589ca0, can_create=, feedback_strm=0x0000000000000000) at Module.cpp:1083:13 [opt] frame #43: 0x000000015041f366 LLDB`lldb_private::PlatformDarwin::LocateExecutableScriptingResources(this=, target=0x000000010309e800, module=0x0000000106589ca0, feedback_stream=0x00007ff7bfefa770) at PlatformDarwin.cpp:212:40 [opt] frame #44: 0x000000014fe8f97c LLDB`lldb_private::Module::LoadScriptingResourceInTarget(this=, target=0x000000010309e800, error=0x00007ff7bfefa750, feedback_stream=) at Module.cpp:1588:44 [opt] frame #45: 0x0000000150027520 LLDB`lldb_private::Target::ModulesDidLoad(lldb_private::ModuleList&) [inlined] LoadScriptingResourceForModule(module_sp=, target=0x000000010309e800) at Target.cpp:1415:32 [opt] frame #46: 0x00000001500274f4 LLDB`lldb_private::Target::ModulesDidLoad(this=0x000000010309e800, module_list=) at Target.cpp:1672:7 [opt] frame #47: 0x00000001500284ca LLDB`non-virtual thunk to lldb_private::Target::NotifyModuleAdded(lldb_private::ModuleList const&, std::__1::shared_ptr const&) at Target.cpp:1637:5 [opt] frame #48: 0x00000001500284a7 LLDB`non-virtual thunk to lldb_private::Target::NotifyModuleAdded(lldb_private::ModuleList const&, std::__1::shared_ptr const&) at Target.cpp:0 [opt] frame #49: 0x000000014fe91f8b LLDB`lldb_private::ModuleList::Append(std::__1::shared_ptr const&, bool) at ModuleList.cpp:334:19 [opt] frame #50: 0x000000014fe91f44 LLDB`lldb_private::ModuleList::Append(this=0x000000010309eb48, module_sp=std::__1::shared_ptr::element_type @ 0x0000000106589ca0 strong=12 weak=26, notify=) at ModuleList.cpp:339:3 [opt] frame #51: 0x000000014fef5200 LLDB`lldb_private::IRExecutionUnit::CreateJITModule(this=, name="$__lldb_expr2") at IRExecutionUnit.cpp:1339:27 [opt] frame #52: 0x000000015011063b LLDB`lldb_private::SwiftUserExpression::Parse(this=, diagnostic_manager=, exe_ctx=, execution_policy=eExecutionPolicyOnlyWhenNeeded, keep_result_in_memory=, generate_debug_info=) at SwiftUserExpression.cpp:802:28 [opt] frame #53: 0x000000014ff0cd05 LLDB`lldb_private::UserExpression::Evaluate(exe_ctx=, options=0x00006000033441e0, expr="", prefix="", result_valobj_sp=nullptr, error=0x00007ff7bfefaf40, fixed_expression=Summary Unavailable, ctx_obj=0x0000000000000000) at UserExpression.cpp:281:27 [opt] frame #54: 0x000000015002e124 LLDB`lldb_private::Target::EvaluateExpression(this=0x000000010309e800, expr="", exe_scope=, result_valobj_sp=nullptr, options=, fixed_expression=Summary Unavailable, ctx_obj=0x0000000000000000) at Target.cpp:2960:25 [opt] frame #55: 0x000000014fcc3e62 LLDB`lldb::SBFrame::EvaluateExpression(this=, expr=, options=0x0000600000011880) at SBFrame.cpp:1084:17 [opt] frame #56: 0x000000014fdaaf70 LLDB`_wrap_SBFrame_EvaluateExpression(_object*, _object*) at LLDBWrapPython.cpp:32887:22 [opt] frame #57: 0x000000014fdaaebf LLDB`_wrap_SBFrame_EvaluateExpression(self=, args=) at LLDBWrapPython.cpp:32933:18 [opt] --- .../include/lldb/Expression/IRExecutionUnit.h | 3 +++ lldb/source/Expression/IRExecutionUnit.cpp | 21 ++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h index 0f64753eadbc5..a76294de474bf 100644 --- a/lldb/include/lldb/Expression/IRExecutionUnit.h +++ b/lldb/include/lldb/Expression/IRExecutionUnit.h @@ -391,6 +391,9 @@ class IRExecutionUnit : public std::enable_shared_from_this, std::vector m_failed_lookups; std::atomic m_did_jit; + // BEGIN SWIFT + std::atomic m_in_populate_symtab = false; + // END SWIFT lldb::addr_t m_function_load_addr; lldb::addr_t m_function_end_load_addr; diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 7479b34055c91..e3183158430a1 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -839,17 +839,20 @@ IRExecutionUnit::FindInSymbols(const std::vector &names, } if (sc.target_sp) { + ModuleList images = sc.target_sp->GetImages(); + // BEGIN SWIFT + if (m_in_populate_symtab) + if (lldb::ModuleSP module_sp = m_jit_module_wp.lock()) + images.Remove(module_sp); + // END SWIFT + SymbolContextList sc_list; - sc.target_sp->GetImages().FindFunctions(name, lldb::eFunctionNameTypeFull, - function_options, sc_list); + images.FindFunctions(name, lldb::eFunctionNameTypeFull, function_options, + sc_list); if (auto load_addr = resolver.Resolve(sc_list)) return *load_addr; - } - if (sc.target_sp) { - SymbolContextList sc_list; - sc.target_sp->GetImages().FindSymbolsWithNameAndType( - name, lldb::eSymbolTypeAny, sc_list); + images.FindSymbolsWithNameAndType(name, lldb::eSymbolTypeAny, sc_list); if (auto load_addr = resolver.Resolve(sc_list)) return *load_addr; } @@ -1194,6 +1197,9 @@ uint32_t IRExecutionUnit::GetAddressByteSize() const { void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file, lldb_private::Symtab &symtab) { + // BEGIN SWIFT + m_in_populate_symtab = true; + auto _ = llvm::make_scope_exit([this]() { m_in_populate_symtab = false; }); if (m_execution_engine_up) { uint32_t symbol_id = 0; lldb_private::SectionList *section_list = obj_file->GetSectionList(); @@ -1271,6 +1277,7 @@ void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file, } } } + // END SWIFT } void IRExecutionUnit::PopulateSectionList( From 03c984b435b8a8efc9675419499c02f7569c3acc Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 19 Jan 2023 17:12:00 -0800 Subject: [PATCH 3/4] Remove debug code --- lldb/packages/Python/lldbsuite/test/lldbplaygroundrepl.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/lldbplaygroundrepl.py b/lldb/packages/Python/lldbsuite/test/lldbplaygroundrepl.py index 18e3a7bce6b63..d9d87cd343468 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplaygroundrepl.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplaygroundrepl.py @@ -77,7 +77,6 @@ def execute_code(self, inputFile): with open(inputFile, 'r') as contents_file: contents = contents_file.read() - self.expect("log enable lldb types expr -f /tmp/types.log") result = self.frame.EvaluateExpression(contents, self.options) output = self.frame.EvaluateExpression("get_output()") with recording(self, self.TraceOn()) as sbuf: From 5ac442fbe3c5144d61b7e7fede0adbcea0d4eec2 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 19 Jan 2023 17:35:03 -0800 Subject: [PATCH 4/4] Further streamline TestSwiftPlaygrounds. --- .../API/lang/swift/playgrounds/Import.swift | 2 + .../swift/playgrounds/TestSwiftPlaygrounds.py | 56 +++++++++++-------- 2 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 lldb/test/API/lang/swift/playgrounds/Import.swift diff --git a/lldb/test/API/lang/swift/playgrounds/Import.swift b/lldb/test/API/lang/swift/playgrounds/Import.swift new file mode 100644 index 0000000000000..d751f122f7dcc --- /dev/null +++ b/lldb/test/API/lang/swift/playgrounds/Import.swift @@ -0,0 +1,2 @@ +import Dylib +f() diff --git a/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py b/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py index f8889327f8086..fc2e8d351f045 100644 --- a/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py +++ b/lldb/test/API/lang/swift/playgrounds/TestSwiftPlaygrounds.py @@ -88,6 +88,7 @@ def test_no_force_target(self): @swiftTest @skipIf(setting=('symbols.use-swift-clangimporter', 'false')) @skipIf(debug_info=decorators.no_match("dsym")) + @skipIf(macos_version=["<", "12"]) def test_concurrency(self): """Test that concurrency is available in playgrounds""" self.launch(True) @@ -144,15 +145,35 @@ def launch(self, force_target): self.options.SetTryAllThreads(True) - def do_basic_test(self, force_target): - contents = "" - - with open('Contents.swift', 'r') as contents_file: + def execute_code(self, input_file, expect_error=False): + contents = "syntax error" + with open(input_file, 'r') as contents_file: contents = contents_file.read() - - self.frame().EvaluateExpression(contents, self.options) + res = self.frame().EvaluateExpression(contents, self.options) ret = self.frame().EvaluateExpression("get_output()") + is_error = res.GetError().Fail() and not ( + res.GetError().GetType() == 1 and + res.GetError().GetError() == 0x1001) playground_output = ret.GetSummary() + with recording(self, self.TraceOn()) as sbuf: + print("playground result: ", file=sbuf) + print(str(res), file=sbuf) + if is_error: + print("error:", file=sbuf) + print(str(res.GetError()), file=sbuf) + else: + print("playground output:", file=sbuf) + print(str(ret), file=sbuf) + + if expect_error: + self.assertTrue(is_error) + return playground_output + self.assertFalse(is_error) + self.assertIsNotNone(playground_output) + return playground_output + + def do_basic_test(self, force_target): + playground_output = self.execute_code('Contents.swift', not force_target) if not force_target: # This is expected to fail because the deployment target # is less than the availability of the function being @@ -160,31 +181,20 @@ def do_basic_test(self, force_target): self.assertEqual(playground_output, '""') return - self.assertTrue(playground_output is not None) - self.assertTrue("a=\\'3\\'" in playground_output) - self.assertTrue("b=\\'5\\'" in playground_output) - self.assertTrue("=\\'8\\'" in playground_output) - self.assertTrue("=\\'11\\'" in playground_output) + self.assertIn("a=\\'3\\'", playground_output) + self.assertIn("b=\\'5\\'", playground_output) + self.assertIn("=\\'8\\'", playground_output) + self.assertIn("=\\'11\\'", playground_output) def do_concurrency_test(self): - contents = "error" - with open('Concurrency.swift', 'r') as contents_file: - contents = contents_file.read() - res = self.frame().EvaluateExpression(contents, self.options) - ret = self.frame().EvaluateExpression("get_output()") - playground_output = ret.GetSummary() - self.assertTrue(playground_output is not None) + playground_output = self.execute_code('Concurrency.swift') self.assertIn("=\\'23\\'", playground_output) def do_import_test(self): # Test importing a library that adds new Clang options. log = self.getBuildArtifact('types.log') self.expect('log enable lldb types -f ' + log) - contents = "import Dylib\nf()\n" - res = self.frame().EvaluateExpression(contents, self.options) - ret = self.frame().EvaluateExpression("get_output()") - playground_output = ret.GetSummary() - self.assertTrue(playground_output is not None) + playground_output = self.execute_code('Import.swift') self.assertIn("Hello from the Dylib", playground_output) # Scan through the types log to make sure the SwiftASTContext was poisoned.