[Lldb-commits] [lldb] r342185 - Add a "scripted" breakpoint type to lldb.
Jim Ingham via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 13 14:35:33 PDT 2018
Modified: lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lldbutil.py Thu Sep 13 14:35:32 2018
@@ -330,6 +330,20 @@ def sort_stopped_threads(process,
# Utility functions for setting breakpoints
# ==================================================
+def run_break_set_by_script(
+ test,
+ class_name,
+ extra_options=None,
+ num_expected_locations=1):
+ """Set a scripted breakpoint. Check that it got the right number of locations."""
+ test.assertTrue(class_name is not None, "Must pass in a class name.")
+ command = "breakpoint set -P " + class_name
+ if extra_options is not None:
+ command += " " + extra_options
+
+ break_results = run_break_set_command(test, command)
+ check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
+ return get_bpno_from_match(break_results)
def run_break_set_by_file_and_line(
test,
@@ -737,7 +751,7 @@ def get_crashed_threads(test, process):
# Helper functions for run_to_{source,name}_breakpoint:
-def run_to_breakpoint_make_target(test, exe_name, in_cwd):
+def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
if in_cwd:
exe = test.getBuildArtifact(exe_name)
@@ -746,7 +760,7 @@ def run_to_breakpoint_make_target(test,
test.assertTrue(target, "Target: %s is not valid."%(exe_name))
return target
-def run_to_breakpoint_do_run(test, target, bkpt, launch_info):
+def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None):
# Launch the process, and do not stop at the entry point.
if not launch_info:
Modified: lldb/trunk/scripts/Python/python-swigsafecast.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-swigsafecast.swig?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-swigsafecast.swig (original)
+++ lldb/trunk/scripts/Python/python-swigsafecast.swig Thu Sep 13 14:35:32 2018
@@ -147,3 +147,17 @@ SBTypeToSWIGWrapper (lldb::SBTypeSummary
{
return SWIG_NewPointerObj((void *) summary_options_sb, SWIGTYPE_p_lldb__SBTypeSummaryOptions, 0);
}
+
+template <>
+PyObject*
+SBTypeToSWIGWrapper (lldb::SBStructuredData* structured_data_sb)
+{
+ return SWIG_NewPointerObj((void *) structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0);
+}
+
+template <>
+PyObject*
+SBTypeToSWIGWrapper (lldb::SBSymbolContext* sym_ctx_sb)
+{
+ return SWIG_NewPointerObj((void *) sym_ctx_sb, SWIGTYPE_p_lldb__SBSymbolContext, 0);
+}
Modified: lldb/trunk/scripts/Python/python-wrapper.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-wrapper.swig (original)
+++ lldb/trunk/scripts/Python/python-wrapper.swig Thu Sep 13 14:35:32 2018
@@ -333,6 +333,101 @@ LLDBSWIGPythonCallThreadPlan
return false;
}
+SWIGEXPORT void *
+LLDBSwigPythonCreateScriptedBreakpointResolver
+(
+ const char *python_class_name,
+ const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args_impl,
+ lldb::BreakpointSP &breakpoint_sp
+)
+{
+ using namespace lldb_private;
+
+ if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
+ Py_RETURN_NONE;
+
+ PyErr_Cleaner py_err_cleaner(true);
+
+ auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
+ auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
+
+ if (!pfunc.IsAllocated())
+ return nullptr;
+
+ lldb::SBBreakpoint *bkpt_value = new lldb::SBBreakpoint(breakpoint_sp);
+
+ PythonObject bkpt_arg(PyRefType::Owned, SBTypeToSWIGWrapper(bkpt_value));
+
+ lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
+ PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
+
+ PythonObject result = pfunc(bkpt_arg, args_arg, dict);
+ // FIXME: At this point we should check that the class we found supports all the methods
+ // that we need.
+
+ if (result.IsAllocated())
+ {
+ // Check that __callback__ is defined:
+ auto callback_func = result.ResolveName<PythonCallable>("__callback__");
+ if (callback_func.IsAllocated())
+ return result.release();
+ else
+ result.release();
+ }
+ Py_RETURN_NONE;
+}
+
+SWIGEXPORT unsigned int
+LLDBSwigPythonCallBreakpointResolver
+(
+ void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx
+)
+{
+ using namespace lldb_private;
+
+ PyErr_Cleaner py_err_cleaner(false);
+ PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
+ auto pfunc = self.ResolveName<PythonCallable>(method_name);
+
+ if (!pfunc.IsAllocated())
+ return 0;
+
+ PythonObject result;
+ if (sym_ctx != nullptr) {
+ lldb::SBSymbolContext sb_sym_ctx(sym_ctx);
+ PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx));
+ result = pfunc(sym_ctx_arg);
+ } else
+ result = pfunc();
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ return 0;
+ }
+
+ // The callback will return a bool, but we're need to also return ints
+ // so we're squirrelling the bool through as an int... And if you return
+ // nothing, we'll continue.
+ if (strcmp(method_name, "__callback__") == 0) {
+ if (result.get() == Py_False)
+ return 0;
+ else
+ return 1;
+ }
+
+ PythonInteger int_result = result.AsType<PythonInteger>();
+ if (!int_result.IsAllocated())
+ return 0;
+
+ unsigned int ret_val = int_result.GetInteger();
+
+ return ret_val;
+}
+
// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember
Modified: lldb/trunk/scripts/interface/SBBreakpoint.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBBreakpoint.i?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBBreakpoint.i (original)
+++ lldb/trunk/scripts/interface/SBBreakpoint.i Thu Sep 13 14:35:32 2018
@@ -226,6 +226,10 @@ public:
bool
GetDescription(lldb::SBStream &description, bool include_locations);
+ // Can only be called from a ScriptedBreakpointResolver...
+ SBError
+ AddLocation(SBAddress &address);
+
bool
operator == (const lldb::SBBreakpoint& rhs);
Modified: lldb/trunk/scripts/interface/SBStructuredData.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBStructuredData.i?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBStructuredData.i (original)
+++ lldb/trunk/scripts/interface/SBStructuredData.i Thu Sep 13 14:35:32 2018
@@ -38,6 +38,8 @@ namespace lldb {
size_t GetSize() const;
+ bool GetKeys(lldb::SBStringList &keys) const;
+
lldb::SBStructuredData GetValueForKey(const char *key) const;
lldb::SBStructuredData GetItemAtIndex(size_t idx) const;
Modified: lldb/trunk/scripts/interface/SBTarget.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBTarget.i?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBTarget.i (original)
+++ lldb/trunk/scripts/interface/SBTarget.i Thu Sep 13 14:35:32 2018
@@ -731,6 +731,74 @@ public:
lldb::SBBreakpoint
BreakpointCreateBySBAddress (SBAddress &sb_address);
+
+ %feature("docstring", "
+ //------------------------------------------------------------------
+ /// Create a breakpoint using a scripted resolver.
+ ///
+ /// @param[in] class_name
+ /// This is the name of the class that implements a scripted resolver.
+ /// The class should have the following signature:
+ /// class Resolver:
+ /// def __init__(self, bkpt, extra_args):
+ /// # bkpt - the breakpoint for which this is the resolver. When
+ /// # the resolver finds an interesting address, call AddLocation
+ /// # on this breakpoint to add it.
+ /// #
+ /// # extra_args - an SBStructuredData that can be used to
+ /// # parametrize this instance. Same as the extra_args passed
+ /// # to BreakpointCreateFromScript.
+ ///
+ /// def __get_depth__ (self):
+ /// # This is optional, but if defined, you should return the
+ /// # depth at which you want the callback to be called. The
+ /// # available options are:
+ /// # lldb.eSearchDepthModule
+ /// # lldb.eSearchDepthCompUnit
+ /// # The default if you don't implement this method is
+ /// # eSearchDepthModule.
+ ///
+ /// def __callback__(self, sym_ctx):
+ /// # sym_ctx - an SBSymbolContext that is the cursor in the
+ /// # search through the program to resolve breakpoints.
+ /// # The sym_ctx will be filled out to the depth requested in
+ /// # __get_depth__.
+ /// # Look in this sym_ctx for new breakpoint locations,
+ /// # and if found use bkpt.AddLocation to add them.
+ /// # Note, you will only get called for modules/compile_units that
+ /// # pass the SearchFilter provided by the module_list & file_list
+ /// # passed into BreakpointCreateFromScript.
+ ///
+ /// def get_short_help(self):
+ /// # Optional, but if implemented return a short string that will
+ /// # be printed at the beginning of the break list output for the
+ /// # breakpoint.
+ ///
+ /// @param[in] extra_args
+ /// This is an SBStructuredData object that will get passed to the
+ /// constructor of the class in class_name. You can use this to
+ /// reuse the same class, parametrizing it with entries from this
+ /// dictionary.
+ ///
+ /// @param module_list
+ /// If this is non-empty, this will be used as the module filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @param file_list
+ /// If this is non-empty, this will be used as the comp unit filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @return
+ /// An SBBreakpoint that will set locations based on the logic in the
+ /// resolver's search callback.
+ //------------------------------------------------------------------
+ ") BreakpointCreateFromScript;
+ lldb::SBBreakpoint BreakpointCreateFromScript(
+ const char *class_name,
+ SBStructuredData &extra_args,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &file_list,
+ bool request_hardware = false);
uint32_t
GetNumBreakpoints () const;
Modified: lldb/trunk/source/API/SBBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBBreakpoint.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/API/SBBreakpoint.cpp (original)
+++ lldb/trunk/source/API/SBBreakpoint.cpp Thu Sep 13 14:35:32 2018
@@ -23,6 +23,8 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
@@ -487,6 +489,40 @@ bool SBBreakpoint::GetDescription(SBStre
return false;
}
+SBError
+SBBreakpoint::AddLocation(SBAddress &address) {
+ BreakpointSP bkpt_sp = GetSP();
+ SBError error;
+
+ if (!address.IsValid()) {
+ error.SetErrorString("Can't add an invalid address.");
+ return error;
+ }
+
+ if (!bkpt_sp) {
+ error.SetErrorString("No breakpoint to add a location to.");
+ return error;
+ }
+
+ if (!llvm::isa<BreakpointResolverScripted>(bkpt_sp->GetResolver().get())) {
+ error.SetErrorString("Only a scripted resolver can add locations.");
+ return error;
+ }
+
+ if (bkpt_sp->GetSearchFilter()->AddressPasses(address.ref()))
+ bkpt_sp->AddLocation(address.ref());
+ else
+ {
+ StreamString s;
+ address.get()->Dump(&s, &bkpt_sp->GetTarget(),
+ Address::DumpStyleModuleWithFileAddress);
+ error.SetErrorStringWithFormat("Address: %s didn't pass the filter.",
+ s.GetData());
+ }
+ return error;
+}
+
+
void SBBreakpoint
::SetCallback(SBBreakpointHitCallback callback,
void *baton) {
Modified: lldb/trunk/source/API/SBStructuredData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBStructuredData.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/API/SBStructuredData.cpp (original)
+++ lldb/trunk/source/API/SBStructuredData.cpp Thu Sep 13 14:35:32 2018
@@ -10,6 +10,7 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/StructuredDataPlugin.h"
@@ -31,6 +32,9 @@ SBStructuredData::SBStructuredData(const
SBStructuredData::SBStructuredData(const lldb::EventSP &event_sp)
: m_impl_up(new StructuredDataImpl(event_sp)) {}
+SBStructuredData::SBStructuredData(lldb_private::StructuredDataImpl *impl)
+ : m_impl_up(impl) {}
+
SBStructuredData::~SBStructuredData() {}
SBStructuredData &SBStructuredData::
@@ -76,6 +80,33 @@ size_t SBStructuredData::GetSize() const
return (m_impl_up ? m_impl_up->GetSize() : 0);
}
+bool SBStructuredData::GetKeys(lldb::SBStringList &keys) const {
+ if (!m_impl_up)
+ return false;
+
+ if (GetType() != eStructuredDataTypeDictionary)
+ return false;
+
+ StructuredData::ObjectSP obj_sp = m_impl_up->GetObjectSP();
+ if (!obj_sp)
+ return false;
+
+ StructuredData::Dictionary *dict = obj_sp->GetAsDictionary();
+ // We claimed we were a dictionary, so this can't be null.
+ assert(dict);
+ // The return kind of GetKeys is an Array:
+ StructuredData::ObjectSP array_sp = dict->GetKeys();
+ StructuredData::Array *key_arr = array_sp->GetAsArray();
+ assert(key_arr);
+
+ key_arr->ForEach([&keys] (StructuredData::Object *object) -> bool {
+ llvm::StringRef key = object->GetStringValue("");
+ keys.AppendString(key.str().c_str());
+ return true;
+ });
+ return true;
+}
+
lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const {
if (!m_impl_up)
return SBStructuredData();
Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Thu Sep 13 14:35:32 2018
@@ -1044,7 +1044,7 @@ SBTarget::BreakpointCreateForException(l
}
if (log)
- log->Printf("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: "
+ log->Printf("SBTarget(%p)::BreakpointCreateForException (Language: %s, catch: "
"%s throw: %s) => SBBreakpoint(%p)",
static_cast<void *>(target_sp.get()),
Language::GetNameForLanguageType(language),
@@ -1054,6 +1054,42 @@ SBTarget::BreakpointCreateForException(l
return sb_bp;
}
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateFromScript(const char *class_name,
+ SBStructuredData &extra_args,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &file_list,
+ bool request_hardware)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ SBBreakpoint sb_bp;
+ TargetSP target_sp(GetSP());
+ if (target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+ Status error;
+
+ StructuredData::ObjectSP obj_sp = extra_args.m_impl_up->GetObjectSP();
+ sb_bp =
+ target_sp->CreateScriptedBreakpoint(class_name,
+ module_list.get(),
+ file_list.get(),
+ false, /* internal */
+ request_hardware,
+ obj_sp,
+ &error);
+ }
+ if (log)
+ log->Printf("SBTarget(%p)::BreakpointCreateFromScript (class name: %s) "
+ " => SBBreakpoint(%p)",
+ static_cast<void *>(target_sp.get()),
+ class_name,
+ static_cast<void *>(sb_bp.GetSP().get()));
+
+ return sb_bp;
+}
+
+
uint32_t SBTarget::GetNumBreakpoints() const {
TargetSP target_sp(GetSP());
if (target_sp) {
Modified: lldb/trunk/source/API/SystemInitializerFull.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Thu Sep 13 14:35:32 2018
@@ -176,6 +176,18 @@ extern "C" void *LLDBSwigPythonCreateScr
extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor,
const char *method_name,
Event *event_sp, bool &got_error);
+
+extern "C" void *LLDBSwigPythonCreateScriptedBreakpointResolver(
+ const char *python_class_name,
+ const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args,
+ lldb::BreakpointSP &bkpt_sp);
+
+extern "C" unsigned int LLDBSwigPythonCallBreakpointResolver(
+ void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx
+);
extern "C" size_t LLDBSwigPython_CalculateNumChildren(void *implementor,
uint32_t max);
@@ -413,7 +425,8 @@ void SystemInitializerFull::InitializeSW
LLDBSWIGPythonRunScriptKeywordThread,
LLDBSWIGPythonRunScriptKeywordTarget, LLDBSWIGPythonRunScriptKeywordFrame,
LLDBSWIGPythonRunScriptKeywordValue, LLDBSWIGPython_GetDynamicSetting,
- LLDBSwigPythonCreateScriptedThreadPlan, LLDBSWIGPythonCallThreadPlan);
+ LLDBSwigPythonCreateScriptedThreadPlan, LLDBSWIGPythonCallThreadPlan,
+ LLDBSwigPythonCreateScriptedBreakpointResolver, LLDBSwigPythonCallBreakpointResolver);
#endif
}
Modified: lldb/trunk/source/Breakpoint/BreakpointResolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolver.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolver.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolver.cpp Thu Sep 13 14:35:32 2018
@@ -21,6 +21,7 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/SearchFilter.h"
@@ -44,9 +45,10 @@ const char *BreakpointResolver::g_ty_to_
const char *BreakpointResolver::g_option_names[static_cast<uint32_t>(
BreakpointResolver::OptionNames::LastOptionName)] = {
- "AddressOffset", "Exact", "FileName", "Inlines", "Language",
- "LineNumber", "Column", "ModuleName", "NameMask", "Offset",
- "Regex", "SectionName", "SkipPrologue", "SymbolNames"};
+ "AddressOffset", "Exact", "FileName", "Inlines", "Language",
+ "LineNumber", "Column", "ModuleName", "NameMask", "Offset",
+ "PythonClass", "Regex", "ScriptArgs", "SectionName", "SearchDepth",
+ "SkipPrologue", "SymbolNames"};
const char *BreakpointResolver::ResolverTyToName(enum ResolverTy type) {
if (type > LastKnownResolverType)
@@ -132,6 +134,10 @@ BreakpointResolverSP BreakpointResolver:
resolver = BreakpointResolverFileRegex::CreateFromStructuredData(
nullptr, *subclass_options, error);
break;
+ case PythonResolver:
+ resolver = BreakpointResolverScripted::CreateFromStructuredData(
+ nullptr, *subclass_options, error);
+ break;
case ExceptionResolver:
error.SetErrorString("Exception resolvers are hard.");
break;
@@ -165,6 +171,7 @@ StructuredData::DictionarySP BreakpointR
void BreakpointResolver::SetBreakpoint(Breakpoint *bkpt) {
m_breakpoint = bkpt;
+ NotifyBreakpointSet();
}
void BreakpointResolver::ResolveBreakpointInModules(SearchFilter &filter,
Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Thu Sep 13 14:35:32 2018
@@ -245,10 +245,10 @@ public:
// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
-#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
-#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
+#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
-#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
+#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
+#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
@@ -301,6 +301,9 @@ static OptionDefinition g_breakpoint_set
"are specified, uses the current \"default source file\". If you want to "
"match against all source files, pass the \"--all-files\" option." },
{ LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." },
+ { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
+ { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
+ { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
{ LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
"options, on throw but not catch.)" },
{ LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
@@ -336,7 +339,8 @@ public:
eSetTypeFunctionName,
eSetTypeFunctionRegexp,
eSetTypeSourceRegexp,
- eSetTypeException
+ eSetTypeException,
+ eSetTypeScripted,
} BreakpointSetType;
CommandObjectBreakpointSet(CommandInterpreter &interpreter)
@@ -454,7 +458,15 @@ public:
case 'H':
m_hardware = true;
break;
-
+
+ case 'k': {
+ if (m_current_key.empty())
+ m_current_key.assign(option_arg);
+ else
+ error.SetErrorStringWithFormat("Key: %s missing value.",
+ m_current_key.c_str());
+
+ } break;
case 'K': {
bool success;
bool value;
@@ -535,6 +547,10 @@ public:
case 'p':
m_source_text_regexp.assign(option_arg);
break;
+
+ case 'P':
+ m_python_class.assign(option_arg);
+ break;
case 'r':
m_func_regexp.assign(option_arg);
@@ -549,6 +565,16 @@ public:
m_func_name_type_mask |= eFunctionNameTypeSelector;
break;
+ case 'v': {
+ if (!m_current_key.empty()) {
+ m_extra_args_sp->AddStringItem(m_current_key, option_arg);
+ m_current_key.clear();
+ }
+ else
+ error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
+ option_arg.str().c_str());
+ } break;
+
case 'w': {
bool success;
m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
@@ -593,6 +619,9 @@ public:
m_exception_extra_args.Clear();
m_move_to_nearest_code = eLazyBoolCalculate;
m_source_regex_func_names.clear();
+ m_python_class.clear();
+ m_extra_args_sp.reset(new StructuredData::Dictionary());
+ m_current_key.clear();
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -623,6 +652,9 @@ public:
Args m_exception_extra_args;
LazyBool m_move_to_nearest_code;
std::unordered_set<std::string> m_source_regex_func_names;
+ std::string m_python_class;
+ StructuredData::DictionarySP m_extra_args_sp;
+ std::string m_current_key;
};
protected:
@@ -649,7 +681,9 @@ protected:
BreakpointSetType break_type = eSetTypeInvalid;
- if (m_options.m_line_num != 0)
+ if (!m_options.m_python_class.empty())
+ break_type = eSetTypeScripted;
+ else if (m_options.m_line_num != 0)
break_type = eSetTypeFileAndLine;
else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
break_type = eSetTypeAddress;
@@ -822,6 +856,25 @@ protected:
target->RemoveBreakpointByID(bp_sp->GetID());
result.SetStatus(eReturnStatusFailed);
return false;
+ }
+ } break;
+ case eSetTypeScripted: {
+
+ Status error;
+ bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
+ &(m_options.m_modules),
+ &(m_options.m_filenames),
+ false,
+ m_options.m_hardware,
+ m_options.m_extra_args_sp,
+ &error);
+ if (error.Fail()) {
+ result.AppendErrorWithFormat(
+ "Error setting extra exception arguments: %s",
+ error.AsCString());
+ target->RemoveBreakpointByID(bp_sp->GetID());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
} break;
default:
Modified: lldb/trunk/source/Core/SearchFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/SearchFilter.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Core/SearchFilter.cpp (original)
+++ lldb/trunk/source/Core/SearchFilter.cpp Thu Sep 13 14:35:32 2018
@@ -311,7 +311,7 @@ SearchFilter::DoCUIteration(const Module
return Searcher::eCallbackReturnContinue;
else if (shouldContinue == Searcher::eCallbackReturnStop)
return shouldContinue;
- } else {
+ } else if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
// FIXME Descend to block.
}
}
@@ -748,7 +748,15 @@ SearchFilterByModuleListAndCU::Serialize
}
bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
- return true;
+ SymbolContext sym_ctx;
+ address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
+ if (!sym_ctx.comp_unit) {
+ if (m_cu_spec_list.GetSize() != 0)
+ return false; // Has no comp_unit so can't pass the file check.
+ }
+ if (m_cu_spec_list.FindFileIndex(0, sym_ctx.comp_unit, false) == UINT32_MAX)
+ return false; // Fails the file check
+ return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
}
bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Thu Sep 13 14:35:32 2018
@@ -107,6 +107,10 @@ static ScriptInterpreterPython::SWIGPyth
g_swig_thread_plan_script = nullptr;
static ScriptInterpreterPython::SWIGPythonCallThreadPlan
g_swig_call_thread_plan = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateScriptedBreakpointResolver
+ g_swig_bkpt_resolver_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallBreakpointResolver
+ g_swig_call_bkpt_resolver = nullptr;
static bool g_initialized = false;
@@ -1868,6 +1872,84 @@ lldb::StateType ScriptInterpreterPython:
return lldb::eStateRunning;
}
+StructuredData::GenericSP
+ScriptInterpreterPython::CreateScriptedBreakpointResolver(
+ const char *class_name,
+ StructuredDataImpl *args_data,
+ lldb::BreakpointSP &bkpt_sp) {
+
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ if (!bkpt_sp.get())
+ return StructuredData::GenericSP();
+
+ Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ static_cast<ScriptInterpreterPython *>(script_interpreter);
+
+ if (!script_interpreter)
+ return StructuredData::GenericSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ ret_val = g_swig_bkpt_resolver_script(
+ class_name, python_interpreter->m_dictionary_name.c_str(),
+ args_data, bkpt_sp);
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+bool
+ScriptInterpreterPython::ScriptedBreakpointResolverSearchCallback(
+ StructuredData::GenericSP implementor_sp,
+ SymbolContext *sym_ctx) {
+ bool should_continue = false;
+
+ if (implementor_sp) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_continue
+ = g_swig_call_bkpt_resolver(implementor_sp->GetValue(), "__callback__",
+ sym_ctx);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ return should_continue;
+}
+
+lldb::SearchDepth
+ScriptInterpreterPython::ScriptedBreakpointResolverSearchDepth(
+ StructuredData::GenericSP implementor_sp) {
+ int depth_as_int = lldb::eSearchDepthModule;
+ if (implementor_sp) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ depth_as_int
+ = g_swig_call_bkpt_resolver(implementor_sp->GetValue(), "__get_depth__", nullptr);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ if (depth_as_int == lldb::eSearchDepthInvalid)
+ return lldb::eSearchDepthModule;
+
+ if (depth_as_int <= lldb::kLastSearchDepthKind)
+ return (lldb::SearchDepth) depth_as_int;
+ else
+ return lldb::eSearchDepthModule;
+}
+
StructuredData::ObjectSP
ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec,
lldb_private::Status &error) {
@@ -3107,7 +3189,9 @@ void ScriptInterpreterPython::Initialize
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan) {
+ SWIGPythonCallThreadPlan swig_call_thread_plan,
+ SWIGPythonCreateScriptedBreakpointResolver swig_bkpt_resolver_script,
+ SWIGPythonCallBreakpointResolver swig_call_bkpt_resolver) {
g_swig_init_callback = swig_init_callback;
g_swig_breakpoint_callback = swig_breakpoint_callback;
g_swig_watchpoint_callback = swig_watchpoint_callback;
@@ -3134,6 +3218,8 @@ void ScriptInterpreterPython::Initialize
g_swig_plugin_get = swig_plugin_get;
g_swig_thread_plan_script = swig_thread_plan_script;
g_swig_call_thread_plan = swig_call_thread_plan;
+ g_swig_bkpt_resolver_script = swig_bkpt_resolver_script;
+ g_swig_call_bkpt_resolver = swig_call_bkpt_resolver;
}
void ScriptInterpreterPython::InitializePrivate() {
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h Thu Sep 13 14:35:32 2018
@@ -81,6 +81,15 @@ public:
const char *method_name,
Event *event_sp, bool &got_error);
+ typedef void *(*SWIGPythonCreateScriptedBreakpointResolver)(
+ const char *python_class_name, const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args_impl,
+ lldb::BreakpointSP &bkpt_sp);
+
+ typedef unsigned int (*SWIGPythonCallBreakpointResolver)(void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx);
+
typedef void *(*SWIGPythonCreateOSPlugin)(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP &process_sp);
@@ -208,6 +217,19 @@ public:
lldb::StateType
ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
bool &script_error) override;
+
+ StructuredData::GenericSP
+ CreateScriptedBreakpointResolver(const char *class_name,
+ StructuredDataImpl *args_data,
+ lldb::BreakpointSP &bkpt_sp) override;
+ bool
+ ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP
+ implementor_sp,
+ SymbolContext *sym_ctx) override;
+
+ lldb::SearchDepth
+ ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP
+ implementor_sp) override;
StructuredData::GenericSP
OSPlugin_CreatePluginObject(const char *class_name,
@@ -411,7 +433,9 @@ public:
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan);
+ SWIGPythonCallThreadPlan swig_call_thread_plan,
+ SWIGPythonCreateScriptedBreakpointResolver swig_bkpt_resolver_script,
+ SWIGPythonCallBreakpointResolver swig_call_breakpoint_resolver);
const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=342185&r1=342184&r2=342185&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Thu Sep 13 14:35:32 2018
@@ -21,6 +21,7 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Event.h"
@@ -28,8 +29,10 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
+#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
@@ -579,6 +582,48 @@ Target::CreateExceptionBreakpoint(enum l
return exc_bkpt_sp;
}
+lldb::BreakpointSP
+Target::CreateScriptedBreakpoint(const llvm::StringRef class_name,
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ bool internal,
+ bool request_hardware,
+ StructuredData::ObjectSP extra_args_sp,
+ Status *creation_error)
+{
+ SearchFilterSP filter_sp;
+
+ lldb::SearchDepth depth = lldb::eSearchDepthTarget;
+ bool has_files = containingSourceFiles && containingSourceFiles->GetSize() > 0;
+ bool has_modules = containingModules && containingModules->GetSize() > 0;
+
+ if (has_files && has_modules) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ containingModules, containingSourceFiles);
+ } else if (has_files) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ nullptr, containingSourceFiles);
+ } else if (has_modules) {
+ filter_sp = GetSearchFilterForModuleList(containingModules);
+ } else {
+ filter_sp.reset(new SearchFilterForUnconstrainedSearches(shared_from_this()));
+ }
+
+ StructuredDataImpl *extra_args_impl = new StructuredDataImpl();
+ if (extra_args_sp)
+ extra_args_impl->SetObjectSP(extra_args_sp);
+
+ BreakpointResolverSP resolver_sp(new
+ BreakpointResolverScripted(nullptr, class_name,
+ depth,
+ extra_args_impl,
+ *GetDebugger().GetCommandInterpreter()
+ .GetScriptInterpreter()));
+ return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true);
+
+}
+
+
BreakpointSP Target::CreateBreakpoint(SearchFilterSP &filter_sp,
BreakpointResolverSP &resolver_sp,
bool internal, bool request_hardware,
More information about the lldb-commits
mailing list