From 8652cd1bddd2454a15709c88322182ec47714815 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 16 Jul 2025 21:25:54 -0700 Subject: [PATCH 1/3] [lldb] Add an extra optional did_read_live_memory to Target::ReadMemory Target::ReadMemory may or may not read live memory, but whether it did read from live memory or from the filecache is opaque to callers. Add an extra out parameter to indicate whether live memory was read or not. --- lldb/include/lldb/Target/Target.h | 7 +++++-- lldb/source/Target/Target.cpp | 5 ++++- lldb/unittests/Expression/DWARFExpressionTest.cpp | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index fb062affccc14..50ebcc5a77946 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -1193,11 +1193,14 @@ class Target : public std::enable_shared_from_this, // 2 - if there is a process, then read from memory // 3 - if there is no process, then read from the file cache // + // The optional did_read_live_memory parameter will be set true if live memory + // was read successfully. + // // The method is virtual for mocking in the unit tests. virtual size_t ReadMemory(const Address &addr, void *dst, size_t dst_len, Status &error, bool force_live_memory = false, - lldb::addr_t *load_addr_ptr = nullptr); - + lldb::addr_t *load_addr_ptr = nullptr, + bool *did_read_live_memory = nullptr); size_t ReadCStringFromMemory(const Address &addr, std::string &out_str, Status &error, bool force_live_memory = false); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 853e166e25067..87f9be1b75669 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1921,7 +1921,8 @@ size_t Target::ReadMemoryFromFileCache(const Address &addr, void *dst, size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len, Status &error, bool force_live_memory, - lldb::addr_t *load_addr_ptr) { + lldb::addr_t *load_addr_ptr, + bool *did_read_live_memory) { error.Clear(); Address fixed_addr = addr; @@ -2020,6 +2021,8 @@ size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len, if (bytes_read) { if (load_addr_ptr) *load_addr_ptr = load_addr; + if (did_read_live_memory) + *did_read_live_memory = true; return bytes_read; } } diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index f9e0605fce29d..562e79d657181 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -111,7 +111,8 @@ class MockTarget : public Target { size_t ReadMemory(const Address &addr, void *dst, size_t dst_len, Status &error, bool force_live_memory = false, - lldb::addr_t *load_addr_ptr = nullptr) /*override*/ { + lldb::addr_t *load_addr_ptr = nullptr, + bool *did_read_live_memory = nullptr) /*override*/ { auto expected_memory = this->ReadMemory(addr.GetOffset(), dst_len); if (!expected_memory) { llvm::consumeError(expected_memory.takeError()); From 45b98286f656a0298e8b4f052114e21037949688 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 16 Jul 2025 21:27:51 -0700 Subject: [PATCH 2/3] [lldb] Implement LLDBMemoryReader::readRemoteAddressImpl Use the new out parameter on Target::ReadMemory to set the correct remote address space in readRemoteAddressImpl. rdar://148361743 (cherry picked from commit 3c0342ac3c83499773db6508172b354fc8d48bdd) --- .../Swift/LLDBMemoryReader.cpp | 60 +++++++++++++++---- .../LanguageRuntime/Swift/LLDBMemoryReader.h | 11 ++++ 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp index f8462bf1dc8e5..d3e7d565758f4 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp @@ -225,7 +225,8 @@ LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address, // to a tagged address so further memory reads originating from it benefit // from the file-cache optimization. swift::remote::RemoteAbsolutePointer process_pointer{ - swift::remote::RemoteAddress{readValue, address.getAddressSpace()}}; + swift::remote::RemoteAddress{ + readValue, swift::remote::RemoteAddress::DefaultAddressSpace}}; if (!readMetadataFromFileCacheEnabled()) { assert(address.getAddressSpace() == @@ -314,6 +315,13 @@ LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address, bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, uint8_t *dest, uint64_t size) { + auto [success, _] = readBytesImpl(address, dest, size); + return success; +} + +std::pair +LLDBMemoryReader::readBytesImpl(swift::remote::RemoteAddress address, + uint8_t *dest, uint64_t size) { Log *log = GetLog(LLDBLog::Types); if (m_local_buffer) { bool overflow = false; @@ -322,7 +330,7 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, if (overflow) { LLDB_LOGV(log, "[MemoryReader] address {0:x} + size {1} overflows", addr, size); - return false; + return {false, false}; } if (addr >= *m_local_buffer && end <= *m_local_buffer + m_local_buffer_size) { @@ -330,7 +338,7 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, // GetDynamicTypeAndAddress_Protocol() most likely no longer // hold. memcpy(dest, (void *)addr, size); - return true; + return {true, false}; } } @@ -345,7 +353,7 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, if (!maybeAddr) { LLDB_LOGV(log, "[MemoryReader] could not resolve address {0:x}", address.getRawAddress()); - return false; + return {false, false}; } auto addr = *maybeAddr; if (addr.IsSectionOffset()) { @@ -354,14 +362,15 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, if (object_file->GetType() == ObjectFile::Type::eTypeDebugInfo) { LLDB_LOGV(log, "[MemoryReader] Reading memory from symbol rich binary"); - return object_file->ReadSectionData(section.get(), addr.GetOffset(), dest, - size); + bool success = object_file->ReadSectionData(section.get(), + addr.GetOffset(), dest, size); + return {success, false}; } } if (size > m_max_read_amount) { LLDB_LOGV(log, "[MemoryReader] memory read exceeds maximum allowed size"); - return false; + return {false, false}; } Target &target(m_process.GetTarget()); Status error; @@ -369,15 +378,18 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, // address to section + offset. const bool force_live_memory = !readMetadataFromFileCacheEnabled() || !addr.IsSectionOffset(); - if (size > target.ReadMemory(addr, dest, size, error, force_live_memory)) { + bool did_read_live_memory = false; + if (size > target.ReadMemory(addr, dest, size, error, force_live_memory, + /*load_addr_ptr=*/nullptr, + &did_read_live_memory)) { LLDB_LOGV(log, "[MemoryReader] memory read returned fewer bytes than asked for"); - return false; + return {false, did_read_live_memory}; } if (error.Fail()) { LLDB_LOGV(log, "[MemoryReader] memory read returned error: {0}", error.AsCString()); - return false; + return {false, did_read_live_memory}; } auto format_data = [](auto dest, auto size) { @@ -391,7 +403,7 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address, LLDB_LOGV(log, "[MemoryReader] memory read returned data: {0}", format_data(dest, size)); - return true; + return {true, did_read_live_memory}; } bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address, @@ -596,6 +608,32 @@ LLDBMemoryReader::getFileAddressAndModuleForTaggedAddress( return {{file_address, module}}; } +bool LLDBMemoryReader::readRemoteAddressImpl( + swift::remote::RemoteAddress address, swift::remote::RemoteAddress &out, + std::size_t size) { + assert((size == 4 || size == 8) && + "Only 32 or 64 bit architectures are supported!"); + auto *dest = (uint8_t *)std::malloc(size); + auto defer = llvm::make_scope_exit([&] { free(dest); }); + + auto [success, did_read_live_memory] = readBytesImpl(address, dest, size); + if (!success) + return false; + + uint8_t addressSpace = did_read_live_memory + ? swift::remote::RemoteAddress::DefaultAddressSpace + : LLDBAddressSpace; + if (size == 4) + out = swift::remote::RemoteAddress(*reinterpret_cast(dest), + addressSpace); + else if (size == 8) + out = swift::remote::RemoteAddress(*reinterpret_cast(dest), + addressSpace); + else + return false; + return true; +} + std::optional LLDBMemoryReader::resolveRemoteAddress( swift::reflection::RemoteAddress address) const { diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h index aa52ff047ecda..901e4636561c6 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h @@ -98,6 +98,11 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { /// Returns whether the filecache optimization is enabled or not. bool readMetadataFromFileCacheEnabled() const; +protected: + bool readRemoteAddressImpl(swift::remote::RemoteAddress address, + swift::remote::RemoteAddress &out, + std::size_t integerSize) override; + private: friend MemoryReaderLocalBufferHolder; @@ -119,6 +124,12 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { std::optional
remoteAddressToLLDBAddress(swift::remote::RemoteAddress address) const; + /// Implementation detail of readBytes. Returns a pair where the first element + /// indicates whether the memory was read successfully, the second element + /// indicates whether live memory was read. + std::pair readBytesImpl(swift::remote::RemoteAddress address, + uint8_t *dest, uint64_t size); + /// Reads memory from the symbol rich binary from the address into dest. /// \return true if it was able to successfully read memory. std::optional
resolveRemoteAddressFromSymbolObjectFile( From f5ba18f6dedae7f7751e67c1c376d4055fb98c36 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 16 Jul 2025 21:46:47 -0700 Subject: [PATCH 3/3] [lldb] Enable filecache optz in 32 bit platforms (cherry picked from commit 9cf59f4dca98889144cb719b7b27d24ca9dd7d1a) --- .../Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp index d3e7d565758f4..ee7237c6c1ddc 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp @@ -768,11 +768,6 @@ LLDBMemoryReader::resolveRemoteAddressFromSymbolObjectFile( } 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(); + return m_process.GetTarget().GetSwiftReadMetadataFromFileCache(); } } // namespace lldb_private