diff options
author | Jason Molenda <jason@molenda.com> | 2021-06-20 12:19:50 -0700 |
---|---|---|
committer | Jason Molenda <jason@molenda.com> | 2021-06-20 12:26:54 -0700 |
commit | 9ea6dd5cfac0b233fbb148c1e2d0f81f816737c8 (patch) | |
tree | 9498050b63f4c736f4f86d9cb3c65734517001d2 /lldb/source/Commands/CommandObjectProcess.cpp | |
parent | 1ae266f4529fe17c11331f11db74428b879f3737 (diff) | |
download | llvm-9ea6dd5cfac0b233fbb148c1e2d0f81f816737c8.zip llvm-9ea6dd5cfac0b233fbb148c1e2d0f81f816737c8.tar.gz llvm-9ea6dd5cfac0b233fbb148c1e2d0f81f816737c8.tar.bz2 |
Add a corefile style option to process save-core; skinny corefiles
Add a new feature to process save-core on Darwin systems -- for
lldb to create a user process corefile with only the dirty (modified
memory) pages included. All of the binaries that were used in the
corefile are assumed to still exist on the system for the duration
of the use of the corefile. A new --style option to process save-core
is added, so a full corefile can be requested if portability across
systems, or across time, is needed for this corefile.
debugserver can now identify the dirty pages in a memory region
when queried with qMemoryRegionInfo, and the size of vm pages is
given in qHostInfo.
Create a new "all image infos" LC_NOTE for Mach-O which allows us
to describe all of the binaries that were loaded in the process --
load address, UUID, file path, segment load addresses, and optionally
whether code from the binary was executing on any thread. The old
"read dyld_all_image_infos and then the in-memory Mach-O load
commands to get segment load addresses" no longer works when we
only have dirty memory.
rdar://69670807
Differential Revision: https://reviews.llvm.org/D88387
Diffstat (limited to 'lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectProcess.cpp | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index ad608a6..a0c5fc9 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -1161,26 +1161,91 @@ protected: // CommandObjectProcessSaveCore #pragma mark CommandObjectProcessSaveCore +static constexpr OptionEnumValueElement g_corefile_save_style[] = { + {eSaveCoreFull, "full", "Create a core file with all memory saved"}, + {eSaveCoreDirtyOnly, "modified-memory", + "Create a corefile with only modified memory saved"}}; + +static constexpr OptionEnumValues SaveCoreStyles() { + return OptionEnumValues(g_corefile_save_style); +} + +#define LLDB_OPTIONS_process_save_core +#include "CommandOptions.inc" + class CommandObjectProcessSaveCore : public CommandObjectParsed { public: CommandObjectProcessSaveCore(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process save-core", "Save the current process as a core file using an " "appropriate file type.", - "process save-core FILE", + "process save-core [-s corefile-style] FILE", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched) {} ~CommandObjectProcessSaveCore() override = default; + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() + : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {} + + ~CommandOptions() override = default; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_process_save_core_options); + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + const int short_option = m_getopt_table[option_idx].val; + Status error; + + switch (short_option) { + case 's': + m_requested_save_core_style = + (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( + option_arg, GetDefinitions()[option_idx].enum_values, + eSaveCoreUnspecified, error); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return {}; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_requested_save_core_style = eSaveCoreUnspecified; + } + + // Instance variables to hold the values for command options. + SaveCoreStyle m_requested_save_core_style; + }; + protected: bool DoExecute(Args &command, CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); if (process_sp) { if (command.GetArgumentCount() == 1) { FileSpec output_file(command.GetArgumentAtIndex(0)); - Status error = PluginManager::SaveCore(process_sp, output_file); + SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; + Status error = + PluginManager::SaveCore(process_sp, output_file, corefile_style); if (error.Success()) { + if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) { + result.AppendMessageWithFormat( + "\nModified-memory only corefile " + "created. This corefile may not show \n" + "library/framework/app binaries " + "on a different system, or when \n" + "those binaries have " + "been updated/modified. Copies are not included\n" + "in this corefile. Use --style full to include all " + "process memory.\n"); + } result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat( @@ -1197,6 +1262,8 @@ protected: return result.Succeeded(); } + + CommandOptions m_options; }; // CommandObjectProcessStatus |