Files
clang-p2996/lldb/source/Target/ScriptedThreadPlan.cpp
Med Ismail Bennani 039cfe812c [lldb/Target] Rename ThreadPlanPython into ScriptedThreadPlan (#101931)
Following 9a9ec228cd, since the ThreadPlanPython class started making
use of the Scripted Interface instead of calling directly into the
python methods, this class can work with other scripting languages (as
long as someone add the interfact for that language ;p).

So it doesn't make sense anymore for it to keep this name and also we
should avoid having language specific related classes outside the plugin
directory.

This patch renames the internal class from `ThreadPlanPython` to
`ScriptedThreadPlan` as its advertised externally, and also updates the
various log messages.

This should hopefully make the codebase more coherent.

Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2024-08-05 10:43:42 -07:00

218 lines
7.5 KiB
C++

//===-- ScriptedThreadPlan.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ScriptedThreadPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
ScriptedThreadPlan::ScriptedThreadPlan(Thread &thread, const char *class_name,
const StructuredDataImpl &args_data)
: ThreadPlan(ThreadPlan::eKindPython, "Script based Thread Plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
m_class_name(class_name), m_args_data(args_data), m_did_push(false),
m_stop_others(false) {
ScriptInterpreter *interpreter = GetScriptInterpreter();
if (!interpreter) {
SetPlanComplete(false);
// FIXME: error handling
// error.SetErrorStringWithFormat(
// "ScriptedThreadPlan::%s () - ERROR: %s", __FUNCTION__,
// "Couldn't get script interpreter");
return;
}
m_interface = interpreter->CreateScriptedThreadPlanInterface();
if (!m_interface) {
SetPlanComplete(false);
// FIXME: error handling
// error.SetErrorStringWithFormat(
// "ScriptedThreadPlan::%s () - ERROR: %s", __FUNCTION__,
// "Script interpreter couldn't create Scripted Thread Plan Interface");
return;
}
SetIsControllingPlan(true);
SetOkayToDiscard(true);
SetPrivate(false);
}
bool ScriptedThreadPlan::ValidatePlan(Stream *error) {
if (!m_did_push)
return true;
if (!m_implementation_sp) {
if (error)
error->Printf("Error constructing Python ThreadPlan: %s",
m_error_str.empty() ? "<unknown error>"
: m_error_str.c_str());
return false;
}
return true;
}
ScriptInterpreter *ScriptedThreadPlan::GetScriptInterpreter() {
return m_process.GetTarget().GetDebugger().GetScriptInterpreter();
}
void ScriptedThreadPlan::DidPush() {
// We set up the script side in DidPush, so that it can push other plans in
// the constructor, and doesn't have to care about the details of DidPush.
m_did_push = true;
if (m_interface) {
auto obj_or_err = m_interface->CreatePluginObject(
m_class_name, this->shared_from_this(), m_args_data);
if (!obj_or_err) {
m_error_str = llvm::toString(obj_or_err.takeError());
SetPlanComplete(false);
} else
m_implementation_sp = *obj_or_err;
}
}
bool ScriptedThreadPlan::ShouldStop(Event *event_ptr) {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
bool should_stop = true;
if (m_implementation_sp) {
auto should_stop_or_err = m_interface->ShouldStop(event_ptr);
if (!should_stop_or_err) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), should_stop_or_err.takeError(),
"Can't call ScriptedThreadPlan::ShouldStop.");
SetPlanComplete(false);
} else
should_stop = *should_stop_or_err;
}
return should_stop;
}
bool ScriptedThreadPlan::IsPlanStale() {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
bool is_stale = true;
if (m_implementation_sp) {
auto is_stale_or_err = m_interface->IsStale();
if (!is_stale_or_err) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), is_stale_or_err.takeError(),
"Can't call ScriptedThreadPlan::IsStale.");
SetPlanComplete(false);
} else
is_stale = *is_stale_or_err;
}
return is_stale;
}
bool ScriptedThreadPlan::DoPlanExplainsStop(Event *event_ptr) {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
bool explains_stop = true;
if (m_implementation_sp) {
auto explains_stop_or_error = m_interface->ExplainsStop(event_ptr);
if (!explains_stop_or_error) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread),
explains_stop_or_error.takeError(),
"Can't call ScriptedThreadPlan::ExplainsStop.");
SetPlanComplete(false);
} else
explains_stop = *explains_stop_or_error;
}
return explains_stop;
}
bool ScriptedThreadPlan::MischiefManaged() {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
bool mischief_managed = true;
if (m_implementation_sp) {
// I don't really need mischief_managed, since it's simpler to just call
// SetPlanComplete in should_stop.
mischief_managed = IsPlanComplete();
if (mischief_managed) {
// We need to cache the stop reason here we'll need it in GetDescription.
GetDescription(&m_stop_description, eDescriptionLevelBrief);
m_implementation_sp.reset();
}
}
return mischief_managed;
}
lldb::StateType ScriptedThreadPlan::GetPlanRunState() {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
lldb::StateType run_state = eStateRunning;
if (m_implementation_sp)
run_state = m_interface->GetRunState();
return run_state;
}
void ScriptedThreadPlan::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
if (m_implementation_sp) {
ScriptInterpreter *script_interp = GetScriptInterpreter();
if (script_interp) {
lldb::StreamSP stream = std::make_shared<lldb_private::StreamString>();
llvm::Error err = m_interface->GetStopDescription(stream);
if (err) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),
"Can't call ScriptedThreadPlan::GetStopDescription.");
s->Printf("Scripted thread plan implemented by class %s.",
m_class_name.c_str());
} else
s->PutCString(
reinterpret_cast<StreamString *>(stream.get())->GetData());
}
return;
}
// It's an error not to have a description, so if we get here, we should
// add something.
if (m_stop_description.Empty())
s->Printf("Scripted thread plan implemented by class %s.",
m_class_name.c_str());
s->PutCString(m_stop_description.GetData());
}
// The ones below are not currently exported to Python.
bool ScriptedThreadPlan::WillStop() {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
LLVM_PRETTY_FUNCTION, m_class_name.c_str());
return true;
}
bool ScriptedThreadPlan::DoWillResume(lldb::StateType resume_state,
bool current_plan) {
m_stop_description.Clear();
return true;
}