blob: 7cdfc99a6b4c8bbfe32febb57c3479318488eb18 [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) {
Status error;
return Dispatch<lldb::ValueObjectListSP>("get_recognized_arguments", error,
frame_sp);
}
bool ScriptedStackFrameRecognizerPythonInterface::ShouldHide(
lldb::StackFrameSP frame_sp) {
Status error;
StructuredData::ObjectSP obj = Dispatch("should_hide", error, frame_sp);
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
error))
return false;
return obj->GetBooleanValue();
}
lldb::StackFrameSP
ScriptedStackFrameRecognizerPythonInterface::SelectMostRelevantFrame(
lldb::StackFrameSP frame_sp) {
Status error;
return Dispatch<lldb::StackFrameSP>("select_most_relevant_frame", error,
frame_sp);
}
lldb::ValueObjectSP ScriptedStackFrameRecognizerPythonInterface::GetException(
lldb::StackFrameSP frame_sp) {
Status error;
return Dispatch<lldb::ValueObjectSP>("get_exception", error, frame_sp);
}
std::string ScriptedStackFrameRecognizerPythonInterface::GetStopDescription(
lldb::StackFrameSP frame_sp) {
Status error;
StructuredData::ObjectSP obj =
Dispatch("get_stop_description", error, frame_sp);
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
error))
return "";
return obj->GetStringValue().str();
}
lldb::ThreadPlanSP
ScriptedStackFrameRecognizerPythonInterface::GetStepThroughPlan(
lldb::ThreadSP thread_sp) {
Status error;
StructuredData::DictionarySP dict_sp = Dispatch<StructuredData::DictionarySP>(
"get_step_through_plan", error, thread_sp);
if (error.Fail())
return {};
// The return value is an StructuredData::Dictionary with the class name and
// the extra args for the call:
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION,
dict_sp, error))
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);
}