Path: blob/main/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
39587 views
//===-- CommandObjectProcess.cpp ------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CommandObjectProcess.h"9#include "CommandObjectBreakpoint.h"10#include "CommandObjectTrace.h"11#include "CommandOptionsProcessAttach.h"12#include "CommandOptionsProcessLaunch.h"13#include "lldb/Breakpoint/Breakpoint.h"14#include "lldb/Breakpoint/BreakpointIDList.h"15#include "lldb/Breakpoint/BreakpointLocation.h"16#include "lldb/Breakpoint/BreakpointName.h"17#include "lldb/Breakpoint/BreakpointSite.h"18#include "lldb/Core/Module.h"19#include "lldb/Core/PluginManager.h"20#include "lldb/Host/OptionParser.h"21#include "lldb/Interpreter/CommandInterpreter.h"22#include "lldb/Interpreter/CommandOptionArgumentTable.h"23#include "lldb/Interpreter/CommandReturnObject.h"24#include "lldb/Interpreter/OptionArgParser.h"25#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"26#include "lldb/Interpreter/Options.h"27#include "lldb/Target/Platform.h"28#include "lldb/Target/Process.h"29#include "lldb/Target/StopInfo.h"30#include "lldb/Target/Target.h"31#include "lldb/Target/Thread.h"32#include "lldb/Target/UnixSignals.h"33#include "lldb/Utility/Args.h"34#include "lldb/Utility/ScriptedMetadata.h"35#include "lldb/Utility/State.h"3637#include "llvm/ADT/ScopeExit.h"3839#include <bitset>40#include <optional>4142using namespace lldb;43using namespace lldb_private;4445class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {46public:47CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,48const char *name, const char *help,49const char *syntax, uint32_t flags,50const char *new_process_action)51: CommandObjectParsed(interpreter, name, help, syntax, flags),52m_new_process_action(new_process_action) {}5354~CommandObjectProcessLaunchOrAttach() override = default;5556protected:57bool StopProcessIfNecessary(Process *process, StateType &state,58CommandReturnObject &result) {59state = eStateInvalid;60if (process) {61state = process->GetState();6263if (process->IsAlive() && state != eStateConnected) {64std::string message;65if (process->GetState() == eStateAttaching)66message =67llvm::formatv("There is a pending attach, abort it and {0}?",68m_new_process_action);69else if (process->GetShouldDetach())70message = llvm::formatv(71"There is a running process, detach from it and {0}?",72m_new_process_action);73else74message =75llvm::formatv("There is a running process, kill it and {0}?",76m_new_process_action);7778if (!m_interpreter.Confirm(message, true)) {79result.SetStatus(eReturnStatusFailed);80return false;81} else {82if (process->GetShouldDetach()) {83bool keep_stopped = false;84Status detach_error(process->Detach(keep_stopped));85if (detach_error.Success()) {86result.SetStatus(eReturnStatusSuccessFinishResult);87process = nullptr;88} else {89result.AppendErrorWithFormat(90"Failed to detach from process: %s\n",91detach_error.AsCString());92}93} else {94Status destroy_error(process->Destroy(false));95if (destroy_error.Success()) {96result.SetStatus(eReturnStatusSuccessFinishResult);97process = nullptr;98} else {99result.AppendErrorWithFormat("Failed to kill process: %s\n",100destroy_error.AsCString());101}102}103}104}105}106return result.Succeeded();107}108109std::string m_new_process_action;110};111112// CommandObjectProcessLaunch113#pragma mark CommandObjectProcessLaunch114class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {115public:116CommandObjectProcessLaunch(CommandInterpreter &interpreter)117: CommandObjectProcessLaunchOrAttach(118interpreter, "process launch",119"Launch the executable in the debugger.", nullptr,120eCommandRequiresTarget, "restart"),121122m_class_options("scripted process", true, 'C', 'k', 'v', 0) {123m_all_options.Append(&m_options);124m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,125LLDB_OPT_SET_ALL);126m_all_options.Finalize();127128AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatOptional);129}130131~CommandObjectProcessLaunch() override = default;132133Options *GetOptions() override { return &m_all_options; }134135std::optional<std::string> GetRepeatCommand(Args ¤t_command_args,136uint32_t index) override {137// No repeat for "process launch"...138return std::string("");139}140141protected:142void DoExecute(Args &launch_args, CommandReturnObject &result) override {143Debugger &debugger = GetDebugger();144Target *target = debugger.GetSelectedTarget().get();145// If our listener is nullptr, users aren't allows to launch146ModuleSP exe_module_sp = target->GetExecutableModule();147148// If the target already has an executable module, then use that. If it149// doesn't then someone must be trying to launch using a path that will150// make sense to the remote stub, but doesn't exist on the local host.151// In that case use the ExecutableFile that was set in the target's152// ProcessLaunchInfo.153if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {154result.AppendError("no file in target, create a debug target using the "155"'target create' command");156return;157}158159StateType state = eStateInvalid;160161if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))162return;163164// Determine whether we will disable ASLR or leave it in the default state165// (i.e. enabled if the platform supports it). First check if the process166// launch options explicitly turn on/off167// disabling ASLR. If so, use that setting;168// otherwise, use the 'settings target.disable-aslr' setting.169bool disable_aslr = false;170if (m_options.disable_aslr != eLazyBoolCalculate) {171// The user specified an explicit setting on the process launch line.172// Use it.173disable_aslr = (m_options.disable_aslr == eLazyBoolYes);174} else {175// The user did not explicitly specify whether to disable ASLR. Fall176// back to the target.disable-aslr setting.177disable_aslr = target->GetDisableASLR();178}179180if (!m_class_options.GetName().empty()) {181m_options.launch_info.SetProcessPluginName("ScriptedProcess");182ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(183m_class_options.GetName(), m_class_options.GetStructuredData());184m_options.launch_info.SetScriptedMetadata(metadata_sp);185target->SetProcessLaunchInfo(m_options.launch_info);186}187188if (disable_aslr)189m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);190else191m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);192193if (target->GetInheritTCC())194m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);195196if (target->GetDetachOnError())197m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);198199if (target->GetDisableSTDIO())200m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);201202// Merge the launch info environment with the target environment.203Environment target_env = target->GetEnvironment();204m_options.launch_info.GetEnvironment().insert(target_env.begin(),205target_env.end());206207llvm::StringRef target_settings_argv0 = target->GetArg0();208209if (!target_settings_argv0.empty()) {210m_options.launch_info.GetArguments().AppendArgument(211target_settings_argv0);212if (exe_module_sp)213m_options.launch_info.SetExecutableFile(214exe_module_sp->GetPlatformFileSpec(), false);215else216m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);217} else {218if (exe_module_sp)219m_options.launch_info.SetExecutableFile(220exe_module_sp->GetPlatformFileSpec(), true);221else222m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);223}224225if (launch_args.GetArgumentCount() == 0) {226m_options.launch_info.GetArguments().AppendArguments(227target->GetProcessLaunchInfo().GetArguments());228} else {229m_options.launch_info.GetArguments().AppendArguments(launch_args);230// Save the arguments for subsequent runs in the current target.231target->SetRunArguments(launch_args);232}233234StreamString stream;235Status error = target->Launch(m_options.launch_info, &stream);236237if (error.Success()) {238ProcessSP process_sp(target->GetProcessSP());239if (process_sp) {240// There is a race condition where this thread will return up the call241// stack to the main command handler and show an (lldb) prompt before242// HandlePrivateEvent (from PrivateStateThread) has a chance to call243// PushProcessIOHandler().244process_sp->SyncIOHandler(0, std::chrono::seconds(2));245246// If we didn't have a local executable, then we wouldn't have had an247// executable module before launch.248if (!exe_module_sp)249exe_module_sp = target->GetExecutableModule();250if (!exe_module_sp) {251result.AppendWarning("Could not get executable module after launch.");252} else {253254const char *archname =255exe_module_sp->GetArchitecture().GetArchitectureName();256result.AppendMessageWithFormat(257"Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),258exe_module_sp->GetFileSpec().GetPath().c_str(), archname);259}260result.SetStatus(eReturnStatusSuccessFinishResult);261// This message will refer to an event that happened after the process262// launched.263llvm::StringRef data = stream.GetString();264if (!data.empty())265result.AppendMessage(data);266result.SetDidChangeProcessState(true);267} else {268result.AppendError(269"no error returned from Target::Launch, and target has no process");270}271} else {272result.AppendError(error.AsCString());273}274}275276CommandOptionsProcessLaunch m_options;277OptionGroupPythonClassWithDict m_class_options;278OptionGroupOptions m_all_options;279};280281#define LLDB_OPTIONS_process_attach282#include "CommandOptions.inc"283284#pragma mark CommandObjectProcessAttach285class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {286public:287CommandObjectProcessAttach(CommandInterpreter &interpreter)288: CommandObjectProcessLaunchOrAttach(289interpreter, "process attach", "Attach to a process.",290"process attach <cmd-options>", 0, "attach"),291m_class_options("scripted process", true, 'C', 'k', 'v', 0) {292m_all_options.Append(&m_options);293m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,294LLDB_OPT_SET_ALL);295m_all_options.Finalize();296}297298~CommandObjectProcessAttach() override = default;299300Options *GetOptions() override { return &m_all_options; }301302protected:303void DoExecute(Args &command, CommandReturnObject &result) override {304PlatformSP platform_sp(305GetDebugger().GetPlatformList().GetSelectedPlatform());306307Target *target = GetDebugger().GetSelectedTarget().get();308// N.B. The attach should be synchronous. It doesn't help much to get the309// prompt back between initiating the attach and the target actually310// stopping. So even if the interpreter is set to be asynchronous, we wait311// for the stop ourselves here.312313StateType state = eStateInvalid;314Process *process = m_exe_ctx.GetProcessPtr();315316if (!StopProcessIfNecessary(process, state, result))317return;318319if (target == nullptr) {320// If there isn't a current target create one.321TargetSP new_target_sp;322Status error;323324error = GetDebugger().GetTargetList().CreateTarget(325GetDebugger(), "", "", eLoadDependentsNo,326nullptr, // No platform options327new_target_sp);328target = new_target_sp.get();329if (target == nullptr || error.Fail()) {330result.AppendError(error.AsCString("Error creating target"));331return;332}333}334335if (!m_class_options.GetName().empty()) {336m_options.attach_info.SetProcessPluginName("ScriptedProcess");337ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(338m_class_options.GetName(), m_class_options.GetStructuredData());339m_options.attach_info.SetScriptedMetadata(metadata_sp);340}341342// Record the old executable module, we want to issue a warning if the343// process of attaching changed the current executable (like somebody said344// "file foo" then attached to a PID whose executable was bar.)345346ModuleSP old_exec_module_sp = target->GetExecutableModule();347ArchSpec old_arch_spec = target->GetArchitecture();348349StreamString stream;350ProcessSP process_sp;351const auto error = target->Attach(m_options.attach_info, &stream);352if (error.Success()) {353process_sp = target->GetProcessSP();354if (process_sp) {355result.AppendMessage(stream.GetString());356result.SetStatus(eReturnStatusSuccessFinishNoResult);357result.SetDidChangeProcessState(true);358} else {359result.AppendError(360"no error returned from Target::Attach, and target has no process");361}362} else {363result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());364}365366if (!result.Succeeded())367return;368369// Okay, we're done. Last step is to warn if the executable module has370// changed:371char new_path[PATH_MAX];372ModuleSP new_exec_module_sp(target->GetExecutableModule());373if (!old_exec_module_sp) {374// We might not have a module if we attached to a raw pid...375if (new_exec_module_sp) {376new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);377result.AppendMessageWithFormat("Executable module set to \"%s\".\n",378new_path);379}380} else if (old_exec_module_sp->GetFileSpec() !=381new_exec_module_sp->GetFileSpec()) {382char old_path[PATH_MAX];383384old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);385new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);386387result.AppendWarningWithFormat(388"Executable module changed from \"%s\" to \"%s\".\n", old_path,389new_path);390}391392if (!old_arch_spec.IsValid()) {393result.AppendMessageWithFormat(394"Architecture set to: %s.\n",395target->GetArchitecture().GetTriple().getTriple().c_str());396} else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {397result.AppendWarningWithFormat(398"Architecture changed from %s to %s.\n",399old_arch_spec.GetTriple().getTriple().c_str(),400target->GetArchitecture().GetTriple().getTriple().c_str());401}402403// This supports the use-case scenario of immediately continuing the404// process once attached.405if (m_options.attach_info.GetContinueOnceAttached()) {406// We have made a process but haven't told the interpreter about it yet,407// so CheckRequirements will fail for "process continue". Set the override408// here:409ExecutionContext exe_ctx(process_sp);410m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);411}412}413414CommandOptionsProcessAttach m_options;415OptionGroupPythonClassWithDict m_class_options;416OptionGroupOptions m_all_options;417};418419// CommandObjectProcessContinue420421#define LLDB_OPTIONS_process_continue422#include "CommandOptions.inc"423424#pragma mark CommandObjectProcessContinue425426class CommandObjectProcessContinue : public CommandObjectParsed {427public:428CommandObjectProcessContinue(CommandInterpreter &interpreter)429: CommandObjectParsed(430interpreter, "process continue",431"Continue execution of all threads in the current process.",432"process continue",433eCommandRequiresProcess | eCommandTryTargetAPILock |434eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}435436~CommandObjectProcessContinue() override = default;437438protected:439class CommandOptions : public Options {440public:441CommandOptions() {442// Keep default values of all options in one place: OptionParsingStarting443// ()444OptionParsingStarting(nullptr);445}446447~CommandOptions() override = default;448449Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,450ExecutionContext *exe_ctx) override {451Status error;452const int short_option = m_getopt_table[option_idx].val;453switch (short_option) {454case 'i':455if (option_arg.getAsInteger(0, m_ignore))456error.SetErrorStringWithFormat(457"invalid value for ignore option: \"%s\", should be a number.",458option_arg.str().c_str());459break;460case 'b':461m_run_to_bkpt_args.AppendArgument(option_arg);462m_any_bkpts_specified = true;463break;464default:465llvm_unreachable("Unimplemented option");466}467return error;468}469470void OptionParsingStarting(ExecutionContext *execution_context) override {471m_ignore = 0;472m_run_to_bkpt_args.Clear();473m_any_bkpts_specified = false;474}475476llvm::ArrayRef<OptionDefinition> GetDefinitions() override {477return llvm::ArrayRef(g_process_continue_options);478}479480uint32_t m_ignore = 0;481Args m_run_to_bkpt_args;482bool m_any_bkpts_specified = false;483};484485void DoExecute(Args &command, CommandReturnObject &result) override {486Process *process = m_exe_ctx.GetProcessPtr();487bool synchronous_execution = m_interpreter.GetSynchronous();488StateType state = process->GetState();489if (state == eStateStopped) {490if (m_options.m_ignore > 0) {491ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());492if (sel_thread_sp) {493StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();494if (stop_info_sp &&495stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {496lldb::break_id_t bp_site_id =497(lldb::break_id_t)stop_info_sp->GetValue();498BreakpointSiteSP bp_site_sp(499process->GetBreakpointSiteList().FindByID(bp_site_id));500if (bp_site_sp) {501const size_t num_owners = bp_site_sp->GetNumberOfConstituents();502for (size_t i = 0; i < num_owners; i++) {503Breakpoint &bp_ref =504bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();505if (!bp_ref.IsInternal()) {506bp_ref.SetIgnoreCount(m_options.m_ignore);507}508}509}510}511}512}513514Target *target = m_exe_ctx.GetTargetPtr();515BreakpointIDList run_to_bkpt_ids;516// Don't pass an empty run_to_breakpoint list, as Verify will look for the517// default breakpoint.518if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)519CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(520m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,521BreakpointName::Permissions::disablePerm);522if (!result.Succeeded()) {523return;524}525result.Clear();526if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {527result.AppendError("continue-to breakpoints did not specify any actual "528"breakpoints or locations");529return;530}531532// First figure out which breakpoints & locations were specified by the533// user:534size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();535std::vector<break_id_t> bkpts_disabled;536std::vector<BreakpointID> locs_disabled;537if (num_run_to_bkpt_ids != 0) {538// Go through the ID's specified, and separate the breakpoints from are539// the breakpoint.location specifications since the latter require540// special handling. We also figure out whether there's at least one541// specifier in the set that is enabled.542BreakpointList &bkpt_list = target->GetBreakpointList();543std::unordered_set<break_id_t> bkpts_seen;544std::unordered_set<break_id_t> bkpts_with_locs_seen;545BreakpointIDList with_locs;546bool any_enabled = false;547548for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {549BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);550break_id_t bp_id = bkpt_id.GetBreakpointID();551break_id_t loc_id = bkpt_id.GetLocationID();552BreakpointSP bp_sp553= bkpt_list.FindBreakpointByID(bp_id);554// Note, VerifyBreakpointOrLocationIDs checks for existence, so we555// don't need to do it again here.556if (bp_sp->IsEnabled()) {557if (loc_id == LLDB_INVALID_BREAK_ID) {558// A breakpoint (without location) was specified. Make sure that559// at least one of the locations is enabled.560size_t num_locations = bp_sp->GetNumLocations();561for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {562BreakpointLocationSP loc_sp563= bp_sp->GetLocationAtIndex(loc_idx);564if (loc_sp->IsEnabled()) {565any_enabled = true;566break;567}568}569} else {570// A location was specified, check if it was enabled:571BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);572if (loc_sp->IsEnabled())573any_enabled = true;574}575576// Then sort the bp & bp.loc entries for later use:577if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)578bkpts_seen.insert(bkpt_id.GetBreakpointID());579else {580bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());581with_locs.AddBreakpointID(bkpt_id);582}583}584}585// Do all the error checking here so once we start disabling we don't586// have to back out half-way through.587588// Make sure at least one of the specified breakpoints is enabled.589if (!any_enabled) {590result.AppendError("at least one of the continue-to breakpoints must "591"be enabled.");592return;593}594595// Also, if you specify BOTH a breakpoint and one of it's locations,596// we flag that as an error, since it won't do what you expect, the597// breakpoint directive will mean "run to all locations", which is not598// what the location directive means...599for (break_id_t bp_id : bkpts_with_locs_seen) {600if (bkpts_seen.count(bp_id)) {601result.AppendErrorWithFormatv("can't specify both a breakpoint and "602"one of its locations: {0}", bp_id);603}604}605606// Now go through the breakpoints in the target, disabling all the ones607// that the user didn't mention:608for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {609break_id_t bp_id = bp_sp->GetID();610// Handle the case where no locations were specified. Note we don't611// have to worry about the case where a breakpoint and one of its612// locations are both in the lists, we've already disallowed that.613if (!bkpts_with_locs_seen.count(bp_id)) {614if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {615bkpts_disabled.push_back(bp_id);616bp_sp->SetEnabled(false);617}618continue;619}620// Next, handle the case where a location was specified:621// Run through all the locations of this breakpoint and disable622// the ones that aren't on our "with locations" BreakpointID list:623size_t num_locations = bp_sp->GetNumLocations();624BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);625for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {626BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);627tmp_id.SetBreakpointLocationID(loc_idx);628if (!with_locs.Contains(tmp_id) && loc_sp->IsEnabled()) {629locs_disabled.push_back(tmp_id);630loc_sp->SetEnabled(false);631}632}633}634}635636{ // Scope for thread list mutex:637std::lock_guard<std::recursive_mutex> guard(638process->GetThreadList().GetMutex());639const uint32_t num_threads = process->GetThreadList().GetSize();640641// Set the actions that the threads should each take when resuming642for (uint32_t idx = 0; idx < num_threads; ++idx) {643const bool override_suspend = false;644process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(645eStateRunning, override_suspend);646}647}648649const uint32_t iohandler_id = process->GetIOHandlerID();650651StreamString stream;652Status error;653// For now we can only do -b with synchronous:654bool old_sync = GetDebugger().GetAsyncExecution();655656if (run_to_bkpt_ids.GetSize() != 0) {657GetDebugger().SetAsyncExecution(false);658synchronous_execution = true;659}660if (synchronous_execution)661error = process->ResumeSynchronous(&stream);662else663error = process->Resume();664665if (run_to_bkpt_ids.GetSize() != 0) {666GetDebugger().SetAsyncExecution(old_sync);667}668669// Now re-enable the breakpoints we disabled:670BreakpointList &bkpt_list = target->GetBreakpointList();671for (break_id_t bp_id : bkpts_disabled) {672BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);673if (bp_sp)674bp_sp->SetEnabled(true);675}676for (const BreakpointID &bkpt_id : locs_disabled) {677BreakpointSP bp_sp678= bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());679if (bp_sp) {680BreakpointLocationSP loc_sp681= bp_sp->FindLocationByID(bkpt_id.GetLocationID());682if (loc_sp)683loc_sp->SetEnabled(true);684}685}686687if (error.Success()) {688// There is a race condition where this thread will return up the call689// stack to the main command handler and show an (lldb) prompt before690// HandlePrivateEvent (from PrivateStateThread) has a chance to call691// PushProcessIOHandler().692process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));693694result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",695process->GetID());696if (synchronous_execution) {697// If any state changed events had anything to say, add that to the698// result699result.AppendMessage(stream.GetString());700701result.SetDidChangeProcessState(true);702result.SetStatus(eReturnStatusSuccessFinishNoResult);703} else {704result.SetStatus(eReturnStatusSuccessContinuingNoResult);705}706} else {707result.AppendErrorWithFormat("Failed to resume process: %s.\n",708error.AsCString());709}710} else {711result.AppendErrorWithFormat(712"Process cannot be continued from its current state (%s).\n",713StateAsCString(state));714}715}716717Options *GetOptions() override { return &m_options; }718719CommandOptions m_options;720};721722// CommandObjectProcessDetach723#define LLDB_OPTIONS_process_detach724#include "CommandOptions.inc"725726#pragma mark CommandObjectProcessDetach727728class CommandObjectProcessDetach : public CommandObjectParsed {729public:730class CommandOptions : public Options {731public:732CommandOptions() { OptionParsingStarting(nullptr); }733734~CommandOptions() override = default;735736Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,737ExecutionContext *execution_context) override {738Status error;739const int short_option = m_getopt_table[option_idx].val;740741switch (short_option) {742case 's':743bool tmp_result;744bool success;745tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);746if (!success)747error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",748option_arg.str().c_str());749else {750if (tmp_result)751m_keep_stopped = eLazyBoolYes;752else753m_keep_stopped = eLazyBoolNo;754}755break;756default:757llvm_unreachable("Unimplemented option");758}759return error;760}761762void OptionParsingStarting(ExecutionContext *execution_context) override {763m_keep_stopped = eLazyBoolCalculate;764}765766llvm::ArrayRef<OptionDefinition> GetDefinitions() override {767return llvm::ArrayRef(g_process_detach_options);768}769770// Instance variables to hold the values for command options.771LazyBool m_keep_stopped;772};773774CommandObjectProcessDetach(CommandInterpreter &interpreter)775: CommandObjectParsed(interpreter, "process detach",776"Detach from the current target process.",777"process detach",778eCommandRequiresProcess | eCommandTryTargetAPILock |779eCommandProcessMustBeLaunched) {}780781~CommandObjectProcessDetach() override = default;782783Options *GetOptions() override { return &m_options; }784785protected:786void DoExecute(Args &command, CommandReturnObject &result) override {787Process *process = m_exe_ctx.GetProcessPtr();788// FIXME: This will be a Command Option:789bool keep_stopped;790if (m_options.m_keep_stopped == eLazyBoolCalculate) {791// Check the process default:792keep_stopped = process->GetDetachKeepsStopped();793} else if (m_options.m_keep_stopped == eLazyBoolYes)794keep_stopped = true;795else796keep_stopped = false;797798Status error(process->Detach(keep_stopped));799if (error.Success()) {800result.SetStatus(eReturnStatusSuccessFinishResult);801} else {802result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());803}804}805806CommandOptions m_options;807};808809// CommandObjectProcessConnect810#define LLDB_OPTIONS_process_connect811#include "CommandOptions.inc"812813#pragma mark CommandObjectProcessConnect814815class CommandObjectProcessConnect : public CommandObjectParsed {816public:817class CommandOptions : public Options {818public:819CommandOptions() {820// Keep default values of all options in one place: OptionParsingStarting821// ()822OptionParsingStarting(nullptr);823}824825~CommandOptions() override = default;826827Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,828ExecutionContext *execution_context) override {829Status error;830const int short_option = m_getopt_table[option_idx].val;831832switch (short_option) {833case 'p':834plugin_name.assign(std::string(option_arg));835break;836837default:838llvm_unreachable("Unimplemented option");839}840return error;841}842843void OptionParsingStarting(ExecutionContext *execution_context) override {844plugin_name.clear();845}846847llvm::ArrayRef<OptionDefinition> GetDefinitions() override {848return llvm::ArrayRef(g_process_connect_options);849}850851// Instance variables to hold the values for command options.852853std::string plugin_name;854};855856CommandObjectProcessConnect(CommandInterpreter &interpreter)857: CommandObjectParsed(interpreter, "process connect",858"Connect to a remote debug service.",859"process connect <remote-url>", 0) {860AddSimpleArgumentList(eArgTypeConnectURL);861}862863~CommandObjectProcessConnect() override = default;864865Options *GetOptions() override { return &m_options; }866867protected:868void DoExecute(Args &command, CommandReturnObject &result) override {869if (command.GetArgumentCount() != 1) {870result.AppendErrorWithFormat(871"'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),872m_cmd_syntax.c_str());873return;874}875876Process *process = m_exe_ctx.GetProcessPtr();877if (process && process->IsAlive()) {878result.AppendErrorWithFormat(879"Process %" PRIu64880" is currently being debugged, kill the process before connecting.\n",881process->GetID());882return;883}884885const char *plugin_name = nullptr;886if (!m_options.plugin_name.empty())887plugin_name = m_options.plugin_name.c_str();888889Status error;890Debugger &debugger = GetDebugger();891PlatformSP platform_sp = m_interpreter.GetPlatform(true);892ProcessSP process_sp =893debugger.GetAsyncExecution()894? platform_sp->ConnectProcess(895command.GetArgumentAtIndex(0), plugin_name, debugger,896debugger.GetSelectedTarget().get(), error)897: platform_sp->ConnectProcessSynchronous(898command.GetArgumentAtIndex(0), plugin_name, debugger,899result.GetOutputStream(), debugger.GetSelectedTarget().get(),900error);901if (error.Fail() || process_sp == nullptr) {902result.AppendError(error.AsCString("Error connecting to the process"));903}904}905906CommandOptions m_options;907};908909// CommandObjectProcessPlugin910#pragma mark CommandObjectProcessPlugin911912class CommandObjectProcessPlugin : public CommandObjectProxy {913public:914CommandObjectProcessPlugin(CommandInterpreter &interpreter)915: CommandObjectProxy(916interpreter, "process plugin",917"Send a custom command to the current target process plug-in.",918"process plugin <args>", 0) {}919920~CommandObjectProcessPlugin() override = default;921922CommandObject *GetProxyCommandObject() override {923Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();924if (process)925return process->GetPluginCommandObject();926return nullptr;927}928};929930// CommandObjectProcessLoad931#define LLDB_OPTIONS_process_load932#include "CommandOptions.inc"933934#pragma mark CommandObjectProcessLoad935936class CommandObjectProcessLoad : public CommandObjectParsed {937public:938class CommandOptions : public Options {939public:940CommandOptions() {941// Keep default values of all options in one place: OptionParsingStarting942// ()943OptionParsingStarting(nullptr);944}945946~CommandOptions() override = default;947948Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,949ExecutionContext *execution_context) override {950Status error;951const int short_option = m_getopt_table[option_idx].val;952ArchSpec arch =953execution_context->GetProcessPtr()->GetSystemArchitecture();954switch (short_option) {955case 'i':956do_install = true;957if (!option_arg.empty())958install_path.SetFile(option_arg, arch.GetTriple());959break;960default:961llvm_unreachable("Unimplemented option");962}963return error;964}965966void OptionParsingStarting(ExecutionContext *execution_context) override {967do_install = false;968install_path.Clear();969}970971llvm::ArrayRef<OptionDefinition> GetDefinitions() override {972return llvm::ArrayRef(g_process_load_options);973}974975// Instance variables to hold the values for command options.976bool do_install;977FileSpec install_path;978};979980CommandObjectProcessLoad(CommandInterpreter &interpreter)981: CommandObjectParsed(interpreter, "process load",982"Load a shared library into the current process.",983"process load <filename> [<filename> ...]",984eCommandRequiresProcess | eCommandTryTargetAPILock |985eCommandProcessMustBeLaunched |986eCommandProcessMustBePaused) {987AddSimpleArgumentList(eArgTypePath, eArgRepeatPlus);988}989990~CommandObjectProcessLoad() override = default;991992void993HandleArgumentCompletion(CompletionRequest &request,994OptionElementVector &opt_element_vector) override {995if (!m_exe_ctx.HasProcessScope())996return;997CommandObject::HandleArgumentCompletion(request, opt_element_vector);998}9991000Options *GetOptions() override { return &m_options; }10011002protected:1003void DoExecute(Args &command, CommandReturnObject &result) override {1004Process *process = m_exe_ctx.GetProcessPtr();10051006for (auto &entry : command.entries()) {1007Status error;1008PlatformSP platform = process->GetTarget().GetPlatform();1009llvm::StringRef image_path = entry.ref();1010uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;10111012if (!m_options.do_install) {1013FileSpec image_spec(image_path);1014platform->ResolveRemotePath(image_spec, image_spec);1015image_token =1016platform->LoadImage(process, FileSpec(), image_spec, error);1017} else if (m_options.install_path) {1018FileSpec image_spec(image_path);1019FileSystem::Instance().Resolve(image_spec);1020platform->ResolveRemotePath(m_options.install_path,1021m_options.install_path);1022image_token = platform->LoadImage(process, image_spec,1023m_options.install_path, error);1024} else {1025FileSpec image_spec(image_path);1026FileSystem::Instance().Resolve(image_spec);1027image_token =1028platform->LoadImage(process, image_spec, FileSpec(), error);1029}10301031if (image_token != LLDB_INVALID_IMAGE_TOKEN) {1032result.AppendMessageWithFormat(1033"Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),1034image_token);1035result.SetStatus(eReturnStatusSuccessFinishResult);1036} else {1037result.AppendErrorWithFormat("failed to load '%s': %s",1038image_path.str().c_str(),1039error.AsCString());1040}1041}1042}10431044CommandOptions m_options;1045};10461047// CommandObjectProcessUnload1048#pragma mark CommandObjectProcessUnload10491050class CommandObjectProcessUnload : public CommandObjectParsed {1051public:1052CommandObjectProcessUnload(CommandInterpreter &interpreter)1053: CommandObjectParsed(1054interpreter, "process unload",1055"Unload a shared library from the current process using the index "1056"returned by a previous call to \"process load\".",1057"process unload <index>",1058eCommandRequiresProcess | eCommandTryTargetAPILock |1059eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {1060AddSimpleArgumentList(eArgTypeUnsignedInteger);1061}10621063~CommandObjectProcessUnload() override = default;10641065void1066HandleArgumentCompletion(CompletionRequest &request,1067OptionElementVector &opt_element_vector) override {10681069if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())1070return;10711072Process *process = m_exe_ctx.GetProcessPtr();10731074const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();1075const size_t token_num = tokens.size();1076for (size_t i = 0; i < token_num; ++i) {1077if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)1078continue;1079request.TryCompleteCurrentArg(std::to_string(i));1080}1081}10821083protected:1084void DoExecute(Args &command, CommandReturnObject &result) override {1085Process *process = m_exe_ctx.GetProcessPtr();10861087for (auto &entry : command.entries()) {1088uint32_t image_token;1089if (entry.ref().getAsInteger(0, image_token)) {1090result.AppendErrorWithFormat("invalid image index argument '%s'",1091entry.ref().str().c_str());1092break;1093} else {1094Status error(process->GetTarget().GetPlatform()->UnloadImage(1095process, image_token));1096if (error.Success()) {1097result.AppendMessageWithFormat(1098"Unloading shared library with index %u...ok\n", image_token);1099result.SetStatus(eReturnStatusSuccessFinishResult);1100} else {1101result.AppendErrorWithFormat("failed to unload image: %s",1102error.AsCString());1103break;1104}1105}1106}1107}1108};11091110// CommandObjectProcessSignal1111#pragma mark CommandObjectProcessSignal11121113class CommandObjectProcessSignal : public CommandObjectParsed {1114public:1115CommandObjectProcessSignal(CommandInterpreter &interpreter)1116: CommandObjectParsed(1117interpreter, "process signal",1118"Send a UNIX signal to the current target process.", nullptr,1119eCommandRequiresProcess | eCommandTryTargetAPILock) {1120AddSimpleArgumentList(eArgTypeUnixSignal);1121}11221123~CommandObjectProcessSignal() override = default;11241125void1126HandleArgumentCompletion(CompletionRequest &request,1127OptionElementVector &opt_element_vector) override {1128if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)1129return;11301131UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();1132int signo = signals->GetFirstSignalNumber();1133while (signo != LLDB_INVALID_SIGNAL_NUMBER) {1134request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo));1135signo = signals->GetNextSignalNumber(signo);1136}1137}11381139protected:1140void DoExecute(Args &command, CommandReturnObject &result) override {1141Process *process = m_exe_ctx.GetProcessPtr();11421143if (command.GetArgumentCount() == 1) {1144int signo = LLDB_INVALID_SIGNAL_NUMBER;11451146const char *signal_name = command.GetArgumentAtIndex(0);1147if (::isxdigit(signal_name[0])) {1148if (!llvm::to_integer(signal_name, signo))1149signo = LLDB_INVALID_SIGNAL_NUMBER;1150} else1151signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);11521153if (signo == LLDB_INVALID_SIGNAL_NUMBER) {1154result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",1155command.GetArgumentAtIndex(0));1156} else {1157Status error(process->Signal(signo));1158if (error.Success()) {1159result.SetStatus(eReturnStatusSuccessFinishResult);1160} else {1161result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,1162error.AsCString());1163}1164}1165} else {1166result.AppendErrorWithFormat(1167"'%s' takes exactly one signal number argument:\nUsage: %s\n",1168m_cmd_name.c_str(), m_cmd_syntax.c_str());1169}1170}1171};11721173// CommandObjectProcessInterrupt1174#pragma mark CommandObjectProcessInterrupt11751176class CommandObjectProcessInterrupt : public CommandObjectParsed {1177public:1178CommandObjectProcessInterrupt(CommandInterpreter &interpreter)1179: CommandObjectParsed(interpreter, "process interrupt",1180"Interrupt the current target process.",1181"process interrupt",1182eCommandRequiresProcess | eCommandTryTargetAPILock |1183eCommandProcessMustBeLaunched) {}11841185~CommandObjectProcessInterrupt() override = default;11861187protected:1188void DoExecute(Args &command, CommandReturnObject &result) override {1189Process *process = m_exe_ctx.GetProcessPtr();1190if (process == nullptr) {1191result.AppendError("no process to halt");1192return;1193}11941195bool clear_thread_plans = true;1196Status error(process->Halt(clear_thread_plans));1197if (error.Success()) {1198result.SetStatus(eReturnStatusSuccessFinishResult);1199} else {1200result.AppendErrorWithFormat("Failed to halt process: %s\n",1201error.AsCString());1202}1203}1204};12051206// CommandObjectProcessKill1207#pragma mark CommandObjectProcessKill12081209class CommandObjectProcessKill : public CommandObjectParsed {1210public:1211CommandObjectProcessKill(CommandInterpreter &interpreter)1212: CommandObjectParsed(interpreter, "process kill",1213"Terminate the current target process.",1214"process kill",1215eCommandRequiresProcess | eCommandTryTargetAPILock |1216eCommandProcessMustBeLaunched) {}12171218~CommandObjectProcessKill() override = default;12191220protected:1221void DoExecute(Args &command, CommandReturnObject &result) override {1222Process *process = m_exe_ctx.GetProcessPtr();1223if (process == nullptr) {1224result.AppendError("no process to kill");1225return;1226}12271228Status error(process->Destroy(true));1229if (error.Success()) {1230result.SetStatus(eReturnStatusSuccessFinishResult);1231} else {1232result.AppendErrorWithFormat("Failed to kill process: %s\n",1233error.AsCString());1234}1235}1236};12371238#define LLDB_OPTIONS_process_save_core1239#include "CommandOptions.inc"12401241class CommandObjectProcessSaveCore : public CommandObjectParsed {1242public:1243CommandObjectProcessSaveCore(CommandInterpreter &interpreter)1244: CommandObjectParsed(1245interpreter, "process save-core",1246"Save the current process as a core file using an "1247"appropriate file type.",1248"process save-core [-s corefile-style -p plugin-name] FILE",1249eCommandRequiresProcess | eCommandTryTargetAPILock |1250eCommandProcessMustBeLaunched) {1251AddSimpleArgumentList(eArgTypePath);1252}12531254~CommandObjectProcessSaveCore() override = default;12551256Options *GetOptions() override { return &m_options; }12571258class CommandOptions : public Options {1259public:1260CommandOptions() = default;12611262~CommandOptions() override = default;12631264llvm::ArrayRef<OptionDefinition> GetDefinitions() override {1265return llvm::ArrayRef(g_process_save_core_options);1266}12671268Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,1269ExecutionContext *execution_context) override {1270const int short_option = m_getopt_table[option_idx].val;1271Status error;12721273switch (short_option) {1274case 'p':1275error = m_core_dump_options.SetPluginName(option_arg.data());1276break;1277case 's':1278m_core_dump_options.SetStyle(1279(lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(1280option_arg, GetDefinitions()[option_idx].enum_values,1281eSaveCoreUnspecified, error));1282break;1283default:1284llvm_unreachable("Unimplemented option");1285}12861287return {};1288}12891290void OptionParsingStarting(ExecutionContext *execution_context) override {1291m_core_dump_options.Clear();1292}12931294// Instance variables to hold the values for command options.1295SaveCoreOptions m_core_dump_options;1296};12971298protected:1299void DoExecute(Args &command, CommandReturnObject &result) override {1300ProcessSP process_sp = m_exe_ctx.GetProcessSP();1301if (process_sp) {1302if (command.GetArgumentCount() == 1) {1303FileSpec output_file(command.GetArgumentAtIndex(0));1304FileSystem::Instance().Resolve(output_file);1305auto &core_dump_options = m_options.m_core_dump_options;1306core_dump_options.SetOutputFile(output_file);1307Status error = PluginManager::SaveCore(process_sp, core_dump_options);1308if (error.Success()) {1309if (core_dump_options.GetStyle() ==1310SaveCoreStyle::eSaveCoreDirtyOnly ||1311core_dump_options.GetStyle() ==1312SaveCoreStyle::eSaveCoreStackOnly) {1313result.AppendMessageWithFormat(1314"\nModified-memory or stack-memory only corefile "1315"created. This corefile may \n"1316"not show library/framework/app binaries "1317"on a different system, or when \n"1318"those binaries have "1319"been updated/modified. Copies are not included\n"1320"in this corefile. Use --style full to include all "1321"process memory.\n");1322}1323result.SetStatus(eReturnStatusSuccessFinishResult);1324} else {1325result.AppendErrorWithFormat(1326"Failed to save core file for process: %s\n", error.AsCString());1327}1328} else {1329result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",1330m_cmd_name.c_str(), m_cmd_syntax.c_str());1331}1332} else {1333result.AppendError("invalid process");1334}1335}13361337CommandOptions m_options;1338};13391340// CommandObjectProcessStatus1341#pragma mark CommandObjectProcessStatus1342#define LLDB_OPTIONS_process_status1343#include "CommandOptions.inc"13441345class CommandObjectProcessStatus : public CommandObjectParsed {1346public:1347CommandObjectProcessStatus(CommandInterpreter &interpreter)1348: CommandObjectParsed(1349interpreter, "process status",1350"Show status and stop location for the current target process.",1351"process status",1352eCommandRequiresProcess | eCommandTryTargetAPILock) {}13531354~CommandObjectProcessStatus() override = default;13551356Options *GetOptions() override { return &m_options; }13571358class CommandOptions : public Options {1359public:1360CommandOptions() = default;13611362~CommandOptions() override = default;13631364Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,1365ExecutionContext *execution_context) override {1366const int short_option = m_getopt_table[option_idx].val;13671368switch (short_option) {1369case 'v':1370m_verbose = true;1371break;1372default:1373llvm_unreachable("Unimplemented option");1374}13751376return {};1377}13781379void OptionParsingStarting(ExecutionContext *execution_context) override {1380m_verbose = false;1381}13821383llvm::ArrayRef<OptionDefinition> GetDefinitions() override {1384return llvm::ArrayRef(g_process_status_options);1385}13861387// Instance variables to hold the values for command options.1388bool m_verbose = false;1389};13901391protected:1392void DoExecute(Args &command, CommandReturnObject &result) override {1393Stream &strm = result.GetOutputStream();1394result.SetStatus(eReturnStatusSuccessFinishNoResult);13951396// No need to check "process" for validity as eCommandRequiresProcess1397// ensures it is valid1398Process *process = m_exe_ctx.GetProcessPtr();1399const bool only_threads_with_stop_reason = true;1400const uint32_t start_frame = 0;1401const uint32_t num_frames = 1;1402const uint32_t num_frames_with_source = 1;1403const bool stop_format = true;1404process->GetStatus(strm);1405process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,1406num_frames, num_frames_with_source, stop_format);14071408if (m_options.m_verbose) {1409addr_t code_mask = process->GetCodeAddressMask();1410addr_t data_mask = process->GetDataAddressMask();1411if (code_mask != LLDB_INVALID_ADDRESS_MASK) {1412int bits = std::bitset<64>(~code_mask).count();1413result.AppendMessageWithFormat(1414"Addressable code address mask: 0x%" PRIx64 "\n", code_mask);1415result.AppendMessageWithFormat(1416"Addressable data address mask: 0x%" PRIx64 "\n", data_mask);1417result.AppendMessageWithFormat(1418"Number of bits used in addressing (code): %d\n", bits);1419}14201421PlatformSP platform_sp = process->GetTarget().GetPlatform();1422if (!platform_sp) {1423result.AppendError("Couldn'retrieve the target's platform");1424return;1425}14261427auto expected_crash_info =1428platform_sp->FetchExtendedCrashInformation(*process);14291430if (!expected_crash_info) {1431result.AppendError(llvm::toString(expected_crash_info.takeError()));1432return;1433}14341435StructuredData::DictionarySP crash_info_sp = *expected_crash_info;14361437if (crash_info_sp) {1438strm.EOL();1439strm.PutCString("Extended Crash Information:\n");1440crash_info_sp->GetDescription(strm);1441}1442}1443}14441445private:1446CommandOptions m_options;1447};14481449// CommandObjectProcessHandle1450#define LLDB_OPTIONS_process_handle1451#include "CommandOptions.inc"14521453#pragma mark CommandObjectProcessHandle14541455class CommandObjectProcessHandle : public CommandObjectParsed {1456public:1457class CommandOptions : public Options {1458public:1459CommandOptions() { OptionParsingStarting(nullptr); }14601461~CommandOptions() override = default;14621463Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,1464ExecutionContext *execution_context) override {1465Status error;1466const int short_option = m_getopt_table[option_idx].val;14671468switch (short_option) {1469case 'c':1470do_clear = true;1471break;1472case 'd':1473dummy = true;1474break;1475case 's':1476stop = std::string(option_arg);1477break;1478case 'n':1479notify = std::string(option_arg);1480break;1481case 'p':1482pass = std::string(option_arg);1483break;1484case 't':1485only_target_values = true;1486break;1487default:1488llvm_unreachable("Unimplemented option");1489}1490return error;1491}14921493void OptionParsingStarting(ExecutionContext *execution_context) override {1494stop.clear();1495notify.clear();1496pass.clear();1497only_target_values = false;1498do_clear = false;1499dummy = false;1500}15011502llvm::ArrayRef<OptionDefinition> GetDefinitions() override {1503return llvm::ArrayRef(g_process_handle_options);1504}15051506// Instance variables to hold the values for command options.15071508std::string stop;1509std::string notify;1510std::string pass;1511bool only_target_values = false;1512bool do_clear = false;1513bool dummy = false;1514};15151516CommandObjectProcessHandle(CommandInterpreter &interpreter)1517: CommandObjectParsed(interpreter, "process handle",1518"Manage LLDB handling of OS signals for the "1519"current target process. Defaults to showing "1520"current policy.",1521nullptr) {1522SetHelpLong("\nIf no signals are specified but one or more actions are, "1523"and there is a live process, update them all. If no action "1524"is specified, list the current values.\n"1525"If you specify actions with no target (e.g. in an init file) "1526"or in a target with no process "1527"the values will get copied into subsequent targets, but "1528"lldb won't be able to spell-check the options since it can't "1529"know which signal set will later be in force."1530"\nYou can see the signal modifications held by the target"1531"by passing the -t option."1532"\nYou can also clear the target modification for a signal"1533"by passing the -c option");1534AddSimpleArgumentList(eArgTypeUnixSignal, eArgRepeatStar);1535}15361537~CommandObjectProcessHandle() override = default;15381539Options *GetOptions() override { return &m_options; }15401541void PrintSignalHeader(Stream &str) {1542str.Printf("NAME PASS STOP NOTIFY\n");1543str.Printf("=========== ===== ===== ======\n");1544}15451546void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name,1547const UnixSignalsSP &signals_sp) {1548bool stop;1549bool suppress;1550bool notify;15511552str.Format("{0, -11} ", sig_name);1553if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {1554bool pass = !suppress;1555str.Printf("%s %s %s", (pass ? "true " : "false"),1556(stop ? "true " : "false"), (notify ? "true " : "false"));1557}1558str.Printf("\n");1559}15601561void PrintSignalInformation(Stream &str, Args &signal_args,1562int num_valid_signals,1563const UnixSignalsSP &signals_sp) {1564PrintSignalHeader(str);15651566if (num_valid_signals > 0) {1567size_t num_args = signal_args.GetArgumentCount();1568for (size_t i = 0; i < num_args; ++i) {1569int32_t signo = signals_sp->GetSignalNumberFromName(1570signal_args.GetArgumentAtIndex(i));1571if (signo != LLDB_INVALID_SIGNAL_NUMBER)1572PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),1573signals_sp);1574}1575} else // Print info for ALL signals1576{1577int32_t signo = signals_sp->GetFirstSignalNumber();1578while (signo != LLDB_INVALID_SIGNAL_NUMBER) {1579PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo),1580signals_sp);1581signo = signals_sp->GetNextSignalNumber(signo);1582}1583}1584}15851586protected:1587void DoExecute(Args &signal_args, CommandReturnObject &result) override {1588Target &target = GetSelectedOrDummyTarget();15891590// Any signals that are being set should be added to the Target's1591// DummySignals so they will get applied on rerun, etc.1592// If we have a process, however, we can do a more accurate job of vetting1593// the user's options.1594ProcessSP process_sp = target.GetProcessSP();15951596std::optional<bool> stop_action = {};1597std::optional<bool> pass_action = {};1598std::optional<bool> notify_action = {};15991600if (!m_options.stop.empty()) {1601bool success = false;1602bool value = OptionArgParser::ToBoolean(m_options.stop, false, &success);1603if (!success) {1604result.AppendError(1605"Invalid argument for command option --stop; must be "1606"true or false.\n");1607return;1608}16091610stop_action = value;1611}16121613if (!m_options.pass.empty()) {1614bool success = false;1615bool value = OptionArgParser::ToBoolean(m_options.pass, false, &success);1616if (!success) {1617result.AppendError(1618"Invalid argument for command option --pass; must be "1619"true or false.\n");1620return;1621}1622pass_action = value;1623}16241625if (!m_options.notify.empty()) {1626bool success = false;1627bool value =1628OptionArgParser::ToBoolean(m_options.notify, false, &success);1629if (!success) {1630result.AppendError("Invalid argument for command option --notify; must "1631"be true or false.\n");1632return;1633}1634notify_action = value;1635}16361637if (!m_options.notify.empty() && !notify_action.has_value()) {1638}16391640bool no_actions = (!stop_action.has_value() && !pass_action.has_value() &&1641!notify_action.has_value());1642if (m_options.only_target_values && !no_actions) {1643result.AppendError("-t is for reporting, not setting, target values.");1644return;1645}16461647size_t num_args = signal_args.GetArgumentCount();1648UnixSignalsSP signals_sp;1649if (process_sp)1650signals_sp = process_sp->GetUnixSignals();16511652int num_signals_set = 0;16531654// If we were just asked to print the target values, do that here and1655// return:1656if (m_options.only_target_values) {1657target.PrintDummySignals(result.GetOutputStream(), signal_args);1658result.SetStatus(eReturnStatusSuccessFinishResult);1659return;1660}16611662// This handles clearing values:1663if (m_options.do_clear) {1664target.ClearDummySignals(signal_args);1665if (m_options.dummy)1666GetDummyTarget().ClearDummySignals(signal_args);1667result.SetStatus(eReturnStatusSuccessFinishNoResult);1668return;1669}16701671// This rest handles setting values:1672if (num_args > 0) {1673for (const auto &arg : signal_args) {1674// Do the process first. If we have a process we can catch1675// invalid signal names, which we do here.1676if (signals_sp) {1677int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());1678if (signo != LLDB_INVALID_SIGNAL_NUMBER) {1679if (stop_action.has_value())1680signals_sp->SetShouldStop(signo, *stop_action);1681if (pass_action.has_value()) {1682bool suppress = !*pass_action;1683signals_sp->SetShouldSuppress(signo, suppress);1684}1685if (notify_action.has_value())1686signals_sp->SetShouldNotify(signo, *notify_action);1687++num_signals_set;1688} else {1689result.AppendErrorWithFormat("Invalid signal name '%s'\n",1690arg.c_str());1691continue;1692}1693} else {1694// If there's no process we can't check, so we just set them all.1695// But since the map signal name -> signal number across all platforms1696// is not 1-1, we can't sensibly set signal actions by number before1697// we have a process. Check that here:1698int32_t signo;1699if (llvm::to_integer(arg.c_str(), signo)) {1700result.AppendErrorWithFormat("Can't set signal handling by signal "1701"number with no process");1702return;1703}1704num_signals_set = num_args;1705}1706auto set_lazy_bool = [](std::optional<bool> action) -> LazyBool {1707if (!action.has_value())1708return eLazyBoolCalculate;1709return (*action) ? eLazyBoolYes : eLazyBoolNo;1710};17111712// If there were no actions, we're just listing, don't add the dummy:1713if (!no_actions)1714target.AddDummySignal(arg.ref(), set_lazy_bool(pass_action),1715set_lazy_bool(notify_action),1716set_lazy_bool(stop_action));1717}1718} else {1719// No signal specified, if any command options were specified, update ALL1720// signals. But we can't do this without a process since we don't know1721// all the possible signals that might be valid for this target.1722if ((notify_action.has_value() || stop_action.has_value() ||1723pass_action.has_value()) &&1724process_sp) {1725if (m_interpreter.Confirm(1726"Do you really want to update all the signals?", false)) {1727int32_t signo = signals_sp->GetFirstSignalNumber();1728while (signo != LLDB_INVALID_SIGNAL_NUMBER) {1729if (notify_action.has_value())1730signals_sp->SetShouldNotify(signo, *notify_action);1731if (stop_action.has_value())1732signals_sp->SetShouldStop(signo, *stop_action);1733if (pass_action.has_value()) {1734bool suppress = !*pass_action;1735signals_sp->SetShouldSuppress(signo, suppress);1736}1737signo = signals_sp->GetNextSignalNumber(signo);1738}1739}1740}1741}17421743if (signals_sp)1744PrintSignalInformation(result.GetOutputStream(), signal_args,1745num_signals_set, signals_sp);1746else1747target.PrintDummySignals(result.GetOutputStream(),1748signal_args);17491750if (num_signals_set > 0)1751result.SetStatus(eReturnStatusSuccessFinishResult);1752else1753result.SetStatus(eReturnStatusFailed);1754}17551756CommandOptions m_options;1757};17581759// Next are the subcommands of CommandObjectMultiwordProcessTrace17601761// CommandObjectProcessTraceStart1762class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {1763public:1764CommandObjectProcessTraceStart(CommandInterpreter &interpreter)1765: CommandObjectTraceProxy(1766/*live_debug_session_only*/ true, interpreter,1767"process trace start",1768"Start tracing this process with the corresponding trace "1769"plug-in.",1770"process trace start [<trace-options>]") {}17711772protected:1773lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {1774return trace.GetProcessTraceStartCommand(m_interpreter);1775}1776};17771778// CommandObjectProcessTraceStop1779class CommandObjectProcessTraceStop : public CommandObjectParsed {1780public:1781CommandObjectProcessTraceStop(CommandInterpreter &interpreter)1782: CommandObjectParsed(interpreter, "process trace stop",1783"Stop tracing this process. This does not affect "1784"traces started with the "1785"\"thread trace start\" command.",1786"process trace stop",1787eCommandRequiresProcess | eCommandTryTargetAPILock |1788eCommandProcessMustBeLaunched |1789eCommandProcessMustBePaused |1790eCommandProcessMustBeTraced) {}17911792~CommandObjectProcessTraceStop() override = default;17931794void DoExecute(Args &command, CommandReturnObject &result) override {1795ProcessSP process_sp = m_exe_ctx.GetProcessSP();17961797TraceSP trace_sp = process_sp->GetTarget().GetTrace();17981799if (llvm::Error err = trace_sp->Stop())1800result.AppendError(toString(std::move(err)));1801else1802result.SetStatus(eReturnStatusSuccessFinishResult);1803}1804};18051806// CommandObjectMultiwordProcessTrace1807class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {1808public:1809CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)1810: CommandObjectMultiword(1811interpreter, "trace", "Commands for tracing the current process.",1812"process trace <subcommand> [<subcommand objects>]") {1813LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(1814interpreter)));1815LoadSubCommand("stop", CommandObjectSP(1816new CommandObjectProcessTraceStop(interpreter)));1817}18181819~CommandObjectMultiwordProcessTrace() override = default;1820};18211822// CommandObjectMultiwordProcess18231824CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(1825CommandInterpreter &interpreter)1826: CommandObjectMultiword(1827interpreter, "process",1828"Commands for interacting with processes on the current platform.",1829"process <subcommand> [<subcommand-options>]") {1830LoadSubCommand("attach",1831CommandObjectSP(new CommandObjectProcessAttach(interpreter)));1832LoadSubCommand("launch",1833CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));1834LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(1835interpreter)));1836LoadSubCommand("connect",1837CommandObjectSP(new CommandObjectProcessConnect(interpreter)));1838LoadSubCommand("detach",1839CommandObjectSP(new CommandObjectProcessDetach(interpreter)));1840LoadSubCommand("load",1841CommandObjectSP(new CommandObjectProcessLoad(interpreter)));1842LoadSubCommand("unload",1843CommandObjectSP(new CommandObjectProcessUnload(interpreter)));1844LoadSubCommand("signal",1845CommandObjectSP(new CommandObjectProcessSignal(interpreter)));1846LoadSubCommand("handle",1847CommandObjectSP(new CommandObjectProcessHandle(interpreter)));1848LoadSubCommand("status",1849CommandObjectSP(new CommandObjectProcessStatus(interpreter)));1850LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(1851interpreter)));1852LoadSubCommand("kill",1853CommandObjectSP(new CommandObjectProcessKill(interpreter)));1854LoadSubCommand("plugin",1855CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));1856LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(1857interpreter)));1858LoadSubCommand(1859"trace",1860CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));1861}18621863CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;186418651866