[Lldb-commits] [lldb] r235538 - This is some groundwork for filtering the language Exception

Jim Ingham jingham at apple.com
Wed Apr 22 12:42:19 PDT 2015


Author: jingham
Date: Wed Apr 22 14:42:18 2015
New Revision: 235538

URL: http://llvm.org/viewvc/llvm-project?rev=235538&view=rev
Log:
This is some groundwork for filtering the language Exception
breakpoints, for instance on the class of the thrown object.

This change doesn't actually make that work, the part where we
extract the thrown object type from the throw site isn't done yet.

This provides a general programmatic "precondition" that you can add
to breakpoints to give them the ability to do filtering on the LLDB
side before we pass the stop on to the user-provided conditions & 
callbacks.

Modified:
    lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
    lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
    lldb/trunk/include/lldb/Target/LanguageRuntime.h
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/source/Breakpoint/Breakpoint.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
    lldb/trunk/source/Interpreter/CommandObject.cpp
    lldb/trunk/source/Target/LanguageRuntime.cpp
    lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/Breakpoint.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h Wed Apr 22 14:42:18 2015
@@ -155,6 +155,23 @@ public:
     };
 
 
+    class BreakpointPrecondition
+    {
+    public:
+        virtual ~BreakpointPrecondition() {}
+
+        virtual bool
+        EvaluatePrecondition(StoppointCallbackContext &context);
+
+        virtual Error
+        ConfigurePrecondition(Args &options);
+
+        virtual void
+        DescribePrecondition(Stream &stream, lldb::DescriptionLevel level);
+    };
+
+    typedef std::shared_ptr<BreakpointPrecondition> BreakpointPreconditionSP;
+
     //------------------------------------------------------------------
     /// Destructor.
     ///
@@ -665,6 +682,31 @@ public:
         }
     }
 
+    //------------------------------------------------------------------
+    /// Set a pre-condition filter that overrides all user provided filters/callbacks etc.
+    ///
+    /// Used to define fancy breakpoints that can do dynamic hit detection without taking up the condition slot -
+    /// which really belongs to the user anyway...
+    ///
+    /// The Precondition should not continue the target, it should return true if the condition says to stop and
+    /// false otherwise.
+    ///
+    //------------------------------------------------------------------
+    void
+    SetPrecondition(BreakpointPreconditionSP precondition_sp)
+    {
+        m_precondition_sp = precondition_sp;
+    }
+
+    bool
+    EvaluatePrecondition (StoppointCallbackContext &context);
+
+    BreakpointPreconditionSP
+    GetPrecondition()
+    {
+        return m_precondition_sp;
+    }
+
 protected:
     friend class Target;
     //------------------------------------------------------------------
@@ -737,13 +779,17 @@ private:
     // For Breakpoint only
     //------------------------------------------------------------------
     bool m_being_created;
-    bool m_hardware;                          // If this breakpoint is required to use a hardware breakpoint
-    Target &m_target;                         // The target that holds this breakpoint.
+    bool m_hardware;                             // If this breakpoint is required to use a hardware breakpoint
+    Target &m_target;                            // The target that holds this breakpoint.
     std::unordered_set<std::string> m_name_list; // If not empty, this is the name of this breakpoint (many breakpoints can share the same name.)
-    lldb::SearchFilterSP m_filter_sp;         // The filter that constrains the breakpoint's domain.
-    lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint.
-    BreakpointOptions m_options;              // Settable breakpoint options
-    BreakpointLocationList m_locations;       // The list of locations currently found for this breakpoint.
+    lldb::SearchFilterSP m_filter_sp;            // The filter that constrains the breakpoint's domain.
+    lldb::BreakpointResolverSP m_resolver_sp;    // The resolver that defines this breakpoint.
+    BreakpointPreconditionSP m_precondition_sp;  // The precondition is a breakpoint-level hit filter that can be used
+                                                 // to skip certain breakpoint hits.  For instance, exception breakpoints
+                                                 // use this to limit the stop to certain exception classes, while leaving
+                                                 // the condition & callback free for user specification.
+    BreakpointOptions m_options;                 // Settable breakpoint options
+    BreakpointLocationList m_locations;          // The list of locations currently found for this breakpoint.
     std::string m_kind_description;
     bool m_resolve_indirect_symbols;
     uint32_t    m_hit_count;                   // Number of times this breakpoint/watchpoint has been hit.  This is kept

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h Wed Apr 22 14:42:18 2015
@@ -89,6 +89,9 @@ public:
     //    callback.
     // Asynchronous callbacks get run as part of the "ShouldStop" logic in the thread plan.  The logic there is:
     //   a) If the breakpoint is thread specific and not for this thread, continue w/o running the callback.
