aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands/CommandObjectProcess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp153
1 files changed, 122 insertions, 31 deletions
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 484ef6a..f5961d9 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -1432,6 +1432,12 @@ public:
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
+ case 'c':
+ do_clear = true;
+ break;
+ case 'd':
+ dummy = true;
+ break;
case 's':
stop = std::string(option_arg);
break;
@@ -1441,6 +1447,9 @@ public:
case 'p':
pass = std::string(option_arg);
break;
+ case 't':
+ only_target_values = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -1451,6 +1460,9 @@ public:
stop.clear();
notify.clear();
pass.clear();
+ only_target_values = false;
+ do_clear = false;
+ dummy = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -1462,6 +1474,9 @@ public:
std::string stop;
std::string notify;
std::string pass;
+ bool only_target_values = false;
+ bool do_clear = false;
+ bool dummy = false;
};
CommandObjectProcessHandle(CommandInterpreter &interpreter)
@@ -1469,9 +1484,19 @@ public:
"Manage LLDB handling of OS signals for the "
"current target process. Defaults to showing "
"current policy.",
- nullptr, eCommandRequiresTarget) {
- SetHelpLong("\nIf no signals are specified, update them all. If no update "
- "option is specified, list the current values.");
+ nullptr) {
+ SetHelpLong("\nIf no signals are specified but one or more actions are, "
+ "and there is a live process, update them all. If no action "
+ "is specified, list the current values.\n"
+ "If you specify actions with no target (e.g. in an init file) "
+ "or in a target with no process "
+ "the values will get copied into subsequent targets, but "
+ "lldb won't be able to spell-check the options since it can't "
+ "know which signal set will later be in force."
+ "\nYou can see the signal modifications held by the target"
+ "by passing the -t option."
+ "\nYou can also clear the target modification for a signal"
+ "by passing the -c option");
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@@ -1554,15 +1579,13 @@ public:
protected:
bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
- Target *target_sp = &GetSelectedTarget();
+ Target &target = GetSelectedOrDummyTarget();
- ProcessSP process_sp = target_sp->GetProcessSP();
-
- if (!process_sp) {
- result.AppendError("No current process; cannot handle signals until you "
- "have a valid process.\n");
- return false;
- }
+ // Any signals that are being set should be added to the Target's
+ // DummySignals so they will get applied on rerun, etc.
+ // If we have a process, however, we can do a more accurate job of vetting
+ // the user's options.
+ ProcessSP process_sp = target.GetProcessSP();
int stop_action = -1; // -1 means leave the current setting alone
int pass_action = -1; // -1 means leave the current setting alone
@@ -1588,35 +1611,99 @@ protected:
"true or false.\n");
return false;
}
+
+ bool no_actions = (stop_action == -1 && pass_action == -1
+ && notify_action == -1);
+ if (m_options.only_target_values && !no_actions) {
+ result.AppendError("-t is for reporting, not setting, target values.");
+ return false;
+ }
size_t num_args = signal_args.GetArgumentCount();
- UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
+ UnixSignalsSP signals_sp;
+ if (process_sp)
+ signals_sp = process_sp->GetUnixSignals();
+
int num_signals_set = 0;
+ // If we were just asked to print the target values, do that here and
+ // return:
+ if (m_options.only_target_values) {
+ target.PrintDummySignals(result.GetOutputStream(), signal_args);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ // This handles clearing values:
+ if (m_options.do_clear) {
+ target.ClearDummySignals(signal_args);
+ if (m_options.dummy)
+ GetDummyTarget().ClearDummySignals(signal_args);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ // This rest handles setting values:
if (num_args > 0) {
for (const auto &arg : signal_args) {
- int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
- if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
- // Casting the actions as bools here should be okay, because
- // VerifyCommandOptionValue guarantees the value is either 0 or 1.
- if (stop_action != -1)
- signals_sp->SetShouldStop(signo, stop_action);
- if (pass_action != -1) {
- bool suppress = !pass_action;
- signals_sp->SetShouldSuppress(signo, suppress);
+ // Do the process first. If we have a process we can catch
+ // invalid signal names, which we do here.
+ if (signals_sp) {
+ int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
+ if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
+ // Casting the actions as bools here should be okay, because
+ // VerifyCommandOptionValue guarantees the value is either 0 or 1.
+ if (stop_action != -1)
+ signals_sp->SetShouldStop(signo, stop_action);
+ if (pass_action != -1) {
+ bool suppress = !pass_action;
+ signals_sp->SetShouldSuppress(signo, suppress);
+ }
+ if (notify_action != -1)
+ signals_sp->SetShouldNotify(signo, notify_action);
+ ++num_signals_set;
+ } else {
+ result.AppendErrorWithFormat("Invalid signal name '%s'\n",
+ arg.c_str());
+ continue;
}
- if (notify_action != -1)
- signals_sp->SetShouldNotify(signo, notify_action);
- ++num_signals_set;
} else {
- result.AppendErrorWithFormat("Invalid signal name '%s'\n",
- arg.c_str());
+ // If there's no process we can't check, so we just set them all.
+ // But since the map signal name -> signal number across all platforms
+ // is not 1-1, we can't sensibly set signal actions by number before
+ // we have a process. Check that here:
+ int32_t signo;
+ if (llvm::to_integer(arg.c_str(), signo)) {
+ result.AppendErrorWithFormat("Can't set signal handling by signal "
+ "number with no process");
+ return false;
+ }
+ num_signals_set = num_args;
}
+ auto set_lazy_bool = [] (int action) -> LazyBool {
+ LazyBool lazy;
+ if (action == -1)
+ lazy = eLazyBoolCalculate;
+ else if (action)
+ lazy = eLazyBoolYes;
+ else
+ lazy = eLazyBoolNo;
+ return lazy;
+ };
+
+ // If there were no actions, we're just listing, don't add the dummy:
+ if (!no_actions)
+ target.AddDummySignal(arg.ref(),
+ set_lazy_bool(pass_action),
+ set_lazy_bool(notify_action),
+ set_lazy_bool(stop_action));
}
} else {
// No signal specified, if any command options were specified, update ALL
- // signals.
- if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
+ // signals. But we can't do this without a process since we don't know
+ // all the possible signals that might be valid for this target.
+ if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
+ && process_sp) {
if (m_interpreter.Confirm(
"Do you really want to update all the signals?", false)) {
int32_t signo = signals_sp->GetFirstSignalNumber();
@@ -1635,11 +1722,15 @@ protected:
}
}
- PrintSignalInformation(result.GetOutputStream(), signal_args,
- num_signals_set, signals_sp);
+ if (signals_sp)
+ PrintSignalInformation(result.GetOutputStream(), signal_args,
+ num_signals_set, signals_sp);
+ else
+ target.PrintDummySignals(result.GetOutputStream(),
+ signal_args);
if (num_signals_set > 0)
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
else
result.SetStatus(eReturnStatusFailed);