blob: 07b7e4c24161884c9040c224ccfdc9903cb815b0 [file]
//===----------------------------------------------------------------------===//
//
// 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-python.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/ScriptedThreadPlan.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-enumerations.h"
#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"
#include "ScriptedStackFrameRecognizerPythonInterface.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
ScriptedStackFrameRecognizerPythonInterface::
ScriptedStackFrameRecognizerPythonInterface(
ScriptInterpreterPythonImpl &interpreter)
: ScriptedStackFrameRecognizerInterface(),
ScriptedPythonInterface(interpreter) {}
llvm::Expected<StructuredData::GenericSP>
ScriptedStackFrameRecognizerPythonInterface::CreatePluginObject(
const ScriptedMetadata &scripted_metadata) {
return ScriptedPythonInterface::CreatePluginObject(scripted_metadata,
nullptr);
}
lldb::ValueObjectListSP
ScriptedStackFrameRecognizerPythonInterface::GetRecognizedArguments(
lldb::StackFrameSP frame_sp) {
return LogAndDefault(
Dispatch<lldb::ValueObjectListSP>("get_recognized_arguments", frame_sp),
LLVM_PRETTY_FUNCTION);
}
bool ScriptedStackFrameRecognizerPythonInterface::ShouldHide(
lldb::StackFrameSP frame_sp) {
StructuredData::ObjectSP obj =
LogAndDefault(Dispatch("should_hide", frame_sp), LLVM_PRETTY_FUNCTION);
if (!obj)
return false;
return obj->GetBooleanValue();
}
lldb::StackFrameSP
ScriptedStackFrameRecognizerPythonInterface::SelectMostRelevantFrame(
lldb::StackFrameSP frame_sp) {
return LogAndDefault(
Dispatch<lldb::StackFrameSP>("select_most_relevant_frame", frame_sp),
LLVM_PRETTY_FUNCTION);
}
lldb::ValueObjectSP ScriptedStackFrameRecognizerPythonInterface::GetException(
lldb::StackFrameSP frame_sp) {
return LogAndDefault(Dispatch<lldb::ValueObjectSP>("get_exception", frame_sp),
LLVM_PRETTY_FUNCTION);
}
std::string ScriptedStackFrameRecognizerPythonInterface::GetStopDescription(
lldb::StackFrameSP frame_sp) {
StructuredData::ObjectSP obj = LogAndDefault(
Dispatch("get_stop_description", frame_sp), LLVM_PRETTY_FUNCTION);
if (!obj)
return "";
return obj->GetStringValue().str();
}
lldb::ThreadPlanSP
ScriptedStackFrameRecognizerPythonInterface::GetStepThroughPlan(
lldb::ThreadSP thread_sp) {
StructuredData::DictionarySP dict_sp =
LogAndDefault(Dispatch<StructuredData::DictionarySP>(
"get_step_through_plan", thread_sp),
LLVM_PRETTY_FUNCTION);
// The return value is an StructuredData::Dictionary with the class name and
// the extra args for the call:
if (!dict_sp || !dict_sp->IsValid())
return {};
StructuredData::ObjectSP obj = dict_sp->GetValueForKey("class_name");
if (!obj)
return {};
llvm::StringRef class_string = obj->GetStringValue();
if (class_string.empty())
return {};
// Look for extra args, this is optional:
StructuredData::Dictionary *extra_args_ptr = nullptr;
StructuredData::DictionarySP extra_args_sp;
if (dict_sp->GetValueForKeyAsDictionary("extra_args", extra_args_ptr))
extra_args_sp = std::static_pointer_cast<StructuredData::Dictionary>(
extra_args_ptr->shared_from_this());
// Now make a new thread plan for stepping using the provided class name and
// extra args.
ScriptedMetadata plan_metadata(class_string, extra_args_sp);
ThreadPlanSP step_through_plan_sp(
new ScriptedThreadPlan(*thread_sp.get(), plan_metadata));
step_through_plan_sp->SetStopOthers(true);
return step_through_plan_sp;
}
void ScriptedStackFrameRecognizerPythonInterface::Initialize() {
const std::vector<llvm::StringRef> ci_usages = {
"frame recognizer add -l <script-name> [-s <shlib> ...] "
"[-n <symbol> ... | -x <symbol-regex>] [-f false] "
"[--mangled-name-preference <mode>]"};
PluginManager::RegisterPlugin(
GetPluginNameStatic(),
"Recognize a stack frame and provide extra information about it "
"(recognized arguments, exception object, stop description, "
"hidden/most-relevant frame).",
CreateInstance, eScriptedExtensionScriptedStackFrameRecognizer,
eScriptLanguagePython, {ci_usages, {}});
}
void ScriptedStackFrameRecognizerPythonInterface::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}