+    //      NB. This is actually enforced underneath the breakpoint system, the Process plugin is expected to
+    //      call BreakpointSite::IsValidForThread, and set the thread's StopInfo to "no reason".  That way,
+    //      thread displays won't show stops for breakpoints not for that thread...
     //   b) If the ignore count says we shouldn't stop, then ditto.
     //   c) If the condition says we shouldn't stop, then ditto.
     //   d) Otherwise, the callback will get run, and if it returns true we will stop, and if false we won't.

Modified: lldb/trunk/include/lldb/Target/LanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/LanguageRuntime.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/LanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/LanguageRuntime.h Wed Apr 22 14:42:18 2015
@@ -80,11 +80,16 @@ public:
     
     static lldb::BreakpointSP
     CreateExceptionBreakpoint (Target &target,
-                               lldb::LanguageType language, 
+                               lldb::LanguageType language,
                                bool catch_bp, 
                                bool throw_bp, 
                                bool is_internal = false);
-                            
+
+    static Breakpoint::BreakpointPreconditionSP
+    CreateExceptionPrecondition (lldb::LanguageType language,
+                                 bool catch_bp,
+                                 bool throw_bp);
+
     static lldb::LanguageType
     GetLanguageTypeFromString (const char *string);
     

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Wed Apr 22 14:42:18 2015
@@ -289,6 +289,24 @@ public:
     protected:
         std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_ap;
     };
+
+    class ObjCExceptionPrecondition : public Breakpoint::BreakpointPrecondition
+    {
+    public:
+        ObjCExceptionPrecondition();
+
+        virtual ~ObjCExceptionPrecondition() {}
+
+        bool EvaluatePrecondition(StoppointCallbackContext &context) override;
+        void DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) override;
+        Error ConfigurePrecondition(Args &args) override;
+
+    protected:
+        void AddClassName(const char *class_name);
+
+    private:
+        std::unordered_set<std::string> m_class_names;
+    };
     
     typedef std::shared_ptr<EncodingToType> EncodingToTypeSP;
     

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Wed Apr 22 14:42:18 2015
@@ -741,7 +741,12 @@ public:
                       bool request_hardware);
                       
     lldb::BreakpointSP
-    CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal);
+    CreateExceptionBreakpoint (enum lldb::LanguageType language,
+                               bool catch_bp,
+                               bool throw_bp,
+                               bool internal,
+                               Args *additional_args = nullptr,
+                               Error *additional_args_error = nullptr);
     
     // This is the same as the func_name breakpoint except that you can specify a vector of names.  This is cheaper
     // than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Wed Apr 22 14:42:18 2015
@@ -521,6 +521,7 @@ namespace lldb {
         eArgTypeThreadID,
         eArgTypeThreadIndex,
         eArgTypeThreadName,
+        eArgTypeTypeName,
         eArgTypeUnsignedInteger,
         eArgTypeUnixSignal,
         eArgTypeVarName,

Modified: lldb/trunk/source/Breakpoint/Breakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Breakpoint.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Breakpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Breakpoint.cpp Wed Apr 22 14:42:18 2015
@@ -949,6 +949,34 @@ Breakpoint::GetFilterDescription (Stream
     m_filter_sp->GetDescription (s);
 }
 
+bool
+Breakpoint::EvaluatePrecondition (StoppointCallbackContext &context)
+{
+    if (!m_precondition_sp)
+        return true;
+
+    return m_precondition_sp->EvaluatePrecondition(context);
+}
+
+bool
+Breakpoint::BreakpointPrecondition::EvaluatePrecondition(StoppointCallbackContext &context)
+{
+    return true;
+}
+
+void
+Breakpoint::BreakpointPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
+{
+}
+
+Error
+Breakpoint::BreakpointPrecondition::ConfigurePrecondition(Args &options)
+{
+    Error error;
+    error.SetErrorString("Base breakpoint precondition has no options.");
+    return error;
+}
+
 void
 Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind)
 {

Modified: lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpoint.cpp Wed Apr 22 14:42:18 2015
@@ -112,7 +112,7 @@ public:
             m_catch_bp (false),
             m_throw_bp (true),
             m_hardware (false),
-            m_language (eLanguageTypeUnknown),
+            m_exception_language (eLanguageTypeUnknown),
             m_skip_prologue (eLazyBoolCalculate),
             m_one_shot (false),
             m_all_files (false)
@@ -173,16 +173,16 @@ public:
                         case eLanguageTypeC:
                         case eLanguageTypeC99:
                         case eLanguageTypeC11:
-                            m_language = eLanguageTypeC;
+                            m_exception_language = eLanguageTypeC;
                             break;
                         case eLanguageTypeC_plus_plus:
                         case eLanguageTypeC_plus_plus_03:
                         case eLanguageTypeC_plus_plus_11:
                         case eLanguageTypeC_plus_plus_14:
-                            m_language = eLanguageTypeC_plus_plus;
+                            m_exception_language = eLanguageTypeC_plus_plus;
                             break;
                         case eLanguageTypeObjC:
-                            m_language = eLanguageTypeObjC;
+                            m_exception_language = eLanguageTypeObjC;
                             break;
                         case eLanguageTypeObjC_plus_plus:
                             error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
@@ -268,6 +268,11 @@ public:
                     m_one_shot = true;
                     break;
 
+                case 'O':
+                    m_exception_extra_args.AppendArgument ("-O");
+                    m_exception_extra_args.AppendArgument (option_arg);
+                    break;
+
                 case 'p':
                     m_source_text_regexp.assign (option_arg);
                     break;
@@ -349,12 +354,13 @@ public:
             m_catch_bp = false;
             m_throw_bp = true;
             m_hardware = false;
-            m_language = eLanguageTypeUnknown;
+            m_exception_language = eLanguageTypeUnknown;
             m_skip_prologue = eLazyBoolCalculate;
             m_one_shot = false;
             m_use_dummy = false;
             m_breakpoint_names.clear();
             m_all_files = false;
+            m_exception_extra_args.Clear();
         }
     
         const OptionDefinition*
@@ -388,11 +394,12 @@ public:
         bool m_catch_bp;
         bool m_throw_bp;
         bool m_hardware; // Request to use hardware breakpoints
-        lldb::LanguageType m_language;
+        lldb::LanguageType m_exception_language;
         LazyBool m_skip_prologue;
         bool m_one_shot;
         bool m_use_dummy;
         bool m_all_files;
+        Args m_exception_extra_args;
 
     };
 
@@ -430,7 +437,7 @@ protected:
             break_type = eSetTypeFunctionRegexp;
         else if (!m_options.m_source_text_regexp.empty())
             break_type = eSetTypeSourceRegexp;
-        else if (m_options.m_language != eLanguageTypeUnknown)
+        else if (m_options.m_exception_language != eLanguageTypeUnknown)
             break_type = eSetTypeException;
 
         Breakpoint *bp = NULL;
@@ -556,10 +563,21 @@ protected:
                 break;
             case eSetTypeException:
                 {
-                    bp = target->CreateExceptionBreakpoint (m_options.m_language,
+                    Error precond_error;
+                    bp = target->CreateExceptionBreakpoint (m_options.m_exception_language,
                                                             m_options.m_catch_bp,
                                                             m_options.m_throw_bp,
-                                                            internal).get();
+                                                            internal,
+                                                            &m_options.m_exception_extra_args,
+                                                            &precond_error).get();
+                    if (precond_error.Fail())
+                    {
+                        result.AppendErrorWithFormat("Error setting extra exception arguments: %s",
+                                                     precond_error.AsCString());
+                        target->RemoveBreakpointByID(bp->GetID());
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
                 }
                 break;
             default:
@@ -758,6 +776,10 @@ CommandObjectBreakpointSet::CommandOptio
     { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
         "Set the breakpoint on exception catcH." },
 
+//  Don't add this option till it actually does something useful...
+//    { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeTypeName,
+//        "The breakpoint will only stop if an exception Object of this type is thrown.  Can be repeated multiple times to stop for multiple object types" },
+
     { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
         "sKip the prologue if the breakpoint is at the beginning of a function.  If not set the target.skip-prologue setting is used." },
 

Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Wed Apr 22 14:42:18 2015
@@ -1193,6 +1193,7 @@ CommandObject::g_arguments_data[] =
     { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." },
     { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." },
     { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." },
+    { eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A type name." },
     { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
     { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
     { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." },

Modified: lldb/trunk/source/Target/LanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/LanguageRuntime.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Target/LanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/LanguageRuntime.cpp Wed Apr 22 14:42:18 2015
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/SearchFilter.h"
@@ -277,6 +278,23 @@ LanguageRuntime::~LanguageRuntime()
 {
 }
 
+Breakpoint::BreakpointPreconditionSP
+LanguageRuntime::CreateExceptionPrecondition (lldb::LanguageType language,
+                                              bool catch_bp,
+                                              bool throw_bp)
+{
+    switch (language)
+    {
+    case eLanguageTypeObjC:
+        if (throw_bp)
+            return Breakpoint::BreakpointPreconditionSP(new ObjCLanguageRuntime::ObjCExceptionPrecondition ());
+        break;
+    default:
+        break;
+    }
+    return Breakpoint::BreakpointPreconditionSP();
+}
+
 BreakpointSP
 LanguageRuntime::CreateExceptionBreakpoint (Target &target,
                                             lldb::LanguageType language,
@@ -289,8 +307,15 @@ LanguageRuntime::CreateExceptionBreakpoi
     bool hardware = false;
     bool resolve_indirect_functions = false;
     BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions));
-    if (is_internal)
-        exc_breakpt_sp->SetBreakpointKind("exception");
+    if (exc_breakpt_sp)
+    {
+        Breakpoint::BreakpointPreconditionSP precondition_sp = CreateExceptionPrecondition(language, catch_bp, throw_bp);
+        if (precondition_sp)
+            exc_breakpt_sp->SetPrecondition(precondition_sp);
+
+        if (is_internal)
+            exc_breakpt_sp->SetBreakpointKind("exception");
+    }
     
     return exc_breakpt_sp;
 }

Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Wed Apr 22 14:42:18 2015
@@ -670,3 +670,36 @@ ObjCLanguageRuntime::GetTypeBitSize (con
     
     return found;
 }
+
+//------------------------------------------------------------------
+// Exception breakpoint Precondition class for ObjC:
+//------------------------------------------------------------------
+void
+ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(const char *class_name)
+{
+    m_class_names.insert(class_name);
+}
+
+ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition()
+{
+}
+
+bool
+ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCallbackContext &context)
+{
+    return true;
+}
+
+void
+ObjCLanguageRuntime::ObjCExceptionPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
+{
+}
+
+Error
+ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(Args &args)
+{
+    Error error;
+    if (args.GetArgumentCount() > 0)
+        error.SetErrorString("The ObjC Exception breakpoint doesn't support extra options.");
+    return error;
+}

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=235538&r1=235537&r2=235538&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Wed Apr 22 14:42:18 2015
@@ -523,11 +523,23 @@ Target::CreateFuncRegexBreakpoint (const
 }
 
 lldb::BreakpointSP
-Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal)
+Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal, Args *additional_args, Error *error)
 {
-    return LanguageRuntime::CreateExceptionBreakpoint (*this, language, catch_bp, throw_bp, internal);
+    BreakpointSP exc_bkpt_sp = LanguageRuntime::CreateExceptionBreakpoint (*this, language, catch_bp, throw_bp, internal);
+    if (exc_bkpt_sp && additional_args)
+    {
+        Breakpoint::BreakpointPreconditionSP precondition_sp = exc_bkpt_sp->GetPrecondition();
+        if (precondition_sp && additional_args)
+        {
+            if (error)
+                *error = precondition_sp->ConfigurePrecondition(*additional_args);
+            else
+                precondition_sp->ConfigurePrecondition(*additional_args);
+        }
+    }
+    return exc_bkpt_sp;
 }
-    
+
 BreakpointSP
 Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware, bool resolve_indirect_symbols)
 {





More information about the lldb-commits mailing list