diff options
Diffstat (limited to 'lldb/source')
12 files changed, 144 insertions, 177 deletions
diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp index ec59e27..9a0b47c 100644 --- a/lldb/source/API/SBPlatform.cpp +++ b/lldb/source/API/SBPlatform.cpp @@ -331,6 +331,11 @@ SBPlatform::operator bool() const { return m_opaque_sp.get() != nullptr; } +bool SBPlatform::IsHost() const { + LLDB_INSTRUMENT_VA(this); + return m_opaque_sp.get() != nullptr && m_opaque_sp->IsHost(); +} + void SBPlatform::Clear() { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt index 2aae7d1..01d588f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt @@ -5,7 +5,6 @@ add_lldb_library(lldbPluginExpressionParserClang ClangASTImporter.cpp ClangASTMetadata.cpp ClangASTSource.cpp - ClangDeclVendor.cpp ClangExpressionDeclMap.cpp ClangExpressionHelper.cpp ClangExpressionParser.cpp diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index ebe7be4..0efeb2e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -8,7 +8,6 @@ #include "ClangASTSource.h" -#include "ClangDeclVendor.h" #include "ClangModulesDeclVendor.h" #include "lldb/Core/Module.h" @@ -799,7 +798,7 @@ void ClangASTSource::FindDeclInModules(NameSearchContext &context, bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) return; @@ -807,7 +806,8 @@ void ClangASTSource::FindDeclInModules(NameSearchContext &context, LLDB_LOG(log, " CAS::FEVD Matching entity found for \"{0}\" in the modules", name); - clang::NamedDecl *const decl_from_modules = decls[0]; + auto *const decl_from_modules = + llvm::cast<NamedDecl>(ClangUtil::GetDecl(decls[0])); if (llvm::isa<clang::TypeDecl>(decl_from_modules) || llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || @@ -849,16 +849,16 @@ void ClangASTSource::FindDeclInObjCRuntime(NameSearchContext &context, bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; - auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + auto *clang_decl_vendor = llvm::cast<DeclVendor>(decl_vendor); if (!clang_decl_vendor->FindDecls(name, append, max_matches, decls)) return; LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\" in the runtime", name); - clang::Decl *copied_decl = CopyDecl(decls[0]); + clang::Decl *copied_decl = CopyDecl(ClangUtil::GetDecl(decls[0])); clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; @@ -1081,14 +1081,14 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ConstString interface_name(interface_decl->getNameAsString().c_str()); bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; if (!modules_decl_vendor->FindDecls(interface_name, append, max_matches, decls)) break; ObjCInterfaceDecl *interface_decl_from_modules = - dyn_cast<ObjCInterfaceDecl>(decls[0]); + dyn_cast<ObjCInterfaceDecl>(ClangUtil::GetDecl(decls[0])); if (!interface_decl_from_modules) break; @@ -1121,15 +1121,15 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ConstString interface_name(interface_decl->getNameAsString().c_str()); bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; - auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + auto *clang_decl_vendor = llvm::cast<DeclVendor>(decl_vendor); if (!clang_decl_vendor->FindDecls(interface_name, append, max_matches, decls)) break; ObjCInterfaceDecl *runtime_interface_decl = - dyn_cast<ObjCInterfaceDecl>(decls[0]); + dyn_cast<ObjCInterfaceDecl>(ClangUtil::GetDecl(decls[0])); if (!runtime_interface_decl) break; @@ -1254,13 +1254,13 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; if (!modules_decl_vendor->FindDecls(class_name, append, max_matches, decls)) break; DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules( - dyn_cast<ObjCInterfaceDecl>(decls[0])); + dyn_cast<ObjCInterfaceDecl>(ClangUtil::GetDecl(decls[0]))); if (!interface_decl_from_modules.IsValid()) break; @@ -1297,14 +1297,14 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; - auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + auto *clang_decl_vendor = llvm::cast<DeclVendor>(decl_vendor); if (!clang_decl_vendor->FindDecls(class_name, append, max_matches, decls)) break; DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime( - dyn_cast<ObjCInterfaceDecl>(decls[0])); + dyn_cast<ObjCInterfaceDecl>(ClangUtil::GetDecl(decls[0]))); if (!interface_decl_from_runtime.IsValid()) break; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp deleted file mode 100644 index 867d4ff..0000000 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===-- ClangDeclVendor.cpp -----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" -#include "Plugins/ExpressionParser/Clang/ClangUtil.h" -#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" - -#include "lldb/Utility/ConstString.h" - -using namespace lldb_private; - -uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append, - uint32_t max_matches, - std::vector<clang::NamedDecl *> &decls) { - if (!append) - decls.clear(); - - std::vector<CompilerDecl> compiler_decls; - uint32_t ret = FindDecls(name, /*append*/ false, max_matches, compiler_decls); - for (CompilerDecl compiler_decl : compiler_decls) { - clang::Decl *d = ClangUtil::GetDecl(compiler_decl); - clang::NamedDecl *nd = llvm::cast<clang::NamedDecl>(d); - decls.push_back(nd); - } - return ret; -} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h deleted file mode 100644 index a9b2d41..0000000 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- ClangDeclVendor.h ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGDECLVENDOR_H -#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGDECLVENDOR_H - -#include "lldb/Symbol/DeclVendor.h" - -namespace clang { -class NamedDecl; -} - -namespace lldb_private { - -// A clang specialized extension to DeclVendor. -class ClangDeclVendor : public DeclVendor { -public: - ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {} - - ~ClangDeclVendor() override = default; - - using DeclVendor::FindDecls; - - uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, - std::vector<clang::NamedDecl *> &decls); - - static bool classof(const DeclVendor *vendor) { - return vendor->GetKind() >= eClangDeclVendor && - vendor->GetKind() < eLastClangDeclVendor; - } - -private: - ClangDeclVendor(const ClangDeclVendor &) = delete; - const ClangDeclVendor &operator=(const ClangDeclVendor &) = delete; -}; -} // namespace lldb_private - -#endif diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 833bc3b..9cb8f7a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1023,13 +1023,14 @@ void ClangExpressionDeclMap::LookupInModulesDeclVendor( bool append = false; uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) return; assert(!decls.empty() && "FindDecls returned true but no decls?"); - clang::NamedDecl *const decl_from_modules = decls[0]; + auto *const decl_from_modules = + llvm::cast<NamedDecl>(ClangUtil::GetDecl(decls[0])); LLDB_LOG(log, " CAS::FEVD Matching decl found for " @@ -1223,7 +1224,7 @@ bool ClangExpressionDeclMap::LookupFunction( Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - std::vector<clang::NamedDecl *> decls_from_modules; + std::vector<CompilerDecl> decls_from_modules; if (target) { if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor = @@ -1314,7 +1315,8 @@ bool ClangExpressionDeclMap::LookupFunction( } if (!found_function_with_type_info) { - for (clang::NamedDecl *decl : decls_from_modules) { + for (const CompilerDecl &compiler_decl : decls_from_modules) { + clang::Decl *decl = ClangUtil::GetDecl(compiler_decl); if (llvm::isa<clang::FunctionDecl>(decl)) { clang::NamedDecl *copied_decl = llvm::cast_or_null<FunctionDecl>(CopyDecl(decl)); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 67984c5..b77e269 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -226,7 +226,7 @@ void StoringDiagnosticConsumer::SetCurrentModuleProgress( } ClangModulesDeclVendor::ClangModulesDeclVendor() - : ClangDeclVendor(eClangModuleDeclVendor) {} + : DeclVendor(eClangModuleDeclVendor) {} ClangModulesDeclVendor::~ClangModulesDeclVendor() = default; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index d820552..ad4d060 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -9,17 +9,16 @@ #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGMODULESDECLVENDOR_H #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGMODULESDECLVENDOR_H +#include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/SourceModule.h" #include "lldb/Target/Platform.h" -#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" - #include <set> #include <vector> namespace lldb_private { -class ClangModulesDeclVendor : public ClangDeclVendor { +class ClangModulesDeclVendor : public DeclVendor { public: // Constructors and Destructors ClangModulesDeclVendor(); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 460c503..954f269 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -281,22 +281,23 @@ ClassDescriptorV2::ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses, const size_t num_methods = addresses.size(); llvm::SmallVector<uint8_t, 0> buffer(num_methods * size, 0); - llvm::DenseSet<uint32_t> failed_indices; - for (auto [idx, addr] : llvm::enumerate(addresses)) { - Status error; - process->ReadMemory(addr, buffer.data() + idx * size, size, error); - if (error.Fail()) - failed_indices.insert(idx); - } + llvm::SmallVector<Range<addr_t, size_t>> mem_ranges = + llvm::to_vector(llvm::map_range(llvm::seq(num_methods), [&](size_t idx) { + return Range<addr_t, size_t>(addresses[idx], size); + })); + + llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> read_results = + process->ReadMemoryRanges(mem_ranges, buffer); llvm::SmallVector<method_t, 0> methods; methods.reserve(num_methods); - for (auto [idx, addr] : llvm::enumerate(addresses)) { - if (failed_indices.contains(idx)) + for (auto [addr, memory] : llvm::zip(addresses, read_results)) { + // Ignore partial reads. + if (memory.size() != size) continue; - DataExtractor extractor(buffer.data() + idx * size, size, - process->GetByteOrder(), + + DataExtractor extractor(memory.data(), size, process->GetByteOrder(), process->GetAddressByteSize()); methods.push_back(method_t()); methods.back().Read(extractor, process, addr, relative_string_base_addr, diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index d6d2df2..60f9893 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -131,7 +131,7 @@ private: }; AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) - : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), + : DeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), m_type_realizer_sp(m_runtime.GetEncodingToType()) { m_ast_ctx = std::make_shared<TypeSystemClang>( "AppleObjCDeclVendor AST", @@ -537,83 +537,75 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, if (!append) decls.clear(); - uint32_t ret = 0; + // See if the type is already in our ASTContext. - do { - // See if the type is already in our ASTContext. - - clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); - - clang::IdentifierInfo &identifier_info = - ast_ctx.Idents.get(name.GetStringRef()); - clang::DeclarationName decl_name = - ast_ctx.DeclarationNames.getIdentifier(&identifier_info); - - clang::DeclContext::lookup_result lookup_result = - ast_ctx.getTranslationUnitDecl()->lookup(decl_name); - - if (!lookup_result.empty()) { - if (clang::ObjCInterfaceDecl *result_iface_decl = - llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) { - if (log) { - clang::QualType result_iface_type = - ast_ctx.getObjCInterfaceType(result_iface_decl); - - uint64_t isa_value = LLDB_INVALID_ADDRESS; - if (std::optional<ClangASTMetadata> metadata = - m_ast_ctx->GetMetadata(result_iface_decl)) - isa_value = metadata->GetISAPtr(); - - LLDB_LOGF(log, - "AOCTV::FT Found %s (isa 0x%" PRIx64 ") in the ASTContext", - result_iface_type.getAsString().data(), isa_value); - } + clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); - decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl)); - ret++; - break; - } else { - LLDB_LOGF(log, "AOCTV::FT There's something in the ASTContext, but " - "it's not something we know about"); - break; + clang::IdentifierInfo &identifier_info = + ast_ctx.Idents.get(name.GetStringRef()); + clang::DeclarationName decl_name = + ast_ctx.DeclarationNames.getIdentifier(&identifier_info); + + clang::DeclContext::lookup_result lookup_result = + ast_ctx.getTranslationUnitDecl()->lookup(decl_name); + + if (!lookup_result.empty()) { + if (clang::ObjCInterfaceDecl *result_iface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) { + if (log) { + clang::QualType result_iface_type = + ast_ctx.getObjCInterfaceType(result_iface_decl); + + uint64_t isa_value = LLDB_INVALID_ADDRESS; + if (std::optional<ClangASTMetadata> metadata = + m_ast_ctx->GetMetadata(result_iface_decl)) + isa_value = metadata->GetISAPtr(); + + LLDB_LOGF(log, + "AOCTV::FT Found %s (isa 0x%" PRIx64 ") in the ASTContext", + result_iface_type.getAsString().data(), isa_value); } - } else if (log) { - LLDB_LOGF(log, "AOCTV::FT Couldn't find %s in the ASTContext", - name.AsCString()); + + decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl)); + return 1; } - // It's not. If it exists, we have to put it into our ASTContext. + LLDB_LOGF(log, "AOCTV::FT There's something in the ASTContext, but " + "it's not something we know about"); + return 0; + } - ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); + LLDB_LOGF(log, "AOCTV::FT Couldn't find %s in the ASTContext", + name.AsCString()); - if (!isa) { - LLDB_LOGF(log, "AOCTV::FT Couldn't find the isa"); + // It's not. If it exists, we have to put it into our ASTContext. - break; - } + ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); - clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); + if (!isa) { + LLDB_LOGF(log, "AOCTV::FT Couldn't find the isa"); - if (!iface_decl) { - LLDB_LOGF(log, - "AOCTV::FT Couldn't get the Objective-C interface for " - "isa 0x%" PRIx64, - (uint64_t)isa); + return 0; + } - break; - } + clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); - if (log) { - clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl); + if (!iface_decl) { + LLDB_LOGF(log, + "AOCTV::FT Couldn't get the Objective-C interface for " + "isa 0x%" PRIx64, + (uint64_t)isa); - LLDB_LOG(log, "AOCTV::FT Created {0} (isa 0x{1:x})", - new_iface_type.getAsString(), (uint64_t)isa); - } + return 0; + } - decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl)); - ret++; - break; - } while (false); + if (log) { + clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl); + + LLDB_LOG(log, "AOCTV::FT Created {0} (isa 0x{1:x})", + new_iface_type.getAsString(), (uint64_t)isa); + } - return ret; + decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl)); + return 1; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 3bb0f77..2cfa86d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -11,15 +11,15 @@ #include "lldb/lldb-private.h" -#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/Symbol/DeclVendor.h" namespace lldb_private { class AppleObjCExternalASTSource; -class AppleObjCDeclVendor : public ClangDeclVendor { +class AppleObjCDeclVendor : public DeclVendor { public: AppleObjCDeclVendor(ObjCLanguageRuntime &runtime); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 3176852..fb9e7eb 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1971,6 +1971,49 @@ size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) { } } +llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> +Process::ReadMemoryRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges, + llvm::MutableArrayRef<uint8_t> buffer) { + auto total_ranges_len = llvm::sum_of( + llvm::map_range(ranges, [](auto range) { return range.size; })); + // If the buffer is not large enough, this is a programmer error. + // In production builds, gracefully fail by returning a length of 0 for all + // ranges. + assert(buffer.size() >= total_ranges_len && "provided buffer is too short"); + if (buffer.size() < total_ranges_len) { + llvm::MutableArrayRef<uint8_t> empty; + return {ranges.size(), empty}; + } + + llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results; + + // While `buffer` has space, take the next requested range and read + // memory into a `buffer` piece, then slice it to remove the used memory. + for (auto [addr, range_len] : ranges) { + Status status; + size_t num_bytes_read = + ReadMemoryFromInferior(addr, buffer.data(), range_len, status); + // FIXME: ReadMemoryFromInferior promises to return 0 in case of errors, but + // it doesn't; it never checks for errors. + if (status.Fail()) + num_bytes_read = 0; + + assert(num_bytes_read <= range_len && "read more than requested bytes"); + if (num_bytes_read > range_len) { + // In production builds, gracefully fail by returning length zero for this + // range. + results.emplace_back(); + continue; + } + + results.push_back(buffer.take_front(num_bytes_read)); + // Slice buffer to remove the used memory. + buffer = buffer.drop_front(num_bytes_read); + } + + return results; +} + void Process::DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr, const uint8_t *buf, size_t size, AddressRanges &matches, size_t alignment, |