From a91c0279aa23a2c481961a3810c6549be837424f Mon Sep 17 00:00:00 2001 From: Todd Fiala Date: Thu, 15 Sep 2016 20:37:57 -0700 Subject: [PATCH 1/2] support debugging statically-linked Swift binaries on macOS This change supports the scenario of linking multiple Swift module .o files with multiple .swiftmodule files provided to the linker. This change expects the "main" Swift module's .swiftmodule to be specified first in the -add_ast_path directive given to the clang linker line. Fixes: bugs.swift.org/SR-2637 --- include/lldb/Symbol/SwiftASTContext.h | 4 +- include/lldb/Symbol/SymbolFile.h | 29 +++++-- include/lldb/Symbol/SymbolVendor.h | 3 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 73 +++++++++++++--- .../DWARF/SymbolFileDWARFDebugMap.h | 3 +- source/Symbol/SwiftASTContext.cpp | 87 ++++++++++++++----- source/Symbol/SymbolFile.cpp | 5 +- source/Symbol/SymbolVendor.cpp | 20 +++-- 8 files changed, 167 insertions(+), 57 deletions(-) diff --git a/include/lldb/Symbol/SwiftASTContext.h b/include/lldb/Symbol/SwiftASTContext.h index 9198dba6a0ac..90b1111d17bf 100644 --- a/include/lldb/Symbol/SwiftASTContext.h +++ b/include/lldb/Symbol/SwiftASTContext.h @@ -822,6 +822,8 @@ class SwiftASTContext : public TypeSystem { bool TargetHasNoSDK(); + std::vector &GetASTVectorForModule(const Module *module); + std::unique_ptr m_source_manager_ap; std::unique_ptr m_diagnostic_engine_ap; std::unique_ptr m_ast_context_ap; @@ -850,7 +852,7 @@ class SwiftASTContext : public TypeSystem { // target's process pointer be filled in std::string m_platform_sdk_path; std::string m_resource_dir; - typedef std::map ASTFileDataMap; + typedef std::map> ASTFileDataMap; ASTFileDataMap m_ast_file_data_map; /// FIXME: this vector is needed because the LLDBNameLookup debugger clients /// are being put into diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h index c53a32693687..22ed447d8eac 100644 --- a/include/lldb/Symbol/SymbolFile.h +++ b/include/lldb/Symbol/SymbolFile.h @@ -10,6 +10,8 @@ #ifndef liblldb_SymbolFile_h_ #define liblldb_SymbolFile_h_ +#include + #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" @@ -223,15 +225,26 @@ class SymbolFile : public PluginInterface { virtual bool ForceInlineSourceFileCheck(); //------------------------------------------------------------------ - // Symbol files can store AST data for any language that wants to - // store the native AST format supported by the current compiler. - // This information is often only usable by a compiler that is in - // sync with the compiler sources that were used to build LLDB so - // any data should be versioned appropriately so the compiler can - // try to load the data and know if the data will be able to be - // used. + /// Retrieve all the AST data blobs from the SymbolFile. + /// + /// Symbol files can store AST data for any language that wants to + /// store the native AST format supported by the current compiler. + /// This information is often only usable by a compiler that is in + /// sync with the compiler sources that were used to build LLDB so + /// any data should be versioned appropriately so the compiler can + /// try to load the data and know if the data will be able to be + /// used. + /// + /// @param[in] language + /// The language for which AST data is being requested. + /// A given file can contain ASTs for more than one language. + /// + /// @return + /// Zero or more buffers, each of which contain the raw data + /// of an AST in the requested language. //------------------------------------------------------------------ - virtual lldb::DataBufferSP GetASTData(lldb::LanguageType language); + virtual std::vector + GetASTData(lldb::LanguageType language); // Used for the REPL to limit source file ranges that are valid within "file". // Since diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h index caa82b2d80df..6ca6cd3cf2e6 100644 --- a/include/lldb/Symbol/SymbolVendor.h +++ b/include/lldb/Symbol/SymbolVendor.h @@ -163,7 +163,8 @@ class SymbolVendor : public ModuleChild, public PluginInterface { virtual bool SymbolContextShouldBeExcluded(const SymbolContext &sc, uint32_t actual_line); - virtual lldb::DataBufferSP GetASTData(lldb::LanguageType language); + virtual std::vector + GetASTData(lldb::LanguageType language); virtual bool ForceInlineSourceFileCheck(); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 6657995caa58..fdfef1dbeed9 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1441,20 +1441,65 @@ SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data, return num_line_entries_added; } -DataBufferSP SymbolFileDWARFDebugMap::GetASTData(lldb::LanguageType language) { - if (language == eLanguageTypeSwift) { - Symtab *symtab = m_obj_file->GetSymtab(); - if (symtab) { - uint32_t start_idx = 0; - Symbol *symbol = - symtab->FindSymbolWithType(eSymbolTypeASTFile, Symtab::eDebugAny, - Symtab::eVisibilityAny, start_idx); - if (symbol) { - FileSpec file_spec(symbol->GetName().GetCString(), false); - if (file_spec.Exists()) - return file_spec.ReadFileContents(); +std::vector +SymbolFileDWARFDebugMap::GetASTData(lldb::LanguageType language) { + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); + + std::vector ast_datas; + if (language != eLanguageTypeSwift) { + if (log) + log->Printf("SymbolFileDWARFDebugMap::%s() - ignoring because not Swift", + __FUNCTION__); + return ast_datas; + } + + Symtab *symtab = m_obj_file->GetSymtab(); + if (!symtab) { + if (log) + log->Printf("SymbolFileDWARFDebugMap::%s() - ignoring because the obj " + "file has no symbol table", + __FUNCTION__); + return ast_datas; + } + + uint32_t next_idx = 0; + bool done = false; + do { + Symbol *symbol = + symtab->FindSymbolWithType(eSymbolTypeASTFile, Symtab::eDebugAny, + Symtab::eVisibilityAny, next_idx); + if (symbol == nullptr) { + // We didn't find any more symbols of type eSymbolTypeASTFile. We are + // done looping for them. + done = true; + } else { + // Try to load the specified file. + FileSpec file_spec(symbol->GetName().GetCString(), false); + if (file_spec.Exists()) { + // We found the source data for the AST data blob. + // Read it in and add it to our return vector. + ast_datas.push_back(file_spec.ReadFileContents()); + if (log) + log->Printf("SymbolFileDWARFDebugMap::%s() - found and loaded AST " + "data from file %s", + __FUNCTION__, file_spec.GetPath().c_str()); + } else { + if (log) + log->Printf("SymbolFileDWARFDebugMap::%s() - found reference to AST " + "file %s, but could not find the file, ignoring", + __FUNCTION__, file_spec.GetPath().c_str()); } + + // Regardless of whether we could find the specified file, start the next + // symbol search at the index past the one we just found. + ++next_idx; } - } - return DataBufferSP(); + } while (!done); + + // Return the vector of AST data blobs + if (log) + log->Printf("SymbolFileDWARFDebugMap::%s() - returning %d AST data blobs", + __FUNCTION__, (int)ast_datas.size()); + + return ast_datas; } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 130cb0e34317..25cceb415738 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -122,7 +122,8 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { uint32_t type_mask, lldb_private::TypeList &type_list) override; - lldb::DataBufferSP GetASTData(lldb::LanguageType language) override; + std::vector + GetASTData(lldb::LanguageType language) override; //------------------------------------------------------------------ // PluginInterface protocol diff --git a/source/Symbol/SwiftASTContext.cpp b/source/Symbol/SwiftASTContext.cpp index f7b7a174b3b2..855f532461c6 100644 --- a/source/Symbol/SwiftASTContext.cpp +++ b/source/Symbol/SwiftASTContext.cpp @@ -1345,19 +1345,23 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, if (sym_vendor) { // Use the new loadFromSerializedAST if possible: - DataBufferSP ast_file_data_sp = - sym_vendor->GetASTData(eLanguageTypeSwift); + auto ast_file_datas = sym_vendor->GetASTData(eLanguageTypeSwift); bool got_serialized_options = false; - if (ast_file_data_sp) { + DataBufferSP ast_file_data_sp; + if (!ast_file_datas.empty() && + ((ast_file_data_sp = ast_file_datas.front()) != nullptr)) { if (log) - log->Printf("Found AST file data for library: %s.", + log->Printf("Found %d AST file data entries for library: %s.", + (int)ast_file_datas.size(), module->GetSpecificationDescription().c_str()); + + // Retrieve the first serialized AST data blob and initialize + // the compiler invocation with it. llvm::StringRef section_data_ref( (const char *)ast_file_data_sp->GetBytes(), ast_file_data_sp->GetByteSize()); - - swift::serialization::Status result = + auto result = swift_ast_sp->GetCompilerInvocation().loadFromSerializedAST( section_data_ref); @@ -1702,8 +1706,13 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, if (exe_module_sp) { SymbolVendor *sym_vendor = exe_module_sp->GetSymbolVendor(); if (sym_vendor) { - DataBufferSP ast_data_sp = sym_vendor->GetASTData(eLanguageTypeSwift); - if (ast_data_sp) { + // Retrieve the Swift ASTs from the symbol vendor. + auto ast_datas = sym_vendor->GetASTData(eLanguageTypeSwift); + if (!ast_datas.empty()) { + // We only initialize the compiler invocation with the first + // AST since it initializes some data that must remain static, like + // the SDK path and the triple for the produced output. + auto ast_data_sp = ast_datas.front(); llvm::StringRef section_data_ref( (const char *)ast_data_sp->GetBytes(), ast_data_sp->GetByteSize()); @@ -1716,8 +1725,8 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); if (log) log->Printf("Attempt to load compiler options from Serialized " - "AST failed: %d.", - result); + "AST failed: %d (%zu AST data blobs total).", + result, ast_datas.size()); } } } @@ -3914,6 +3923,8 @@ bool SwiftASTContext::RegisterSectionModules( Module &module, std::vector &module_names) { VALID_OR_RETURN(false); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + swift::SerializedModuleLoader *sml = GetSerializeModuleLoader(); if (sml) { SectionList *section_list = module.GetSectionList(); @@ -3940,20 +3951,54 @@ bool SwiftASTContext::RegisterSectionModules( SymbolVendor *sym_vendor = module.GetSymbolVendor(); if (sym_vendor) { - DataBufferSP ast_file_data_sp = - sym_vendor->GetASTData(eLanguageTypeSwift); - if (ast_file_data_sp) { - m_ast_file_data_map[&module] = ast_file_data_sp; + // Grab all the AST blobs from the symbol vendor. + auto ast_file_datas = sym_vendor->GetASTData(eLanguageTypeSwift); + if (log) + log->Printf("SwiftASTContext::%s() retrieved %zu AST Data blobs " + "from the symbol vendor.", + __FUNCTION__, ast_file_datas.size()); + + // Add each of the AST blobs to the vector of AST blobs for the + // module. + auto &ast_vector = GetASTVectorForModule(&module); + ast_vector.insert(ast_vector.end(), ast_file_datas.begin(), + ast_file_datas.end()); + + // Retrieve the module names from the AST blobs retrieved from the + // symbol vendor. + size_t parse_fail_count = 0; + size_t ast_number = 0; + for (auto ast_file_data_sp : ast_file_datas) { + // Parse the AST section info from the AST blob. + ++ast_number; llvm::StringRef section_data_ref( (const char *)ast_file_data_sp->GetBytes(), ast_file_data_sp->GetByteSize()); llvm::SmallVector llvm_modules; if (swift::parseASTSection(sml, section_data_ref, llvm_modules)) { + // Collect the LLVM module names referenced by the AST. for (auto module_name : llvm_modules) module_names.push_back(module_name); - return true; + if (log) + log->Printf("SwiftASTContext::%s() - parsed %zu llvm modules " + "from Swift AST section %zu of %zu.", + __FUNCTION__, llvm_modules.size(), ast_number, + ast_file_datas.size()); + } else { + // Keep track of the fact that we failed to parse the AST + // section info. + if (log) + log->Printf("SwiftASTContext::%s() - failed to parse AST " + "section %zu of %zu.", + __FUNCTION__, ast_number, ast_file_datas.size()); + ++parse_fail_count; } } + if (!ast_file_datas.empty() && (parse_fail_count == 0)) { + // We found AST data entries and we successfully parsed all of + // them. + return true; + } } } } @@ -5609,13 +5654,6 @@ bool SwiftASTContext::IsSelfArchetypeType(const CompilerType &compiler_type) { } } return false; - - if (llvm::dyn_cast_or_null(compiler_type.GetTypeSystem())) { - if (swift::ArchetypeType *archetype = llvm::dyn_cast( - (swift::TypeBase *)compiler_type.GetOpaqueQualType())) - return archetype->isSelfDerived(); - } - return false; } bool SwiftASTContext::IsPossibleZeroSizeType( @@ -9168,6 +9206,11 @@ DWARFASTParser *SwiftASTContext::GetDWARFParser() { return m_dwarf_ast_parser_ap.get(); } +std::vector & +SwiftASTContext::GetASTVectorForModule(const Module *module) { + return m_ast_file_data_map[const_cast(module)]; +} + SwiftASTContextForExpressions::SwiftASTContextForExpressions(Target &target) : SwiftASTContext(target.GetArchitecture().GetTriple().getTriple().c_str(), &target), diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp index a30d9a19159c..9beb0a3b8f67 100644 --- a/source/Symbol/SymbolFile.cpp +++ b/source/Symbol/SymbolFile.cpp @@ -129,9 +129,10 @@ bool SymbolFile::SymbolContextShouldBeExcluded(const SymbolContext &sc, return false; } -lldb::DataBufferSP SymbolFile::GetASTData(lldb::LanguageType language) { +std::vector +SymbolFile::GetASTData(lldb::LanguageType language) { // SymbolFile subclasses must add this functionality - return lldb::DataBufferSP(); + return std::vector(); } uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp index 0579ba0cf8b4..6ed988111f3c 100644 --- a/source/Symbol/SymbolVendor.cpp +++ b/source/Symbol/SymbolVendor.cpp @@ -537,12 +537,16 @@ bool SymbolVendor::SymbolContextShouldBeExcluded(const SymbolContext &sc, return false; } -DataBufferSP SymbolVendor::GetASTData(lldb::LanguageType language) { +std::vector +SymbolVendor::GetASTData(lldb::LanguageType language) { + std::vector ast_datas; + + if (language != eLanguageTypeSwift) + return ast_datas; + // Sometimes the AST Section data is found from the module, so look there // first: SectionList *section_list = GetModule()->GetSectionList(); - if (language != eLanguageTypeSwift) - return DataBufferSP(); if (section_list) { SectionSP section_sp( @@ -551,20 +555,20 @@ DataBufferSP SymbolVendor::GetASTData(lldb::LanguageType language) { DataExtractor section_data; if (section_sp->GetSectionData(section_data)) { - return DataBufferSP( + ast_datas.push_back(DataBufferSP( new DataBufferHeap((const char *)section_data.GetDataStart(), - section_data.GetByteSize())); + section_data.GetByteSize()))); + return ast_datas; } } } // If we couldn't find it in the Module, then look for it in the SymbolFile: SymbolFile *sym_file = GetSymbolFile(); - if (sym_file) - return sym_file->GetASTData(language); + ast_datas = sym_file->GetASTData(language); - return DataBufferSP(); + return ast_datas; } bool SymbolVendor::ForceInlineSourceFileCheck() { From a646342616653fb17aae53ba82807dfc875ce100 Mon Sep 17 00:00:00 2001 From: Todd Fiala Date: Fri, 16 Sep 2016 14:37:10 -0700 Subject: [PATCH 2/2] added tests for SR-2637 --- .../lang/swift/static_linking/macOS/A.swift | 7 ++ .../lang/swift/static_linking/macOS/B.swift | 7 ++ .../lang/swift/static_linking/macOS/Makefile | 29 +++++ .../macOS/TestSwiftStaticLinkingMacOS.py | 114 ++++++++++++++++++ .../swift/static_linking/macOS/objc_main.m | 13 ++ .../swift/static_linking/macOS/output_map | 3 + 6 files changed, 173 insertions(+) create mode 100644 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/A.swift create mode 100644 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/B.swift create mode 100755 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/TestSwiftStaticLinkingMacOS.py create mode 100644 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/objc_main.m create mode 100644 packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/output_map diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/A.swift b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/A.swift new file mode 100644 index 000000000000..2b1cd5ae94b6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/A.swift @@ -0,0 +1,7 @@ +import Foundation + +@objc public class A: NSObject { + public func foo() -> Int { + return 4 // Set breakpoint here + } +} \ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/B.swift b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/B.swift new file mode 100644 index 000000000000..ea6d6e80340e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/B.swift @@ -0,0 +1,7 @@ +import Foundation + +@objc public class B: NSObject { + public func bar() -> Int { + return 8 // Set breakpoint here + } +} \ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/Makefile b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/Makefile new file mode 100755 index 000000000000..9964302b9196 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/Makefile @@ -0,0 +1,29 @@ +# Build swift modules with debug info + +LEVEL=../../../../make + +# Don't use 'all' target. There is a default build rule that will kick in that +# will be wrong. WE use 'first' so that the normal 'make' command (without +# a target) selects the first (but not 'all') target so we avoid the undesired +# default behavior. +first: main + +include $(LEVEL)/Makefile.rules + +# To use the path commented out below, which is what we'd really want to do, +# we'd also need to require that the Swift standard library be built along +# with the compiler. I'd like to avoid that requirement. +# SWIFT_LIB_DIR=$(dir $(SWIFTCC))../lib +SWIFT_LIB_DIR="$(shell xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx" + +main: A.o B.o objc_main.m + $(CC) objc_main.m -fobjc-arc -o main A.o B.o -L$(SWIFT_LIB_DIR) -Xlinker -add_ast_path -Xlinker A.swiftmodule -Xlinker -add_ast_path -Xlinker B.swiftmodule -Xlinker -rpath -Xlinker $(SWIFT_LIB_DIR) + +A.o: A.swift + $(SWIFTCC) -c -g -Onone -sdk "$(SWIFTSDKROOT)" -parse-as-library -module-name A -emit-module-path A.swiftmodule -emit-objc-header-path A-Swift.h -output-file-map output_map A.swift + +B.o: B.swift + $(SWIFTCC) -c -g -Onone -sdk "$(SWIFTSDKROOT)" -parse-as-library -module-name B -emit-module-path B.swiftmodule -emit-objc-header-path B-Swift.h -output-file-map output_map B.swift -o B.o + +clean:: + rm -f *.o main *-Swift.h *.swiftmodule *.swiftdoc diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/TestSwiftStaticLinkingMacOS.py b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/TestSwiftStaticLinkingMacOS.py new file mode 100644 index 000000000000..7e8f723e5f88 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/TestSwiftStaticLinkingMacOS.py @@ -0,0 +1,114 @@ +# TestSwiftStaticLinkingMacOS.py +# +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See http://swift.org/LICENSE.txt for license information +# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +# +# ------------------------------------------------------------------------------ +""" +Test that macOS can statically link two separately-compiled Swift modules +with one Objective-C module, link them through the clang driver, and still +access debug info for each of the Swift modules. +""" +from __future__ import print_function + + +# System imports +import os +import commands + +# Third-party imports + +# LLDB imports +import lldb +from lldbsuite.test.lldbtest import TestBase +from lldbsuite.test import decorators, lldbtest, lldbutil + + +class SwiftStaticLinkingMacOSTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def expect_self_var_available_at_breakpoint( + self, process, breakpoint, module_name): + # Frame #0 should be at the given breakpoint + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, breakpoint) + + self.assertEquals(1, len(threads)) + self.thread = threads[0] + self.frame = self.thread.frames[0] + self.assertTrue(self.frame, "Frame 0 is valid.") + + patterns = [ + # Ensure we report a self with an address. + r"self\s*=\s*0x[0-9a-fA-F]+", + # Ensure we think it is an NSObject. + r"ObjectiveC.NSObject"] + substrs = [ + "(%s.%s)" % (module_name, module_name) + ] + self.expect("frame variable self", patterns=patterns, + substrs=substrs) + + @decorators.skipUnlessDarwin + def test_variables_print_from_both_swift_modules(self): + """Test that variables from two modules can be accessed.""" + self.build() + + # I could not find a reasonable way to say "skipUnless(archs=[])". + # That would probably be worth adding. + if self.getArchitecture() != 'x86_64': + self.skipTest("This test requires x86_64 as the architecture " + "for the inferior") + + exe_name = "main" + src_a = lldb.SBFileSpec("A.swift") + line_a = 5 + src_b = lldb.SBFileSpec("B.swift") + line_b = 5 + exe = os.path.join(os.getcwd(), exe_name) + + # Create the target + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, lldbtest.VALID_TARGET) + + # Set the breakpoints + # breakpoint_a = target.BreakpointCreateBySourceRegex( + # 'Set breakpoint here', src_a) + breakpoint_a = target.BreakpointCreateByLocation( + src_a, line_a) + self.assertTrue(breakpoint_a.GetNumLocations() > 0, + lldbtest.VALID_BREAKPOINT) + + # breakpoint_b = target.BreakpointCreateBySourceRegex( + # 'Set breakpoint here', src_b) + breakpoint_b = target.BreakpointCreateByLocation( + src_b, line_b) + self.assertTrue(breakpoint_b.GetNumLocations() > 0, + lldbtest.VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + envp = ['DYLD_FRAMEWORK_PATH=.'] + process = target.LaunchSimple(None, envp, os.getcwd()) + + self.assertTrue(process, lldbtest.PROCESS_IS_VALID) + + # We should be at breakpoint in module A. + self.expect_self_var_available_at_breakpoint( + process, breakpoint_a, "A") + + # Jump to the next breakpoint + process.Continue() + + # We should be at breakpoint in module B. + self.expect_self_var_available_at_breakpoint( + process, breakpoint_b, "B") + + return diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/objc_main.m b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/objc_main.m new file mode 100644 index 000000000000..98f98b404a70 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/objc_main.m @@ -0,0 +1,13 @@ +#import + +#import "A-Swift.h" +#import "B-Swift.h" + +int main(int argc, const char * argv[]) { + @autoreleasepool { + NSLog(@"Hello, World!"); + NSLog(@"A = %ld", [[[A alloc] init] foo]); + NSLog(@"B = %ld", [[[B alloc] init] bar]); + } + return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/output_map b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/output_map new file mode 100644 index 000000000000..e6c3a615a1f2 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/static_linking/macOS/output_map @@ -0,0 +1,3 @@ +{'A.swift': {'object': 'A.o'}, + 'B.swift': {'object': 'B.o'}, +}