"""
return lldb.SBError()
- def resume(self):
+ def resume(self, should_stop=True):
""" Simulate the scripted process resume.
- Returns:
- lldb.SBError: An `lldb.SBError` with error code 0.
- """
- return lldb.SBError()
-
- @abstractmethod
- def should_stop(self):
- """ Check if the scripted process plugin should produce the stop event.
-
- Returns:
- bool: True if scripted process should broadcast a stop event.
- False otherwise.
- """
- pass
-
- def stop(self):
- """ Trigger the scripted process stop.
+ Args:
+ should_stop (bool): If True, resume will also force the process
+ state to stopped after running it.
Returns:
lldb.SBError: An `lldb.SBError` with error code 0.
"""
+ process = self.target.GetProcess()
+ if not process:
+ error = lldb.SBError()
+ error.SetErrorString("Invalid process.")
+ return error
+
+ process.ForceScriptedState(lldb.eStateRunning);
+ if (should_stop):
+ process.ForceScriptedState(lldb.eStateStopped);
return lldb.SBError()
@abstractmethod
virtual Status Resume() { return Status("ScriptedProcess did not resume"); }
- virtual bool ShouldStop() { return true; }
-
- virtual Status Stop() { return Status("ScriptedProcess did not stop"); }
-
virtual std::optional<MemoryRegionInfo>
GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) {
error.SetErrorString("ScriptedProcess have no memory region.");
Status ScriptedProcess::DoLaunch(Module *exe_module,
ProcessLaunchInfo &launch_info) {
- /* FIXME: This doesn't reflect how lldb actually launches a process.
- In reality, it attaches to debugserver, then resume the process. */
+ LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
+
+ /* MARK: This doesn't reflect how lldb actually launches a process.
+ In reality, it attaches to debugserver, then resume the process.
+ That's not true in all cases. If debugserver is remote, lldb
+ asks debugserver to launch the process for it. */
Status error = GetInterface().Launch();
- SetPrivateState(eStateRunning);
-
- if (error.Fail())
- return error;
-
- // TODO: Fetch next state from stopped event queue then send stop event
- // const StateType state = SetThreadStopInfo(response);
- // if (state != eStateInvalid) {
- // SetPrivateState(state);
-
SetPrivateState(eStateStopped);
-
- return {};
+ return error;
}
void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
}
Status ScriptedProcess::DoResume() {
- Log *log = GetLog(LLDBLog::Process);
- // FIXME: Fetch data from thread.
- const StateType thread_resume_state = eStateRunning;
- LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
- StateAsCString(thread_resume_state));
-
- bool resume = (thread_resume_state == eStateRunning);
- assert(thread_resume_state == eStateRunning && "invalid thread resume state");
+ LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
- Status error;
- if (resume) {
- LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
-
- SetPrivateState(eStateRunning);
- SetPrivateState(eStateStopped);
- error = GetInterface().Resume();
- }
-
- return error;
+ return GetInterface().Resume();
}
Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
process_arch = GetArchitecture();
}
-Status ScriptedProcess::DoStop() {
- Log *log = GetLog(LLDBLog::Process);
-
- if (GetInterface().ShouldStop()) {
- SetPrivateState(eStateStopped);
- LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
- return {};
- }
-
- LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
- return GetInterface().Stop();
-}
-
Status ScriptedProcess::DoDestroy() { return Status(); }
bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
const ScriptedMetadata &scripted_metadata, Status &error);
- Status DoStop();
-
void Clear();
bool DoUpdateThreadList(ThreadList &old_thread_list,
template <>
struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {};
template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {};
+template <> struct PythonFormat<bool> : PassthroughFormat<bool, 'p'> {};
template <>
struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {};
template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {};
}
Status ScriptedProcessPythonInterface::Resume() {
- return GetStatusFromMethod("resume");
-}
-
-bool ScriptedProcessPythonInterface::ShouldStop() {
- Status error;
- StructuredData::ObjectSP obj = Dispatch("is_alive", error);
-
- if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
- return {};
-
- return obj->GetBooleanValue();
-}
-
-Status ScriptedProcessPythonInterface::Stop() {
- return GetStatusFromMethod("stop");
+ // When calling ScriptedProcess.Resume from lldb we should always stop.
+ return GetStatusFromMethod("resume", /*should_stop=*/true);
}
std::optional<MemoryRegionInfo>
Status Resume() override;
- bool ShouldStop() override;
-
- Status Stop() override;
-
std::optional<MemoryRegionInfo>
GetMemoryRegionContainingAddress(lldb::addr_t address,
Status &error) override;
return {object};
}
+ python::PythonObject Transform(bool arg) {
+ // Boolean arguments need to be turned into python objects.
+ return python::PythonBoolean(arg);
+ }
+
python::PythonObject Transform(Status arg) {
return python::ToSWIGWrapper(arg);
}
original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error);
}
+ template <>
+ void ReverseTransform(bool &original_arg,
+ python::PythonObject transformed_arg, Status &error) {
+ python::PythonBoolean boolean_arg = python::PythonBoolean(
+ python::PyRefType::Borrowed, transformed_arg.get());
+ if (boolean_arg.IsValid())
+ original_arg = boolean_arg.GetValue();
+ else
+ error.SetErrorString(
+ llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION)
+ .str());
+ }
+
template <std::size_t... I, typename... Args>
auto TransformTuple(const std::tuple<Args...> &args,
std::index_sequence<I...>) {