mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
This patch adds the notion of "Facade" locations which can be reported from a ScriptedResolver instead of the actual underlying breakpoint location for the breakpoint. Also add a "was_hit" method to the scripted resolver that allows the breakpoint to say which of these "Facade" locations was hit, and "get_location_description" to provide a description for the facade locations. I apologize in advance for the size of the patch. Almost all of what's here was necessary to (a) make the feature testable and (b) not break any of the current behavior. The motivation for this feature is given in the "Providing Facade Locations" section that I added to the python-reference.rst so I won't repeat it here. rdar://152112327
127 lines
4.3 KiB
C++
127 lines
4.3 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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/Core/PluginManager.h"
|
|
#include "lldb/Host/Config.h"
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
#include "lldb/Target/ExecutionContext.h"
|
|
#include "lldb/Utility/Log.h"
|
|
#include "lldb/lldb-enumerations.h"
|
|
|
|
#if LLDB_ENABLE_PYTHON
|
|
|
|
// LLDB Python header must be included first
|
|
#include "../lldb-python.h"
|
|
|
|
#include "../SWIGPythonBridge.h"
|
|
#include "../ScriptInterpreterPythonImpl.h"
|
|
#include "ScriptedBreakpointPythonInterface.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::python;
|
|
|
|
ScriptedBreakpointPythonInterface::ScriptedBreakpointPythonInterface(
|
|
ScriptInterpreterPythonImpl &interpreter)
|
|
: ScriptedBreakpointInterface(), ScriptedPythonInterface(interpreter) {}
|
|
|
|
llvm::Expected<StructuredData::GenericSP>
|
|
ScriptedBreakpointPythonInterface::CreatePluginObject(
|
|
llvm::StringRef class_name, lldb::BreakpointSP break_sp,
|
|
const StructuredDataImpl &args_sp) {
|
|
return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr,
|
|
break_sp, args_sp);
|
|
}
|
|
|
|
bool ScriptedBreakpointPythonInterface::ResolverCallback(
|
|
SymbolContext sym_ctx) {
|
|
Status error;
|
|
|
|
StructuredData::ObjectSP obj = Dispatch("__callback__", error, sym_ctx);
|
|
|
|
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
|
error)) {
|
|
Log *log = GetLog(LLDBLog::Script);
|
|
LLDB_LOG(log, "Error calling __callback__ method: {1}", error);
|
|
return true;
|
|
}
|
|
return obj->GetBooleanValue();
|
|
}
|
|
|
|
lldb::SearchDepth ScriptedBreakpointPythonInterface::GetDepth() {
|
|
Status error;
|
|
StructuredData::ObjectSP obj = Dispatch("__get_depth__", error);
|
|
|
|
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
|
error)) {
|
|
return lldb::eSearchDepthModule;
|
|
}
|
|
uint64_t value = obj->GetUnsignedIntegerValue();
|
|
if (value <= lldb::kLastSearchDepthKind)
|
|
return (lldb::SearchDepth)value;
|
|
// This is what we were doing on error before, though I'm not sure that's
|
|
// better than returning eSearchDepthInvalid.
|
|
return lldb::eSearchDepthModule;
|
|
}
|
|
|
|
std::optional<std::string> ScriptedBreakpointPythonInterface::GetShortHelp() {
|
|
Status error;
|
|
StructuredData::ObjectSP obj = Dispatch("get_short_help", error);
|
|
|
|
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
|
error)) {
|
|
return {};
|
|
}
|
|
|
|
return obj->GetAsString()->GetValue().str();
|
|
}
|
|
|
|
lldb::BreakpointLocationSP ScriptedBreakpointPythonInterface::WasHit(
|
|
lldb::StackFrameSP frame_sp, lldb::BreakpointLocationSP bp_loc_sp) {
|
|
Status py_error;
|
|
lldb::BreakpointLocationSP loc_sp = Dispatch<lldb::BreakpointLocationSP>(
|
|
"was_hit", py_error, frame_sp, bp_loc_sp);
|
|
|
|
if (py_error.Fail())
|
|
return bp_loc_sp;
|
|
|
|
return loc_sp;
|
|
}
|
|
|
|
std::optional<std::string>
|
|
ScriptedBreakpointPythonInterface::GetLocationDescription(
|
|
lldb::BreakpointLocationSP bp_loc_sp, lldb::DescriptionLevel level) {
|
|
Status error;
|
|
StructuredData::ObjectSP obj =
|
|
Dispatch("get_location_description", error, bp_loc_sp, level);
|
|
|
|
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
|
error))
|
|
return {};
|
|
|
|
return obj->GetAsString()->GetValue().str();
|
|
}
|
|
|
|
void ScriptedBreakpointPythonInterface::Initialize() {
|
|
const std::vector<llvm::StringRef> ci_usages = {
|
|
"breakpoint set -P classname [-k key -v value ...]"};
|
|
const std::vector<llvm::StringRef> api_usages = {
|
|
"SBTarget.BreakpointCreateFromScript"};
|
|
PluginManager::RegisterPlugin(
|
|
GetPluginNameStatic(),
|
|
llvm::StringRef("Create a breakpoint that chooses locations based on "
|
|
"user-created callbacks"),
|
|
CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
|
|
}
|
|
|
|
void ScriptedBreakpointPythonInterface::Terminate() {
|
|
PluginManager::UnregisterPlugin(CreateInstance);
|
|
}
|
|
|
|
#endif
|