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, _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits