https://github.com/satyajanga created https://github.com/llvm/llvm-project/pull/149019
Summary: This patch adds a new `DynamicLoaderDumpWithModuleList` plugin which can be used for coredump debugging. It leverages NT_FILE note in coredump to get module list instead of relying on posix rdebug data structure which highly depends on having a matching main executable available. Once the module list is generated a ObjectFilePlaceholder is created for each module. This feature is only activated by both two conditions are true: * `use-module-list-dyld` setting is true (false by default) * coredump having `NT_FILE` notes Per my testing, Meta's internal modern Linux kernel seems to always generate `NT_FILE` note so this should be very useful. With this patch, coredump can be changed from ``` lldb <path_to_main_executable> -c <path_to_coredump> ``` to ``` lldb -c <path_to_coredump> ``` Test Plan: * Added new unit test Followup PR for `target module replace` command which enables to replace the object file place holders https://github.com/llvm/llvm-project/pull/148735/ >From 30c14619b06713074423bf879c8d46dbbf5b80a3 Mon Sep 17 00:00:00 2001 From: Jeffrey Tan <jeffrey...@meta.com> Date: Wed, 21 Jul 2021 13:32:56 -0700 Subject: [PATCH] New DynamicLoaderDumpWithModuleList for coredump debugging Summary: This patch adds a new `DynamicLoaderDumpWithModuleList` plugin which can be used for coredump debugging. It leverages NT_FILE note in coredump to get module list instead of relying on posix rdebug data structure which highly depends on having a matching main executable available. Once the module list is generated a ObjectFilePlaceholder is created for each module. This feature is only activated by both two conditions are true: * `use-module-list-dyld` setting is true (false by default) * coredump having `NT_FILE` notes Per my testing, Meta's modern Linux kernel seems to always generate `NT_FILE` note so this should be very useful. With this patch, Meta's internal coredump can be changed from ``` lldb <path_to_main_executable> -c <path_to_coredump> ``` to ``` lldb -c <path_to_coredump> ``` Further diffs involving: * New `target module replace` command to upgrade PlaceHolder module to real module * Coredumper side change to generate fbpkg/rpm metadata so that `auto_debuginfo.py` can automatically locate debug info (in review) * Implement `auto_debuginfo` to parse coredumper metadata to download fbpkg, unzip it, automatically run `target module replace` to upgrade all Placeholder modules into real modules. I am landing this feature internally first because: * Unblock the further work listed above * Early beta testing from our users to get feedback and dogfooding. * Quick turnover from open source code review Once we got solid feedback, I will bring this to open source. Test Plan: * Added new unit test * c4crasher end-to-end debugging Reviewers: wanyi, hyubo, #lldb_team Reviewed By: wanyi Subscribers: jimmymalone, frd, #lldb_team Differential Revision: https://phabricator.intern.facebook.com/D44558615 --- lldb/include/lldb/Core/Debugger.h | 2 + lldb/include/lldb/Core/LoadedModuleInfoList.h | 11 ++ lldb/source/Core/CoreProperties.td | 4 + lldb/source/Core/Debugger.cpp | 7 ++ .../Plugins/DynamicLoader/CMakeLists.txt | 1 + .../ModuleList-DYLD/CMakeLists.txt | 11 ++ .../DynamicLoaderDumpWithModuleList.cpp | 109 ++++++++++++++++++ .../DynamicLoaderDumpWithModuleList.h | 75 ++++++++++++ .../Plugins/Process/elf-core/CMakeLists.txt | 1 + .../Process/elf-core/ProcessElfCore.cpp | 70 ++++++++--- .../Plugins/Process/elf-core/ProcessElfCore.h | 6 + 11 files changed, 283 insertions(+), 14 deletions(-) create mode 100644 lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/CMakeLists.txt create mode 100644 lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.cpp create mode 100644 lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.h diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 504f936fe317a..e854b731270af 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -247,6 +247,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>, FormatEntity::Entry GetDisassemblyFormat() const; + bool GetUseModuleListDyld() const; + FormatEntity::Entry GetFrameFormat() const; FormatEntity::Entry GetFrameFormatUnique() const; diff --git a/lldb/include/lldb/Core/LoadedModuleInfoList.h b/lldb/include/lldb/Core/LoadedModuleInfoList.h index 537a2b0f1d379..5ff62b38d9a9c 100644 --- a/lldb/include/lldb/Core/LoadedModuleInfoList.h +++ b/lldb/include/lldb/Core/LoadedModuleInfoList.h @@ -27,6 +27,7 @@ class LoadedModuleInfoList { e_has_base, e_has_dynamic, e_has_link_map, + e_has_size, e_num }; @@ -77,6 +78,15 @@ class LoadedModuleInfoList { return m_has[e_has_dynamic]; } + void set_size(const lldb::addr_t size) { + m_size = size; + m_has[e_has_size] = true; + } + bool get_size(lldb::addr_t &out) const { + out = m_size; + return m_has[e_has_size]; + } + bool has_info(e_data_point datum) const { assert(datum < e_num); return m_has[datum]; @@ -99,6 +109,7 @@ class LoadedModuleInfoList { lldb::addr_t m_base = LLDB_INVALID_ADDRESS; bool m_base_is_offset = false; lldb::addr_t m_dynamic = LLDB_INVALID_ADDRESS; + lldb::addr_t m_size = 0; }; LoadedModuleInfoList() = default; diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index 53dd333f045c9..9aa86efb48bf4 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -268,4 +268,8 @@ let Definition = "debugger" in { Global, DefaultFalse, Desc<"Controls whether diagnostics can refer directly to the command input, drawing arrows to it. If false, diagnostics will echo the input.">; + def UseModuleListDyld: Property<"use-module-list-dyld", "Boolean">, + Global, + DefaultFalse, + Desc<"Use module list dynamic loader plugin for coredump debugging.">; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index ed674ee1275c7..c653a2caf5405 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -295,6 +295,13 @@ bool Debugger::GetAutoConfirm() const { idx, g_debugger_properties[idx].default_uint_value != 0); } + +bool Debugger::GetUseModuleListDyld() const { + const uint32_t idx = ePropertyUseModuleListDyld; + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); +} + FormatEntity::Entry Debugger::GetDisassemblyFormat() const { constexpr uint32_t idx = ePropertyDisassemblyFormat; return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); diff --git a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt index 01aba34b94169..6db81b125ed9c 100644 --- a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt @@ -8,6 +8,7 @@ set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES add_subdirectory(Darwin-Kernel) add_subdirectory(FreeBSD-Kernel) add_subdirectory(MacOSX-DYLD) +add_subdirectory(ModuleList-DYLD) add_subdirectory(POSIX-DYLD) add_subdirectory(Static) add_subdirectory(Hexagon-DYLD) diff --git a/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/CMakeLists.txt new file mode 100644 index 0000000000000..94d95e3715da1 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginDynamicLoaderDumpWithModuleList PLUGIN + DynamicLoaderDumpWithModuleList.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbTarget + lldbPluginProcessElfCore + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.cpp b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.cpp new file mode 100644 index 0000000000000..3337a69ea80e4 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.cpp @@ -0,0 +1,109 @@ +//===-- DynamicLoaderDumpWithModuleList.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 +// +//===----------------------------------------------------------------------===// + +// Main header include +#include "DynamicLoaderDumpWithModuleList.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +#include "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderDumpWithModuleList, + DynamicLoaderDumpWithModuleList) + +void DynamicLoaderDumpWithModuleList::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); +} + +void DynamicLoaderDumpWithModuleList::Terminate() {} + +llvm::StringRef DynamicLoaderDumpWithModuleList::GetPluginDescriptionStatic() { + return "Dynamic loader plug-in for dumps with module list available"; +} + +DynamicLoader *DynamicLoaderDumpWithModuleList::CreateInstance(Process *process, + bool force) { + // This plug-in is only used when it is requested by name from + // ProcessELFCore. ProcessELFCore will look to see if the core + // file contains a NT_FILE ELF note, and ask for this plug-in + // by name if it does. + if (force) + return new DynamicLoaderDumpWithModuleList(process); + return nullptr; +} + +DynamicLoaderDumpWithModuleList::DynamicLoaderDumpWithModuleList( + Process *process) + : DynamicLoader(process) {} + +DynamicLoaderDumpWithModuleList::~DynamicLoaderDumpWithModuleList() {} + +void DynamicLoaderDumpWithModuleList::DidAttach() { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF(log, "DynamicLoaderDumpWithModuleList::%s() pid %" PRIu64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + + // Curently only used by ProcessELFCore who will return the results of the + // NT_FILE list from ProcessELFCore::GetLoadedModuleList. + llvm::Expected<LoadedModuleInfoList> module_info_list_ep = + m_process->GetLoadedModuleList(); + if (!module_info_list_ep) { + // TODO: log failure. + llvm::consumeError(module_info_list_ep.takeError()); + return; + } + + ModuleList module_list; + const LoadedModuleInfoList &module_info_list = *module_info_list_ep; + for (const LoadedModuleInfoList::LoadedModuleInfo &modInfo : + module_info_list.m_list) { + addr_t base_addr, module_size; + std::string name; + if (!modInfo.get_base(base_addr) || !modInfo.get_name(name) || + !modInfo.get_size(module_size)) + continue; + + addr_t link_map_addr = 0; + FileSpec file(name, m_process->GetTarget().GetArchitecture().GetTriple()); + const bool base_addr_is_offset = false; + ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress( + file, link_map_addr, base_addr, base_addr_is_offset); + if (module_sp.get()) { + LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}", name.c_str()); + module_list.Append(module_sp); + } else { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF( + log, + "DynamicLoaderDumpWithModuleList::%s unable to locate the matching " + "object file %s, creating a placeholder module at 0x%" PRIx64, + __FUNCTION__, name.c_str(), base_addr); + + ModuleSpec module_spec(file, m_process->GetTarget().GetArchitecture()); + module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>( + module_spec, base_addr, module_size); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, + base_addr_is_offset); + m_process->GetTarget().GetImages().Append(module_sp, /*notify*/ true); + } + } + m_process->GetTarget().ModulesDidLoad(module_list); +} + +lldb_private::Status DynamicLoaderDumpWithModuleList::CanLoadImage() { + return Status(); +} diff --git a/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.h b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.h new file mode 100644 index 0000000000000..30c493bdff999 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.h @@ -0,0 +1,75 @@ +//===-- DynamicLoaderDumpWithModuleList.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_DYNAMICLOADER_MODULELIST_DYLD_DYNAMICLOADERDUMPWITHMODULELIST_H +#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MODULELIST_DYLD_DYNAMICLOADERDUMPWITHMODULELIST_H + +#include "lldb/Core/ModuleList.h" +#include "lldb/Target/DynamicLoader.h" + +/** + * Dynamic loader for dump process with module list available. + * For example, some coredump files have NT_FILE note section available + * so can directly provide the module list without main executable's dynamic + * section. + */ +class DynamicLoaderDumpWithModuleList : public lldb_private::DynamicLoader { +public: + DynamicLoaderDumpWithModuleList(lldb_private::Process *process); + + ~DynamicLoaderDumpWithModuleList() override; + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "dump-modulelist-dyld"; + } + + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance(lldb_private::Process *process, bool force); + + // DynamicLoader protocol + + void DidAttach() override; + + void DidLaunch() override { + llvm_unreachable( + "DynamicLoaderDumpWithModuleList::DidLaunch shouldn't be called"); + } + + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override { + llvm_unreachable("DynamicLoaderDumpWithModuleList::" + "GetStepThroughTrampolinePlan shouldn't be called"); + } + + lldb_private::Status CanLoadImage() override; + + lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module, + const lldb::ThreadSP thread, + lldb::addr_t tls_file_addr) override { + // TODO: how to implement this? + return LLDB_INVALID_ADDRESS; + } + + // PluginInterface protocol + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +private: + DynamicLoaderDumpWithModuleList(const DynamicLoaderDumpWithModuleList &) = + delete; + const DynamicLoaderDumpWithModuleList & + operator=(const DynamicLoaderDumpWithModuleList &) = delete; +}; + +#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MODULELIST_DYLD_DYNAMICLOADERDUMPWITHMODULELIST_H diff --git a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt index 0bc26bb0efbe3..7c636e88b58f1 100644 --- a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt @@ -20,6 +20,7 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN LINK_LIBS lldbCore lldbTarget + lldbPluginDynamicLoaderDumpWithModuleList lldbPluginDynamicLoaderPosixDYLD lldbPluginObjectFileELF lldbPluginProcessUtility diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 88eeddf178788..a0402dde5594a 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -11,6 +11,7 @@ #include <memory> #include <mutex> +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -28,6 +29,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Threading.h" +#include "Plugins/DynamicLoader/ModuleList-DYLD/DynamicLoaderDumpWithModuleList.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" @@ -295,12 +297,53 @@ UUID ProcessElfCore::FindModuleUUID(const llvm::StringRef path) { } lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() { - if (m_dyld_up.get() == nullptr) - m_dyld_up.reset(DynamicLoader::FindPlugin( - this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic())); + if (m_dyld_up.get() == nullptr) { + if (GetTarget().GetDebugger().GetUseModuleListDyld()) { + llvm::Expected<LoadedModuleInfoList> module_info_list_ep = + GetLoadedModuleList(); + if (module_info_list_ep && !(*module_info_list_ep).m_list.empty()) + m_dyld_up.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderDumpWithModuleList::GetPluginNameStatic())); + } + + if (m_dyld_up.get() == nullptr) + m_dyld_up.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic())); + } return m_dyld_up.get(); } +llvm::Expected<lldb_private::LoadedModuleInfoList> +ProcessElfCore::GetLoadedModuleList() { + if (m_module_info_list.m_list.empty()) { + std::unordered_map<std::string, std::pair<lldb::addr_t, lldb::addr_t>> + module_range_map; + for (const NT_FILE_Entry &file_entry : m_nt_file_entries) { + const std::string& module_path = file_entry.path; + auto module_iter = module_range_map.find(module_path); + if (module_iter == module_range_map.end() || + module_iter->second.first > file_entry.start) + module_range_map[module_path] = + std::make_pair(file_entry.start, file_entry.end - file_entry.start); + else { + // Expand module's range to include later sections. + auto &module_range = module_range_map[module_path]; + assert(file_entry.end >= module_range.first); + module_range.second = file_entry.end - module_range.first; + } + } + + for (const auto &module_range_entry : module_range_map) { + LoadedModuleInfoList::LoadedModuleInfo module; + module.set_name(module_range_entry.first); + module.set_base(module_range_entry.second.first); + module.set_size(module_range_entry.second.second); + m_module_info_list.add(module); + } + } + return m_module_info_list; +} + bool ProcessElfCore::DoUpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { const uint32_t num_threads = GetNumThreadContexts(); @@ -406,7 +449,7 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, const lldb::addr_t file_start = address_range->data.GetRangeBase(); const lldb::addr_t file_end = address_range->data.GetRangeEnd(); size_t bytes_to_read = size; // Number of bytes to read from the core file - size_t bytes_copied = 0; // Number of bytes actually read from the core file + size_t bytes_copied = 0; // Number of bytes actually read from the core file lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address @@ -489,8 +532,7 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() { // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, - const DataExtractor &data, - bool lp64) { + const DataExtractor &data, bool lp64) { lldb::offset_t offset = 0; int pr_version = data.GetU32(&offset); @@ -517,8 +559,7 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, // Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrPsInfo(ProcessElfCore &process, - const DataExtractor &data, - bool lp64) { + const DataExtractor &data, bool lp64) { lldb::offset_t offset = 0; int pr_version = data.GetU32(&offset); @@ -537,8 +578,7 @@ static void ParseFreeBSDPrPsInfo(ProcessElfCore &process, } static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data, - uint32_t &cpi_nlwps, - uint32_t &cpi_signo, + uint32_t &cpi_nlwps, uint32_t &cpi_signo, uint32_t &cpi_siglwp, uint32_t &cpi_pid) { lldb::offset_t offset = 0; @@ -706,8 +746,8 @@ llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { if (name == "NetBSD-CORE") { if (note.info.n_type == NETBSD::NT_PROCINFO) { - llvm::Error error = ParseNetBSDProcInfo(note.data, nlwps, signo, - siglwp, pr_pid); + llvm::Error error = + ParseNetBSDProcInfo(note.data, nlwps, signo, siglwp, pr_pid); if (error) return error; SetID(pr_pid); @@ -933,7 +973,9 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { Status status = prpsinfo.Parse(note.data, arch); if (status.Fail()) return status.ToError(); - thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname))); + thread_data.name.assign( + prpsinfo.pr_fname, + strnlen(prpsinfo.pr_fname, sizeof(prpsinfo.pr_fname))); SetID(prpsinfo.pr_pid); break; } @@ -987,7 +1029,7 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment( assert(segment_header.p_type == llvm::ELF::PT_NOTE); auto notes_or_error = parseSegment(segment_data); - if(!notes_or_error) + if (!notes_or_error) return notes_or_error.takeError(); switch (GetArchitecture().GetTriple().getOS()) { case llvm::Triple::FreeBSD: diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index a91c04a277f60..cbfa366e90204 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -19,6 +19,7 @@ #include <list> #include <vector> +#include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Target/PostMortemProcess.h" #include "lldb/Utility/Status.h" @@ -74,6 +75,9 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { // Process Queries bool IsAlive() override; + llvm::Expected<lldb_private::LoadedModuleInfoList> + GetLoadedModuleList() override; + bool WarnBeforeDetach() const override { return false; } // Process Memory @@ -152,6 +156,8 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { // NT_FILE entries found from the NOTE segment std::vector<NT_FILE_Entry> m_nt_file_entries; + lldb_private::LoadedModuleInfoList m_module_info_list; + // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment llvm::Error ParseThreadContextsFromNoteSegment( const elf::ELFProgramHeader &segment_header, _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits