1//===-- CommandObjectProcess.cpp ------------------------------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "CommandObjectProcess.h" 10#include "CommandObjectBreakpoint.h" 11#include "CommandObjectTrace.h" 12#include "CommandOptionsProcessAttach.h" 13#include "CommandOptionsProcessLaunch.h" 14#include "lldb/Breakpoint/Breakpoint.h" 15#include "lldb/Breakpoint/BreakpointIDList.h" 16#include "lldb/Breakpoint/BreakpointLocation.h" 17#include "lldb/Breakpoint/BreakpointName.h" 18#include "lldb/Breakpoint/BreakpointSite.h" 19#include "lldb/Core/Module.h" 20#include "lldb/Core/PluginManager.h" 21#include "lldb/Host/OptionParser.h" 22#include "lldb/Interpreter/CommandInterpreter.h" 23#include "lldb/Interpreter/CommandOptionArgumentTable.h" 24#include "lldb/Interpreter/CommandReturnObject.h" 25#include "lldb/Interpreter/OptionArgParser.h" 26#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 27#include "lldb/Interpreter/Options.h" 28#include "lldb/Target/Platform.h" 29#include "lldb/Target/Process.h" 30#include "lldb/Target/StopInfo.h" 31#include "lldb/Target/Target.h" 32#include "lldb/Target/Thread.h" 33#include "lldb/Target/UnixSignals.h" 34#include "lldb/Utility/Args.h" 35#include "lldb/Utility/ScriptedMetadata.h" 36#include "lldb/Utility/State.h" 37 38#include "llvm/ADT/ScopeExit.h" 39 40#include <bitset> 41#include <optional> 42 43using namespace lldb; 44using namespace lldb_private; 45 46class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed { 47public: 48 CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter, 49 const char *name, const char *help, 50 const char *syntax, uint32_t flags, 51 const char *new_process_action) 52 : CommandObjectParsed(interpreter, name, help, syntax, flags), 53 m_new_process_action(new_process_action) {} 54 55 ~CommandObjectProcessLaunchOrAttach() override = default; 56 57protected: 58 bool StopProcessIfNecessary(Process *process, StateType &state, 59 CommandReturnObject &result) { 60 state = eStateInvalid; 61 if (process) { 62 state = process->GetState(); 63 64 if (process->IsAlive() && state != eStateConnected) { 65 std::string message; 66 if (process->GetState() == eStateAttaching) 67 message = 68 llvm::formatv("There is a pending attach, abort it and {0}?", 69 m_new_process_action); 70 else if (process->GetShouldDetach()) 71 message = llvm::formatv( 72 "There is a running process, detach from it and {0}?", 73 m_new_process_action); 74 else 75 message = 76 llvm::formatv("There is a running process, kill it and {0}?", 77 m_new_process_action); 78 79 if (!m_interpreter.Confirm(message, true)) { 80 result.SetStatus(eReturnStatusFailed); 81 return false; 82 } else { 83 if (process->GetShouldDetach()) { 84 bool keep_stopped = false; 85 Status detach_error(process->Detach(keep_stopped)); 86 if (detach_error.Success()) { 87 result.SetStatus(eReturnStatusSuccessFinishResult); 88 process = nullptr; 89 } else { 90 result.AppendErrorWithFormat( 91 "Failed to detach from process: %s\n", 92 detach_error.AsCString()); 93 } 94 } else { 95 Status destroy_error(process->Destroy(false)); 96 if (destroy_error.Success()) { 97 result.SetStatus(eReturnStatusSuccessFinishResult); 98 process = nullptr; 99 } else { 100 result.AppendErrorWithFormat("Failed to kill process: %s\n", 101 destroy_error.AsCString()); 102 } 103 } 104 } 105 } 106 } 107 return result.Succeeded(); 108 } 109 110 std::string m_new_process_action; 111}; 112 113// CommandObjectProcessLaunch 114#pragma mark CommandObjectProcessLaunch 115class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach { 116public: 117 CommandObjectProcessLaunch(CommandInterpreter &interpreter) 118 : CommandObjectProcessLaunchOrAttach( 119 interpreter, "process launch", 120 "Launch the executable in the debugger.", nullptr, 121 eCommandRequiresTarget, "restart"), 122 123 m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 124 m_all_options.Append(&m_options); 125 m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 126 LLDB_OPT_SET_ALL); 127 m_all_options.Finalize(); 128 129 CommandArgumentEntry arg; 130 CommandArgumentData run_args_arg; 131 132 // Define the first (and only) variant of this arg. 133 run_args_arg.arg_type = eArgTypeRunArgs; 134 run_args_arg.arg_repetition = eArgRepeatOptional; 135 136 // There is only one variant this argument could be; put it into the 137 // argument entry. 138 arg.push_back(run_args_arg); 139 140 // Push the data for the first argument into the m_arguments vector. 141 m_arguments.push_back(arg); 142 } 143 144 ~CommandObjectProcessLaunch() override = default; 145 146 void 147 HandleArgumentCompletion(CompletionRequest &request, 148 OptionElementVector &opt_element_vector) override { 149 150 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 151 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 152 } 153 154 Options *GetOptions() override { return &m_all_options; } 155 156 std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 157 uint32_t index) override { 158 // No repeat for "process launch"... 159 return std::string(""); 160 } 161 162protected: 163 void DoExecute(Args &launch_args, CommandReturnObject &result) override { 164 Debugger &debugger = GetDebugger(); 165 Target *target = debugger.GetSelectedTarget().get(); 166 // If our listener is nullptr, users aren't allows to launch 167 ModuleSP exe_module_sp = target->GetExecutableModule(); 168 169 // If the target already has an executable module, then use that. If it 170 // doesn't then someone must be trying to launch using a path that will 171 // make sense to the remote stub, but doesn't exist on the local host. 172 // In that case use the ExecutableFile that was set in the target's 173 // ProcessLaunchInfo. 174 if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { 175 result.AppendError("no file in target, create a debug target using the " 176 "'target create' command"); 177 return; 178 } 179 180 StateType state = eStateInvalid; 181 182 if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 183 return; 184 185 // Determine whether we will disable ASLR or leave it in the default state 186 // (i.e. enabled if the platform supports it). First check if the process 187 // launch options explicitly turn on/off 188 // disabling ASLR. If so, use that setting; 189 // otherwise, use the 'settings target.disable-aslr' setting. 190 bool disable_aslr = false; 191 if (m_options.disable_aslr != eLazyBoolCalculate) { 192 // The user specified an explicit setting on the process launch line. 193 // Use it. 194 disable_aslr = (m_options.disable_aslr == eLazyBoolYes); 195 } else { 196 // The user did not explicitly specify whether to disable ASLR. Fall 197 // back to the target.disable-aslr setting. 198 disable_aslr = target->GetDisableASLR(); 199 } 200 201 if (!m_class_options.GetName().empty()) { 202 m_options.launch_info.SetProcessPluginName("ScriptedProcess"); 203 ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( 204 m_class_options.GetName(), m_class_options.GetStructuredData()); 205 m_options.launch_info.SetScriptedMetadata(metadata_sp); 206 target->SetProcessLaunchInfo(m_options.launch_info); 207 } 208 209 if (disable_aslr) 210 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 211 else 212 m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 213 214 if (target->GetInheritTCC()) 215 m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent); 216 217 if (target->GetDetachOnError()) 218 m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 219 220 if (target->GetDisableSTDIO()) 221 m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 222 223 // Merge the launch info environment with the target environment. 224 Environment target_env = target->GetEnvironment(); 225 m_options.launch_info.GetEnvironment().insert(target_env.begin(), 226 target_env.end()); 227 228 llvm::StringRef target_settings_argv0 = target->GetArg0(); 229 230 if (!target_settings_argv0.empty()) { 231 m_options.launch_info.GetArguments().AppendArgument( 232 target_settings_argv0); 233 if (exe_module_sp) 234 m_options.launch_info.SetExecutableFile( 235 exe_module_sp->GetPlatformFileSpec(), false); 236 else 237 m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false); 238 } else { 239 if (exe_module_sp) 240 m_options.launch_info.SetExecutableFile( 241 exe_module_sp->GetPlatformFileSpec(), true); 242 else 243 m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true); 244 } 245 246 if (launch_args.GetArgumentCount() == 0) { 247 m_options.launch_info.GetArguments().AppendArguments( 248 target->GetProcessLaunchInfo().GetArguments()); 249 } else { 250 m_options.launch_info.GetArguments().AppendArguments(launch_args); 251 // Save the arguments for subsequent runs in the current target. 252 target->SetRunArguments(launch_args); 253 } 254 255 StreamString stream; 256 Status error = target->Launch(m_options.launch_info, &stream); 257 258 if (error.Success()) { 259 ProcessSP process_sp(target->GetProcessSP()); 260 if (process_sp) { 261 // There is a race condition where this thread will return up the call 262 // stack to the main command handler and show an (lldb) prompt before 263 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 264 // PushProcessIOHandler(). 265 process_sp->SyncIOHandler(0, std::chrono::seconds(2)); 266 267 // If we didn't have a local executable, then we wouldn't have had an 268 // executable module before launch. 269 if (!exe_module_sp) 270 exe_module_sp = target->GetExecutableModule(); 271 if (!exe_module_sp) { 272 result.AppendWarning("Could not get executable module after launch."); 273 } else { 274 275 const char *archname = 276 exe_module_sp->GetArchitecture().GetArchitectureName(); 277 result.AppendMessageWithFormat( 278 "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), 279 exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 280 } 281 result.SetStatus(eReturnStatusSuccessFinishResult); 282 // This message will refer to an event that happened after the process 283 // launched. 284 llvm::StringRef data = stream.GetString(); 285 if (!data.empty()) 286 result.AppendMessage(data); 287 result.SetDidChangeProcessState(true); 288 } else { 289 result.AppendError( 290 "no error returned from Target::Launch, and target has no process"); 291 } 292 } else { 293 result.AppendError(error.AsCString()); 294 } 295 } 296 297 CommandOptionsProcessLaunch m_options; 298 OptionGroupPythonClassWithDict m_class_options; 299 OptionGroupOptions m_all_options; 300}; 301 302#define LLDB_OPTIONS_process_attach 303#include "CommandOptions.inc" 304 305#pragma mark CommandObjectProcessAttach 306class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { 307public: 308 CommandObjectProcessAttach(CommandInterpreter &interpreter) 309 : CommandObjectProcessLaunchOrAttach( 310 interpreter, "process attach", "Attach to a process.", 311 "process attach <cmd-options>", 0, "attach"), 312 m_class_options("scripted process", true, 'C', 'k', 'v', 0) { 313 m_all_options.Append(&m_options); 314 m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 315 LLDB_OPT_SET_ALL); 316 m_all_options.Finalize(); 317 } 318 319 ~CommandObjectProcessAttach() override = default; 320 321 Options *GetOptions() override { return &m_all_options; } 322 323protected: 324 void DoExecute(Args &command, CommandReturnObject &result) override { 325 PlatformSP platform_sp( 326 GetDebugger().GetPlatformList().GetSelectedPlatform()); 327 328 Target *target = GetDebugger().GetSelectedTarget().get(); 329 // N.B. The attach should be synchronous. It doesn't help much to get the 330 // prompt back between initiating the attach and the target actually 331 // stopping. So even if the interpreter is set to be asynchronous, we wait 332 // for the stop ourselves here. 333 334 StateType state = eStateInvalid; 335 Process *process = m_exe_ctx.GetProcessPtr(); 336 337 if (!StopProcessIfNecessary(process, state, result)) 338 return; 339 340 if (target == nullptr) { 341 // If there isn't a current target create one. 342 TargetSP new_target_sp; 343 Status error; 344 345 error = GetDebugger().GetTargetList().CreateTarget( 346 GetDebugger(), "", "", eLoadDependentsNo, 347 nullptr, // No platform options 348 new_target_sp); 349 target = new_target_sp.get(); 350 if (target == nullptr || error.Fail()) { 351 result.AppendError(error.AsCString("Error creating target")); 352 return; 353 } 354 } 355 356 if (!m_class_options.GetName().empty()) { 357 m_options.attach_info.SetProcessPluginName("ScriptedProcess"); 358 ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( 359 m_class_options.GetName(), m_class_options.GetStructuredData()); 360 m_options.attach_info.SetScriptedMetadata(metadata_sp); 361 } 362 363 // Record the old executable module, we want to issue a warning if the 364 // process of attaching changed the current executable (like somebody said 365 // "file foo" then attached to a PID whose executable was bar.) 366 367 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 368 ArchSpec old_arch_spec = target->GetArchitecture(); 369 370 StreamString stream; 371 ProcessSP process_sp; 372 const auto error = target->Attach(m_options.attach_info, &stream); 373 if (error.Success()) { 374 process_sp = target->GetProcessSP(); 375 if (process_sp) { 376 result.AppendMessage(stream.GetString()); 377 result.SetStatus(eReturnStatusSuccessFinishNoResult); 378 result.SetDidChangeProcessState(true); 379 } else { 380 result.AppendError( 381 "no error returned from Target::Attach, and target has no process"); 382 } 383 } else { 384 result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString()); 385 } 386 387 if (!result.Succeeded()) 388 return; 389 390 // Okay, we're done. Last step is to warn if the executable module has 391 // changed: 392 char new_path[PATH_MAX]; 393 ModuleSP new_exec_module_sp(target->GetExecutableModule()); 394 if (!old_exec_module_sp) { 395 // We might not have a module if we attached to a raw pid... 396 if (new_exec_module_sp) { 397 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 398 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 399 new_path); 400 } 401 } else if (old_exec_module_sp->GetFileSpec() != 402 new_exec_module_sp->GetFileSpec()) { 403 char old_path[PATH_MAX]; 404 405 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 406 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 407 408 result.AppendWarningWithFormat( 409 "Executable module changed from \"%s\" to \"%s\".\n", old_path, 410 new_path); 411 } 412 413 if (!old_arch_spec.IsValid()) { 414 result.AppendMessageWithFormat( 415 "Architecture set to: %s.\n", 416 target->GetArchitecture().GetTriple().getTriple().c_str()); 417 } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) { 418 result.AppendWarningWithFormat( 419 "Architecture changed from %s to %s.\n", 420 old_arch_spec.GetTriple().getTriple().c_str(), 421 target->GetArchitecture().GetTriple().getTriple().c_str()); 422 } 423 424 // This supports the use-case scenario of immediately continuing the 425 // process once attached. 426 if (m_options.attach_info.GetContinueOnceAttached()) { 427 // We have made a process but haven't told the interpreter about it yet, 428 // so CheckRequirements will fail for "process continue". Set the override 429 // here: 430 ExecutionContext exe_ctx(process_sp); 431 m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); 432 } 433 } 434 435 CommandOptionsProcessAttach m_options; 436 OptionGroupPythonClassWithDict m_class_options; 437 OptionGroupOptions m_all_options; 438}; 439 440// CommandObjectProcessContinue 441 442#define LLDB_OPTIONS_process_continue 443#include "CommandOptions.inc" 444 445#pragma mark CommandObjectProcessContinue 446 447class CommandObjectProcessContinue : public CommandObjectParsed { 448public: 449 CommandObjectProcessContinue(CommandInterpreter &interpreter) 450 : CommandObjectParsed( 451 interpreter, "process continue", 452 "Continue execution of all threads in the current process.", 453 "process continue", 454 eCommandRequiresProcess | eCommandTryTargetAPILock | 455 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 456 457 ~CommandObjectProcessContinue() override = default; 458 459protected: 460 class CommandOptions : public Options { 461 public: 462 CommandOptions() { 463 // Keep default values of all options in one place: OptionParsingStarting 464 // () 465 OptionParsingStarting(nullptr); 466 } 467 468 ~CommandOptions() override = default; 469 470 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 471 ExecutionContext *exe_ctx) override { 472 Status error; 473 const int short_option = m_getopt_table[option_idx].val; 474 switch (short_option) { 475 case 'i': 476 if (option_arg.getAsInteger(0, m_ignore)) 477 error.SetErrorStringWithFormat( 478 "invalid value for ignore option: \"%s\", should be a number.", 479 option_arg.str().c_str()); 480 break; 481 case 'b': 482 m_run_to_bkpt_args.AppendArgument(option_arg); 483 m_any_bkpts_specified = true; 484 break; 485 default: 486 llvm_unreachable("Unimplemented option"); 487 } 488 return error; 489 } 490 491 void OptionParsingStarting(ExecutionContext *execution_context) override { 492 m_ignore = 0; 493 m_run_to_bkpt_args.Clear(); 494 m_any_bkpts_specified = false; 495 } 496 497 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 498 return llvm::ArrayRef(g_process_continue_options); 499 } 500 501 uint32_t m_ignore = 0; 502 Args m_run_to_bkpt_args; 503 bool m_any_bkpts_specified = false; 504 }; 505 506 void DoExecute(Args &command, CommandReturnObject &result) override { 507 Process *process = m_exe_ctx.GetProcessPtr(); 508 bool synchronous_execution = m_interpreter.GetSynchronous(); 509 StateType state = process->GetState(); 510 if (state == eStateStopped) { 511 if (m_options.m_ignore > 0) { 512 ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this()); 513 if (sel_thread_sp) { 514 StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 515 if (stop_info_sp && 516 stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { 517 lldb::break_id_t bp_site_id = 518 (lldb::break_id_t)stop_info_sp->GetValue(); 519 BreakpointSiteSP bp_site_sp( 520 process->GetBreakpointSiteList().FindByID(bp_site_id)); 521 if (bp_site_sp) { 522 const size_t num_owners = bp_site_sp->GetNumberOfConstituents(); 523 for (size_t i = 0; i < num_owners; i++) { 524 Breakpoint &bp_ref = 525 bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint(); 526 if (!bp_ref.IsInternal()) { 527 bp_ref.SetIgnoreCount(m_options.m_ignore); 528 } 529 } 530 } 531 } 532 } 533 } 534 535 Target *target = m_exe_ctx.GetTargetPtr(); 536 BreakpointIDList run_to_bkpt_ids; 537 // Don't pass an empty run_to_breakpoint list, as Verify will look for the 538 // default breakpoint. 539 if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0) 540 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 541 m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids, 542 BreakpointName::Permissions::disablePerm); 543 if (!result.Succeeded()) { 544 return; 545 } 546 result.Clear(); 547 if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) { 548 result.AppendError("continue-to breakpoints did not specify any actual " 549 "breakpoints or locations"); 550 return; 551 } 552 553 // First figure out which breakpoints & locations were specified by the 554 // user: 555 size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize(); 556 std::vector<break_id_t> bkpts_disabled; 557 std::vector<BreakpointID> locs_disabled; 558 if (num_run_to_bkpt_ids != 0) { 559 // Go through the ID's specified, and separate the breakpoints from are 560 // the breakpoint.location specifications since the latter require 561 // special handling. We also figure out whether there's at least one 562 // specifier in the set that is enabled. 563 BreakpointList &bkpt_list = target->GetBreakpointList(); 564 std::unordered_set<break_id_t> bkpts_seen; 565 std::unordered_set<break_id_t> bkpts_with_locs_seen; 566 BreakpointIDList with_locs; 567 bool any_enabled = false; 568 569 for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) { 570 BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx); 571 break_id_t bp_id = bkpt_id.GetBreakpointID(); 572 break_id_t loc_id = bkpt_id.GetLocationID(); 573 BreakpointSP bp_sp 574 = bkpt_list.FindBreakpointByID(bp_id); 575 // Note, VerifyBreakpointOrLocationIDs checks for existence, so we 576 // don't need to do it again here. 577 if (bp_sp->IsEnabled()) { 578 if (loc_id == LLDB_INVALID_BREAK_ID) { 579 // A breakpoint (without location) was specified. Make sure that 580 // at least one of the locations is enabled. 581 size_t num_locations = bp_sp->GetNumLocations(); 582 for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 583 BreakpointLocationSP loc_sp 584 = bp_sp->GetLocationAtIndex(loc_idx); 585 if (loc_sp->IsEnabled()) { 586 any_enabled = true; 587 break; 588 } 589 } 590 } else { 591 // A location was specified, check if it was enabled: 592 BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id); 593 if (loc_sp->IsEnabled()) 594 any_enabled = true; 595 } 596 597 // Then sort the bp & bp.loc entries for later use: 598 if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 599 bkpts_seen.insert(bkpt_id.GetBreakpointID()); 600 else { 601 bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID()); 602 with_locs.AddBreakpointID(bkpt_id); 603 } 604 } 605 } 606 // Do all the error checking here so once we start disabling we don't 607 // have to back out half-way through. 608 609 // Make sure at least one of the specified breakpoints is enabled. 610 if (!any_enabled) { 611 result.AppendError("at least one of the continue-to breakpoints must " 612 "be enabled."); 613 return; 614 } 615 616 // Also, if you specify BOTH a breakpoint and one of it's locations, 617 // we flag that as an error, since it won't do what you expect, the 618 // breakpoint directive will mean "run to all locations", which is not 619 // what the location directive means... 620 for (break_id_t bp_id : bkpts_with_locs_seen) { 621 if (bkpts_seen.count(bp_id)) { 622 result.AppendErrorWithFormatv("can't specify both a breakpoint and " 623 "one of its locations: {0}", bp_id); 624 } 625 } 626 627 // Now go through the breakpoints in the target, disabling all the ones 628 // that the user didn't mention: 629 for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) { 630 break_id_t bp_id = bp_sp->GetID(); 631 // Handle the case where no locations were specified. Note we don't 632 // have to worry about the case where a breakpoint and one of its 633 // locations are both in the lists, we've already disallowed that. 634 if (!bkpts_with_locs_seen.count(bp_id)) { 635 if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) { 636 bkpts_disabled.push_back(bp_id); 637 bp_sp->SetEnabled(false); 638 } 639 continue; 640 } 641 // Next, handle the case where a location was specified: 642 // Run through all the locations of this breakpoint and disable 643 // the ones that aren't on our "with locations" BreakpointID list: 644 size_t num_locations = bp_sp->GetNumLocations(); 645 BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID); 646 for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) { 647 BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx); 648 tmp_id.SetBreakpointLocationID(loc_idx); 649 size_t position = 0; 650 if (!with_locs.FindBreakpointID(tmp_id, &position) 651 && loc_sp->IsEnabled()) { 652 locs_disabled.push_back(tmp_id); 653 loc_sp->SetEnabled(false); 654 } 655 } 656 } 657 } 658 659 { // Scope for thread list mutex: 660 std::lock_guard<std::recursive_mutex> guard( 661 process->GetThreadList().GetMutex()); 662 const uint32_t num_threads = process->GetThreadList().GetSize(); 663 664 // Set the actions that the threads should each take when resuming 665 for (uint32_t idx = 0; idx < num_threads; ++idx) { 666 const bool override_suspend = false; 667 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState( 668 eStateRunning, override_suspend); 669 } 670 } 671 672 const uint32_t iohandler_id = process->GetIOHandlerID(); 673 674 StreamString stream; 675 Status error; 676 // For now we can only do -b with synchronous: 677 bool old_sync = GetDebugger().GetAsyncExecution(); 678 679 if (run_to_bkpt_ids.GetSize() != 0) { 680 GetDebugger().SetAsyncExecution(false); 681 synchronous_execution = true; 682 } 683 if (synchronous_execution) 684 error = process->ResumeSynchronous(&stream); 685 else 686 error = process->Resume(); 687 688 if (run_to_bkpt_ids.GetSize() != 0) { 689 GetDebugger().SetAsyncExecution(old_sync); 690 } 691 692 // Now re-enable the breakpoints we disabled: 693 BreakpointList &bkpt_list = target->GetBreakpointList(); 694 for (break_id_t bp_id : bkpts_disabled) { 695 BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id); 696 if (bp_sp) 697 bp_sp->SetEnabled(true); 698 } 699 for (const BreakpointID &bkpt_id : locs_disabled) { 700 BreakpointSP bp_sp 701 = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID()); 702 if (bp_sp) { 703 BreakpointLocationSP loc_sp 704 = bp_sp->FindLocationByID(bkpt_id.GetLocationID()); 705 if (loc_sp) 706 loc_sp->SetEnabled(true); 707 } 708 } 709 710 if (error.Success()) { 711 // There is a race condition where this thread will return up the call 712 // stack to the main command handler and show an (lldb) prompt before 713 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 714 // PushProcessIOHandler(). 715 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 716 717 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 718 process->GetID()); 719 if (synchronous_execution) { 720 // If any state changed events had anything to say, add that to the 721 // result 722 result.AppendMessage(stream.GetString()); 723 724 result.SetDidChangeProcessState(true); 725 result.SetStatus(eReturnStatusSuccessFinishNoResult); 726 } else { 727 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 728 } 729 } else { 730 result.AppendErrorWithFormat("Failed to resume process: %s.\n", 731 error.AsCString()); 732 } 733 } else { 734 result.AppendErrorWithFormat( 735 "Process cannot be continued from its current state (%s).\n", 736 StateAsCString(state)); 737 } 738 } 739 740 Options *GetOptions() override { return &m_options; } 741 742 CommandOptions m_options; 743}; 744 745// CommandObjectProcessDetach 746#define LLDB_OPTIONS_process_detach 747#include "CommandOptions.inc" 748 749#pragma mark CommandObjectProcessDetach 750 751class CommandObjectProcessDetach : public CommandObjectParsed { 752public: 753 class CommandOptions : public Options { 754 public: 755 CommandOptions() { OptionParsingStarting(nullptr); } 756 757 ~CommandOptions() override = default; 758 759 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 760 ExecutionContext *execution_context) override { 761 Status error; 762 const int short_option = m_getopt_table[option_idx].val; 763 764 switch (short_option) { 765 case 's': 766 bool tmp_result; 767 bool success; 768 tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success); 769 if (!success) 770 error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", 771 option_arg.str().c_str()); 772 else { 773 if (tmp_result) 774 m_keep_stopped = eLazyBoolYes; 775 else 776 m_keep_stopped = eLazyBoolNo; 777 } 778 break; 779 default: 780 llvm_unreachable("Unimplemented option"); 781 } 782 return error; 783 } 784 785 void OptionParsingStarting(ExecutionContext *execution_context) override { 786 m_keep_stopped = eLazyBoolCalculate; 787 } 788 789 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 790 return llvm::ArrayRef(g_process_detach_options); 791 } 792 793 // Instance variables to hold the values for command options. 794 LazyBool m_keep_stopped; 795 }; 796 797 CommandObjectProcessDetach(CommandInterpreter &interpreter) 798 : CommandObjectParsed(interpreter, "process detach", 799 "Detach from the current target process.", 800 "process detach", 801 eCommandRequiresProcess | eCommandTryTargetAPILock | 802 eCommandProcessMustBeLaunched) {} 803 804 ~CommandObjectProcessDetach() override = default; 805 806 Options *GetOptions() override { return &m_options; } 807 808protected: 809 void DoExecute(Args &command, CommandReturnObject &result) override { 810 Process *process = m_exe_ctx.GetProcessPtr(); 811 // FIXME: This will be a Command Option: 812 bool keep_stopped; 813 if (m_options.m_keep_stopped == eLazyBoolCalculate) { 814 // Check the process default: 815 keep_stopped = process->GetDetachKeepsStopped(); 816 } else if (m_options.m_keep_stopped == eLazyBoolYes) 817 keep_stopped = true; 818 else 819 keep_stopped = false; 820 821 Status error(process->Detach(keep_stopped)); 822 if (error.Success()) { 823 result.SetStatus(eReturnStatusSuccessFinishResult); 824 } else { 825 result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); 826 } 827 } 828 829 CommandOptions m_options; 830}; 831 832// CommandObjectProcessConnect 833#define LLDB_OPTIONS_process_connect 834#include "CommandOptions.inc" 835 836#pragma mark CommandObjectProcessConnect 837 838class CommandObjectProcessConnect : public CommandObjectParsed { 839public: 840 class CommandOptions : public Options { 841 public: 842 CommandOptions() { 843 // Keep default values of all options in one place: OptionParsingStarting 844 // () 845 OptionParsingStarting(nullptr); 846 } 847 848 ~CommandOptions() override = default; 849 850 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 851 ExecutionContext *execution_context) override { 852 Status error; 853 const int short_option = m_getopt_table[option_idx].val; 854 855 switch (short_option) { 856 case 'p': 857 plugin_name.assign(std::string(option_arg)); 858 break; 859 860 default: 861 llvm_unreachable("Unimplemented option"); 862 } 863 return error; 864 } 865 866 void OptionParsingStarting(ExecutionContext *execution_context) override { 867 plugin_name.clear(); 868 } 869 870 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 871 return llvm::ArrayRef(g_process_connect_options); 872 } 873 874 // Instance variables to hold the values for command options. 875 876 std::string plugin_name; 877 }; 878 879 CommandObjectProcessConnect(CommandInterpreter &interpreter) 880 : CommandObjectParsed(interpreter, "process connect", 881 "Connect to a remote debug service.", 882 "process connect <remote-url>", 0) { 883 CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain}; 884 m_arguments.push_back({connect_arg}); 885 } 886 887 ~CommandObjectProcessConnect() override = default; 888 889 Options *GetOptions() override { return &m_options; } 890 891protected: 892 void DoExecute(Args &command, CommandReturnObject &result) override { 893 if (command.GetArgumentCount() != 1) { 894 result.AppendErrorWithFormat( 895 "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), 896 m_cmd_syntax.c_str()); 897 return; 898 } 899 900 Process *process = m_exe_ctx.GetProcessPtr(); 901 if (process && process->IsAlive()) { 902 result.AppendErrorWithFormat( 903 "Process %" PRIu64 904 " is currently being debugged, kill the process before connecting.\n", 905 process->GetID()); 906 return; 907 } 908 909 const char *plugin_name = nullptr; 910 if (!m_options.plugin_name.empty()) 911 plugin_name = m_options.plugin_name.c_str(); 912 913 Status error; 914 Debugger &debugger = GetDebugger(); 915 PlatformSP platform_sp = m_interpreter.GetPlatform(true); 916 ProcessSP process_sp = 917 debugger.GetAsyncExecution() 918 ? platform_sp->ConnectProcess( 919 command.GetArgumentAtIndex(0), plugin_name, debugger, 920 debugger.GetSelectedTarget().get(), error) 921 : platform_sp->ConnectProcessSynchronous( 922 command.GetArgumentAtIndex(0), plugin_name, debugger, 923 result.GetOutputStream(), debugger.GetSelectedTarget().get(), 924 error); 925 if (error.Fail() || process_sp == nullptr) { 926 result.AppendError(error.AsCString("Error connecting to the process")); 927 } 928 } 929 930 CommandOptions m_options; 931}; 932 933// CommandObjectProcessPlugin 934#pragma mark CommandObjectProcessPlugin 935 936class CommandObjectProcessPlugin : public CommandObjectProxy { 937public: 938 CommandObjectProcessPlugin(CommandInterpreter &interpreter) 939 : CommandObjectProxy( 940 interpreter, "process plugin", 941 "Send a custom command to the current target process plug-in.", 942 "process plugin <args>", 0) {} 943 944 ~CommandObjectProcessPlugin() override = default; 945 946 CommandObject *GetProxyCommandObject() override { 947 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 948 if (process) 949 return process->GetPluginCommandObject(); 950 return nullptr; 951 } 952}; 953 954// CommandObjectProcessLoad 955#define LLDB_OPTIONS_process_load 956#include "CommandOptions.inc" 957 958#pragma mark CommandObjectProcessLoad 959 960class CommandObjectProcessLoad : public CommandObjectParsed { 961public: 962 class CommandOptions : public Options { 963 public: 964 CommandOptions() { 965 // Keep default values of all options in one place: OptionParsingStarting 966 // () 967 OptionParsingStarting(nullptr); 968 } 969 970 ~CommandOptions() override = default; 971 972 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 973 ExecutionContext *execution_context) override { 974 Status error; 975 const int short_option = m_getopt_table[option_idx].val; 976 switch (short_option) { 977 case 'i': 978 do_install = true; 979 if (!option_arg.empty()) 980 install_path.SetFile(option_arg, FileSpec::Style::native); 981 break; 982 default: 983 llvm_unreachable("Unimplemented option"); 984 } 985 return error; 986 } 987 988 void OptionParsingStarting(ExecutionContext *execution_context) override { 989 do_install = false; 990 install_path.Clear(); 991 } 992 993 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 994 return llvm::ArrayRef(g_process_load_options); 995 } 996 997 // Instance variables to hold the values for command options. 998 bool do_install; 999 FileSpec install_path; 1000 }; 1001 1002 CommandObjectProcessLoad(CommandInterpreter &interpreter) 1003 : CommandObjectParsed(interpreter, "process load", 1004 "Load a shared library into the current process.", 1005 "process load <filename> [<filename> ...]", 1006 eCommandRequiresProcess | eCommandTryTargetAPILock | 1007 eCommandProcessMustBeLaunched | 1008 eCommandProcessMustBePaused) { 1009 CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus}; 1010 m_arguments.push_back({file_arg}); 1011 } 1012 1013 ~CommandObjectProcessLoad() override = default; 1014 1015 void 1016 HandleArgumentCompletion(CompletionRequest &request, 1017 OptionElementVector &opt_element_vector) override { 1018 if (!m_exe_ctx.HasProcessScope()) 1019 return; 1020 1021 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 1022 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 1023 } 1024 1025 Options *GetOptions() override { return &m_options; } 1026 1027protected: 1028 void DoExecute(Args &command, CommandReturnObject &result) override { 1029 Process *process = m_exe_ctx.GetProcessPtr(); 1030 1031 for (auto &entry : command.entries()) { 1032 Status error; 1033 PlatformSP platform = process->GetTarget().GetPlatform(); 1034 llvm::StringRef image_path = entry.ref(); 1035 uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; 1036 1037 if (!m_options.do_install) { 1038 FileSpec image_spec(image_path); 1039 platform->ResolveRemotePath(image_spec, image_spec); 1040 image_token = 1041 platform->LoadImage(process, FileSpec(), image_spec, error); 1042 } else if (m_options.install_path) { 1043 FileSpec image_spec(image_path); 1044 FileSystem::Instance().Resolve(image_spec); 1045 platform->ResolveRemotePath(m_options.install_path, 1046 m_options.install_path); 1047 image_token = platform->LoadImage(process, image_spec, 1048 m_options.install_path, error); 1049 } else { 1050 FileSpec image_spec(image_path); 1051 FileSystem::Instance().Resolve(image_spec); 1052 image_token = 1053 platform->LoadImage(process, image_spec, FileSpec(), error); 1054 } 1055 1056 if (image_token != LLDB_INVALID_IMAGE_TOKEN) { 1057 result.AppendMessageWithFormat( 1058 "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(), 1059 image_token); 1060 result.SetStatus(eReturnStatusSuccessFinishResult); 1061 } else { 1062 result.AppendErrorWithFormat("failed to load '%s': %s", 1063 image_path.str().c_str(), 1064 error.AsCString()); 1065 } 1066 } 1067 } 1068 1069 CommandOptions m_options; 1070}; 1071 1072// CommandObjectProcessUnload 1073#pragma mark CommandObjectProcessUnload 1074 1075class CommandObjectProcessUnload : public CommandObjectParsed { 1076public: 1077 CommandObjectProcessUnload(CommandInterpreter &interpreter) 1078 : CommandObjectParsed( 1079 interpreter, "process unload", 1080 "Unload a shared library from the current process using the index " 1081 "returned by a previous call to \"process load\".", 1082 "process unload <index>", 1083 eCommandRequiresProcess | eCommandTryTargetAPILock | 1084 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 1085 CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain}; 1086 m_arguments.push_back({load_idx_arg}); 1087 } 1088 1089 ~CommandObjectProcessUnload() override = default; 1090 1091 void 1092 HandleArgumentCompletion(CompletionRequest &request, 1093 OptionElementVector &opt_element_vector) override { 1094 1095 if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope()) 1096 return; 1097 1098 Process *process = m_exe_ctx.GetProcessPtr(); 1099 1100 const std::vector<lldb::addr_t> &tokens = process->GetImageTokens(); 1101 const size_t token_num = tokens.size(); 1102 for (size_t i = 0; i < token_num; ++i) { 1103 if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN) 1104 continue; 1105 request.TryCompleteCurrentArg(std::to_string(i)); 1106 } 1107 } 1108 1109protected: 1110 void DoExecute(Args &command, CommandReturnObject &result) override { 1111 Process *process = m_exe_ctx.GetProcessPtr(); 1112 1113 for (auto &entry : command.entries()) { 1114 uint32_t image_token; 1115 if (entry.ref().getAsInteger(0, image_token)) { 1116 result.AppendErrorWithFormat("invalid image index argument '%s'", 1117 entry.ref().str().c_str()); 1118 break; 1119 } else { 1120 Status error(process->GetTarget().GetPlatform()->UnloadImage( 1121 process, image_token)); 1122 if (error.Success()) { 1123 result.AppendMessageWithFormat( 1124 "Unloading shared library with index %u...ok\n", image_token); 1125 result.SetStatus(eReturnStatusSuccessFinishResult); 1126 } else { 1127 result.AppendErrorWithFormat("failed to unload image: %s", 1128 error.AsCString()); 1129 break; 1130 } 1131 } 1132 } 1133 } 1134}; 1135 1136// CommandObjectProcessSignal 1137#pragma mark CommandObjectProcessSignal 1138 1139class CommandObjectProcessSignal : public CommandObjectParsed { 1140public: 1141 CommandObjectProcessSignal(CommandInterpreter &interpreter) 1142 : CommandObjectParsed( 1143 interpreter, "process signal", 1144 "Send a UNIX signal to the current target process.", nullptr, 1145 eCommandRequiresProcess | eCommandTryTargetAPILock) { 1146 CommandArgumentEntry arg; 1147 CommandArgumentData signal_arg; 1148 1149 // Define the first (and only) variant of this arg. 1150 signal_arg.arg_type = eArgTypeUnixSignal; 1151 signal_arg.arg_repetition = eArgRepeatPlain; 1152 1153 // There is only one variant this argument could be; put it into the 1154 // argument entry. 1155 arg.push_back(signal_arg); 1156 1157 // Push the data for the first argument into the m_arguments vector. 1158 m_arguments.push_back(arg); 1159 } 1160 1161 ~CommandObjectProcessSignal() override = default; 1162 1163 void 1164 HandleArgumentCompletion(CompletionRequest &request, 1165 OptionElementVector &opt_element_vector) override { 1166 if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) 1167 return; 1168 1169 UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); 1170 int signo = signals->GetFirstSignalNumber(); 1171 while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1172 request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo)); 1173 signo = signals->GetNextSignalNumber(signo); 1174 } 1175 } 1176 1177protected: 1178 void DoExecute(Args &command, CommandReturnObject &result) override { 1179 Process *process = m_exe_ctx.GetProcessPtr(); 1180 1181 if (command.GetArgumentCount() == 1) { 1182 int signo = LLDB_INVALID_SIGNAL_NUMBER; 1183 1184 const char *signal_name = command.GetArgumentAtIndex(0); 1185 if (::isxdigit(signal_name[0])) { 1186 if (!llvm::to_integer(signal_name, signo)) 1187 signo = LLDB_INVALID_SIGNAL_NUMBER; 1188 } else 1189 signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name); 1190 1191 if (signo == LLDB_INVALID_SIGNAL_NUMBER) { 1192 result.AppendErrorWithFormat("Invalid signal argument '%s'.\n", 1193 command.GetArgumentAtIndex(0)); 1194 } else { 1195 Status error(process->Signal(signo)); 1196 if (error.Success()) { 1197 result.SetStatus(eReturnStatusSuccessFinishResult); 1198 } else { 1199 result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo, 1200 error.AsCString()); 1201 } 1202 } 1203 } else { 1204 result.AppendErrorWithFormat( 1205 "'%s' takes exactly one signal number argument:\nUsage: %s\n", 1206 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1207 } 1208 } 1209}; 1210 1211// CommandObjectProcessInterrupt 1212#pragma mark CommandObjectProcessInterrupt 1213 1214class CommandObjectProcessInterrupt : public CommandObjectParsed { 1215public: 1216 CommandObjectProcessInterrupt(CommandInterpreter &interpreter) 1217 : CommandObjectParsed(interpreter, "process interrupt", 1218 "Interrupt the current target process.", 1219 "process interrupt", 1220 eCommandRequiresProcess | eCommandTryTargetAPILock | 1221 eCommandProcessMustBeLaunched) {} 1222 1223 ~CommandObjectProcessInterrupt() override = default; 1224 1225protected: 1226 void DoExecute(Args &command, CommandReturnObject &result) override { 1227 Process *process = m_exe_ctx.GetProcessPtr(); 1228 if (process == nullptr) { 1229 result.AppendError("no process to halt"); 1230 return; 1231 } 1232 1233 bool clear_thread_plans = true; 1234 Status error(process->Halt(clear_thread_plans)); 1235 if (error.Success()) { 1236 result.SetStatus(eReturnStatusSuccessFinishResult); 1237 } else { 1238 result.AppendErrorWithFormat("Failed to halt process: %s\n", 1239 error.AsCString()); 1240 } 1241 } 1242}; 1243 1244// CommandObjectProcessKill 1245#pragma mark CommandObjectProcessKill 1246 1247class CommandObjectProcessKill : public CommandObjectParsed { 1248public: 1249 CommandObjectProcessKill(CommandInterpreter &interpreter) 1250 : CommandObjectParsed(interpreter, "process kill", 1251 "Terminate the current target process.", 1252 "process kill", 1253 eCommandRequiresProcess | eCommandTryTargetAPILock | 1254 eCommandProcessMustBeLaunched) {} 1255 1256 ~CommandObjectProcessKill() override = default; 1257 1258protected: 1259 void DoExecute(Args &command, CommandReturnObject &result) override { 1260 Process *process = m_exe_ctx.GetProcessPtr(); 1261 if (process == nullptr) { 1262 result.AppendError("no process to kill"); 1263 return; 1264 } 1265 1266 Status error(process->Destroy(true)); 1267 if (error.Success()) { 1268 result.SetStatus(eReturnStatusSuccessFinishResult); 1269 } else { 1270 result.AppendErrorWithFormat("Failed to kill process: %s\n", 1271 error.AsCString()); 1272 } 1273 } 1274}; 1275 1276#define LLDB_OPTIONS_process_save_core 1277#include "CommandOptions.inc" 1278 1279class CommandObjectProcessSaveCore : public CommandObjectParsed { 1280public: 1281 CommandObjectProcessSaveCore(CommandInterpreter &interpreter) 1282 : CommandObjectParsed( 1283 interpreter, "process save-core", 1284 "Save the current process as a core file using an " 1285 "appropriate file type.", 1286 "process save-core [-s corefile-style -p plugin-name] FILE", 1287 eCommandRequiresProcess | eCommandTryTargetAPILock | 1288 eCommandProcessMustBeLaunched) { 1289 CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain}; 1290 m_arguments.push_back({file_arg}); 1291 } 1292 1293 ~CommandObjectProcessSaveCore() override = default; 1294 1295 Options *GetOptions() override { return &m_options; } 1296 1297 void 1298 HandleArgumentCompletion(CompletionRequest &request, 1299 OptionElementVector &opt_element_vector) override { 1300 CommandCompletions::InvokeCommonCompletionCallbacks( 1301 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); 1302 } 1303 1304 class CommandOptions : public Options { 1305 public: 1306 CommandOptions() = default; 1307 1308 ~CommandOptions() override = default; 1309 1310 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1311 return llvm::ArrayRef(g_process_save_core_options); 1312 } 1313 1314 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1315 ExecutionContext *execution_context) override { 1316 const int short_option = m_getopt_table[option_idx].val; 1317 Status error; 1318 1319 switch (short_option) { 1320 case 'p': 1321 m_requested_plugin_name = option_arg.str(); 1322 break; 1323 case 's': 1324 m_requested_save_core_style = 1325 (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum( 1326 option_arg, GetDefinitions()[option_idx].enum_values, 1327 eSaveCoreUnspecified, error); 1328 break; 1329 default: 1330 llvm_unreachable("Unimplemented option"); 1331 } 1332 1333 return {}; 1334 } 1335 1336 void OptionParsingStarting(ExecutionContext *execution_context) override { 1337 m_requested_save_core_style = eSaveCoreUnspecified; 1338 m_requested_plugin_name.clear(); 1339 } 1340 1341 // Instance variables to hold the values for command options. 1342 SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified; 1343 std::string m_requested_plugin_name; 1344 }; 1345 1346protected: 1347 void DoExecute(Args &command, CommandReturnObject &result) override { 1348 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1349 if (process_sp) { 1350 if (command.GetArgumentCount() == 1) { 1351 FileSpec output_file(command.GetArgumentAtIndex(0)); 1352 FileSystem::Instance().Resolve(output_file); 1353 SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; 1354 Status error = 1355 PluginManager::SaveCore(process_sp, output_file, corefile_style, 1356 m_options.m_requested_plugin_name); 1357 if (error.Success()) { 1358 if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly || 1359 corefile_style == SaveCoreStyle::eSaveCoreStackOnly) { 1360 result.AppendMessageWithFormat( 1361 "\nModified-memory or stack-memory only corefile " 1362 "created. This corefile may \n" 1363 "not show library/framework/app binaries " 1364 "on a different system, or when \n" 1365 "those binaries have " 1366 "been updated/modified. Copies are not included\n" 1367 "in this corefile. Use --style full to include all " 1368 "process memory.\n"); 1369 } 1370 result.SetStatus(eReturnStatusSuccessFinishResult); 1371 } else { 1372 result.AppendErrorWithFormat( 1373 "Failed to save core file for process: %s\n", error.AsCString()); 1374 } 1375 } else { 1376 result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n", 1377 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1378 } 1379 } else { 1380 result.AppendError("invalid process"); 1381 } 1382 } 1383 1384 CommandOptions m_options; 1385}; 1386 1387// CommandObjectProcessStatus 1388#pragma mark CommandObjectProcessStatus 1389#define LLDB_OPTIONS_process_status 1390#include "CommandOptions.inc" 1391 1392class CommandObjectProcessStatus : public CommandObjectParsed { 1393public: 1394 CommandObjectProcessStatus(CommandInterpreter &interpreter) 1395 : CommandObjectParsed( 1396 interpreter, "process status", 1397 "Show status and stop location for the current target process.", 1398 "process status", 1399 eCommandRequiresProcess | eCommandTryTargetAPILock) {} 1400 1401 ~CommandObjectProcessStatus() override = default; 1402 1403 Options *GetOptions() override { return &m_options; } 1404 1405 class CommandOptions : public Options { 1406 public: 1407 CommandOptions() = default; 1408 1409 ~CommandOptions() override = default; 1410 1411 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1412 ExecutionContext *execution_context) override { 1413 const int short_option = m_getopt_table[option_idx].val; 1414 1415 switch (short_option) { 1416 case 'v': 1417 m_verbose = true; 1418 break; 1419 default: 1420 llvm_unreachable("Unimplemented option"); 1421 } 1422 1423 return {}; 1424 } 1425 1426 void OptionParsingStarting(ExecutionContext *execution_context) override { 1427 m_verbose = false; 1428 } 1429 1430 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1431 return llvm::ArrayRef(g_process_status_options); 1432 } 1433 1434 // Instance variables to hold the values for command options. 1435 bool m_verbose = false; 1436 }; 1437 1438protected: 1439 void DoExecute(Args &command, CommandReturnObject &result) override { 1440 Stream &strm = result.GetOutputStream(); 1441 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1442 1443 // No need to check "process" for validity as eCommandRequiresProcess 1444 // ensures it is valid 1445 Process *process = m_exe_ctx.GetProcessPtr(); 1446 const bool only_threads_with_stop_reason = true; 1447 const uint32_t start_frame = 0; 1448 const uint32_t num_frames = 1; 1449 const uint32_t num_frames_with_source = 1; 1450 const bool stop_format = true; 1451 process->GetStatus(strm); 1452 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1453 num_frames, num_frames_with_source, stop_format); 1454 1455 if (m_options.m_verbose) { 1456 addr_t code_mask = process->GetCodeAddressMask(); 1457 addr_t data_mask = process->GetDataAddressMask(); 1458 if (code_mask != 0) { 1459 int bits = std::bitset<64>(~code_mask).count(); 1460 result.AppendMessageWithFormat( 1461 "Addressable code address mask: 0x%" PRIx64 "\n", code_mask); 1462 result.AppendMessageWithFormat( 1463 "Addressable data address mask: 0x%" PRIx64 "\n", data_mask); 1464 result.AppendMessageWithFormat( 1465 "Number of bits used in addressing (code): %d\n", bits); 1466 } 1467 1468 PlatformSP platform_sp = process->GetTarget().GetPlatform(); 1469 if (!platform_sp) { 1470 result.AppendError("Couldn'retrieve the target's platform"); 1471 return; 1472 } 1473 1474 auto expected_crash_info = 1475 platform_sp->FetchExtendedCrashInformation(*process); 1476 1477 if (!expected_crash_info) { 1478 result.AppendError(llvm::toString(expected_crash_info.takeError())); 1479 return; 1480 } 1481 1482 StructuredData::DictionarySP crash_info_sp = *expected_crash_info; 1483 1484 if (crash_info_sp) { 1485 strm.EOL(); 1486 strm.PutCString("Extended Crash Information:\n"); 1487 crash_info_sp->GetDescription(strm); 1488 } 1489 } 1490 } 1491 1492private: 1493 CommandOptions m_options; 1494}; 1495 1496// CommandObjectProcessHandle 1497#define LLDB_OPTIONS_process_handle 1498#include "CommandOptions.inc" 1499 1500#pragma mark CommandObjectProcessHandle 1501 1502class CommandObjectProcessHandle : public CommandObjectParsed { 1503public: 1504 class CommandOptions : public Options { 1505 public: 1506 CommandOptions() { OptionParsingStarting(nullptr); } 1507 1508 ~CommandOptions() override = default; 1509 1510 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1511 ExecutionContext *execution_context) override { 1512 Status error; 1513 const int short_option = m_getopt_table[option_idx].val; 1514 1515 switch (short_option) { 1516 case 'c': 1517 do_clear = true; 1518 break; 1519 case 'd': 1520 dummy = true; 1521 break; 1522 case 's': 1523 stop = std::string(option_arg); 1524 break; 1525 case 'n': 1526 notify = std::string(option_arg); 1527 break; 1528 case 'p': 1529 pass = std::string(option_arg); 1530 break; 1531 case 't': 1532 only_target_values = true; 1533 break; 1534 default: 1535 llvm_unreachable("Unimplemented option"); 1536 } 1537 return error; 1538 } 1539 1540 void OptionParsingStarting(ExecutionContext *execution_context) override { 1541 stop.clear(); 1542 notify.clear(); 1543 pass.clear(); 1544 only_target_values = false; 1545 do_clear = false; 1546 dummy = false; 1547 } 1548 1549 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1550 return llvm::ArrayRef(g_process_handle_options); 1551 } 1552 1553 // Instance variables to hold the values for command options. 1554 1555 std::string stop; 1556 std::string notify; 1557 std::string pass; 1558 bool only_target_values = false; 1559 bool do_clear = false; 1560 bool dummy = false; 1561 }; 1562 1563 CommandObjectProcessHandle(CommandInterpreter &interpreter) 1564 : CommandObjectParsed(interpreter, "process handle", 1565 "Manage LLDB handling of OS signals for the " 1566 "current target process. Defaults to showing " 1567 "current policy.", 1568 nullptr) { 1569 SetHelpLong("\nIf no signals are specified but one or more actions are, " 1570 "and there is a live process, update them all. If no action " 1571 "is specified, list the current values.\n" 1572 "If you specify actions with no target (e.g. in an init file) " 1573 "or in a target with no process " 1574 "the values will get copied into subsequent targets, but " 1575 "lldb won't be able to spell-check the options since it can't " 1576 "know which signal set will later be in force." 1577 "\nYou can see the signal modifications held by the target" 1578 "by passing the -t option." 1579 "\nYou can also clear the target modification for a signal" 1580 "by passing the -c option"); 1581 CommandArgumentEntry arg; 1582 CommandArgumentData signal_arg; 1583 1584 signal_arg.arg_type = eArgTypeUnixSignal; 1585 signal_arg.arg_repetition = eArgRepeatStar; 1586 1587 arg.push_back(signal_arg); 1588 1589 m_arguments.push_back(arg); 1590 } 1591 1592 ~CommandObjectProcessHandle() override = default; 1593 1594 Options *GetOptions() override { return &m_options; } 1595 1596 bool VerifyCommandOptionValue(const std::string &option, int &real_value) { 1597 bool okay = true; 1598 bool success = false; 1599 bool tmp_value = OptionArgParser::ToBoolean(option, false, &success); 1600 1601 if (success && tmp_value) 1602 real_value = 1; 1603 else if (success && !tmp_value) 1604 real_value = 0; 1605 else { 1606 // If the value isn't 'true' or 'false', it had better be 0 or 1. 1607 if (!llvm::to_integer(option, real_value)) 1608 real_value = 3; 1609 if (real_value != 0 && real_value != 1) 1610 okay = false; 1611 } 1612 1613 return okay; 1614 } 1615 1616 void PrintSignalHeader(Stream &str) { 1617 str.Printf("NAME PASS STOP NOTIFY\n"); 1618 str.Printf("=========== ===== ===== ======\n"); 1619 } 1620 1621 void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name, 1622 const UnixSignalsSP &signals_sp) { 1623 bool stop; 1624 bool suppress; 1625 bool notify; 1626 1627 str.Format("{0, -11} ", sig_name); 1628 if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { 1629 bool pass = !suppress; 1630 str.Printf("%s %s %s", (pass ? "true " : "false"), 1631 (stop ? "true " : "false"), (notify ? "true " : "false")); 1632 } 1633 str.Printf("\n"); 1634 } 1635 1636 void PrintSignalInformation(Stream &str, Args &signal_args, 1637 int num_valid_signals, 1638 const UnixSignalsSP &signals_sp) { 1639 PrintSignalHeader(str); 1640 1641 if (num_valid_signals > 0) { 1642 size_t num_args = signal_args.GetArgumentCount(); 1643 for (size_t i = 0; i < num_args; ++i) { 1644 int32_t signo = signals_sp->GetSignalNumberFromName( 1645 signal_args.GetArgumentAtIndex(i)); 1646 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1647 PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i), 1648 signals_sp); 1649 } 1650 } else // Print info for ALL signals 1651 { 1652 int32_t signo = signals_sp->GetFirstSignalNumber(); 1653 while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1654 PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo), 1655 signals_sp); 1656 signo = signals_sp->GetNextSignalNumber(signo); 1657 } 1658 } 1659 } 1660 1661protected: 1662 void DoExecute(Args &signal_args, CommandReturnObject &result) override { 1663 Target &target = GetSelectedOrDummyTarget(); 1664 1665 // Any signals that are being set should be added to the Target's 1666 // DummySignals so they will get applied on rerun, etc. 1667 // If we have a process, however, we can do a more accurate job of vetting 1668 // the user's options. 1669 ProcessSP process_sp = target.GetProcessSP(); 1670 1671 int stop_action = -1; // -1 means leave the current setting alone 1672 int pass_action = -1; // -1 means leave the current setting alone 1673 int notify_action = -1; // -1 means leave the current setting alone 1674 1675 if (!m_options.stop.empty() && 1676 !VerifyCommandOptionValue(m_options.stop, stop_action)) { 1677 result.AppendError("Invalid argument for command option --stop; must be " 1678 "true or false.\n"); 1679 return; 1680 } 1681 1682 if (!m_options.notify.empty() && 1683 !VerifyCommandOptionValue(m_options.notify, notify_action)) { 1684 result.AppendError("Invalid argument for command option --notify; must " 1685 "be true or false.\n"); 1686 return; 1687 } 1688 1689 if (!m_options.pass.empty() && 1690 !VerifyCommandOptionValue(m_options.pass, pass_action)) { 1691 result.AppendError("Invalid argument for command option --pass; must be " 1692 "true or false.\n"); 1693 return; 1694 } 1695 1696 bool no_actions = (stop_action == -1 && pass_action == -1 1697 && notify_action == -1); 1698 if (m_options.only_target_values && !no_actions) { 1699 result.AppendError("-t is for reporting, not setting, target values."); 1700 return; 1701 } 1702 1703 size_t num_args = signal_args.GetArgumentCount(); 1704 UnixSignalsSP signals_sp; 1705 if (process_sp) 1706 signals_sp = process_sp->GetUnixSignals(); 1707 1708 int num_signals_set = 0; 1709 1710 // If we were just asked to print the target values, do that here and 1711 // return: 1712 if (m_options.only_target_values) { 1713 target.PrintDummySignals(result.GetOutputStream(), signal_args); 1714 result.SetStatus(eReturnStatusSuccessFinishResult); 1715 return; 1716 } 1717 1718 // This handles clearing values: 1719 if (m_options.do_clear) { 1720 target.ClearDummySignals(signal_args); 1721 if (m_options.dummy) 1722 GetDummyTarget().ClearDummySignals(signal_args); 1723 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1724 return; 1725 } 1726 1727 // This rest handles setting values: 1728 if (num_args > 0) { 1729 for (const auto &arg : signal_args) { 1730 // Do the process first. If we have a process we can catch 1731 // invalid signal names, which we do here. 1732 if (signals_sp) { 1733 int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str()); 1734 if (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1735 // Casting the actions as bools here should be okay, because 1736 // VerifyCommandOptionValue guarantees the value is either 0 or 1. 1737 if (stop_action != -1) 1738 signals_sp->SetShouldStop(signo, stop_action); 1739 if (pass_action != -1) { 1740 bool suppress = !pass_action; 1741 signals_sp->SetShouldSuppress(signo, suppress); 1742 } 1743 if (notify_action != -1) 1744 signals_sp->SetShouldNotify(signo, notify_action); 1745 ++num_signals_set; 1746 } else { 1747 result.AppendErrorWithFormat("Invalid signal name '%s'\n", 1748 arg.c_str()); 1749 continue; 1750 } 1751 } else { 1752 // If there's no process we can't check, so we just set them all. 1753 // But since the map signal name -> signal number across all platforms 1754 // is not 1-1, we can't sensibly set signal actions by number before 1755 // we have a process. Check that here: 1756 int32_t signo; 1757 if (llvm::to_integer(arg.c_str(), signo)) { 1758 result.AppendErrorWithFormat("Can't set signal handling by signal " 1759 "number with no process"); 1760 return; 1761 } 1762 num_signals_set = num_args; 1763 } 1764 auto set_lazy_bool = [] (int action) -> LazyBool { 1765 LazyBool lazy; 1766 if (action == -1) 1767 lazy = eLazyBoolCalculate; 1768 else if (action) 1769 lazy = eLazyBoolYes; 1770 else 1771 lazy = eLazyBoolNo; 1772 return lazy; 1773 }; 1774 1775 // If there were no actions, we're just listing, don't add the dummy: 1776 if (!no_actions) 1777 target.AddDummySignal(arg.ref(), 1778 set_lazy_bool(pass_action), 1779 set_lazy_bool(notify_action), 1780 set_lazy_bool(stop_action)); 1781 } 1782 } else { 1783 // No signal specified, if any command options were specified, update ALL 1784 // signals. But we can't do this without a process since we don't know 1785 // all the possible signals that might be valid for this target. 1786 if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1787 && process_sp) { 1788 if (m_interpreter.Confirm( 1789 "Do you really want to update all the signals?", false)) { 1790 int32_t signo = signals_sp->GetFirstSignalNumber(); 1791 while (signo != LLDB_INVALID_SIGNAL_NUMBER) { 1792 if (notify_action != -1) 1793 signals_sp->SetShouldNotify(signo, notify_action); 1794 if (stop_action != -1) 1795 signals_sp->SetShouldStop(signo, stop_action); 1796 if (pass_action != -1) { 1797 bool suppress = !pass_action; 1798 signals_sp->SetShouldSuppress(signo, suppress); 1799 } 1800 signo = signals_sp->GetNextSignalNumber(signo); 1801 } 1802 } 1803 } 1804 } 1805 1806 if (signals_sp) 1807 PrintSignalInformation(result.GetOutputStream(), signal_args, 1808 num_signals_set, signals_sp); 1809 else 1810 target.PrintDummySignals(result.GetOutputStream(), 1811 signal_args); 1812 1813 if (num_signals_set > 0) 1814 result.SetStatus(eReturnStatusSuccessFinishResult); 1815 else 1816 result.SetStatus(eReturnStatusFailed); 1817 } 1818 1819 CommandOptions m_options; 1820}; 1821 1822// Next are the subcommands of CommandObjectMultiwordProcessTrace 1823 1824// CommandObjectProcessTraceStart 1825class CommandObjectProcessTraceStart : public CommandObjectTraceProxy { 1826public: 1827 CommandObjectProcessTraceStart(CommandInterpreter &interpreter) 1828 : CommandObjectTraceProxy( 1829 /*live_debug_session_only*/ true, interpreter, 1830 "process trace start", 1831 "Start tracing this process with the corresponding trace " 1832 "plug-in.", 1833 "process trace start [<trace-options>]") {} 1834 1835protected: 1836 lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 1837 return trace.GetProcessTraceStartCommand(m_interpreter); 1838 } 1839}; 1840 1841// CommandObjectProcessTraceStop 1842class CommandObjectProcessTraceStop : public CommandObjectParsed { 1843public: 1844 CommandObjectProcessTraceStop(CommandInterpreter &interpreter) 1845 : CommandObjectParsed(interpreter, "process trace stop", 1846 "Stop tracing this process. This does not affect " 1847 "traces started with the " 1848 "\"thread trace start\" command.", 1849 "process trace stop", 1850 eCommandRequiresProcess | eCommandTryTargetAPILock | 1851 eCommandProcessMustBeLaunched | 1852 eCommandProcessMustBePaused | 1853 eCommandProcessMustBeTraced) {} 1854 1855 ~CommandObjectProcessTraceStop() override = default; 1856 1857 void DoExecute(Args &command, CommandReturnObject &result) override { 1858 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 1859 1860 TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 1861 1862 if (llvm::Error err = trace_sp->Stop()) 1863 result.AppendError(toString(std::move(err))); 1864 else 1865 result.SetStatus(eReturnStatusSuccessFinishResult); 1866 } 1867}; 1868 1869// CommandObjectMultiwordProcessTrace 1870class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword { 1871public: 1872 CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter) 1873 : CommandObjectMultiword( 1874 interpreter, "trace", "Commands for tracing the current process.", 1875 "process trace <subcommand> [<subcommand objects>]") { 1876 LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart( 1877 interpreter))); 1878 LoadSubCommand("stop", CommandObjectSP( 1879 new CommandObjectProcessTraceStop(interpreter))); 1880 } 1881 1882 ~CommandObjectMultiwordProcessTrace() override = default; 1883}; 1884 1885// CommandObjectMultiwordProcess 1886 1887CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( 1888 CommandInterpreter &interpreter) 1889 : CommandObjectMultiword( 1890 interpreter, "process", 1891 "Commands for interacting with processes on the current platform.", 1892 "process <subcommand> [<subcommand-options>]") { 1893 LoadSubCommand("attach", 1894 CommandObjectSP(new CommandObjectProcessAttach(interpreter))); 1895 LoadSubCommand("launch", 1896 CommandObjectSP(new CommandObjectProcessLaunch(interpreter))); 1897 LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue( 1898 interpreter))); 1899 LoadSubCommand("connect", 1900 CommandObjectSP(new CommandObjectProcessConnect(interpreter))); 1901 LoadSubCommand("detach", 1902 CommandObjectSP(new CommandObjectProcessDetach(interpreter))); 1903 LoadSubCommand("load", 1904 CommandObjectSP(new CommandObjectProcessLoad(interpreter))); 1905 LoadSubCommand("unload", 1906 CommandObjectSP(new CommandObjectProcessUnload(interpreter))); 1907 LoadSubCommand("signal", 1908 CommandObjectSP(new CommandObjectProcessSignal(interpreter))); 1909 LoadSubCommand("handle", 1910 CommandObjectSP(new CommandObjectProcessHandle(interpreter))); 1911 LoadSubCommand("status", 1912 CommandObjectSP(new CommandObjectProcessStatus(interpreter))); 1913 LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( 1914 interpreter))); 1915 LoadSubCommand("kill", 1916 CommandObjectSP(new CommandObjectProcessKill(interpreter))); 1917 LoadSubCommand("plugin", 1918 CommandObjectSP(new CommandObjectProcessPlugin(interpreter))); 1919 LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore( 1920 interpreter))); 1921 LoadSubCommand( 1922 "trace", 1923 CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter))); 1924} 1925 1926CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default; 1927