diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index dcdc6e76028d1..c361a7e579664 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -169,6 +169,8 @@ class TargetProperties : public Properties { bool GetSwiftCreateModuleContextsInParallel() const; + bool GetSwiftReadMetadataFromFileCache() const; + bool GetEnableAutoImportClangModules() const; bool GetUseAllCompilerFlags() const; @@ -1067,10 +1069,11 @@ class Target : public std::enable_shared_from_this, lldb::addr_t *load_addr_ptr = nullptr); size_t ReadCStringFromMemory(const Address &addr, std::string &out_str, - Status &error); + Status &error, bool force_live_memory = true); size_t ReadCStringFromMemory(const Address &addr, char *dst, - size_t dst_max_len, Status &result_error); + size_t dst_max_len, Status &result_error, + bool force_live_memory = true); size_t ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_size, bool is_signed, Scalar &scalar, diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp index 8531029ddba3d..2241bba5efa51 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp @@ -3,6 +3,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Logging.h" +#include "llvm/Support/MathExtras.h" + using namespace lldb; using namespace lldb_private; @@ -115,6 +117,73 @@ LLDBMemoryReader::getSymbolAddress(const std::string &name) { return swift::remote::RemoteAddress(load_addr); } +swift::remote::RemoteAbsolutePointer +LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address, + uint64_t readValue) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + + // We may have gotten a pointer to a process address, try to map it back + // to a tagged address so further memory reads originating from it benefit + // from the file-cache optimization. + swift::remote::RemoteAbsolutePointer process_pointer("", readValue); + + if (!readMetadataFromFileCacheEnabled()) + return process_pointer; + + auto &target = m_process.GetTarget(); + Address addr; + if (!target.ResolveLoadAddress(readValue, addr)) { + LLDB_LOGV(log, + "[MemoryReader] Could not resolve load address of pointer {0:x} " + "read from {1:x}.", + readValue, address.getAddressData()); + return process_pointer; + } + + auto module_containing_pointer = addr.GetSection()->GetModule(); + + // Check if the module containing the pointer is registered with + // LLDBMemoryReader. + auto pair_iterator = std::find_if( + m_range_module_map.begin(), m_range_module_map.end(), [&](auto pair) { + return std::get(pair) == module_containing_pointer; + }); + + // We haven't registered the image that contains the pointer. + if (pair_iterator == m_range_module_map.end()) { + LLDB_LOG(log, + "[MemoryReader] Could not resolve find module containing pointer " + "{0:x} read from {1:x}.", + readValue, address.getAddressData()); + return process_pointer; + } + + // If the containing image is the first registered one, the image's tagged + // start address for it is the first tagged address. Otherwise, the previous + // pair's address is the start tagged address. + uint64_t start_tagged_address = pair_iterator == m_range_module_map.begin() + ? LLDB_FILE_ADDRESS_BIT + : std::prev(pair_iterator)->first; + + uint64_t tagged_address = start_tagged_address + addr.GetFileAddress(); + + if (tagged_address >= std::get(*pair_iterator)) { + // If the tagged address invades the next image's tagged address space, + // something went wrong. Log it and just return the process address. + LLDB_LOG(log, + "[MemoryReader] Pointer {0:x} read from {1:x} resolved to tagged " + "address {2:x}, which is outside its image address space.", + readValue, address.getAddressData(), tagged_address); + return process_pointer; + } + + LLDB_LOGV(log, + "[MemoryReader] Successfully resolved pointer {0:x} read from " + "{1:x} to tagged address {2:x}.", + readValue, address.getAddressData(), tagged_address); + return swift::remote::RemoteAbsolutePointer("", tagged_address); +} + bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, uint8_t *dest, uint64_t size) { if (m_local_buffer) { @@ -134,15 +203,26 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, LLDB_LOGV(log, "[MemoryReader] asked to read {0} bytes at address {1:x}", size, address.getAddressData()); + llvm::Optional
maybeAddr = + resolveRemoteAddress(address.getAddressData()); + if (!maybeAddr) { + LLDB_LOGV(log, "[MemoryReader] could not resolve address {1:x}", + address.getAddressData()); + return false; + } + auto addr = *maybeAddr; + if (size > m_max_read_amount) { LLDB_LOGV(log, "[MemoryReader] memory read exceeds maximum allowed size"); return false; } - Target &target(m_process.GetTarget()); - Address addr(address.getAddressData()); Status error; - if (size > target.ReadMemory(addr, dest, size, error, true)) { + // We only want to allow the file-cache optimization if we resolved the + // address to section + offset. + const bool force_live_memory = + !readMetadataFromFileCacheEnabled() || !addr.IsSectionOffset(); + if (size > target.ReadMemory(addr, dest, size, error, force_live_memory)) { LLDB_LOGV(log, "[MemoryReader] memory read returned fewer bytes than asked for"); return false; @@ -171,13 +251,25 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address, std::string &dest) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); - LLDB_LOGV(log, "[MemoryReader] asked to read string data at address {0:x}", + LLDB_LOGV(log, "[MemoryReader] asked to read string data at address {0x}", address.getAddressData()); + llvm::Optional
maybeAddr = + resolveRemoteAddress(address.getAddressData()); + if (!maybeAddr) { + LLDB_LOGV(log, "[MemoryReader] could not resolve address {1:x}", + address.getAddressData()); + return false; + } + auto addr = *maybeAddr; + Target &target(m_process.GetTarget()); - Address addr(address.getAddressData()); Status error; - target.ReadCStringFromMemory(addr, dest, error); + // We only want to allow the file-cache optimization if we resolved the + // address to section + offset. + const bool force_live_memory = + !readMetadataFromFileCacheEnabled() || !addr.IsSectionOffset(); + target.ReadCStringFromMemory(addr, dest, error, force_live_memory); if (error.Success()) { auto format_string = [](const std::string &dest) { StreamString stream; @@ -194,11 +286,10 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address, LLDB_LOGV(log, "[MemoryReader] memory read returned data: \"{0}\"", format_string(dest)); return true; - } else { - LLDB_LOGV(log, "[MemoryReader] memory read returned error: {0}", - error.AsCString()); - return false; } + LLDB_LOGV(log, "[MemoryReader] memory read returned error: {0}", + error.AsCString()); + return false; } void LLDBMemoryReader::pushLocalBuffer(uint64_t local_buffer, @@ -214,4 +305,120 @@ void LLDBMemoryReader::popLocalBuffer() { m_local_buffer_size = 0; } +llvm::Optional> +LLDBMemoryReader::addModuleToAddressMap(ModuleSP module) { + if (!readMetadataFromFileCacheEnabled()) + return {}; + + // The first available address is the mask, since subsequent images are mapped + // in ascending order, all of them will contain this mask. + uint64_t module_start_address = LLDB_FILE_ADDRESS_BIT; + if (!m_range_module_map.empty()) + // We map the images contiguously one after the other, all with the tag bit + // set. + // The address that maps the last module is exactly the address the new + // module should start at. + module_start_address = m_range_module_map.back().first; + +#ifndef NDEBUG + static std::initializer_list objc_bits = { + SWIFT_ABI_ARM_IS_OBJC_BIT, + SWIFT_ABI_X86_64_IS_OBJC_BIT, + SWIFT_ABI_ARM64_IS_OBJC_BIT}; + + for (auto objc_bit : objc_bits) + assert((module_start_address & objc_bit) != objc_bit && + "LLDB file address bit clashes with an obj-c bit!"); +#endif + + SectionList *section_list = module->GetObjectFile()->GetSectionList(); + + auto section_list_size = section_list->GetSize(); + if (section_list_size == 0) + return {}; + + auto last_section = + section_list->GetSectionAtIndex(section_list->GetSize() - 1); + // The virtual file address + the size of last section gives us the total size + // of this image in memory. + uint64_t size = last_section->GetFileAddress() + last_section->GetByteSize(); + auto module_end_address = module_start_address + size; + + // The address for the next image is the next pointer aligned address + // available after the end of the current image. + uint64_t next_module_start_address = llvm::alignTo(module_end_address, 8); + m_range_module_map.emplace_back(next_module_start_address, module); + return {{module_start_address, module_end_address}}; +} + +llvm::Optional
+LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + + if (!readMetadataFromFileCacheEnabled()) + return Address(address); + + // If the address contains our mask, this is an image we registered. + if (!(address & LLDB_FILE_ADDRESS_BIT)) + return Address(address); + + // Dummy pair with the address we're looking for. + auto comparison_pair = std::make_pair(address, ModuleSP()); + + // Explicitly compare only the addresses, never the modules in the pairs. + auto pair_iterator = std::lower_bound( + m_range_module_map.begin(), m_range_module_map.end(), comparison_pair, + [](auto &a, auto &b) { return a.first < b.first; }); + + // If the address is larger than anything we have mapped the address is out + if (pair_iterator == m_range_module_map.end()) { + LLDB_LOG(log, + "[MemoryReader] Address {1:x} is larger than the upper bound " + "address of the mapped in modules", + address); + return {}; + } + + ModuleSP module = pair_iterator->second; + uint64_t file_address; + if (pair_iterator == m_range_module_map.begin()) + // Since this is the first registered module, + // clearing the tag bit will give the virtual file address. + file_address = address & ~LLDB_FILE_ADDRESS_BIT; + else + // The end of the previous section is the start of the current one. + file_address = address - std::prev(pair_iterator)->first; + + LLDB_LOGV(log, + "[MemoryReader] Successfully resolved mapped address {1:x} " + "into file address {1:x}", + address, file_address); + auto *object_file = module->GetObjectFile(); + if (!object_file) + return {}; + + Address resolved(file_address, object_file->GetSectionList()); + if (!resolved.IsValid()) { + LLDB_LOG(log, + "[MemoryReader] Could not make a real address out of file " + "address {1:x} and object file {}", + file_address, object_file->GetFileSpec().GetFilename()); + return {}; + } + + LLDB_LOGV(log, + "[MemoryReader] Unsuccessfully resolved mapped address {1:x} " + "into file address {1:x}", + address, address); + return resolved; +} + +bool LLDBMemoryReader::readMetadataFromFileCacheEnabled() const { + auto &triple = m_process.GetTarget().GetArchitecture().GetTriple(); + + // 32 doesn't have a flag bit we can reliably use, so reading from filecache + // is disabled on it. + return m_process.GetTarget().GetSwiftReadMetadataFromFileCache() && + triple.isArch64Bit(); +} } // namespace lldb_private diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h index a53633142dcbc..c634216aa6a8d 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h @@ -11,7 +11,7 @@ namespace lldb_private { class LLDBMemoryReader : public swift::remote::MemoryReader { public: LLDBMemoryReader(Process &p, size_t max_read_amount = INT32_MAX) - : m_process(p) { + : m_process(p), m_range_module_map() { m_max_read_amount = max_read_amount; } @@ -23,6 +23,10 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { swift::remote::RemoteAddress getSymbolAddress(const std::string &name) override; + swift::remote::RemoteAbsolutePointer + resolvePointer(swift::remote::RemoteAddress address, + uint64_t readValue) override; + bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest, uint64_t size) override; @@ -31,7 +35,27 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { void pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size); - void popLocalBuffer(); + void popLocalBuffer(); + + /// Adds the module to the list of modules we're tracking using tagged + /// addresses, so we can read memory from the file cache whenever possible. + /// \return a pair of addresses indicating the start and end of this image in + /// the tagged address space. None on failure. + llvm::Optional> + addModuleToAddressMap(lldb::ModuleSP module); + + /// Returns whether the filecache optimization is enabled or not. + bool readMetadataFromFileCacheEnabled() const; + +private: + /// Resolves the address by either mapping a tagged address back to an LLDB + /// Address with section + offset, or, in case the address is not tagged, + /// constructing an LLDB address with just the offset. + /// \return an Address with Section + offset if we succesfully converted a tagged + /// address back, an Address with just an offset if the address was not tagged, + /// and None if the address was tagged but we couldn't convert it back to an + /// Address. + llvm::Optional
resolveRemoteAddress(uint64_t address) const; private: Process &m_process; @@ -39,6 +63,25 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { llvm::Optional m_local_buffer; uint64_t m_local_buffer_size = 0; + + /// LLDBMemoryReader prefers to read reflection metadata from the + /// binary on disk, which is faster than reading it out of process + /// memory, especially when debugging remotely. To achieve this LLDB + /// registers virtual addresses starting at (0x0 & + /// LLDB_VIRTUAL_ADDRESS_BIT) with ReflectionContext. Sorted by + /// virtual address, m_lldb_virtual_address_map stores each + /// lldb::Module and the first virtual address after the end of that + /// module's virtual address space. + std::vector> m_range_module_map; + + /// The bit used to tag LLDB's virtual addresses as such. See \c + /// m_range_module_map. + const static uint64_t LLDB_FILE_ADDRESS_BIT = 0x2000000000000000; + static_assert(LLDB_FILE_ADDRESS_BIT & SWIFT_ABI_X86_64_SWIFT_SPARE_BITS_MASK, + "LLDB file address bit not in spare bits mask!"); + static_assert(LLDB_FILE_ADDRESS_BIT & SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK, + "LLDB file address bit not in spare bits mask!"); + }; } // namespace lldb_private #endif diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index 19d7165882c25..b3eddc29c5c22 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "SwiftLanguageRuntime.h" +#include "Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h" #include "SwiftLanguageRuntimeImpl.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" @@ -551,10 +552,8 @@ void SwiftLanguageRuntime::ModulesDidLoad(const ModuleList &module_list) { } } -bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext( - ObjectFile &obj_file, llvm::Triple::ObjectFormatType obj_format_type) { - assert(obj_file.GetType() == ObjectFile::eTypeJIT && - "Not a JIT object file!"); +static std::unique_ptr +GetObjectFileFormat(llvm::Triple::ObjectFormatType obj_format_type) { std::unique_ptr obj_file_format; switch (obj_format_type) { case llvm::Triple::MachO: @@ -571,17 +570,27 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext( log->Printf("%s: Could not find out swift reflection section names for " "object format type.", __FUNCTION__); - return false; } + return obj_file_format; +} + +bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext( + ObjectFile &obj_file, llvm::Triple::ObjectFormatType obj_format_type) { + assert(obj_file.GetType() == ObjectFile::eTypeJIT && + "Not a JIT object file!"); + auto obj_file_format = GetObjectFileFormat(obj_format_type); + + if (!obj_file_format) + return false; return m_reflection_ctx->addImage( [&](swift::ReflectionSectionKind section_kind) -> std::pair, uint64_t> { auto section_name = - ConstString(obj_file_format->getSectionName(section_kind)); + obj_file_format->getSectionName(section_kind); for (auto section : *obj_file.GetSectionList()) { JITSection *jit_section = llvm::dyn_cast(section.get()); - if (jit_section && section->GetName() == section_name) { + if (jit_section && section->GetName().AsCString() == section_name) { DataExtractor extractor; auto section_size = section->GetSectionData(extractor); if (!section_size) @@ -603,6 +612,78 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext( }); } +bool SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext( + ModuleSP module, ObjectFile &obj_file) { + auto obj_format_type = + module->GetArchitecture().GetTriple().getObjectFormat(); + + auto obj_file_format = GetObjectFileFormat(obj_format_type); + if (!obj_file_format) + return false; + + llvm::Optional maybe_segment_name = + obj_file_format->getSegmentName(); + if (!maybe_segment_name) + return false; + + llvm::StringRef segment_name = *maybe_segment_name; + auto lldb_memory_reader = GetMemoryReader(); + auto maybe_start_and_end = + lldb_memory_reader->addModuleToAddressMap(module); + if (!maybe_start_and_end) + return false; + + uint64_t start_address, end_address; + std::tie(start_address, end_address) = *maybe_start_and_end; + + auto *section_list = obj_file.GetSectionList(); + auto segment_iter = llvm::find_if(*section_list, [&](auto segment) { + return segment->GetName() == segment_name.begin(); + }); + + if (segment_iter == section_list->end()) + return false; + + auto *segment = segment_iter->get(); + + return m_reflection_ctx->addImage( + [&](swift::ReflectionSectionKind section_kind) + -> std::pair, uint64_t> { + auto section_name = + obj_file_format->getSectionName(section_kind); + for (auto section : segment->GetChildren()) { + // Iterate over the sections until we find the reflection section we + // need. + if (section->GetName().AsCString() == section_name) { + DataExtractor extractor; + auto size = section->GetSectionData(extractor); + auto data = extractor.GetData(); + size = section->GetFileSize(); + if (!data.begin()) + return {}; + + // Alloc a buffer and copy over the reflection section's contents. + // This buffer will be owned by reflection context. + auto *Buf = malloc(size); + std::memcpy(Buf, data.begin(), size); + + // The section's address is the start address for this image + // added with the section's virtual address. We need to use the + // virtual address instead of the file offset because the offsets + // encoded in the reflection section are calculated in the virtual + // address space. + auto address = start_address + section->GetFileAddress(); + assert(address <= end_address && "Address outside of range!"); + + swift::remote::RemoteRef remote_ref(address, Buf); + return {remote_ref, size}; + ; + } + } + return {}; + }); +} + bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( const lldb::ModuleSP &module_sp) { // This function is called from within SetupReflection so it cannot @@ -615,9 +696,10 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( auto *obj_file = module_sp->GetObjectFile(); if (!obj_file) return false; + auto &target = m_process.GetTarget(); Address start_address = obj_file->GetBaseAddress(); auto load_ptr = static_cast( - start_address.GetLoadAddress(&(m_process.GetTarget()))); + start_address.GetLoadAddress(&target)); if (obj_file->GetType() == ObjectFile::eTypeJIT) { auto object_format_type = module_sp->GetArchitecture().GetTriple().getObjectFormat(); @@ -638,6 +720,8 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( if (!found) return true; + auto read_from_file_cache = + GetMemoryReader()->readMetadataFromFileCacheEnabled(); // When dealing with ELF, we need to pass in the contents of the on-disk // file, since the Section Header Table is not present in the child process if (obj_file->GetPluginName().GetStringRef().equals("elf")) { @@ -648,6 +732,10 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( m_reflection_ctx->readELF( swift::remote::RemoteAddress(load_ptr), llvm::Optional(file_buffer)); + } else if (read_from_file_cache && + obj_file->GetPluginName().GetStringRef().equals("mach-o")) { + if (!AddObjectFileToReflectionContext(module_sp, *obj_file)) + m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr)); } else { m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr)); } diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index f0bede7e143a1..bd8202b976dbc 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -405,7 +405,8 @@ const CompilerType &SwiftLanguageRuntimeImpl::GetBoxMetadataType() { return m_box_metadata_type; } -std::shared_ptr + +std::shared_ptr SwiftLanguageRuntimeImpl::GetMemoryReader() { if (!m_memory_reader_sp) m_memory_reader_sp.reset(new LLDBMemoryReader(m_process)); diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 08e9d45a992ce..1ceff84da58b5 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -13,6 +13,7 @@ #ifndef liblldb_SwiftLanguageRuntimeImpl_h_ #define liblldb_SwiftLanguageRuntimeImpl_h_ +#include "LLDBMemoryReader.h" #include "SwiftLanguageRuntime.h" #include "swift/Reflection/TypeLowering.h" #include "llvm/Support/Memory.h" @@ -290,7 +291,7 @@ class SwiftLanguageRuntimeImpl { const CompilerType &GetBoxMetadataType(); - std::shared_ptr GetMemoryReader(); + std::shared_ptr GetMemoryReader(); void PushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size); @@ -309,7 +310,7 @@ class SwiftLanguageRuntimeImpl { llvm::StringSet<> m_library_negative_cache; std::mutex m_negative_cache_mutex; - std::shared_ptr m_memory_reader_sp; + std::shared_ptr m_memory_reader_sp; llvm::DenseMap, SwiftLanguageRuntime::MetadataPromiseSP> @@ -386,6 +387,12 @@ class SwiftLanguageRuntimeImpl { bool AddJitObjectFileToReflectionContext( ObjectFile &obj_file, llvm::Triple::ObjectFormatType obj_format_type); + /// Add the reflections sections to the reflection context by extracting + /// the directly from the object file. + /// \return true on success. + bool AddObjectFileToReflectionContext( + lldb::ModuleSP module, ObjectFile &obj_file); + /// Cache for the debug-info-originating type infos. /// \{ llvm::DenseMap(bytes_left, cache_line_bytes_left); - size_t bytes_read = - ReadMemory(address, curr_dst, bytes_to_read, error, true); + size_t bytes_read = ReadMemory(address, curr_dst, bytes_to_read, error, + force_live_memory); if (bytes_read == 0) { result_error = error; @@ -4180,6 +4182,18 @@ bool TargetProperties::GetSwiftCreateModuleContextsInParallel() const { return true; } +bool TargetProperties::GetSwiftReadMetadataFromFileCache() const { + const Property *exp_property = m_collection_sp->GetPropertyAtIndex( + nullptr, false, ePropertyExperimental); + OptionValueProperties *exp_values = + exp_property->GetValue()->GetAsProperties(); + if (exp_values) + return exp_values->GetPropertyAtIndexAsBoolean( + nullptr, ePropertySwiftReadMetadataFromFileCache, true); + + return true; +} + ArchSpec TargetProperties::GetDefaultArchitecture() const { OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch( nullptr, ePropertyDefaultArch); diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index 92353e220a10b..bdb45c4bd1abd 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -7,6 +7,9 @@ let Definition = "target_experimental" in { def SwiftCreateModuleContextsInParallel : Property<"swift-create-module-contexts-in-parallel", "Boolean">, DefaultTrue, Desc<"Create the per-module Swift AST contexts in parallel.">; + def SwiftReadMetadataFromFileCache: Property<"swift-read-metadata-from-file-cache", "Boolean">, + DefaultFalse, + Desc<"Read Swift reflection metadata from the file cache instead of the process when possible">; } let Definition = "target" in {